s3: OneFS bulk directory enumeration support
[ira/wip.git] / source3 / modules / vfs_default.c
index 3171d3c5ca5f86b71a9a7d33a2a9ada4c018b5e7..4b123ab03ed56b858a40935fd189dd8c7d484d43 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;
 }
@@ -155,7 +161,7 @@ static int vfswrap_mkdir(vfs_handle_struct *handle,  const char *path, mode_t mo
        START_PROFILE(syscall_mkdir);
 
        if (lp_inherit_acls(SNUM(handle->conn))
-           && parent_dirname_talloc(talloc_tos(), path, &parent, NULL)
+           && parent_dirname(talloc_tos(), path, &parent, NULL)
            && (has_dacl = directory_has_default_acl(handle->conn, parent)))
                mode = 0777;
 
@@ -200,6 +206,12 @@ static int vfswrap_closedir(vfs_handle_struct *handle,  SMB_STRUCT_DIR *dirp)
        return result;
 }
 
+static void vfswrap_init_search_op(vfs_handle_struct *handle,
+                                  SMB_STRUCT_DIR *dirp)
+{
+       /* Default behavior is a NOOP */
+}
+
 /* File operations */
 
 static int vfswrap_open(vfs_handle_struct *handle,  const char *fname,
@@ -551,6 +563,39 @@ int vfswrap_lstat(vfs_handle_struct *handle,  const char *path, SMB_STRUCT_STAT
        return result;
 }
 
+/********************************************************************
+ Given a stat buffer return the allocated size on disk, taking into
+ account sparse files.
+********************************************************************/
+static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
+                                      struct files_struct *fsp,
+                                      const SMB_STRUCT_STAT *sbuf)
+{
+       uint64_t result;
+
+       START_PROFILE(syscall_get_alloc_size);
+
+       if(S_ISDIR(sbuf->st_mode)) {
+               result = 0;
+               goto out;
+       }
+
+#if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
+       result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_blocks;
+#else
+       result = get_file_size_stat(sbuf);
+#endif
+
+       if (fsp && fsp->initial_allocation_size)
+               result = MAX(result,fsp->initial_allocation_size);
+
+       result = smb_roundup(handle->conn, result);
+
+ out:
+       END_PROFILE(syscall_get_alloc_size);
+       return result;
+}
+
 static int vfswrap_unlink(vfs_handle_struct *handle,  const char *path)
 {
        int result;
@@ -682,26 +727,27 @@ static char *vfswrap_getwd(vfs_handle_struct *handle,  char *path)
  system will support.
 **********************************************************************/
 
-static int vfswrap_ntimes(vfs_handle_struct *handle, const char *path, const struct timespec ts[2])
+static int vfswrap_ntimes(vfs_handle_struct *handle, const char *path,
+                         struct smb_file_time *ft)
 {
        int result;
 
        START_PROFILE(syscall_ntimes);
 #if defined(HAVE_UTIMES)
-       if (ts != NULL) {
+       if (ft != NULL) {
                struct timeval tv[2];
-               tv[0] = convert_timespec_to_timeval(ts[0]);
-               tv[1] = convert_timespec_to_timeval(ts[1]);
+               tv[0] = convert_timespec_to_timeval(ft->atime);
+               tv[1] = convert_timespec_to_timeval(ft->mtime);
                result = utimes(path, tv);
        } else {
                result = utimes(path, NULL);
        }
 #elif defined(HAVE_UTIME)
-       if (ts != NULL) {
+       if (ft != NULL) {
                struct utimbuf times;
-               times.actime = convert_timespec_to_time_t(ts[0]);
-               times.modtime = convert_timespec_to_time_t(ts[1]);
-               result = utime(path, times);
+               times.actime = convert_timespec_to_time_t(ft->atime);
+               times.modtime = convert_timespec_to_time_t(ft->mtime);
+               result = utime(path, &times);
        } else {
                result = utime(path, NULL);
        }
@@ -1042,7 +1088,7 @@ static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
        }
 
        streams->size = sbuf.st_size;
-       streams->alloc_size = get_allocation_size(handle->conn, fsp, &sbuf);
+       streams->alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
 
        streams->name = talloc_strdup(streams, "::$DATA");
        if (streams->name == NULL) {
@@ -1409,6 +1455,8 @@ static vfs_op_tuple vfs_default_ops[] = {
         SMB_VFS_LAYER_OPAQUE},
        {SMB_VFS_OP(vfswrap_closedir),  SMB_VFS_OP_CLOSEDIR,
         SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_init_search_op), SMB_VFS_OP_INIT_SEARCH_OP,
+        SMB_VFS_LAYER_OPAQUE},
 
        /* File operations */
 
@@ -1442,6 +1490,8 @@ static vfs_op_tuple vfs_default_ops[] = {
         SMB_VFS_LAYER_OPAQUE},
        {SMB_VFS_OP(vfswrap_lstat),     SMB_VFS_OP_LSTAT,
         SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_get_alloc_size),    SMB_VFS_OP_GET_ALLOC_SIZE,
+        SMB_VFS_LAYER_OPAQUE},
        {SMB_VFS_OP(vfswrap_unlink),    SMB_VFS_OP_UNLINK,
         SMB_VFS_LAYER_OPAQUE},
        {SMB_VFS_OP(vfswrap_chmod),     SMB_VFS_OP_CHMOD,