From e767d8d1b2c1e86e48d827f10f1773b0dab8e565 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 26 Oct 2004 11:11:16 +0000 Subject: r3260: redid the pvfs_dirlist() interface in preparation for a "keep directory open" implementation, as opposed to the "load the whole directory" interface used now. This will be needed to pass RAW-SEARCH (This used to be commit 692623c6c0a2c6817fddfa77cd1c2525c27145c4) --- source4/ntvfs/posix/pvfs_dirlist.c | 40 ++++++++++++++++++++-- source4/ntvfs/posix/pvfs_search.c | 69 +++++++++++++++++--------------------- source4/ntvfs/posix/pvfs_unlink.c | 25 +++++++------- 3 files changed, 79 insertions(+), 55 deletions(-) diff --git a/source4/ntvfs/posix/pvfs_dirlist.c b/source4/ntvfs/posix/pvfs_dirlist.c index 0482cda808..59e755d6ff 100644 --- a/source4/ntvfs/posix/pvfs_dirlist.c +++ b/source4/ntvfs/posix/pvfs_dirlist.c @@ -57,12 +57,11 @@ static NTSTATUS pvfs_list_no_wildcard(struct pvfs_state *pvfs, struct pvfs_filen } /* - read a directory and find all matching file names, returning them in - the structure *dir. The returned names are relative to the directory + start to read a directory if the pattern matches no files then we return NT_STATUS_OK, with dir->count = 0 */ -NTSTATUS pvfs_list(struct pvfs_state *pvfs, struct pvfs_filename *name, struct pvfs_dir *dir) +NTSTATUS pvfs_list_start(struct pvfs_state *pvfs, struct pvfs_filename *name, struct pvfs_dir *dir) { DIR *odir; struct dirent *dent; @@ -134,3 +133,38 @@ NTSTATUS pvfs_list(struct pvfs_state *pvfs, struct pvfs_filename *name, struct p return NT_STATUS_OK; } + +/* + return unix directory of an open search +*/ +const char *pvfs_list_unix_path(struct pvfs_dir *dir) +{ + return dir->unix_path; +} + +/* + return True if end of search has been reached +*/ +BOOL pvfs_list_eos(struct pvfs_dir *dir, uint_t ofs) +{ + return ofs >= dir->count; +} + +/* + return the next entry +*/ +const char *pvfs_list_next(struct pvfs_dir *dir, uint_t ofs) +{ + if (ofs >= dir->count) return NULL; + return dir->names[ofs]; +} + +/* + seek to the given name +*/ +uint_t pvfs_list_seek(struct pvfs_dir *dir, const char *name, uint_t ofs) +{ + /* not correct, needs to be replaced with real search when + DIR* implementation is done */ + return ofs; +} diff --git a/source4/ntvfs/posix/pvfs_search.c b/source4/ntvfs/posix/pvfs_search.c index 9decf0f6ae..5efc2f023f 100644 --- a/source4/ntvfs/posix/pvfs_search.c +++ b/source4/ntvfs/posix/pvfs_search.c @@ -73,12 +73,12 @@ static NTSTATUS fill_search_info(struct pvfs_state *pvfs, memcpy(file->search.id.name, shortname, MIN(strlen(shortname)+1, sizeof(file->search.id.name))); file->search.id.handle = search->handle; - file->search.id.server_cookie = dir_index+1; + file->search.id.server_cookie = dir_index; file->search.id.client_cookie = 0; return NT_STATUS_OK; case RAW_SEARCH_STANDARD: - file->standard.resume_key = dir_index+1; + 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); @@ -89,7 +89,7 @@ static NTSTATUS fill_search_info(struct pvfs_state *pvfs, return NT_STATUS_OK; case RAW_SEARCH_EA_SIZE: - file->ea_size.resume_key = dir_index+1; + 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); @@ -101,7 +101,7 @@ static NTSTATUS fill_search_info(struct pvfs_state *pvfs, return NT_STATUS_OK; case RAW_SEARCH_DIRECTORY_INFO: - file->directory_info.file_index = dir_index+1; + 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; @@ -113,7 +113,7 @@ static NTSTATUS fill_search_info(struct pvfs_state *pvfs, return NT_STATUS_OK; case RAW_SEARCH_FULL_DIRECTORY_INFO: - file->full_directory_info.file_index = dir_index+1; + 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; @@ -131,7 +131,7 @@ static NTSTATUS fill_search_info(struct pvfs_state *pvfs, return NT_STATUS_OK; case RAW_SEARCH_BOTH_DIRECTORY_INFO: - file->both_directory_info.file_index = dir_index+1; + 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; @@ -145,7 +145,7 @@ static NTSTATUS fill_search_info(struct pvfs_state *pvfs, return NT_STATUS_OK; case RAW_SEARCH_ID_FULL_DIRECTORY_INFO: - file->id_full_directory_info.file_index = dir_index+1; + 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; @@ -159,7 +159,7 @@ static NTSTATUS fill_search_info(struct pvfs_state *pvfs, return NT_STATUS_OK; case RAW_SEARCH_ID_BOTH_DIRECTORY_INFO: - file->id_both_directory_info.file_index = dir_index+1; + 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; @@ -192,22 +192,32 @@ static NTSTATUS pvfs_search_fill(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, void *search_private, BOOL (*callback)(void *, union smb_search_data *)) { - int i; struct pvfs_dir *dir = search->dir; NTSTATUS status; *reply_count = 0; - for (i = search->current_index; i < dir->count;i++) { + if (max_count == 0) { + max_count = 1; + } + + while ((*reply_count) < max_count) { union smb_search_data *file; + const char *name; + + name = pvfs_list_next(dir, search->current_index); + if (name == NULL) break; + + search->current_index++; file = talloc_p(mem_ctx, union smb_search_data); if (!file) { return NT_STATUS_NO_MEMORY; } - status = fill_search_info(pvfs, level, dir->unix_path, dir->names[i], - search, i, file); + status = fill_search_info(pvfs, level, + pvfs_list_unix_path(dir), name, + search, search->current_index, file); if (!NT_STATUS_IS_OK(status)) { talloc_free(file); continue; @@ -215,18 +225,14 @@ static NTSTATUS pvfs_search_fill(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, if (!callback(search_private, file)) { talloc_free(file); + search->current_index--; break; } + (*reply_count)++; talloc_free(file); - - /* note that this deliberately allows a reply_count of - 1 for a max_count of 0. w2k3 allows this too. */ - if (*reply_count >= max_count) break; } - search->current_index = i; - return NT_STATUS_OK; } @@ -275,7 +281,7 @@ static NTSTATUS pvfs_search_first_old(struct ntvfs_module_context *ntvfs, } /* do the actual directory listing */ - status = pvfs_list(pvfs, name, dir); + status = pvfs_list_start(pvfs, name, dir); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -406,7 +412,7 @@ NTSTATUS pvfs_search_first(struct ntvfs_module_context *ntvfs, } /* do the actual directory listing */ - status = pvfs_list(pvfs, name, dir); + status = pvfs_list_start(pvfs, name, dir); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -438,7 +444,7 @@ NTSTATUS pvfs_search_first(struct ntvfs_module_context *ntvfs, io->t2ffirst.out.count = reply_count; io->t2ffirst.out.handle = search->handle; - io->t2ffirst.out.end_of_search = (search->current_index == dir->count) ? 1 : 0; + io->t2ffirst.out.end_of_search = pvfs_list_eos(dir, search->current_index) ? 1 : 0; /* work out if we are going to keep the search state and allow for a search continue */ @@ -465,7 +471,6 @@ NTSTATUS pvfs_search_next(struct ntvfs_module_context *ntvfs, uint_t reply_count; uint16_t handle; NTSTATUS status; - int i; if (io->generic.level >= RAW_SEARCH_SEARCH) { return pvfs_search_next_old(ntvfs, req, io, search_private, callback); @@ -483,28 +488,14 @@ NTSTATUS pvfs_search_next(struct ntvfs_module_context *ntvfs, /* work out what type of continuation is being used */ if (io->t2fnext.in.last_name && *io->t2fnext.in.last_name) { - /* look backwards first */ - for (i=search->current_index; i > 0; i--) { - if (strcmp(io->t2fnext.in.last_name, dir->names[i-1]) == 0) { - search->current_index = i; - goto found; - } - } - - /* then look forwards */ - for (i=search->current_index+1; i <= dir->count; i++) { - if (strcmp(io->t2fnext.in.last_name, dir->names[i-1]) == 0) { - search->current_index = i; - goto found; - } - } + search->current_index = pvfs_list_seek(dir, io->t2fnext.in.last_name, + search->current_index); } else if (io->t2fnext.in.flags & FLAG_TRANS2_FIND_CONTINUE) { /* plain continue - nothing to do */ } else { search->current_index = io->t2fnext.in.resume_key; } -found: status = pvfs_search_fill(pvfs, req, io->t2fnext.in.max_count, search, io->generic.level, &reply_count, search_private, callback); if (!NT_STATUS_IS_OK(status)) { @@ -517,7 +508,7 @@ found: } io->t2fnext.out.count = reply_count; - io->t2fnext.out.end_of_search = (search->current_index == dir->count) ? 1 : 0; + io->t2fnext.out.end_of_search = pvfs_list_eos(dir, search->current_index) ? 1 : 0; /* work out if we are going to keep the search state */ if ((io->t2fnext.in.flags & FLAG_TRANS2_FIND_CLOSE) || diff --git a/source4/ntvfs/posix/pvfs_unlink.c b/source4/ntvfs/posix/pvfs_unlink.c index 432481a88a..74614d194a 100644 --- a/source4/ntvfs/posix/pvfs_unlink.c +++ b/source4/ntvfs/posix/pvfs_unlink.c @@ -81,6 +81,7 @@ NTSTATUS pvfs_unlink(struct ntvfs_module_context *ntvfs, NTSTATUS status; uint32_t i, total_deleted=0; struct pvfs_filename *name; + const char *fname; /* resolve the cifs name to a posix name */ status = pvfs_resolve_name(pvfs, req, unl->in.pattern, 0, &name); @@ -103,36 +104,34 @@ NTSTATUS pvfs_unlink(struct ntvfs_module_context *ntvfs, } /* get list of matching files */ - status = pvfs_list(pvfs, name, dir); + status = pvfs_list_start(pvfs, name, dir); if (!NT_STATUS_IS_OK(status)) { return status; } - if (dir->count == 0) { - return NT_STATUS_NO_SUCH_FILE; - } - - for (i=0;icount;i++) { + status = NT_STATUS_NO_SUCH_FILE; + for (i=0; + (fname = pvfs_list_next(dir, i)); + i++) { /* this seems to be a special case */ if ((unl->in.attrib & FILE_ATTRIBUTE_DIRECTORY) && - (strcmp(dir->names[i], ".") == 0 || - strcmp(dir->names[i], "..") == 0)) { + (strcmp(fname, ".") == 0 || + strcmp(fname, "..") == 0)) { return NT_STATUS_OBJECT_NAME_INVALID; } - status = pvfs_unlink_one(pvfs, req, dir->unix_path, - dir->names[i], unl->in.attrib); + status = pvfs_unlink_one(pvfs, req, dir->unix_path, fname, unl->in.attrib); if (NT_STATUS_IS_OK(status)) { total_deleted++; } } - if (total_deleted == 0) { - return status; + if (total_deleted > 0) { + status = NT_STATUS_OK; } - return NT_STATUS_OK; + return status; } -- cgit