/* delete a file - the dirtype specifies the file types to include in the search. The name can contain CIFS wildcards, but rarely does (except with OS/2 clients) */ NTSTATUS pvfs_unlink(struct ntvfs_module_context *ntvfs, struct ntvfs_request *req, union smb_unlink *unl) { struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data, struct pvfs_state); struct pvfs_dir *dir; NTSTATUS status; uint32_t total_deleted=0; struct pvfs_filename *name; const char *fname; off_t ofs; /* resolve the cifs name to a posix name */ status = pvfs_resolve_name(pvfs, req, unl->unlink.in.pattern, PVFS_RESOLVE_WILDCARD | PVFS_RESOLVE_STREAMS | PVFS_RESOLVE_NO_OPENDB, &name); if (!NT_STATUS_IS_OK(status)) { return status; } if (!name->exists && !name->has_wildcard) { return NT_STATUS_OBJECT_NAME_NOT_FOUND; } if (name->exists && (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)) { return NT_STATUS_FILE_IS_A_DIRECTORY; } if (!name->has_wildcard) { return pvfs_unlink_one(pvfs, req, unl, name); } /* * disable async requests in the wildcard case * untill we have proper tests for this */ req->async_states->state &= ~NTVFS_ASYNC_STATE_MAY_ASYNC; /* get list of matching files */ status = pvfs_list_start(pvfs, name, req, &dir); if (!NT_STATUS_IS_OK(status)) { return status; } status = NT_STATUS_NO_SUCH_FILE; talloc_free(name); ofs = 0; while ((fname = pvfs_list_next(dir, &ofs))) { /* this seems to be a special case */ if ((unl->unlink.in.attrib & FILE_ATTRIBUTE_DIRECTORY) && (ISDOT(fname) || ISDOTDOT(fname))) { return NT_STATUS_OBJECT_NAME_INVALID; } /* get a pvfs_filename object */ status = pvfs_resolve_partial(pvfs, req, pvfs_list_unix_path(dir), fname, PVFS_RESOLVE_NO_OPENDB, &name); if (!NT_STATUS_IS_OK(status)) { return status; } status = pvfs_unlink_one(pvfs, req, unl, name); if (NT_STATUS_IS_OK(status)) { total_deleted++; } talloc_free(name); } if (total_deleted > 0) { status = NT_STATUS_OK; } return status; }
/* fill in a single search result for a given info level */ static NTSTATUS fill_search_info(struct pvfs_state *pvfs, enum smb_search_data_level level, const char *unix_path, const char *fname, struct pvfs_search_state *search, off_t dir_offset, union smb_search_data *file) { struct pvfs_filename *name; NTSTATUS status; const char *shortname; uint32_t dir_index = (uint32_t)dir_offset; /* truncated - see the code in pvfs_list_seek_ofs() for how we cope with this */ status = pvfs_resolve_partial(pvfs, file, unix_path, fname, 0, &name); if (!NT_STATUS_IS_OK(status)) { return status; } status = pvfs_match_attrib(pvfs, name, search->search_attrib, search->must_attrib); if (!NT_STATUS_IS_OK(status)) { return status; } switch (level) { case RAW_SEARCH_DATA_SEARCH: shortname = pvfs_short_name(pvfs, name, name); file->search.attrib = name->dos.attrib; file->search.write_time = nt_time_to_unix(name->dos.write_time); file->search.size = name->st.st_size; file->search.name = shortname; file->search.id.reserved = search->handle >> 8; memset(file->search.id.name, ' ', sizeof(file->search.id.name)); memcpy(file->search.id.name, shortname, MIN(strlen(shortname)+1, sizeof(file->search.id.name))); file->search.id.handle = search->handle & 0xFF; file->search.id.server_cookie = dir_index; file->search.id.client_cookie = 0; return NT_STATUS_OK; case RAW_SEARCH_DATA_STANDARD: file->standard.resume_key = dir_index; file->standard.create_time = nt_time_to_unix(name->dos.create_time); file->standard.access_time = nt_time_to_unix(name->dos.access_time); file->standard.write_time = nt_time_to_unix(name->dos.write_time); file->standard.size = name->st.st_size; file->standard.alloc_size = name->dos.alloc_size; file->standard.attrib = name->dos.attrib; file->standard.name.s = fname; return NT_STATUS_OK; case RAW_SEARCH_DATA_EA_SIZE: file->ea_size.resume_key = dir_index; file->ea_size.create_time = nt_time_to_unix(name->dos.create_time); file->ea_size.access_time = nt_time_to_unix(name->dos.access_time); file->ea_size.write_time = nt_time_to_unix(name->dos.write_time); file->ea_size.size = name->st.st_size; file->ea_size.alloc_size = name->dos.alloc_size; file->ea_size.attrib = name->dos.attrib; file->ea_size.ea_size = name->dos.ea_size; file->ea_size.name.s = fname; return NT_STATUS_OK; case RAW_SEARCH_DATA_EA_LIST: file->ea_list.resume_key = dir_index; file->ea_list.create_time = nt_time_to_unix(name->dos.create_time); file->ea_list.access_time = nt_time_to_unix(name->dos.access_time); file->ea_list.write_time = nt_time_to_unix(name->dos.write_time); file->ea_list.size = name->st.st_size; file->ea_list.alloc_size = name->dos.alloc_size; file->ea_list.attrib = name->dos.attrib; file->ea_list.name.s = fname; return pvfs_query_ea_list(pvfs, file, name, -1, search->num_ea_names, search->ea_names, &file->ea_list.eas); case RAW_SEARCH_DATA_DIRECTORY_INFO: file->directory_info.file_index = dir_index; file->directory_info.create_time = name->dos.create_time; file->directory_info.access_time = name->dos.access_time; file->directory_info.write_time = name->dos.write_time; file->directory_info.change_time = name->dos.change_time; file->directory_info.size = name->st.st_size; file->directory_info.alloc_size = name->dos.alloc_size; file->directory_info.attrib = name->dos.attrib; file->directory_info.name.s = fname; return NT_STATUS_OK; case RAW_SEARCH_DATA_FULL_DIRECTORY_INFO: file->full_directory_info.file_index = dir_index; file->full_directory_info.create_time = name->dos.create_time; file->full_directory_info.access_time = name->dos.access_time; file->full_directory_info.write_time = name->dos.write_time; file->full_directory_info.change_time = name->dos.change_time; file->full_directory_info.size = name->st.st_size; file->full_directory_info.alloc_size = name->dos.alloc_size; file->full_directory_info.attrib = name->dos.attrib; file->full_directory_info.ea_size = name->dos.ea_size; file->full_directory_info.name.s = fname; return NT_STATUS_OK; case RAW_SEARCH_DATA_NAME_INFO: file->name_info.file_index = dir_index; file->name_info.name.s = fname; return NT_STATUS_OK; case RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO: file->both_directory_info.file_index = dir_index; file->both_directory_info.create_time = name->dos.create_time; file->both_directory_info.access_time = name->dos.access_time; file->both_directory_info.write_time = name->dos.write_time; file->both_directory_info.change_time = name->dos.change_time; file->both_directory_info.size = name->st.st_size; file->both_directory_info.alloc_size = name->dos.alloc_size; file->both_directory_info.attrib = name->dos.attrib; file->both_directory_info.ea_size = name->dos.ea_size; file->both_directory_info.short_name.s = pvfs_short_name(pvfs, file, name); file->both_directory_info.name.s = fname; return NT_STATUS_OK; case RAW_SEARCH_DATA_ID_FULL_DIRECTORY_INFO: file->id_full_directory_info.file_index = dir_index; file->id_full_directory_info.create_time = name->dos.create_time; file->id_full_directory_info.access_time = name->dos.access_time; file->id_full_directory_info.write_time = name->dos.write_time; file->id_full_directory_info.change_time = name->dos.change_time; file->id_full_directory_info.size = name->st.st_size; file->id_full_directory_info.alloc_size = name->dos.alloc_size; file->id_full_directory_info.attrib = name->dos.attrib; file->id_full_directory_info.ea_size = name->dos.ea_size; file->id_full_directory_info.file_id = name->dos.file_id; file->id_full_directory_info.name.s = fname; return NT_STATUS_OK; case RAW_SEARCH_DATA_ID_BOTH_DIRECTORY_INFO: file->id_both_directory_info.file_index = dir_index; file->id_both_directory_info.create_time = name->dos.create_time; file->id_both_directory_info.access_time = name->dos.access_time; file->id_both_directory_info.write_time = name->dos.write_time; file->id_both_directory_info.change_time = name->dos.change_time; file->id_both_directory_info.size = name->st.st_size; file->id_both_directory_info.alloc_size = name->dos.alloc_size; file->id_both_directory_info.attrib = name->dos.attrib; file->id_both_directory_info.ea_size = name->dos.ea_size; file->id_both_directory_info.file_id = name->dos.file_id; file->id_both_directory_info.short_name.s = pvfs_short_name(pvfs, file, name); file->id_both_directory_info.name.s = fname; return NT_STATUS_OK; case RAW_SEARCH_DATA_GENERIC: break; } return NT_STATUS_INVALID_LEVEL; }