Add an optional SMB_STRUCT_SMB parameter to VFS_OP_READDIR
authorSteven Danneman <steven.danneman@isilon.com>
Fri, 23 Jan 2009 04:14:38 +0000 (20:14 -0800)
committerSteven Danneman <steven.danneman@isilon.com>
Tue, 10 Feb 2009 07:56:16 +0000 (23:56 -0800)
* this allows VFS implementations that prefetch stat information on
  readdir to return it through one VFS call
* backwards compatibility is maintained by passing in NULL
* if the system readdir doesn't return stat info, the stat struct is
  set to invalid

12 files changed:
source3/include/vfs.h
source3/include/vfs_macros.h
source3/modules/onefs_streams.c
source3/modules/vfs_cap.c
source3/modules/vfs_catia.c
source3/modules/vfs_default.c
source3/modules/vfs_full_audit.c
source3/modules/vfs_shadow_copy.c
source3/modules/vfs_shadow_copy2.c
source3/modules/vfs_streams_depot.c
source3/smbd/vfs.c
source3/torture/cmd_vfs.c

index 228f090600f20db641184ce198ba932e57d241f6..6aea0ae6a08725742cb4122a68b1d0c20bfe7c2b 100644 (file)
 /* Leave at 25 - not yet released. Add create_file call. -- tprouty. */
 /* Leave at 25 - not yet released. Add create time to ntimes. -- tstecher. */
 /* Leave at 25 - not yet released. Add get_alloc_size call. -- tprouty. */
+/* Leave at 25 - not yet released. Add SMB_STRUCT_STAT to readdir. - sdann */
 
 #define SMB_VFS_INTERFACE_VERSION 25
 
@@ -303,7 +304,9 @@ struct vfs_ops {
                /* Directory operations */
 
                SMB_STRUCT_DIR *(*opendir)(struct vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attributes);
-               SMB_STRUCT_DIRENT *(*readdir)(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp);
+               SMB_STRUCT_DIRENT *(*readdir)(struct vfs_handle_struct *handle,
+                                             SMB_STRUCT_DIR *dirp,
+                                             SMB_STRUCT_STAT *sbuf);
                void (*seekdir)(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp, long offset);
                long (*telldir)(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp);
                void (*rewind_dir)(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp);
index e7a9cfdc764457aebdb122a8bba497c6e1877e92..208566f77e0926a3c9f254523d9a7192296eb08e 100644 (file)
@@ -38,7 +38,7 @@
 
 /* Directory operations */
 #define SMB_VFS_OPENDIR(conn, fname, mask, attr) ((conn)->vfs.ops.opendir((conn)->vfs.handles.opendir, (fname), (mask), (attr)))
-#define SMB_VFS_READDIR(conn, dirp) ((conn)->vfs.ops.readdir((conn)->vfs.handles.readdir, (dirp)))
+#define SMB_VFS_READDIR(conn, dirp, sbuf) ((conn)->vfs.ops.readdir((conn)->vfs.handles.readdir, (dirp), (sbuf)))
 #define SMB_VFS_SEEKDIR(conn, dirp, offset) ((conn)->vfs.ops.seekdir((conn)->vfs.handles.seekdir, (dirp), (offset)))
 #define SMB_VFS_TELLDIR(conn, dirp) ((conn)->vfs.ops.telldir((conn)->vfs.handles.telldir, (dirp)))
 #define SMB_VFS_REWINDDIR(conn, dirp) ((conn)->vfs.ops.rewind_dir((conn)->vfs.handles.rewind_dir, (dirp)))
 
 /* Directory operations */
 #define SMB_VFS_OPAQUE_OPENDIR(conn, fname, mask, attr) ((conn)->vfs_opaque.ops.opendir((conn)->vfs_opaque.handles.opendir, (fname), (mask), (attr)))
-#define SMB_VFS_OPAQUE_READDIR(conn, dirp) ((conn)->vfs_opaque.ops.readdir((conn)->vfs_opaque.handles.readdir, (dirp)))
+#define SMB_VFS_OPAQUE_READDIR(conn, dirp, sbuf) ((conn)->vfs_opaque.ops.readdir((conn)->vfs_opaque.handles.readdir, (dirp), (sbuf)))
 #define SMB_VFS_OPAQUE_SEEKDIR(conn, dirp, offset) ((conn)->vfs_opaque.ops.seekdir((conn)->vfs_opaque.handles.seekdir, (dirp), (offset)))
 #define SMB_VFS_OPAQUE_TELLDIR(conn, dirp) ((conn)->vfs_opaque.ops.telldir((conn)->vfs_opaque.handles.telldir, (dirp)))
 #define SMB_VFS_OPAQUE_REWINDDIR(conn, dirp) ((conn)->vfs_opaque.ops.rewind_dir((conn)->vfs_opaque.handles.rewind_dir, (dirp)))
 
 /* Directory operations */
 #define SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr) ((handle)->vfs_next.ops.opendir((handle)->vfs_next.handles.opendir, (fname), (mask), (attr)))
-#define SMB_VFS_NEXT_READDIR(handle, dirp) ((handle)->vfs_next.ops.readdir((handle)->vfs_next.handles.readdir, (dirp)))
+#define SMB_VFS_NEXT_READDIR(handle, dirp, sbuf) ((handle)->vfs_next.ops.readdir((handle)->vfs_next.handles.readdir, (dirp), (sbuf)))
 #define SMB_VFS_NEXT_SEEKDIR(handle, dirp, offset) ((handle)->vfs_next.ops.seekdir((handle)->vfs_next.handles.seekdir, (dirp), (offset)))
 #define SMB_VFS_NEXT_TELLDIR(handle, dirp) ((handle)->vfs_next.ops.telldir((handle)->vfs_next.handles.telldir, (dirp)))
 #define SMB_VFS_NEXT_REWINDDIR(handle, dirp) ((handle)->vfs_next.ops.rewind_dir((handle)->vfs_next.handles.rewind_dir, (dirp)))
-#define SMB_VFS_NEXT_DIR(handle, dirp) ((handle)->vfs_next.ops.readdir((handle)->vfs_next.handles.readdir, (dirp)))
+#define SMB_VFS_NEXT_DIR(handle, dirp, sbuf) ((handle)->vfs_next.ops.readdir((handle)->vfs_next.handles.readdir, (dirp), (sbuf)))
 #define SMB_VFS_NEXT_MKDIR(handle, path, mode) ((handle)->vfs_next.ops.mkdir((handle)->vfs_next.handles.mkdir,(path), (mode)))
 #define SMB_VFS_NEXT_RMDIR(handle, path) ((handle)->vfs_next.ops.rmdir((handle)->vfs_next.handles.rmdir, (path)))
 #define SMB_VFS_NEXT_CLOSEDIR(handle, dir) ((handle)->vfs_next.ops.closedir((handle)->vfs_next.handles.closedir, dir))
index 615edf379d34fc140942ca3f2e8647d9d539e5d0..d0dd75f259091a27d2e5766949860b7b2ac87d0c 100644 (file)
@@ -545,7 +545,7 @@ static NTSTATUS walk_onefs_streams(connection_struct *conn, files_struct *fsp,
        fake_fs.fsp_name = SMB_STRDUP(fname);
 
        /* Iterate over the streams in the ADS directory. */
-       while ((dp = SMB_VFS_READDIR(conn, dirp)) != NULL) {
+       while ((dp = SMB_VFS_READDIR(conn, dirp, NULL)) != NULL) {
                /* Skip the "." and ".." entries */
                if ((strcmp(dp->d_name, ".") == 0) ||
                    (strcmp(dp->d_name, "..") == 0))
index ac85d3a8043d65c33a255ebf15c1e883d7766d15..e26d29d6673c6a42d813755370c3b521dc89077f 100644 (file)
@@ -61,7 +61,7 @@ static SMB_STRUCT_DIRENT *cap_readdir(vfs_handle_struct *handle, SMB_STRUCT_DIR
        size_t newnamelen;
        DEBUG(3,("cap: cap_readdir\n"));
 
-       result = SMB_VFS_NEXT_READDIR(handle, dirp);
+       result = SMB_VFS_NEXT_READDIR(handle, dirp, NULL);
        if (!result) {
                return NULL;
        }
index d0c341fdd389cadef07056b1545033f23d8020f3..2870254bfbb487ade50a69c85c19956162449231 100644 (file)
@@ -105,11 +105,12 @@ static SMB_STRUCT_DIR *catia_opendir(vfs_handle_struct *handle,
 static SMB_STRUCT_DIRENT *catia_readdir(vfs_handle_struct *handle,
                                        SMB_STRUCT_DIR *dirp)
 {
-       SMB_STRUCT_DIRENT *result = SMB_VFS_NEXT_READDIR(handle, dirp);
-       SMB_STRUCT_DIRENT *newdirent;
+       SMB_STRUCT_DIRENT *result = NULL;
+       SMB_STRUCT_DIRENT *newdirent = NULL;
        char *newname;
        size_t newnamelen;
 
+       result = SMB_VFS_NEXT_READDIR(handle, dirp, NULL);
        if (result == NULL) {
                return result;
        }
index 679be57558fa400d80675aeada99ae7ff2eddbc4..7d61191a6973a1e50223979fb19148f7ce5db8ff 100644 (file)
@@ -113,12 +113,18 @@ static SMB_STRUCT_DIR *vfswrap_opendir(vfs_handle_struct *handle,  const char *f
        return result;
 }
 
-static SMB_STRUCT_DIRENT *vfswrap_readdir(vfs_handle_struct *handle,  SMB_STRUCT_DIR *dirp)
+static SMB_STRUCT_DIRENT *vfswrap_readdir(vfs_handle_struct *handle,
+                                         SMB_STRUCT_DIR *dirp,
+                                         SMB_STRUCT_STAT *sbuf)
 {
        SMB_STRUCT_DIRENT *result;
 
        START_PROFILE(syscall_readdir);
        result = sys_readdir(dirp);
+       /* Default Posix readdir() does not give us stat info.
+        * Set to invalid to indicate we didn't return this info. */
+       if (sbuf)
+               SET_STAT_INVALID(*sbuf);
        END_PROFILE(syscall_readdir);
        return result;
 }
index c6d62fdd879ed15739928ef2fd1a6f5d379f9f1c..e279772494d752dc1e445d21f515fcc89984a3a0 100644 (file)
@@ -94,7 +94,8 @@ static int smb_full_audit_statvfs(struct vfs_handle_struct *handle,
 static SMB_STRUCT_DIR *smb_full_audit_opendir(vfs_handle_struct *handle,
                          const char *fname, const char *mask, uint32 attr);
 static SMB_STRUCT_DIRENT *smb_full_audit_readdir(vfs_handle_struct *handle,
-                                   SMB_STRUCT_DIR *dirp);
+                                   SMB_STRUCT_DIR *dirp,
+                                   SMB_STRUCT_STAT *sbuf);
 static void smb_full_audit_seekdir(vfs_handle_struct *handle,
                        SMB_STRUCT_DIR *dirp, long offset);
 static long smb_full_audit_telldir(vfs_handle_struct *handle,
@@ -1029,11 +1030,11 @@ static SMB_STRUCT_DIR *smb_full_audit_opendir(vfs_handle_struct *handle,
 }
 
 static SMB_STRUCT_DIRENT *smb_full_audit_readdir(vfs_handle_struct *handle,
-                                   SMB_STRUCT_DIR *dirp)
+                                   SMB_STRUCT_DIR *dirp, SMB_STRUCT_STAT *sbuf)
 {
        SMB_STRUCT_DIRENT *result;
 
-       result = SMB_VFS_NEXT_READDIR(handle, dirp);
+       result = SMB_VFS_NEXT_READDIR(handle, dirp, sbuf);
 
        /* This operation has no reasonable error condition
         * (End of dir is also failure), so always succeed.
index fbd2960abaecd281b28832e07608bba658e524a1..4f5cedb3d44d648bc6e2070be657e7d6af451b4d 100644 (file)
@@ -93,7 +93,7 @@ static SMB_STRUCT_DIR *shadow_copy_opendir(vfs_handle_struct *handle, const char
        while (True) {
                SMB_STRUCT_DIRENT *d;
 
-               d = SMB_VFS_NEXT_READDIR(handle, p);
+               d = SMB_VFS_NEXT_READDIR(handle, p, NULL);
                if (d == NULL) {
                        break;
                }
@@ -176,7 +176,7 @@ static int shadow_copy_get_shadow_copy_data(vfs_handle_struct *handle, files_str
                SHADOW_COPY_LABEL *tlabels;
                SMB_STRUCT_DIRENT *d;
 
-               d = SMB_VFS_NEXT_READDIR(handle, p);
+               d = SMB_VFS_NEXT_READDIR(handle, p, NULL);
                if (d == NULL) {
                        break;
                }
index 56dd6ea8d875455cfac230929b3cfdf4fe8f74f1..9eaf8ee8512999b48c471d90b212c9069a24cb50 100644 (file)
@@ -524,7 +524,7 @@ static int shadow_copy2_get_shadow_copy2_data(vfs_handle_struct *handle,
        shadow_copy2_data->num_volumes = 0;
        shadow_copy2_data->labels      = NULL;
 
-       while ((d = SMB_VFS_NEXT_READDIR(handle, p))) {
+       while ((d = SMB_VFS_NEXT_READDIR(handle, p, NULL))) {
                SHADOW_COPY_LABEL *tlabels;
 
                /* ignore names not of the right form in the snapshot directory */
index 77efb277de09ce2acbc2fff9b06d1507f9a7bd83..1c2c0e5f77cfd2977b6e5dfa79d139892c3baf16 100644 (file)
@@ -352,7 +352,7 @@ static NTSTATUS walk_streams(vfs_handle_struct *handle,
                return map_nt_error_from_unix(errno);
        }
 
-       while ((dirent = vfs_readdirname(handle->conn, dirhandle)) != NULL) {
+       while ((dirent = vfs_readdirname(handle->conn, dirhandle, NULL)) != NULL) {
 
                if (ISDOT(dirent) || ISDOTDOT(dirent)) {
                        continue;
index 8d82ca550c5d22cb390cf6f70420dba73f0fd4b6..95802473680764df8c46cf29695b5e6730654ca5 100644 (file)
@@ -705,7 +705,7 @@ SMB_OFF_T vfs_transfer_file(files_struct *in, files_struct *out, SMB_OFF_T n)
  A vfs_readdir wrapper which just returns the file name.
 ********************************************************************/
 
-char *vfs_readdirname(connection_struct *conn, void *p)
+char *vfs_readdirname(connection_struct *conn, void *p, SMB_STRUCT_STAT *sbuf)
 {
        SMB_STRUCT_DIRENT *ptr= NULL;
        char *dname;
@@ -713,7 +713,7 @@ char *vfs_readdirname(connection_struct *conn, void *p)
        if (!p)
                return(NULL);
 
-       ptr = SMB_VFS_READDIR(conn, (DIR *)p);
+       ptr = SMB_VFS_READDIR(conn, (DIR *)p, sbuf);
        if (!ptr)
                return(NULL);
 
index 31eb27b7568b240da3f76f9689b95f24e043b80a..f273cedb90c2fb005b587c786f4d37555384f590 100644 (file)
@@ -141,20 +141,51 @@ static NTSTATUS cmd_opendir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc
 
 static NTSTATUS cmd_readdir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
 {
-       SMB_STRUCT_DIRENT *dent;
+       const char *user;
+       const char *group;
+       SMB_STRUCT_STAT st;
+       SMB_STRUCT_DIRENT *dent = NULL;
 
        if (vfs->currentdir == NULL) {
                printf("readdir: error=-1 (no open directory)\n");
                return NT_STATUS_UNSUCCESSFUL;
        }
 
-       dent = SMB_VFS_READDIR(vfs->conn, vfs->currentdir);
+       dent = SMB_VFS_READDIR(vfs->conn, vfs->currentdir, &st);
        if (dent == NULL) {
                printf("readdir: NULL\n");
                return NT_STATUS_OK;
        }
 
        printf("readdir: %s\n", dent->d_name);
+       if (VALID_STAT(st)) {
+               printf("  stat available");
+               if (S_ISREG(st.st_mode)) printf("  Regular File\n");
+               else if (S_ISDIR(st.st_mode)) printf("  Directory\n");
+               else if (S_ISCHR(st.st_mode)) printf("  Character Device\n");
+               else if (S_ISBLK(st.st_mode)) printf("  Block Device\n");
+               else if (S_ISFIFO(st.st_mode)) printf("  Fifo\n");
+               else if (S_ISLNK(st.st_mode)) printf("  Symbolic Link\n");
+               else if (S_ISSOCK(st.st_mode)) printf("  Socket\n");
+               printf("  Size: %10u", (unsigned int)st.st_size);
+#ifdef HAVE_STAT_ST_BLOCKS
+               printf(" Blocks: %9u", (unsigned int)st.st_blocks);
+#endif
+#ifdef HAVE_STAT_ST_BLKSIZE
+               printf(" IO Block: %u\n", (unsigned int)st.st_blksize);
+#endif
+               printf("  Device: 0x%10x", (unsigned int)st.st_dev);
+               printf(" Inode: %10u", (unsigned int)st.st_ino);
+               printf(" Links: %10u\n", (unsigned int)st.st_nlink);
+               printf("  Access: %05o", (st.st_mode) & 007777);
+               printf(" Uid: %5lu/%.16s Gid: %5lu/%.16s\n",
+                      (unsigned long)st.st_uid, user,
+                      (unsigned long)st.st_gid, group);
+               printf("  Access: %s", ctime(&(st.st_atime)));
+               printf("  Modify: %s", ctime(&(st.st_mtime)));
+               printf("  Change: %s", ctime(&(st.st_ctime)));
+       }
+
        return NT_STATUS_OK;
 }