LCOV - code coverage report
Current view: top level - source4/ntvfs/posix - pvfs_write.c (source / functions) Hit Total Coverage
Test: coverage report for master 70ed9daf Lines: 47 64 73.4 %
Date: 2024-01-11 09:59:51 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    POSIX NTVFS backend - write
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2004
       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 "vfs_posix.h"
      24             : #include "librpc/gen_ndr/security.h"
      25             : #include "lib/events/events.h"
      26             : 
      27          16 : static void pvfs_write_time_update_handler(struct tevent_context *ev,
      28             :                                            struct tevent_timer *te,
      29             :                                            struct timeval tv,
      30             :                                            void *private_data)
      31             : {
      32          16 :         struct pvfs_file_handle *h = talloc_get_type(private_data,
      33             :                                      struct pvfs_file_handle);
      34           0 :         struct odb_lock *lck;
      35           0 :         NTSTATUS status;
      36           0 :         NTTIME write_time;
      37             : 
      38          16 :         lck = odb_lock(h, h->pvfs->odb_context, &h->odb_locking_key);
      39          16 :         if (lck == NULL) {
      40           0 :                 DEBUG(0,("Unable to lock opendb for write time update\n"));
      41           0 :                 return;
      42             :         }
      43             : 
      44          16 :         write_time = timeval_to_nttime(&tv);
      45             : 
      46          16 :         status = odb_set_write_time(lck, write_time, false);
      47          16 :         if (!NT_STATUS_IS_OK(status)) {
      48           0 :                 DEBUG(0,("Unable to update write time: %s\n",
      49             :                         nt_errstr(status)));
      50           0 :                 return;
      51             :         }
      52             : 
      53          16 :         talloc_free(lck);
      54             : 
      55          16 :         h->write_time.update_event = NULL;
      56             : }
      57             : 
      58       28885 : static void pvfs_trigger_write_time_update(struct pvfs_file_handle *h)
      59             : {
      60       28885 :         struct pvfs_state *pvfs = h->pvfs;
      61           0 :         struct timeval tv;
      62             : 
      63       28885 :         if (h->write_time.update_triggered) {
      64       19356 :                 return;
      65             :         }
      66             : 
      67        9529 :         tv = timeval_current_ofs_usec(pvfs->writetime_delay);
      68             : 
      69        9529 :         h->write_time.update_triggered = true;
      70        9529 :         h->write_time.update_on_close = true;
      71        9529 :         h->write_time.update_event = tevent_add_timer(pvfs->ntvfs->ctx->event_ctx,
      72             :                                                      h, tv,
      73             :                                                      pvfs_write_time_update_handler,
      74             :                                                      h);
      75        9529 :         if (!h->write_time.update_event) {
      76           0 :                 DEBUG(0,("Failed tevent_add_timer\n"));
      77             :         }
      78             : }
      79             : 
      80             : /*
      81             :   write to a file
      82             : */
      83       37849 : NTSTATUS pvfs_write(struct ntvfs_module_context *ntvfs,
      84             :                     struct ntvfs_request *req, union smb_write *wr)
      85             : {
      86       37849 :         struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data,
      87             :                                   struct pvfs_state);
      88           0 :         ssize_t ret;
      89           0 :         struct pvfs_file *f;
      90           0 :         NTSTATUS status;
      91             : 
      92       37849 :         if (wr->generic.level != RAW_WRITE_WRITEX) {
      93         453 :                 return ntvfs_map_write(ntvfs, req, wr);
      94             :         }
      95             : 
      96       37396 :         f = pvfs_find_fd(pvfs, req, wr->writex.in.file.ntvfs);
      97       37396 :         if (!f) {
      98           0 :                 return NT_STATUS_INVALID_HANDLE;
      99             :         }
     100             : 
     101       37396 :         if (f->handle->fd == -1) {
     102           0 :                 return NT_STATUS_INVALID_DEVICE_REQUEST;
     103             :         }
     104             : 
     105       37396 :         if (!(f->access_mask & (SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA))) {
     106        8484 :                 return NT_STATUS_ACCESS_DENIED;
     107             :         }
     108             : 
     109       28912 :         status = pvfs_check_lock(pvfs, f, req->smbpid, 
     110             :                                  wr->writex.in.offset,
     111       28912 :                                  wr->writex.in.count,
     112             :                                  WRITE_LOCK);
     113       28912 :         NT_STATUS_NOT_OK_RETURN(status);
     114             : 
     115       28885 :         status = pvfs_break_level2_oplocks(f);
     116       28885 :         NT_STATUS_NOT_OK_RETURN(status);
     117             : 
     118       28885 :         pvfs_trigger_write_time_update(f->handle);
     119             : 
     120       28885 :         if (f->handle->name->stream_name) {
     121          16 :                 ret = pvfs_stream_write(pvfs,
     122             :                                         f->handle,
     123          16 :                                         wr->writex.in.data, 
     124          16 :                                         wr->writex.in.count,
     125          16 :                                         wr->writex.in.offset);
     126             :         } else {
     127       28869 :                 ret = pwrite(f->handle->fd, 
     128       28869 :                              wr->writex.in.data, 
     129       28869 :                              wr->writex.in.count,
     130       28869 :                              wr->writex.in.offset);
     131             :         }
     132       28885 :         if (ret == -1) {
     133           0 :                 if (errno == EFBIG) {
     134           0 :                         return NT_STATUS_INVALID_PARAMETER;
     135             :                 }
     136           0 :                 return pvfs_map_errno(pvfs, errno);
     137             :         }
     138             : 
     139       28885 :         f->handle->seek_offset = wr->writex.in.offset + ret;
     140             :         
     141       28885 :         wr->writex.out.nwritten = ret;
     142       28885 :         wr->writex.out.remaining = 0; /* should fill this in? */
     143             : 
     144       28885 :         return NT_STATUS_OK;
     145             : }

Generated by: LCOV version 1.14