/* cleanup a open directory handle */ static int pvfs_dir_handle_destructor(struct pvfs_file_handle *h) { int open_count; char *path = NULL; if (h->name->stream_name == NULL && pvfs_delete_on_close_set(h->pvfs, h, &open_count, &path) && open_count == 1) { NTSTATUS status; status = pvfs_xattr_unlink_hook(h->pvfs, path); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Warning: xattr unlink hook failed for '%s' - %s\n", path, nt_errstr(status))); } if (rmdir(path) != 0) { DEBUG(0,("pvfs_dir_handle_destructor: failed to rmdir '%s' - %s\n", path, strerror(errno))); } } talloc_free(path); if (h->have_opendb_entry) { struct odb_lock *lck; NTSTATUS status; lck = odb_lock(h, h->pvfs->odb_context, &h->odb_locking_key); if (lck == NULL) { DEBUG(0,("Unable to lock opendb for close\n")); return 0; } status = odb_close_file(lck, h); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Unable to remove opendb entry for '%s' - %s\n", h->name->full_name, nt_errstr(status))); } talloc_free(lck); } return 0; }
/* query info on a open file */ NTSTATUS pvfs_qfileinfo(struct ntvfs_module_context *ntvfs, struct ntvfs_request *req, union smb_fileinfo *info) { struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data, struct pvfs_state); struct pvfs_file *f; struct pvfs_file_handle *h; NTSTATUS status; uint32_t access_needed; f = pvfs_find_fd(pvfs, req, info->generic.in.file.ntvfs); if (!f) { return NT_STATUS_INVALID_HANDLE; } h = f->handle; access_needed = pvfs_fileinfo_access(info); if ((f->access_mask & access_needed) != access_needed) { return NT_STATUS_ACCESS_DENIED; } /* update the file information */ status = pvfs_resolve_name_handle(pvfs, h); if (!NT_STATUS_IS_OK(status)) { return status; } status = pvfs_map_fileinfo(pvfs, req, h->name, info, h->fd); /* a qfileinfo can fill in a bit more info than a qpathinfo - now modify the levels that need to be fixed up */ switch (info->generic.level) { case RAW_FILEINFO_STANDARD_INFO: case RAW_FILEINFO_STANDARD_INFORMATION: if (pvfs_delete_on_close_set(pvfs, h)) { info->standard_info.out.delete_pending = 1; info->standard_info.out.nlink--; } break; case RAW_FILEINFO_ALL_INFO: case RAW_FILEINFO_ALL_INFORMATION: if (pvfs_delete_on_close_set(pvfs, h)) { info->all_info.out.delete_pending = 1; info->all_info.out.nlink--; } break; case RAW_FILEINFO_POSITION_INFORMATION: info->position_information.out.position = h->position; break; case RAW_FILEINFO_ACCESS_INFORMATION: info->access_information.out.access_flags = f->access_mask; break; case RAW_FILEINFO_MODE_INFORMATION: info->mode_information.out.mode = h->mode; break; case RAW_FILEINFO_SMB2_ALL_INFORMATION: if (pvfs_delete_on_close_set(pvfs, h)) { info->all_info2.out.delete_pending = 1; info->all_info2.out.nlink--; } info->all_info2.out.position = h->position; info->all_info2.out.access_mask = f->access_mask; info->all_info2.out.mode = h->mode; break; default: break; } return status; }
/* destroy a struct pvfs_file_handle */ static int pvfs_handle_destructor(struct pvfs_file_handle *h) { int open_count; char *path = NULL; /* the write time is no longer sticky */ if (h->sticky_write_time) { NTSTATUS status; status = pvfs_dosattrib_load(h->pvfs, h->name, h->fd); if (NT_STATUS_IS_OK(status)) { h->name->dos.flags &= ~XATTR_ATTRIB_FLAG_STICKY_WRITE_TIME; pvfs_dosattrib_save(h->pvfs, h->name, h->fd); } } if ((h->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && h->name->stream_name) { NTSTATUS status; status = pvfs_stream_delete(h->pvfs, h->name, h->fd); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Failed to delete stream '%s' on close of '%s'\n", h->name->stream_name, h->name->full_name)); } } if (h->fd != -1) { if (close(h->fd) != 0) { DEBUG(0,("pvfs_handle_destructor: close(%d) failed for %s - %s\n", h->fd, h->name->full_name, strerror(errno))); } h->fd = -1; } if (h->name->stream_name == NULL && pvfs_delete_on_close_set(h->pvfs, h, &open_count, &path) && open_count == 1) { NTSTATUS status; status = pvfs_xattr_unlink_hook(h->pvfs, path); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Warning: xattr unlink hook failed for '%s' - %s\n", path, nt_errstr(status))); } if (unlink(path) != 0) { DEBUG(0,("pvfs_close: failed to delete '%s' - %s\n", path, strerror(errno))); } else { notify_trigger(h->pvfs->notify_context, NOTIFY_ACTION_REMOVED, FILE_NOTIFY_CHANGE_FILE_NAME, path); } } talloc_free(path); if (h->have_opendb_entry) { struct odb_lock *lck; NTSTATUS status; lck = odb_lock(h, h->pvfs->odb_context, &h->odb_locking_key); if (lck == NULL) { DEBUG(0,("Unable to lock opendb for close\n")); return 0; } status = odb_close_file(lck, h); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Unable to remove opendb entry for '%s' - %s\n", h->name->full_name, nt_errstr(status))); } talloc_free(lck); } return 0; }