smbd/close.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    file closing
00004    Copyright (C) Andrew Tridgell 1992-1998
00005    Copyright (C) Jeremy Allison 1992-2007.
00006    Copyright (C) Volker Lendecke 2005
00007    
00008    This program is free software; you can redistribute it and/or modify
00009    it under the terms of the GNU General Public License as published by
00010    the Free Software Foundation; either version 2 of the License, or
00011    (at your option) any later version.
00012    
00013    This program is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016    GNU General Public License for more details.
00017    
00018    You should have received a copy of the GNU General Public License
00019    along with this program; if not, write to the Free Software
00020    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00021 */
00022 
00023 #include "includes.h"
00024 
00025 extern struct current_user current_user;
00026 
00027 /****************************************************************************
00028  Run a file if it is a magic script.
00029 ****************************************************************************/
00030 
00031 static void check_magic(files_struct *fsp,connection_struct *conn)
00032 {
00033         if (!*lp_magicscript(SNUM(conn)))
00034                 return;
00035 
00036         DEBUG(5,("checking magic for %s\n",fsp->fsp_name));
00037 
00038         {
00039                 char *p;
00040                 if (!(p = strrchr_m(fsp->fsp_name,'/')))
00041                         p = fsp->fsp_name;
00042                 else
00043                         p++;
00044 
00045                 if (!strequal(lp_magicscript(SNUM(conn)),p))
00046                         return;
00047         }
00048 
00049         {
00050                 int ret;
00051                 pstring magic_output;
00052                 pstring fname;
00053                 SMB_STRUCT_STAT st;
00054                 int tmp_fd, outfd;
00055 
00056                 pstrcpy(fname,fsp->fsp_name);
00057                 if (*lp_magicoutput(SNUM(conn)))
00058                         pstrcpy(magic_output,lp_magicoutput(SNUM(conn)));
00059                 else
00060                         slprintf(magic_output,sizeof(fname)-1, "%s.out",fname);
00061 
00062                 chmod(fname,0755);
00063                 ret = smbrun(fname,&tmp_fd);
00064                 DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret));
00065                 unlink(fname);
00066                 if (ret != 0 || tmp_fd == -1) {
00067                         if (tmp_fd != -1)
00068                                 close(tmp_fd);
00069                         return;
00070                 }
00071                 outfd = open(magic_output, O_CREAT|O_EXCL|O_RDWR, 0600);
00072                 if (outfd == -1) {
00073                         close(tmp_fd);
00074                         return;
00075                 }
00076 
00077                 if (sys_fstat(tmp_fd,&st) == -1) {
00078                         close(tmp_fd);
00079                         close(outfd);
00080                         return;
00081                 }
00082 
00083                 transfer_file(tmp_fd,outfd,(SMB_OFF_T)st.st_size);
00084                 close(tmp_fd);
00085                 close(outfd);
00086         }
00087 }
00088 
00089 /****************************************************************************
00090   Common code to close a file or a directory.
00091 ****************************************************************************/
00092 
00093 static NTSTATUS close_filestruct(files_struct *fsp)
00094 {   
00095         NTSTATUS status = NT_STATUS_OK;
00096         connection_struct *conn = fsp->conn;
00097     
00098         if (fsp->fh->fd != -1) {
00099                 if(flush_write_cache(fsp, CLOSE_FLUSH) == -1) {
00100                         status = map_nt_error_from_unix(errno);
00101                 }
00102                 delete_write_cache(fsp);
00103         }
00104 
00105         conn->num_files_open--;
00106         SAFE_FREE(fsp->wbmpx_ptr);
00107         return status;
00108 }    
00109 
00110 /****************************************************************************
00111  If any deferred opens are waiting on this close, notify them.
00112 ****************************************************************************/
00113 
00114 static void notify_deferred_opens(struct share_mode_lock *lck)
00115 {
00116         int i;
00117  
00118         for (i=0; i<lck->num_share_modes; i++) {
00119                 struct share_mode_entry *e = &lck->share_modes[i];
00120  
00121                 if (!is_deferred_open_entry(e)) {
00122                         continue;
00123                 }
00124  
00125                 if (procid_is_me(&e->pid)) {
00126                         /*
00127                          * We need to notify ourself to retry the open.  Do
00128                          * this by finding the queued SMB record, moving it to
00129                          * the head of the queue and changing the wait time to
00130                          * zero.
00131                          */
00132                         schedule_deferred_open_smb_message(e->op_mid);
00133                 } else {
00134                         char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
00135 
00136                         share_mode_entry_to_message(msg, e);
00137 
00138                         message_send_pid(e->pid, MSG_SMB_OPEN_RETRY,
00139                                          msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True);
00140                 }
00141         }
00142 }
00143 
00144 /****************************************************************************
00145  Deal with removing a share mode on last close.
00146 ****************************************************************************/
00147 
00148 static NTSTATUS close_remove_share_mode(files_struct *fsp,
00149                                         enum file_close_type close_type)
00150 {
00151         connection_struct *conn = fsp->conn;
00152         BOOL delete_file = False;
00153         struct share_mode_lock *lck;
00154         SMB_STRUCT_STAT sbuf;
00155         NTSTATUS status = NT_STATUS_OK;
00156         int ret;
00157 
00158         /*
00159          * Lock the share entries, and determine if we should delete
00160          * on close. If so delete whilst the lock is still in effect.
00161          * This prevents race conditions with the file being created. JRA.
00162          */
00163 
00164         lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
00165 
00166         if (lck == NULL) {
00167                 DEBUG(0, ("close_remove_share_mode: Could not get share mode "
00168                           "lock for file %s\n", fsp->fsp_name));
00169                 return NT_STATUS_INVALID_PARAMETER;
00170         }
00171 
00172         if (!del_share_mode(lck, fsp)) {
00173                 DEBUG(0, ("close_remove_share_mode: Could not delete share "
00174                           "entry for file %s\n", fsp->fsp_name));
00175         }
00176 
00177         if (fsp->initial_delete_on_close && (lck->delete_token == NULL)) {
00178                 BOOL became_user = False;
00179 
00180                 /* Initial delete on close was set and no one else
00181                  * wrote a real delete on close. */
00182 
00183                 if (current_user.vuid != fsp->vuid) {
00184                         become_user(conn, fsp->vuid);
00185                         became_user = True;
00186                 }
00187                 set_delete_on_close_lck(lck, True, &current_user.ut);
00188                 if (became_user) {
00189                         unbecome_user();
00190                 }
00191         }
00192 
00193         delete_file = lck->delete_on_close;
00194 
00195         if (delete_file) {
00196                 int i;
00197                 /* See if others still have the file open. If this is the
00198                  * case, then don't delete. If all opens are POSIX delete now. */
00199                 for (i=0; i<lck->num_share_modes; i++) {
00200                         struct share_mode_entry *e = &lck->share_modes[i];
00201                         if (is_valid_share_mode_entry(e)) {
00202                                 if (fsp->posix_open && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) {
00203                                         continue;
00204                                 }
00205                                 delete_file = False;
00206                                 break;
00207                         }
00208                 }
00209         }
00210 
00211         /* Notify any deferred opens waiting on this close. */
00212         notify_deferred_opens(lck);
00213         reply_to_oplock_break_requests(fsp);
00214 
00215         /*
00216          * NT can set delete_on_close of the last open
00217          * reference to a file.
00218          */
00219 
00220         if (!(close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE)
00221             || !delete_file
00222             || (lck->delete_token == NULL)) {
00223                 TALLOC_FREE(lck);
00224                 return NT_STATUS_OK;
00225         }
00226 
00227         /*
00228          * Ok, we have to delete the file
00229          */
00230 
00231         DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set "
00232                  "- deleting file.\n", fsp->fsp_name));
00233 
00234         /* Become the user who requested the delete. */
00235 
00236         if (!push_sec_ctx()) {
00237                 smb_panic("close_remove_share_mode: file %s. failed to push "
00238                           "sec_ctx.\n");
00239         }
00240 
00241         set_sec_ctx(lck->delete_token->uid,
00242                     lck->delete_token->gid,
00243                     lck->delete_token->ngroups,
00244                     lck->delete_token->groups,
00245                     NULL);
00246 
00247         /* We can only delete the file if the name we have is still valid and
00248            hasn't been renamed. */
00249 
00250         if (fsp->posix_open) {
00251                 ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf);
00252         } else {
00253                 ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf);
00254         }
00255 
00256         if (ret != 0) {
00257                 DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
00258                          "was set and stat failed with error %s\n",
00259                          fsp->fsp_name, strerror(errno) ));
00260                 /*
00261                  * Don't save the errno here, we ignore this error
00262                  */
00263                 goto done;
00264         }
00265 
00266         if(sbuf.st_dev != fsp->dev || sbuf.st_ino != fsp->inode) {
00267                 DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
00268                          "was set and dev and/or inode does not match\n",
00269                          fsp->fsp_name ));
00270                 DEBUG(5,("close_remove_share_mode: file %s. stored dev = %x, "
00271                          "inode = %.0f stat dev = %x, inode = %.0f\n",
00272                          fsp->fsp_name,
00273                          (unsigned int)fsp->dev, (double)fsp->inode,
00274                          (unsigned int)sbuf.st_dev, (double)sbuf.st_ino ));
00275                 /*
00276                  * Don't save the errno here, we ignore this error
00277                  */
00278                 goto done;
00279         }
00280 
00281         if (SMB_VFS_UNLINK(conn,fsp->fsp_name) != 0) {
00282                 /*
00283                  * This call can potentially fail as another smbd may
00284                  * have had the file open with delete on close set and
00285                  * deleted it when its last reference to this file
00286                  * went away. Hence we log this but not at debug level
00287                  * zero.
00288                  */
00289 
00290                 DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
00291                          "was set and unlink failed with error %s\n",
00292                          fsp->fsp_name, strerror(errno) ));
00293 
00294                 status = map_nt_error_from_unix(errno);
00295         }
00296 
00297         notify_fname(conn, NOTIFY_ACTION_REMOVED,
00298                      FILE_NOTIFY_CHANGE_FILE_NAME,
00299                      fsp->fsp_name);
00300 
00301         /* As we now have POSIX opens which can unlink
00302          * with other open files we may have taken
00303          * this code path with more than one share mode
00304          * entry - ensure we only delete once by resetting
00305          * the delete on close flag. JRA.
00306          */
00307 
00308         set_delete_on_close_lck(lck, False, NULL);
00309 
00310  done:
00311 
00312         /* unbecome user. */
00313         pop_sec_ctx();
00314         
00315         TALLOC_FREE(lck);
00316         return status;
00317 }
00318 
00319 /****************************************************************************
00320  Close a file.
00321 
00322  close_type can be NORMAL_CLOSE=0,SHUTDOWN_CLOSE,ERROR_CLOSE.
00323  printing and magic scripts are only run on normal close.
00324  delete on close is done on normal and shutdown close.
00325 ****************************************************************************/
00326 
00327 static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_type)
00328 {
00329         NTSTATUS status = NT_STATUS_OK;
00330         NTSTATUS saved_status1 = NT_STATUS_OK;
00331         NTSTATUS saved_status2 = NT_STATUS_OK;
00332         NTSTATUS saved_status3 = NT_STATUS_OK;
00333         connection_struct *conn = fsp->conn;
00334 
00335         if (fsp->aio_write_behind) {
00336                 /*
00337                  * If we're finishing write behind on a close we can get a write
00338                  * error here, we must remember this.
00339                  */
00340                 int ret = wait_for_aio_completion(fsp);
00341                 if (ret) {
00342                         saved_status1 = map_nt_error_from_unix(ret);
00343                 }
00344         } else {
00345                 cancel_aio_by_fsp(fsp);
00346         }
00347  
00348         /*
00349          * If we're flushing on a close we can get a write
00350          * error here, we must remember this.
00351          */
00352 
00353         saved_status2 = close_filestruct(fsp);
00354 
00355         if (fsp->print_file) {
00356                 print_fsp_end(fsp, close_type);
00357                 file_free(fsp);
00358                 return NT_STATUS_OK;
00359         }
00360 
00361         /* If this is an old DOS or FCB open and we have multiple opens on
00362            the same handle we only have one share mode. Ensure we only remove
00363            the share mode on the last close. */
00364 
00365         if (fsp->fh->ref_count == 1) {
00366                 /* Should we return on error here... ? */
00367                 saved_status3 = close_remove_share_mode(fsp, close_type);
00368         }
00369 
00370         if(fsp->oplock_type) {
00371                 release_file_oplock(fsp);
00372         }
00373 
00374         locking_close_file(fsp);
00375 
00376         status = fd_close(conn, fsp);
00377 
00378         /* check for magic scripts */
00379         if (close_type == NORMAL_CLOSE) {
00380                 check_magic(fsp,conn);
00381         }
00382 
00383         /*
00384          * Ensure pending modtime is set after close.
00385          */
00386 
00387         if (fsp->pending_modtime_owner && !null_timespec(fsp->pending_modtime)) {
00388                 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
00389         } else if (!null_timespec(fsp->last_write_time)) {
00390                 set_filetime(conn, fsp->fsp_name, fsp->last_write_time);
00391         }
00392 
00393         if (NT_STATUS_IS_OK(status)) {
00394                 if (!NT_STATUS_IS_OK(saved_status1)) {
00395                         status = saved_status1;
00396                 } else if (!NT_STATUS_IS_OK(saved_status2)) {
00397                         status = saved_status2;
00398                 } else if (!NT_STATUS_IS_OK(saved_status3)) {
00399                         status = saved_status3;
00400                 }
00401         }
00402 
00403         DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
00404                 conn->user,fsp->fsp_name,
00405                 conn->num_files_open,
00406                 nt_errstr(status) ));
00407 
00408         file_free(fsp);
00409         return status;
00410 }
00411 
00412 /****************************************************************************
00413  Close a directory opened by an NT SMB call. 
00414 ****************************************************************************/
00415   
00416 static NTSTATUS close_directory(files_struct *fsp, enum file_close_type close_type)
00417 {
00418         struct share_mode_lock *lck = 0;
00419         BOOL delete_dir = False;
00420         NTSTATUS status = NT_STATUS_OK;
00421 
00422         /*
00423          * NT can set delete_on_close of the last open
00424          * reference to a directory also.
00425          */
00426 
00427         lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
00428 
00429         if (lck == NULL) {
00430                 DEBUG(0, ("close_directory: Could not get share mode lock for %s\n", fsp->fsp_name));
00431                 return NT_STATUS_INVALID_PARAMETER;
00432         }
00433 
00434         if (!del_share_mode(lck, fsp)) {
00435                 DEBUG(0, ("close_directory: Could not delete share entry for %s\n", fsp->fsp_name));
00436         }
00437 
00438         if (fsp->initial_delete_on_close) {
00439                 BOOL became_user = False;
00440 
00441                 /* Initial delete on close was set - for
00442                  * directories we don't care if anyone else
00443                  * wrote a real delete on close. */
00444 
00445                 if (current_user.vuid != fsp->vuid) {
00446                         become_user(fsp->conn, fsp->vuid);
00447                         became_user = True;
00448                 }
00449                 send_stat_cache_delete_message(fsp->fsp_name);
00450                 set_delete_on_close_lck(lck, True, &current_user.ut);
00451                 if (became_user) {
00452                         unbecome_user();
00453                 }
00454         }
00455 
00456         delete_dir = lck->delete_on_close;
00457 
00458         if (delete_dir) {
00459                 int i;
00460                 /* See if others still have the dir open. If this is the
00461                  * case, then don't delete. If all opens are POSIX delete now. */
00462                 for (i=0; i<lck->num_share_modes; i++) {
00463                         struct share_mode_entry *e = &lck->share_modes[i];
00464                         if (is_valid_share_mode_entry(e)) {
00465                                 if (fsp->posix_open && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) {
00466                                         continue;
00467                                 }
00468                                 delete_dir = False;
00469                                 break;
00470                         }
00471                 }
00472         }
00473 
00474         if ((close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) &&
00475                                 delete_dir &&
00476                                 lck->delete_token) {
00477         
00478                 /* Become the user who requested the delete. */
00479 
00480                 if (!push_sec_ctx()) {
00481                         smb_panic("close_directory: failed to push sec_ctx.\n");
00482                 }
00483 
00484                 set_sec_ctx(lck->delete_token->uid,
00485                                 lck->delete_token->gid,
00486                                 lck->delete_token->ngroups,
00487                                 lck->delete_token->groups,
00488                                 NULL);
00489 
00490                 TALLOC_FREE(lck);
00491 
00492                 status = rmdir_internals(fsp->conn, fsp->fsp_name);
00493 
00494                 DEBUG(5,("close_directory: %s. Delete on close was set - "
00495                          "deleting directory returned %s.\n",
00496                          fsp->fsp_name, nt_errstr(status)));
00497 
00498                 /* unbecome user. */
00499                 pop_sec_ctx();
00500 
00501                 /*
00502                  * Ensure we remove any change notify requests that would
00503                  * now fail as the directory has been deleted.
00504                  */
00505 
00506                 if(NT_STATUS_IS_OK(status)) {
00507                         remove_pending_change_notify_requests_by_fid(fsp, NT_STATUS_DELETE_PENDING);
00508                 }
00509         } else {
00510                 TALLOC_FREE(lck);
00511                 remove_pending_change_notify_requests_by_fid(
00512                         fsp, NT_STATUS_OK);
00513         }
00514 
00515         /*
00516          * Do the code common to files and directories.
00517          */
00518         close_filestruct(fsp);
00519         file_free(fsp);
00520         return status;
00521 }
00522 
00523 /****************************************************************************
00524  Close a 'stat file' opened internally.
00525 ****************************************************************************/
00526   
00527 NTSTATUS close_stat(files_struct *fsp)
00528 {
00529         /*
00530          * Do the code common to files and directories.
00531          */
00532         close_filestruct(fsp);
00533         file_free(fsp);
00534         return NT_STATUS_OK;
00535 }
00536 
00537 /****************************************************************************
00538  Close a files_struct.
00539 ****************************************************************************/
00540   
00541 NTSTATUS close_file(files_struct *fsp, enum file_close_type close_type)
00542 {
00543         if(fsp->is_directory) {
00544                 return close_directory(fsp, close_type);
00545         } else if (fsp->is_stat) {
00546                 return close_stat(fsp);
00547         } else if (fsp->fake_file_handle != NULL) {
00548                 return close_fake_file(fsp);
00549         }
00550         return close_normal_file(fsp, close_type);
00551 }

Sambaに対してSat Aug 29 21:23:23 2009に生成されました。  doxygen 1.4.7