s3:smbd: add generic smbd_dirptr_get_entry()
authorStefan Metzmacher <metze@samba.org>
Thu, 6 Aug 2009 18:53:13 +0000 (20:53 +0200)
committerStefan Metzmacher <metze@samba.org>
Fri, 7 Aug 2009 12:18:15 +0000 (14:18 +0200)
metze

source3/smbd/dir.c
source3/smbd/globals.h

index 7acd349b72190545be24f026dd07d86639b8fafa..4c802ab893f9f0ab9186a515240d02792d87f440 100644 (file)
@@ -825,6 +825,148 @@ static bool mangle_mask_match(connection_struct *conn,
        return mask_match_search(mname,mask,False);
 }
 
+bool smbd_dirptr_get_entry(TALLOC_CTX *ctx,
+                          struct dptr_struct *dirptr,
+                          const char *mask,
+                          uint32_t dirtype,
+                          bool dont_descend,
+                          bool ask_sharemode,
+                          bool (*match_fn)(TALLOC_CTX *ctx,
+                                           void *private_data,
+                                           const char *dname,
+                                           const char *mask,
+                                           char **_fname),
+                          bool (*mode_fn)(TALLOC_CTX *ctx,
+                                          void *private_data,
+                                          struct smb_filename *smb_fname,
+                                          uint32_t *_mode),
+                          void *private_data,
+                          char **_fname,
+                          struct smb_filename **_smb_fname,
+                          uint32_t *_mode,
+                          long *_prev_offset)
+{
+       connection_struct *conn = dirptr->conn;
+       bool needslash;
+
+       *_smb_fname = NULL;
+       *_mode = 0;
+
+       needslash = ( dirptr->path[strlen(dirptr->path) -1] != '/');
+
+       while (true) {
+               long cur_offset;
+               long prev_offset;
+               SMB_STRUCT_STAT sbuf;
+               char *dname = NULL;
+               bool isdots;
+               char *fname = NULL;
+               char *pathreal = NULL;
+               struct smb_filename *smb_fname = NULL;
+               uint32_t mode = 0;
+               bool ok;
+               NTSTATUS status;
+
+               cur_offset = dptr_TellDir(dirptr);
+               prev_offset = cur_offset;
+               dname = dptr_ReadDirName(ctx, dirptr, &cur_offset, &sbuf);
+
+               DEBUG(6,("smbd_dirptr_get_entry: dirptr 0x%lx now at offset %ld\n",
+                       (long)dirptr, cur_offset));
+
+               if (dname == NULL) {
+                       return false;
+               }
+
+               isdots = (ISDOT(dname) || ISDOTDOT(dname));
+               if (dont_descend && !isdots) {
+                       TALLOC_FREE(dname);
+                       continue;
+               }
+
+               /*
+                * fname may get mangled, dname is never mangled.
+                * Whenever we're accessing the filesystem we use
+                * pathreal which is composed from dname.
+                */
+
+               ok = match_fn(ctx, private_data, dname, mask, &fname);
+               if (!ok) {
+                       TALLOC_FREE(dname);
+                       continue;
+               }
+
+               pathreal = talloc_asprintf(ctx, "%s%s%s",
+                                          dirptr->path,
+                                          needslash?"/":"",
+                                          dname);
+               if (!pathreal) {
+                       TALLOC_FREE(dname);
+                       TALLOC_FREE(fname);
+                       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(dname);
+                       TALLOC_FREE(fname);
+                       return false;
+               }
+
+               ok = mode_fn(ctx, private_data, smb_fname, &mode);
+               if (!ok) {
+                       TALLOC_FREE(dname);
+                       TALLOC_FREE(fname);
+                       TALLOC_FREE(smb_fname);
+                       continue;
+               }
+
+               if (!dir_check_ftype(conn, mode, dirtype)) {
+                       DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",
+                               fname, (unsigned int)mode, (unsigned int)dirtype));
+                       TALLOC_FREE(dname);
+                       TALLOC_FREE(fname);
+                       TALLOC_FREE(smb_fname);
+                       continue;
+               }
+
+               if (ask_sharemode) {
+                       struct timespec write_time_ts;
+                       struct file_id fileid;
+
+                       fileid = vfs_file_id_from_sbuf(conn,
+                                                      &smb_fname->st);
+                       get_file_infos(fileid, NULL, &write_time_ts);
+                       if (!null_timespec(write_time_ts)) {
+                               update_stat_ex_mtime(&smb_fname->st,
+                                                    write_time_ts);
+                       }
+               }
+
+               DEBUG(3,("smbd_dirptr_get_entry mask=[%s] found %s "
+                       "fname=%s (%s)\n",
+                       mask, smb_fname_str_dbg(smb_fname),
+                       dname, fname));
+
+               DirCacheAdd(dirptr->dir_hnd, dname, cur_offset);
+
+               TALLOC_FREE(dname);
+
+               *_fname = fname;
+               *_smb_fname = smb_fname;
+               *_mode = mode;
+               *_prev_offset = prev_offset;
+
+               return true;
+       }
+
+       return false;
+}
+
 /****************************************************************************
  Get an 8.3 directory entry.
 ****************************************************************************/
index 434204b60de706d68f1af69e0900b1fe8e22ef12..6a62cf6a216e03f513d129ef9c143f8082972903 100644 (file)
@@ -218,6 +218,27 @@ NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
                         char **ppdata,
                         int *ret_data_len);
 
+bool smbd_dirptr_get_entry(TALLOC_CTX *ctx,
+                          struct dptr_struct *dirptr,
+                          const char *mask,
+                          uint32_t dirtype,
+                          bool dont_descend,
+                          bool ask_sharemode,
+                          bool (*match_fn)(TALLOC_CTX *ctx,
+                                           void *private_data,
+                                           const char *dname,
+                                           const char *mask,
+                                           char **_fname),
+                          bool (*mode_fn)(TALLOC_CTX *ctx,
+                                          void *private_data,
+                                          struct smb_filename *smb_fname,
+                                          uint32_t *_mode),
+                          void *private_data,
+                          char **_fname,
+                          struct smb_filename **_smb_fname,
+                          uint32_t *_mode,
+                          long *_prev_offset);
+
 void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
                                         const char *reason,
                                         const char *location);