/* fill in the dos file attributes for a file */ NTSTATUS pvfs_fill_dos_info(struct pvfs_state *pvfs, struct pvfs_filename *name, unsigned int flags, int fd) { NTSTATUS status; DATA_BLOB lkey; NTTIME write_time; /* make directories appear as size 0 with 1 link */ if (S_ISDIR(name->st.st_mode)) { name->st.st_size = 0; name->st.st_nlink = 1; } else if (name->stream_id == 0) { name->stream_name = NULL; } /* for now just use the simple samba mapping */ unix_to_nt_time(&name->dos.create_time, name->st.st_ctime); unix_to_nt_time(&name->dos.access_time, name->st.st_atime); unix_to_nt_time(&name->dos.write_time, name->st.st_mtime); unix_to_nt_time(&name->dos.change_time, name->st.st_ctime); #ifdef HAVE_STAT_TV_NSEC name->dos.create_time += name->st.st_ctim.tv_nsec / 100; name->dos.access_time += name->st.st_atim.tv_nsec / 100; name->dos.write_time += name->st.st_mtim.tv_nsec / 100; name->dos.change_time += name->st.st_ctim.tv_nsec / 100; #endif name->dos.attrib = dos_mode_from_stat(pvfs, &name->st); name->dos.alloc_size = pvfs_round_alloc_size(pvfs, name->st.st_size); name->dos.nlink = name->st.st_nlink; name->dos.ea_size = 4; /* TODO: Fill this in without hitting the stream bad in pvfs_doseas_load() */ if (pvfs->ntvfs->ctx->protocol >= PROTOCOL_SMB2_02) { /* SMB2 represents a null EA with zero bytes */ name->dos.ea_size = 0; } name->dos.file_id = (((uint64_t)name->st.st_dev)<<32) | name->st.st_ino; name->dos.flags = 0; status = pvfs_dosattrib_load(pvfs, name, fd); NT_STATUS_NOT_OK_RETURN(status); if (flags & PVFS_RESOLVE_NO_OPENDB) { return NT_STATUS_OK; } status = pvfs_locking_key(name, name, &lkey); NT_STATUS_NOT_OK_RETURN(status); status = odb_get_file_infos(pvfs->odb_context, &lkey, NULL, &write_time); data_blob_free(&lkey); if (!NT_STATUS_IS_OK(status)) { DEBUG(1,("WARNING: odb_get_file_infos: %s\n", nt_errstr(status))); return status; } if (!null_time(write_time)) { name->dos.write_time = write_time; } return NT_STATUS_OK; }
/* 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; }