LCOV - code coverage report
Current view: top level - source3/smbd - fileio.c (source / functions) Hit Total Coverage
Test: coverage report for master 6248eab5 Lines: 92 111 82.9 %
Date: 2021-08-25 13:27:56 Functions: 9 9 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/Netbios implementation.
       3             :    Version 1.9.
       4             :    read/write to a files_struct
       5             :    Copyright (C) Andrew Tridgell 1992-1998
       6             :    Copyright (C) Jeremy Allison 2000-2002. - write cache.
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "printing.h"
      24             : #include "smbd/smbd.h"
      25             : #include "smbd/globals.h"
      26             : #include "smbprofile.h"
      27             : 
      28             : /****************************************************************************
      29             :  Read from a file.
      30             : ****************************************************************************/
      31             : 
      32        2604 : ssize_t read_file(files_struct *fsp,char *data,off_t pos,size_t n)
      33             : {
      34             :         off_t new_pos;
      35        2604 :         ssize_t ret = 0;
      36             :         bool ok;
      37             : 
      38             :         /* you can't read from print files */
      39        2604 :         if (fsp->print_file) {
      40           0 :                 errno = EBADF;
      41           0 :                 return -1;
      42             :         }
      43             : 
      44        2604 :         ok = vfs_valid_pread_range(pos, n);
      45        2604 :         if (!ok) {
      46           0 :                 errno = EINVAL;
      47           0 :                 return -1;
      48             :         }
      49             : 
      50        2604 :         fh_set_pos(fsp->fh, pos);
      51             : 
      52        2604 :         if (n > 0) {
      53        2548 :                 ret = SMB_VFS_PREAD(fsp,data,n,pos);
      54             : 
      55        2548 :                 if (ret == -1) {
      56           0 :                         return -1;
      57             :                 }
      58             :         }
      59             : 
      60        2604 :         DEBUG(10,("read_file (%s): pos = %.0f, size = %lu, returned %lu\n",
      61             :                   fsp_str_dbg(fsp), (double)pos, (unsigned long)n, (long)ret));
      62             : 
      63        2604 :         new_pos = fh_get_pos(fsp->fh) + ret;
      64        2604 :         fh_set_pos(fsp->fh, new_pos);
      65        2604 :         fh_set_position_information(fsp->fh, new_pos);
      66             : 
      67        2604 :         return(ret);
      68             : }
      69             : 
      70             : /****************************************************************************
      71             :  *Really* write to a file.
      72             : ****************************************************************************/
      73             : 
      74        3316 : static ssize_t real_write_file(struct smb_request *req,
      75             :                                 files_struct *fsp,
      76             :                                 const char *data,
      77             :                                 off_t pos,
      78             :                                 size_t n)
      79             : {
      80             :         ssize_t ret;
      81             :         bool ok;
      82             : 
      83        3316 :         ok = vfs_valid_pwrite_range(pos, n);
      84        3316 :         if (!ok) {
      85           8 :                 errno = EINVAL;
      86           8 :                 return -1;
      87             :         }
      88             : 
      89        3308 :         if (n == 0) {
      90          16 :                 return 0;
      91             :         }
      92             : 
      93        3290 :         fh_set_pos(fsp->fh, pos);
      94        5730 :         if (pos &&
      95        2440 :             lp_strict_allocate(SNUM(fsp->conn)) &&
      96           0 :             !fsp->fsp_flags.is_sparse)
      97             :         {
      98           0 :                 if (vfs_fill_sparse(fsp, pos) == -1) {
      99           0 :                         return -1;
     100             :                 }
     101             :         }
     102        3290 :         ret = vfs_pwrite_data(req, fsp, data, n, pos);
     103             : 
     104        3290 :         DEBUG(10,("real_write_file (%s): pos = %.0f, size = %lu, returned %ld\n",
     105             :                   fsp_str_dbg(fsp), (double)pos, (unsigned long)n, (long)ret));
     106             : 
     107        3290 :         if (ret != -1) {
     108        1088 :                 off_t new_pos = fh_get_pos(fsp->fh) + ret;
     109        1088 :                 fh_set_pos(fsp->fh, new_pos);
     110             : 
     111             : /* Yes - this is correct - writes don't update this. JRA. */
     112             : /* Found by Samba4 tests. */
     113             : #if 0
     114             :                 fsp->position_information = fsp->pos;
     115             : #endif
     116             :         }
     117             : 
     118        3278 :         return ret;
     119             : }
     120             : 
     121        4952 : void fsp_flush_write_time_update(struct files_struct *fsp)
     122             : {
     123             :         /*
     124             :          * Note this won't expect any impersonation!
     125             :          * So don't call any SMB_VFS operations here!
     126             :          */
     127             : 
     128        4952 :         DEBUG(5, ("Update write time on %s\n", fsp_str_dbg(fsp)));
     129             : 
     130        4952 :         trigger_write_time_update_immediate(fsp);
     131        4952 : }
     132             : 
     133         122 : static void update_write_time_handler(struct tevent_context *ctx,
     134             :                                       struct tevent_timer *te,
     135             :                                       struct timeval now,
     136             :                                       void *private_data)
     137             : {
     138         122 :         files_struct *fsp = (files_struct *)private_data;
     139         122 :         fsp_flush_write_time_update(fsp);
     140         122 : }
     141             : 
     142             : /*********************************************************
     143             :  Schedule a write time update for WRITE_TIME_UPDATE_USEC_DELAY
     144             :  in the future.
     145             : *********************************************************/
     146             : 
     147      171639 : void trigger_write_time_update(struct files_struct *fsp)
     148             : {
     149             :         int delay;
     150             : 
     151      171639 :         if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
     152             :                 /* Don't use delayed writes on POSIX files. */
     153           4 :                 return;
     154             :         }
     155             : 
     156      171635 :         if (fsp->fsp_flags.write_time_forced) {
     157             :                 /* No point - "sticky" write times
     158             :                  * in effect.
     159             :                  */
     160         198 :                 return;
     161             :         }
     162             : 
     163             :         /* We need to remember someone did a write
     164             :          * and update to current time on close. */
     165             : 
     166      171434 :         fsp->fsp_flags.update_write_time_on_close = true;
     167             : 
     168      171434 :         if (fsp->fsp_flags.update_write_time_triggered) {
     169             :                 /*
     170             :                  * We only update the write time after 2 seconds
     171             :                  * on the first normal write. After that
     172             :                  * no other writes affect this until close.
     173             :                  */
     174      165555 :                 return;
     175             :         }
     176        5857 :         fsp->fsp_flags.update_write_time_triggered = true;
     177             : 
     178        5857 :         delay = lp_parm_int(SNUM(fsp->conn),
     179             :                             "smbd", "writetimeupdatedelay",
     180             :                             WRITE_TIME_UPDATE_USEC_DELAY);
     181             : 
     182        5857 :         DEBUG(5, ("Update write time %d usec later on %s\n",
     183             :                   delay, fsp_str_dbg(fsp)));
     184             : 
     185             :         /* trigger the update 2 seconds later */
     186        5857 :         fsp->update_write_time_event =
     187        5857 :                 tevent_add_timer(fsp->conn->sconn->ev_ctx, NULL,
     188             :                                  timeval_current_ofs_usec(delay),
     189             :                                  update_write_time_handler, fsp);
     190             : }
     191             : 
     192        6415 : void trigger_write_time_update_immediate(struct files_struct *fsp)
     193             : {
     194             :         struct smb_file_time ft;
     195             : 
     196        6415 :         init_smb_file_time(&ft);
     197             : 
     198        6415 :         if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
     199             :                 /* Don't use delayed writes on POSIX files. */
     200        1159 :                 return;
     201             :         }
     202             : 
     203        6403 :         if (fsp->fsp_flags.write_time_forced) {
     204             :                 /*
     205             :                  * No point - "sticky" write times
     206             :                  * in effect.
     207             :                  */
     208        1113 :                 return;
     209             :         }
     210             : 
     211        5268 :         TALLOC_FREE(fsp->update_write_time_event);
     212        5268 :         DEBUG(5, ("Update write time immediate on %s\n",
     213             :                   fsp_str_dbg(fsp)));
     214             : 
     215             :         /* After an immediate update, reset the trigger. */
     216        5268 :         fsp->fsp_flags.update_write_time_triggered = true;
     217        5268 :         fsp->fsp_flags.update_write_time_on_close = false;
     218             : 
     219        5268 :         ft.mtime = timespec_current();
     220             : 
     221             :         /* Update the time in the open file db. */
     222        5268 :         (void)set_write_time(fsp->file_id, ft.mtime);
     223             : 
     224             :         /* Now set on disk - takes care of notify. */
     225        5268 :         (void)smb_set_file_time(fsp->conn, fsp, fsp->fsp_name, &ft, false);
     226             : }
     227             : 
     228      171639 : void mark_file_modified(files_struct *fsp)
     229             : {
     230             :         int dosmode;
     231             : 
     232      171639 :         trigger_write_time_update(fsp);
     233             : 
     234      171639 :         if (fsp->fsp_flags.modified) {
     235      165739 :                 return;
     236             :         }
     237             : 
     238        5875 :         fsp->fsp_flags.modified = true;
     239             : 
     240        5875 :         if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
     241           4 :                 return;
     242             :         }
     243        5871 :         if (!(lp_store_dos_attributes(SNUM(fsp->conn)) ||
     244           0 :               MAP_ARCHIVE(fsp->conn))) {
     245           0 :                 return;
     246             :         }
     247             : 
     248        5871 :         dosmode = fdos_mode(fsp);
     249        5871 :         if (IS_DOS_ARCHIVE(dosmode)) {
     250        5730 :                 return;
     251             :         }
     252         100 :         file_set_dosmode(fsp->conn, fsp->fsp_name,
     253             :                          dosmode | FILE_ATTRIBUTE_ARCHIVE, NULL, false);
     254             : }
     255             : 
     256             : /****************************************************************************
     257             :  Write to a file.
     258             : ****************************************************************************/
     259             : 
     260        3316 : ssize_t write_file(struct smb_request *req,
     261             :                         files_struct *fsp,
     262             :                         const char *data,
     263             :                         off_t pos,
     264             :                         size_t n)
     265             : {
     266        3316 :         ssize_t total_written = 0;
     267             : 
     268        3316 :         if (fsp->print_file) {
     269             :                 uint32_t t;
     270             :                 int ret;
     271             : 
     272           0 :                 ret = print_spool_write(fsp, data, n, pos, &t);
     273           0 :                 if (ret) {
     274           0 :                         errno = ret;
     275           0 :                         return -1;
     276             :                 }
     277           0 :                 return t;
     278             :         }
     279             : 
     280        3316 :         if (!fsp->fsp_flags.can_write) {
     281           0 :                 errno = EPERM;
     282           0 :                 return -1;
     283             :         }
     284             : 
     285        3316 :         mark_file_modified(fsp);
     286             : 
     287             :         /*
     288             :          * If this file is level II oplocked then we need
     289             :          * to grab the shared memory lock and inform all
     290             :          * other files with a level II lock that they need
     291             :          * to flush their read caches. We keep the lock over
     292             :          * the shared memory area whilst doing this.
     293             :          */
     294             : 
     295             :         /* This should actually be improved to span the write. */
     296        3316 :         contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_WRITE);
     297        3316 :         contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_WRITE);
     298             : 
     299        3316 :         total_written = real_write_file(req, fsp, data, pos, n);
     300        3316 :         return total_written;
     301             : }
     302             : 
     303             : /*******************************************************************
     304             : sync a file
     305             : ********************************************************************/
     306             : 
     307        1150 : NTSTATUS sync_file(connection_struct *conn, files_struct *fsp, bool write_through)
     308             : {
     309        1150 :         if (fsp_get_io_fd(fsp) == -1)
     310           0 :                 return NT_STATUS_INVALID_HANDLE;
     311             : 
     312        2300 :         if (lp_strict_sync(SNUM(conn)) &&
     313        2300 :             (lp_sync_always(SNUM(conn)) || write_through)) {
     314             :                 int ret;
     315           7 :                 ret = smb_vfs_fsync_sync(fsp);
     316           7 :                 if (ret == -1) {
     317           0 :                         return map_nt_error_from_unix(errno);
     318             :                 }
     319             :         }
     320        1150 :         return NT_STATUS_OK;
     321             : }

Generated by: LCOV version 1.13