00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "includes.h"
00024
00025 extern struct current_user current_user;
00026
00027
00028
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
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
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
00128
00129
00130
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
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
00160
00161
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
00181
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, ¤t_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
00198
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
00212 notify_deferred_opens(lck);
00213 reply_to_oplock_break_requests(fsp);
00214
00215
00216
00217
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
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
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
00248
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
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
00277
00278 goto done;
00279 }
00280
00281 if (SMB_VFS_UNLINK(conn,fsp->fsp_name) != 0) {
00282
00283
00284
00285
00286
00287
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
00302
00303
00304
00305
00306
00307
00308 set_delete_on_close_lck(lck, False, NULL);
00309
00310 done:
00311
00312
00313 pop_sec_ctx();
00314
00315 TALLOC_FREE(lck);
00316 return status;
00317 }
00318
00319
00320
00321
00322
00323
00324
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
00338
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
00350
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
00362
00363
00364
00365 if (fsp->fh->ref_count == 1) {
00366
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
00379 if (close_type == NORMAL_CLOSE) {
00380 check_magic(fsp,conn);
00381 }
00382
00383
00384
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
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
00424
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
00442
00443
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, ¤t_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
00461
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
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
00499 pop_sec_ctx();
00500
00501
00502
00503
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
00517
00518 close_filestruct(fsp);
00519 file_free(fsp);
00520 return status;
00521 }
00522
00523
00524
00525
00526
00527 NTSTATUS close_stat(files_struct *fsp)
00528 {
00529
00530
00531
00532 close_filestruct(fsp);
00533 file_free(fsp);
00534 return NT_STATUS_OK;
00535 }
00536
00537
00538
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 }