summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source3/smbd/dir.c228
1 files changed, 89 insertions, 139 deletions
diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
index 4c802ab893f..e2f8e694494 100644
--- a/source3/smbd/dir.c
+++ b/source3/smbd/dir.c
@@ -971,158 +971,108 @@ bool smbd_dirptr_get_entry(TALLOC_CTX *ctx,
Get an 8.3 directory entry.
****************************************************************************/
-bool get_dir_entry(TALLOC_CTX *ctx,
- connection_struct *conn,
- const char *mask,
- uint32 dirtype,
- char **pp_fname_out,
- SMB_OFF_T *size,
- uint32 *mode,
- struct timespec *date,
- bool check_descend,
- bool ask_sharemode)
+static bool smbd_dirptr_8_3_match_fn(TALLOC_CTX *ctx,
+ void *private_data,
+ const char *dname,
+ const char *mask,
+ char **_fname)
{
- char *dname = NULL;
- bool found = False;
- SMB_STRUCT_STAT sbuf;
- char *pathreal = NULL;
- char *filename = NULL;
- bool needslash;
-
- *pp_fname_out = NULL;
-
- needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
-
- if (!conn->dirptr) {
- return(False);
- }
-
- while (!found) {
- long curoff = dptr_TellDir(conn->dirptr);
- dname = dptr_ReadDirName(ctx, conn->dirptr, &curoff, &sbuf);
-
- DEBUG(6,("readdir on dirptr 0x%lx now at offset %ld\n",
- (long)conn->dirptr,TellDir(conn->dirptr->dir_hnd)));
-
- if (dname == NULL) {
- return(False);
- }
-
- filename = dname;
-
- /* notice the special *.* handling. This appears to be the only difference
- between the wildcard handling in this routine and in the trans2 routines.
- see masktest for a demo
- */
- if ((strcmp(mask,"*.*") == 0) ||
- mask_match_search(filename,mask,False) ||
- mangle_mask_match(conn,filename,mask)) {
- bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
- char mname[13];
- struct smb_filename *smb_fname = NULL;
- NTSTATUS status;
-
- if (!mangle_is_8_3(filename, False, conn->params)) {
- if (!name_to_8_3(filename,mname,False,
- conn->params)) {
- TALLOC_FREE(filename);
- continue;
- }
- filename = talloc_strdup(ctx, mname);
- if (!filename) {
- return False;
- }
- }
-
- if (check_descend && !isdots) {
- TALLOC_FREE(filename);
- continue;
- }
-
- if (needslash) {
- pathreal = talloc_asprintf(ctx,
- "%s/%s",
- conn->dirpath,
- dname);
- } else {
- pathreal = talloc_asprintf(ctx,
- "%s%s",
- conn->dirpath,
- dname);
- }
- if (!pathreal) {
- TALLOC_FREE(filename);
- return False;
- }
-
- /* Create smb_fname with NULL stream_name. */
- status = create_synthetic_smb_fname(ctx, pathreal,
- NULL, &sbuf,
- &smb_fname);
-
- TALLOC_FREE(pathreal);
- if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(filename);
+ connection_struct *conn = (connection_struct *)private_data;
+
+ if ((strcmp(mask,"*.*") == 0) ||
+ mask_match_search(dname, mask, false) ||
+ mangle_mask_match(conn, dname, mask)) {
+ char mname[13];
+ const char *fname;
+
+ if (!mangle_is_8_3(dname, false, conn->params)) {
+ bool ok = name_to_8_3(dname, mname, false,
+ conn->params);
+ if (!ok) {
return false;
}
+ fname = mname;
+ } else {
+ fname = dname;
+ }
- if (!VALID_STAT(smb_fname->st)) {
- if ((SMB_VFS_STAT(conn, smb_fname)) != 0) {
- DEBUG(5,("Couldn't stat 1 [%s]. Error "
- "= %s\n",
- smb_fname_str_dbg(smb_fname),
- strerror(errno)));
- TALLOC_FREE(smb_fname);
- TALLOC_FREE(filename);
- continue;
- }
- }
-
- *mode = dos_mode(conn, smb_fname);
-
- if (!dir_check_ftype(conn,*mode,dirtype)) {
- DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",filename,(unsigned int)*mode,(unsigned int)dirtype));
- TALLOC_FREE(smb_fname);
- TALLOC_FREE(filename);
- continue;
- }
-
- *size = smb_fname->st.st_ex_size;
- *date = smb_fname->st.st_ex_mtime;
+ *_fname = talloc_strdup(ctx, fname);
+ if (*_fname == NULL) {
+ return false;
+ }
- if (ask_sharemode) {
- struct timespec write_time_ts;
- struct file_id fileid;
+ return true;
+ }
- fileid = vfs_file_id_from_sbuf(conn,
- &smb_fname->st);
- get_file_infos(fileid, NULL, &write_time_ts);
- if (!null_timespec(write_time_ts)) {
- *date = write_time_ts;
- }
- }
+ return false;
+}
- DEBUG(3,("get_dir_entry mask=[%s] found %s "
- "fname=%s (%s)\n",
- mask,
- smb_fname_str_dbg(smb_fname),
- dname,
- filename));
+static bool smbd_dirptr_8_3_mode_fn(TALLOC_CTX *ctx,
+ void *private_data,
+ struct smb_filename *smb_fname,
+ uint32_t *_mode)
+{
+ connection_struct *conn = (connection_struct *)private_data;
+
+ if (!VALID_STAT(smb_fname->st)) {
+ if ((SMB_VFS_STAT(conn, smb_fname)) != 0) {
+ DEBUG(5,("smbd_dirptr_8_3_mode_fn: "
+ "Couldn't stat [%s]. Error "
+ "= %s\n",
+ smb_fname_str_dbg(smb_fname),
+ strerror(errno)));
+ return false;
+ }
+ }
- found = True;
+ *_mode = dos_mode(conn, smb_fname);
+ return true;
+}
- SMB_ASSERT(filename != NULL);
- *pp_fname_out = filename;
+bool get_dir_entry(TALLOC_CTX *ctx,
+ connection_struct *conn,
+ const char *mask,
+ uint32_t dirtype,
+ char **_fname,
+ SMB_OFF_T *_size,
+ uint32_t *_mode,
+ struct timespec *_date,
+ bool check_descend,
+ bool ask_sharemode)
+{
+ char *fname = NULL;
+ struct smb_filename *smb_fname = NULL;
+ uint32_t mode = 0;
+ long prev_offset;
+ bool ok;
- DirCacheAdd(conn->dirptr->dir_hnd, dname, curoff);
- TALLOC_FREE(smb_fname);
- }
+ if (!conn->dirptr) {
+ return false;
+ }
- if (!found)
- TALLOC_FREE(filename);
+ ok = smbd_dirptr_get_entry(ctx,
+ conn->dirptr,
+ mask,
+ dirtype,
+ check_descend,
+ ask_sharemode,
+ smbd_dirptr_8_3_match_fn,
+ smbd_dirptr_8_3_mode_fn,
+ conn,
+ &fname,
+ &smb_fname,
+ &mode,
+ &prev_offset);
+ if (!ok) {
+ return false;
}
- return(found);
+ *_fname = talloc_move(ctx, &fname);
+ *_size = smb_fname->st.st_ex_size;
+ *_mode = mode;
+ *_date = smb_fname->st.st_ex_mtime;
+ TALLOC_FREE(smb_fname);
+ return true;
}
/*******************************************************************