s3: Prepare the first set of SMB_VFS_CREATE_FILE callers to take an smb_filename...
authorTim Prouty <tprouty@samba.org>
Wed, 10 Jun 2009 17:37:57 +0000 (10:37 -0700)
committerTim Prouty <tprouty@samba.org>
Wed, 10 Jun 2009 20:13:27 +0000 (13:13 -0700)
Some of the callers required minimal changes, while others
(copy_internals) required significant changes.  The task is simplified
a little bit because we are able to do operations and checks on the
base_name when a stream isn't used.

This patch should cause no functional changes.

Volker, Jeremy: Please check

source3/include/proto.h
source3/printing/nt_printing.c
source3/smbd/open.c
source3/smbd/reply.c
source3/smbd/trans2.c
source3/smbd/vfs.c

index f5e44bad64685eece1119c3b100327f6320a7008..a0ad28224245860deb9f8d05e8221bc284ce7254 100644 (file)
@@ -6622,7 +6622,8 @@ NTSTATUS open_file_fchmod(struct smb_request *req, connection_struct *conn,
                          const char *fname,
                          SMB_STRUCT_STAT *psbuf, files_struct **result);
 NTSTATUS close_file_fchmod(struct smb_request *req, files_struct *fsp);
-NTSTATUS create_directory(connection_struct *conn, struct smb_request *req, const char *directory);
+NTSTATUS create_directory(connection_struct *conn, struct smb_request *req,
+                         const struct smb_filename *smb_dname);
 void msg_file_was_renamed(struct messaging_context *msg,
                          void *private_data,
                          uint32_t msg_type,
@@ -6917,8 +6918,8 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
 void reply_mv(struct smb_request *req);
 NTSTATUS copy_file(TALLOC_CTX *ctx,
                        connection_struct *conn,
-                       const char *src,
-                       const char *dest1,
+                       struct smb_filename *smb_fname_src,
+                       struct smb_filename *smb_fname_dst,
                        int ofun,
                        int count,
                        bool target_is_directory);
@@ -7122,7 +7123,7 @@ void *vfs_fetch_fsp_extension(vfs_handle_struct *handle, files_struct *fsp);
 bool smbd_vfs_init(connection_struct *conn);
 bool vfs_directory_exist(connection_struct *conn, const char *dname, SMB_STRUCT_STAT *st);
 bool vfs_object_exist(connection_struct *conn,const char *fname,SMB_STRUCT_STAT *sbuf);
-bool vfs_file_exist(connection_struct *conn, const char *fname,SMB_STRUCT_STAT *sbuf);
+NTSTATUS vfs_file_exist(connection_struct *conn, struct smb_filename *smb_fname);
 ssize_t vfs_read_data(files_struct *fsp, char *buf, size_t byte_count);
 ssize_t vfs_pread_data(files_struct *fsp, char *buf,
                 size_t byte_count, SMB_OFF_T offset);
index 02ac7eeca2530d67570dbf9dc89c6226c932d73d..1aec954f12416253df0c6a68c5660a8a2abcd6bf 100644 (file)
@@ -634,40 +634,30 @@ bool nt_printing_init(struct messaging_context *msg_ctx)
  Function to allow filename parsing "the old way".
 ********************************************************************/
 
-static char *driver_unix_convert(connection_struct *conn,
-               const char *old_name,
-               SMB_STRUCT_STAT *pst)
+static NTSTATUS driver_unix_convert(connection_struct *conn,
+                                   const char *old_name,
+                                   struct smb_filename **smb_fname)
 {
        NTSTATUS status;
        TALLOC_CTX *ctx = talloc_tos();
-       struct smb_filename *smb_fname = NULL;
        char *name = talloc_strdup(ctx, old_name);
-       char *new_name = NULL;
 
        if (!name) {
-               return NULL;
+               return NT_STATUS_NO_MEMORY;
        }
        unix_format(name);
        name = unix_clean_name(ctx, name);
        if (!name) {
-               return NULL;
+               return NT_STATUS_NO_MEMORY;
        }
        trim_string(name,"/","/");
 
-       status = unix_convert(ctx, conn, name, &smb_fname, 0);
+       status = unix_convert(ctx, conn, name, smb_fname, 0);
        if (!NT_STATUS_IS_OK(status)) {
-               return NULL;
-       }
-
-       *pst = smb_fname->st;
-       status = get_full_smb_filename(ctx, smb_fname, &new_name);
-       if (!NT_STATUS_IS_OK(status)) {
-               TALLOC_FREE(smb_fname);
-               return NULL;
+               return NT_STATUS_NO_MEMORY;
        }
 
-       TALLOC_FREE(smb_fname);
-       return new_name;
+       return NT_STATUS_OK;
 }
 
 /*******************************************************************
@@ -1297,11 +1287,13 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
        uint32 old_minor;
        time_t old_create_time;
 
+       struct smb_filename *smb_fname = NULL;
        files_struct    *fsp = NULL;
        SMB_STRUCT_STAT st;
        SMB_STRUCT_STAT stat_buf;
 
        NTSTATUS status;
+       int ret;
 
        SET_STAT_INVALID(st);
        SET_STAT_INVALID(stat_buf);
@@ -1309,8 +1301,13 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
        old_create_time = (time_t)0;
 
        /* Get file version info (if available) for previous file (if it exists) */
-       filepath = driver_unix_convert(conn,old_file,&stat_buf);
-       if (!filepath) {
+       status = driver_unix_convert(conn, old_file, &smb_fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto error_exit;
+       }
+
+       status = get_full_smb_filename(talloc_tos(), smb_fname, &filepath);
+       if (!NT_STATUS_IS_OK(status)) {
                goto error_exit;
        }
 
@@ -1337,10 +1334,11 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
                /* Old file not found, so by definition new file is in fact newer */
                DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
                                filepath, errno));
-               return 1;
+               ret = 1;
+               goto done;
 
        } else {
-               int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
+               ret = get_file_version(fsp, old_file, &old_major, &old_minor);
                if (ret == -1) {
                        goto error_exit;
                }
@@ -1361,8 +1359,13 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
        fsp = NULL;
 
        /* Get file version info (if available) for new file */
-       filepath = driver_unix_convert(conn,new_file,&stat_buf);
-       if (!filepath) {
+       status = driver_unix_convert(conn, new_file, &smb_fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto error_exit;
+       }
+
+       status = get_full_smb_filename(talloc_tos(), smb_fname, &filepath);
+       if (!NT_STATUS_IS_OK(status)) {
                goto error_exit;
        }
 
@@ -1392,7 +1395,7 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
                goto error_exit;
 
        } else {
-               int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
+               ret = get_file_version(fsp, new_file, &new_major, &new_minor);
                if (ret == -1) {
                        goto error_exit;
                }
@@ -1418,29 +1421,36 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
                        (new_major == old_major && new_minor > old_minor)) {
 
                        DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
-                       return 1;
+                       ret = 1;
+                       goto done;
                }
                else {
                        DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
-                       return 0;
+                       ret = 0;
+                       goto done;
                }
 
        } else {
                /* Compare modification time/dates and choose the newest time/date */
                if (new_create_time > old_create_time) {
                        DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
-                       return 1;
+                       ret = 1;
+                       goto done;
                }
                else {
                        DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
-                       return 0;
+                       ret = 0;
+                       goto done;
                }
        }
 
-       error_exit:
-               if(fsp)
-                       close_file(NULL, fsp, NORMAL_CLOSE);
-               return -1;
+ error_exit:
+       if(fsp)
+               close_file(NULL, fsp, NORMAL_CLOSE);
+       ret = -1;
+ done:
+       TALLOC_FREE(smb_fname);
+       return ret;
 }
 
 /****************************************************************************
@@ -1453,7 +1463,8 @@ static uint32 get_correct_cversion(struct pipes_struct *p,
 {
        int               cversion;
        NTSTATUS          nt_status;
-       char *driverpath = NULL;
+       struct smb_filename *smb_fname = NULL;
+       char *driverpath = NULL;
        files_struct      *fsp = NULL;
        SMB_STRUCT_STAT   st;
        connection_struct *conn = NULL;
@@ -1509,17 +1520,24 @@ static uint32 get_correct_cversion(struct pipes_struct *p,
                goto error_exit;
        }
 
-       driverpath = driver_unix_convert(conn,driverpath,&st);
-       if (!driverpath) {
-               *perr = WERR_NOMEM;
+       nt_status = driver_unix_convert(conn, driverpath, &smb_fname);
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               *perr = ntstatus_to_werror(nt_status);
                goto error_exit;
        }
 
-       if (!vfs_file_exist(conn, driverpath, &st)) {
+       nt_status = vfs_file_exist(conn, smb_fname);
+       if (!NT_STATUS_IS_OK(nt_status)) {
                *perr = WERR_BADFILE;
                goto error_exit;
        }
 
+       status = get_full_smb_filename(talloc_tos(), smb_fname, &driverpath);
+       if (!NT_STATUS_IS_OK(status)) {
+               *perr = WERR_NOMEM;
+               goto error_exit;
+       }
+
        status = SMB_VFS_CREATE_FILE(
                conn,                                   /* conn */
                NULL,                                   /* req */
@@ -1586,6 +1604,7 @@ static uint32 get_correct_cversion(struct pipes_struct *p,
  error_exit:
        cversion = -1;
  done:
+       TALLOC_FREE(smb_fname);
        if (fsp != NULL) {
                close_file(NULL, fsp, NORMAL_CLOSE);
        }
@@ -1811,10 +1830,12 @@ static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
                                                uint32_t driver_version,
                                                uint32_t version)
 {
+       struct smb_filename *smb_fname_old = NULL;
+       struct smb_filename *smb_fname_new = NULL;
        char *old_name = NULL;
        char *new_name = NULL;
-       SMB_STRUCT_STAT st;
        NTSTATUS status;
+       WERROR ret;
 
        old_name = talloc_asprintf(mem_ctx, "%s/%s",
                                   short_architecture, driver_file);
@@ -1826,25 +1847,45 @@ static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
 
        if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
 
-               old_name = driver_unix_convert(conn, old_name, &st);
-               W_ERROR_HAVE_NO_MEMORY(old_name);
+               status = driver_unix_convert(conn, old_name, &smb_fname_old);
+               if (!NT_STATUS_IS_OK(status)) {
+                       ret = WERR_NOMEM;
+                       goto out;
+               }
+
+               /* Setup a synthetic smb_filename struct */
+               smb_fname_new = TALLOC_ZERO_P(mem_ctx, struct smb_filename);
+               if (!smb_fname_new) {
+                       ret = WERR_NOMEM;
+                       goto out;
+               }
 
-               DEBUG(10,("move_driver_file_to_download_area: copying '%s' to '%s'\n",
-                       old_name, new_name));
+               smb_fname_new->base_name = new_name;
 
-               status = copy_file(mem_ctx, conn, old_name, new_name,
+               DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
+                         "'%s'\n", smb_fname_old->base_name,
+                         smb_fname_new->base_name));
+
+               status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
                                   OPENX_FILE_EXISTS_TRUNCATE |
                                   OPENX_FILE_CREATE_IF_NOT_EXIST,
                                   0, false);
 
                if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(0,("move_driver_file_to_download_area: Unable to rename [%s] to [%s]: %s\n",
-                               old_name, new_name, nt_errstr(status)));
-                       return WERR_ACCESS_DENIED;
+                       DEBUG(0,("move_driver_file_to_download_area: Unable "
+                                "to rename [%s] to [%s]: %s\n",
+                                smb_fname_old->base_name, new_name,
+                                nt_errstr(status)));
+                       ret = WERR_ACCESS_DENIED;
+                       goto out;
                }
        }
 
-       return WERR_OK;
+       ret = WERR_OK;
+ out:
+       TALLOC_FREE(smb_fname_old);
+       TALLOC_FREE(smb_fname_new);
+       return ret;
 }
 
 WERROR move_driver_to_download_area(struct pipes_struct *p,
@@ -1854,10 +1895,10 @@ WERROR move_driver_to_download_area(struct pipes_struct *p,
        NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
        NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
        const char *short_architecture;
+       struct smb_filename *smb_dname = NULL;
        char *new_dir = NULL;
        connection_struct *conn = NULL;
        NTSTATUS nt_status;
-       SMB_STRUCT_STAT st;
        int i;
        TALLOC_CTX *ctx = talloc_tos();
        int ver = 0;
@@ -1911,15 +1952,15 @@ WERROR move_driver_to_download_area(struct pipes_struct *p,
                *perr = WERR_NOMEM;
                goto err_exit;
        }
-       new_dir = driver_unix_convert(conn,new_dir,&st);
-       if (!new_dir) {
+       nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
+       if (!NT_STATUS_IS_OK(nt_status)) {
                *perr = WERR_NOMEM;
                goto err_exit;
        }
 
-       DEBUG(5,("Creating first directory: %s\n", new_dir));
+       DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
 
-       create_directory(conn, NULL, new_dir);
+       create_directory(conn, NULL, smb_dname);
 
        /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
         * listed for this driver which has already been moved, skip it (note:
@@ -2044,6 +2085,7 @@ WERROR move_driver_to_download_area(struct pipes_struct *p,
        }
 
   err_exit:
+       TALLOC_FREE(smb_dname);
 
        if (conn != NULL) {
                vfs_ChDir(conn, oldcwd);
index 773436fa8e39fa843e347f013e33c4abb04a2b29..718feb4996c6ef00a6830b26cb7af95eefe17fe8 100644 (file)
@@ -2598,10 +2598,17 @@ static NTSTATUS open_directory(connection_struct *conn,
        return NT_STATUS_OK;
 }
 
-NTSTATUS create_directory(connection_struct *conn, struct smb_request *req, const char *directory)
+NTSTATUS create_directory(connection_struct *conn, struct smb_request *req,
+                         const struct smb_filename *smb_dname)
 {
        NTSTATUS status;
        files_struct *fsp;
+       char *directory = NULL;
+
+       status = get_full_smb_filename(talloc_tos(), smb_dname, &directory);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto out;
+       }
 
        status = SMB_VFS_CREATE_FILE(
                conn,                                   /* conn */
@@ -2625,7 +2632,8 @@ NTSTATUS create_directory(connection_struct *conn, struct smb_request *req, cons
        if (NT_STATUS_IS_OK(status)) {
                close_file(req, fsp, NORMAL_CLOSE);
        }
-
+ out:
+       TALLOC_FREE(directory);
        return status;
 }
 
index 844bcc1882a06f39ce1c3247a6039d42b36d5f62..f91a3c755061957f27eb72f20c7de7b269d24c75 100644 (file)
@@ -5233,19 +5233,13 @@ void reply_mkdir(struct smb_request *req)
                goto out;
        }
 
-       status = get_full_smb_filename(ctx, smb_dname, &directory);
-       if (!NT_STATUS_IS_OK(status)) {
-               reply_nterror(req, status);
-               goto out;
-       }
-
-       status = check_name(conn, directory);
+       status = check_name(conn, smb_dname->base_name);
        if (!NT_STATUS_IS_OK(status)) {
                reply_nterror(req, status);
                goto out;
        }
 
-       status = create_directory(conn, req, directory);
+       status = create_directory(conn, req, smb_dname);
 
        DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
 
@@ -5268,7 +5262,7 @@ void reply_mkdir(struct smb_request *req)
 
        reply_outbuf(req, 0, 0);
 
-       DEBUG( 3, ( "mkdir %s\n", directory ) );
+       DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
  out:
        TALLOC_FREE(smb_dname);
        END_PROFILE(SMBmkdir);
@@ -6434,59 +6428,80 @@ void reply_mv(struct smb_request *req)
 
 NTSTATUS copy_file(TALLOC_CTX *ctx,
                        connection_struct *conn,
-                       const char *src,
-                       const char *dest1,
+                       struct smb_filename *smb_fname_src,
+                       struct smb_filename *smb_fname_dst,
                        int ofun,
                        int count,
                        bool target_is_directory)
 {
-       SMB_STRUCT_STAT src_sbuf, sbuf2;
+       struct smb_filename *smb_fname_dst_tmp = NULL;
+       char *fname_src = NULL;
+       char *fname_dst = NULL;
        SMB_OFF_T ret=-1;
        files_struct *fsp1,*fsp2;
-       char *dest = NULL;
        uint32 dosattrs;
        uint32 new_create_disposition;
        NTSTATUS status;
 
-       dest = talloc_strdup(ctx, dest1);
-       if (!dest) {
-               return NT_STATUS_NO_MEMORY;
+
+       status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
        }
+
+       /*
+        * If the target is a directory, extract the last component from the
+        * src filename and append it to the dst filename
+        */
        if (target_is_directory) {
-               const char *p = strrchr_m(src,'/');
+               const char *p;
+
+               /* dest/target can't be a stream if it's a directory. */
+               SMB_ASSERT(smb_fname_dst->stream_name == NULL);
+
+               p = strrchr_m(smb_fname_src->base_name,'/');
                if (p) {
                        p++;
                } else {
-                       p = src;
+                       p = smb_fname_src->base_name;
                }
-               dest = talloc_asprintf_append(dest,
-                               "/%s",
-                               p);
-               if (!dest) {
-                       return NT_STATUS_NO_MEMORY;
+               smb_fname_dst_tmp->base_name =
+                   talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
+                                          p);
+               if (!smb_fname_dst_tmp->base_name) {
+                       status = NT_STATUS_NO_MEMORY;
+                       goto out;
                }
        }
 
-       if (!vfs_file_exist(conn,src,&src_sbuf)) {
-               TALLOC_FREE(dest);
-               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       status = vfs_file_exist(conn, smb_fname_src);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto out;
        }
 
        if (!target_is_directory && count) {
                new_create_disposition = FILE_OPEN;
        } else {
-               if (!map_open_params_to_ntcreate(dest1,0,ofun,
-                               NULL, NULL, &new_create_disposition, NULL)) {
-                       TALLOC_FREE(dest);
-                       return NT_STATUS_INVALID_PARAMETER;
+               if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
+                                                0, ofun, NULL, NULL,
+                                                &new_create_disposition,
+                                                NULL)) {
+                       status = NT_STATUS_INVALID_PARAMETER;
+                       goto out;
                }
        }
 
+       status = get_full_smb_filename(talloc_tos(), smb_fname_src, &fname_src);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto out;
+       }
+
+       /* Open the src file for reading. */
        status = SMB_VFS_CREATE_FILE(
                conn,                                   /* conn */
                NULL,                                   /* req */
                0,                                      /* root_dir_fid */
-               src,                                    /* fname */
+               fname_src,                              /* fname */
                0,                                      /* create_file_flags */
                FILE_GENERIC_READ,                      /* access_mask */
                FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
@@ -6499,23 +6514,29 @@ NTSTATUS copy_file(TALLOC_CTX *ctx,
                NULL,                                   /* ea_list */
                &fsp1,                                  /* result */
                NULL,                                   /* pinfo */
-               &src_sbuf);                             /* psbuf */
+               &smb_fname_src->st);                    /* psbuf */
 
        if (!NT_STATUS_IS_OK(status)) {
-               TALLOC_FREE(dest);
-               return status;
+               goto out;
+       }
+
+       dosattrs = dos_mode(conn, fname_src, &smb_fname_src->st);
+
+       status = get_full_smb_filename(talloc_tos(), smb_fname_dst_tmp, &fname_dst);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto out;
        }
 
-       dosattrs = dos_mode(conn, src, &src_sbuf);
-       if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
-               ZERO_STRUCTP(&sbuf2);
+       if (SMB_VFS_STAT(conn, fname_dst, &smb_fname_dst_tmp->st) == -1) {
+               ZERO_STRUCTP(&smb_fname_dst_tmp->st);
        }
 
+       /* Open the dst file for writing. */
        status = SMB_VFS_CREATE_FILE(
                conn,                                   /* conn */
                NULL,                                   /* req */
                0,                                      /* root_dir_fid */
-               dest,                                   /* fname */
+               fname_dst,                              /* fname */
                0,                                      /* create_file_flags */
                FILE_GENERIC_WRITE,                     /* access_mask */
                FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
@@ -6528,13 +6549,11 @@ NTSTATUS copy_file(TALLOC_CTX *ctx,
                NULL,                                   /* ea_list */
                &fsp2,                                  /* result */
                NULL,                                   /* pinfo */
-               &sbuf2);                                /* psbuf */
-
-       TALLOC_FREE(dest);
+               &smb_fname_dst_tmp->st);                /* psbuf */
 
        if (!NT_STATUS_IS_OK(status)) {
                close_file(NULL, fsp1, ERROR_CLOSE);
-               return status;
+               goto out;
        }
 
        if ((ofun&3) == 1) {
@@ -6544,18 +6563,19 @@ NTSTATUS copy_file(TALLOC_CTX *ctx,
                         * Stop the copy from occurring.
                         */
                        ret = -1;
-                       src_sbuf.st_ex_size = 0;
+                       smb_fname_src->st.st_ex_size = 0;
                }
        }
 
-       if (src_sbuf.st_ex_size) {
-               ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_ex_size);
+       /* Do the actual copy. */
+       if (smb_fname_src->st.st_ex_size) {
+               ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
        }
 
        close_file(NULL, fsp1, NORMAL_CLOSE);
 
        /* Ensure the modtime is set correctly on the destination file. */
-       set_close_write_time(fsp2, src_sbuf.st_ex_mtime);
+       set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
 
        /*
         * As we are opening fsp1 read-only we only expect
@@ -6566,14 +6586,21 @@ NTSTATUS copy_file(TALLOC_CTX *ctx,
        status = close_file(NULL, fsp2, NORMAL_CLOSE);
 
        if (!NT_STATUS_IS_OK(status)) {
-               return status;
+               goto out;
        }
 
-       if (ret != (SMB_OFF_T)src_sbuf.st_ex_size) {
-               return NT_STATUS_DISK_FULL;
+       if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
+               status = NT_STATUS_DISK_FULL;
+               goto out;
        }
 
-       return NT_STATUS_OK;
+       status = NT_STATUS_OK;
+
+ out:
+       TALLOC_FREE(smb_fname_dst_tmp);
+       TALLOC_FREE(fname_src);
+       TALLOC_FREE(fname_dst);
+       return status;
 }
 
 /****************************************************************************
@@ -6583,13 +6610,12 @@ NTSTATUS copy_file(TALLOC_CTX *ctx,
 void reply_copy(struct smb_request *req)
 {
        connection_struct *conn = req->conn;
-       struct smb_filename *smb_fname = NULL;
-       struct smb_filename *smb_fname_new = NULL;
-       char *name = NULL;
-       char *newname = NULL;
-       char *directory = NULL;
-       const char *mask = NULL;
-       const char mask_star[] = "*";
+       struct smb_filename *smb_fname_src = NULL;
+       struct smb_filename *smb_fname_dst = NULL;
+       char *fname_src = NULL;
+       char *fname_dst = NULL;
+       char *fname_src_mask = NULL;
+       char *fname_src_dir = NULL;
        const char *p;
        int count=0;
        int error = ERRnoaccess;
@@ -6615,20 +6641,20 @@ void reply_copy(struct smb_request *req)
        flags = SVAL(req->vwv+2, 0);
 
        p = (const char *)req->buf;
-       p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
+       p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
                                       &status, &source_has_wild);
        if (!NT_STATUS_IS_OK(status)) {
                reply_nterror(req, status);
                goto out;
        }
-       p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
+       p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
                                       &status, &dest_has_wild);
        if (!NT_STATUS_IS_OK(status)) {
                reply_nterror(req, status);
                goto out;
        }
 
-       DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
+       DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
 
        if (tid2 != conn->cnum) {
                /* can't currently handle inter share copies XXXX */
@@ -6639,8 +6665,8 @@ void reply_copy(struct smb_request *req)
 
        status = resolve_dfspath_wcard(ctx, conn,
                                       req->flags2 & FLAGS2_DFS_PATHNAMES,
-                                      name,
-                                      &name,
+                                      fname_src,
+                                      &fname_src,
                                       &source_has_wild);
        if (!NT_STATUS_IS_OK(status)) {
                if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
@@ -6654,8 +6680,8 @@ void reply_copy(struct smb_request *req)
 
        status = resolve_dfspath_wcard(ctx, conn,
                                       req->flags2 & FLAGS2_DFS_PATHNAMES,
-                                      newname,
-                                      &newname,
+                                      fname_dst,
+                                      &fname_dst,
                                       &dest_has_wild);
        if (!NT_STATUS_IS_OK(status)) {
                if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
@@ -6667,33 +6693,21 @@ void reply_copy(struct smb_request *req)
                goto out;
        }
 
-       status = unix_convert(ctx, conn, name, &smb_fname,
+       status = unix_convert(ctx, conn, fname_src, &smb_fname_src,
                              source_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
        if (!NT_STATUS_IS_OK(status)) {
                reply_nterror(req, status);
                goto out;
        }
 
-       status = get_full_smb_filename(ctx, smb_fname, &name);
-       if (!NT_STATUS_IS_OK(status)) {
-               reply_nterror(req, status);
-               goto out;
-       }
-
-       status = unix_convert(ctx, conn, newname, &smb_fname_new,
+       status = unix_convert(ctx, conn, fname_dst, &smb_fname_dst,
                              dest_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
        if (!NT_STATUS_IS_OK(status)) {
                reply_nterror(req, status);
                goto out;
        }
 
-       status = get_full_smb_filename(ctx, smb_fname_new, &newname);
-       if (!NT_STATUS_IS_OK(status)) {
-               reply_nterror(req, status);
-               goto out;
-       }
-
-       target_is_directory = VALID_STAT_OF_DIR(smb_fname_new->st);
+       target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
 
        if ((flags&1) && target_is_directory) {
                reply_doserror(req, ERRDOS, ERRbadfile);
@@ -6705,23 +6719,25 @@ void reply_copy(struct smb_request *req)
                goto out;
        }
 
-       if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname->st)) {
+       if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
                /* wants a tree copy! XXXX */
                DEBUG(3,("Rejecting tree copy\n"));
                reply_doserror(req, ERRSRV, ERRerror);
                goto out;
        }
 
-       p = strrchr_m(name,'/');
+       /* Split up the directory from the filename/mask. */
+       p = strrchr_m(smb_fname_src->base_name,'/');
        if (p != NULL) {
-               directory = talloc_strndup(ctx, name, PTR_DIFF(p, name));
-               mask = p+1;
+               fname_src_dir = talloc_strndup(ctx, smb_fname_src->base_name,
+                                          PTR_DIFF(p, smb_fname_src->base_name));
+               fname_src_mask = talloc_strdup(ctx, p+1);
        } else {
-               directory = talloc_strdup(ctx, "./");
-               mask = name;
+               fname_src_dir = talloc_strdup(ctx, "./");
+               fname_src_mask = talloc_strdup(ctx, smb_fname_src->base_name);
        }
 
-       if (!directory) {
+       if (!fname_src_dir || !fname_src_mask) {
                reply_nterror(req, NT_STATUS_NO_MEMORY);
                goto out;
        }
@@ -6734,47 +6750,62 @@ void reply_copy(struct smb_request *req)
         * for a possible mangle. This patch from
         * Tine Smukavec <valentin.smukavec@hermes.si>.
         */
-
-       if (!VALID_STAT(smb_fname->st) &&
-           mangle_is_mangled(mask, conn->params)) {
+       if (!VALID_STAT(smb_fname_src->st) &&
+           mangle_is_mangled(fname_src_mask, conn->params)) {
                char *new_mask = NULL;
-               mangle_lookup_name_from_8_3(ctx,
-                                       mask,
-                                       &new_mask,
-                                       conn->params );
+               mangle_lookup_name_from_8_3(ctx, fname_src_mask,
+                                           &new_mask, conn->params);
+
+               /* Use demangled name if one was successfully found. */
                if (new_mask) {
-                       mask = new_mask;
+                       TALLOC_FREE(fname_src_mask);
+                       fname_src_mask = new_mask;
                }
        }
 
        if (!source_has_wild) {
-               directory = talloc_asprintf_append(directory,
-                               "/%s",
-                               mask);
+
+               /*
+                * Only one file needs to be copied. Append the mask back onto
+                * the directory.
+                */
+               TALLOC_FREE(smb_fname_src->base_name);
+               smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
+                                                          "%s/%s",
+                                                          fname_src_dir,
+                                                          fname_src_mask);
+               if (!smb_fname_src->base_name) {
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                       goto out;
+               }
+
                if (dest_has_wild) {
-                       char *mod_newname = NULL;
-                       if (!resolve_wildcards(ctx,
-                                       directory,newname,&mod_newname)) {
+                       char *fname_dst_mod = NULL;
+                       if (!resolve_wildcards(smb_fname_dst,
+                                              smb_fname_src->base_name,
+                                              smb_fname_dst->base_name,
+                                              &fname_dst_mod)) {
                                reply_nterror(req, NT_STATUS_NO_MEMORY);
                                goto out;
                        }
-                       newname = mod_newname;
+                       TALLOC_FREE(smb_fname_dst->base_name);
+                       smb_fname_dst->base_name = fname_dst_mod;
                }
 
-               status = check_name(conn, directory);
+               status = check_name(conn, smb_fname_src->base_name);
                if (!NT_STATUS_IS_OK(status)) {
                        reply_nterror(req, status);
                        goto out;
                }
 
-               status = check_name(conn, newname);
+               status = check_name(conn, smb_fname_dst->base_name);
                if (!NT_STATUS_IS_OK(status)) {
                        reply_nterror(req, status);
                        goto out;
                }
 
-               status = copy_file(ctx,conn,directory,newname,ofun,
-                               count,target_is_directory);
+               status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
+                                  ofun, count, target_is_directory);
 
                if(!NT_STATUS_IS_OK(status)) {
                        reply_nterror(req, status);
@@ -6787,17 +6818,34 @@ void reply_copy(struct smb_request *req)
                const char *dname = NULL;
                long offset = 0;
 
-               if (strequal(mask,"????????.???")) {
-                       mask = mask_star;
+               /*
+                * There is a wildcard that requires us to actually read the
+                * src dir and copy each file matching the mask to the dst.
+                * Right now streams won't be copied, but this could
+                * presumably be added with a nested loop for reach dir entry.
+                */
+               SMB_ASSERT(!smb_fname_src->stream_name);
+               SMB_ASSERT(!smb_fname_dst->stream_name);
+
+               smb_fname_src->stream_name = NULL;
+               smb_fname_dst->stream_name = NULL;
+
+               if (strequal(fname_src_mask,"????????.???")) {
+                       TALLOC_FREE(fname_src_mask);
+                       fname_src_mask = talloc_strdup(ctx, "*");
+                       if (!fname_src_mask) {
+                               reply_nterror(req, NT_STATUS_NO_MEMORY);
+                               goto out;
+                       }
                }
 
-               status = check_name(conn, directory);
+               status = check_name(conn, fname_src_dir);
                if (!NT_STATUS_IS_OK(status)) {
                        reply_nterror(req, status);
                        goto out;
                }
 
-               dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, 0);
+               dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
                if (dir_hnd == NULL) {
                        status = map_nt_error_from_unix(errno);
                        reply_nterror(req, status);
@@ -6806,37 +6854,42 @@ void reply_copy(struct smb_request *req)
 
                error = ERRbadfile;
 
+               /* Iterate over the src dir copying each entry to the dst. */
                while ((dname = ReadDirName(dir_hnd, &offset,
-                                           &smb_fname->st))) {
+                                           &smb_fname_src->st))) {
                        char *destname = NULL;
-                       char *fname = NULL;
 
                        if (ISDOT(dname) || ISDOTDOT(dname)) {
                                continue;
                        }
 
-                       if (!is_visible_file(conn, directory, dname,
-                                            &smb_fname->st, False)) {
+                       if (!is_visible_file(conn, fname_src_dir, dname,
+                                            &smb_fname_src->st, false)) {
                                continue;
                        }
 
-                       if(!mask_match(dname, mask, conn->case_sensitive)) {
+                       if(!mask_match(dname, fname_src_mask,
+                                      conn->case_sensitive)) {
                                continue;
                        }
 
                        error = ERRnoaccess;
-                       fname = talloc_asprintf(ctx,
-                                       "%s/%s",
-                                       directory,
-                                       dname);
-                       if (!fname) {
+
+                       /* Get the src smb_fname struct setup. */
+                       TALLOC_FREE(smb_fname_src->base_name);
+                       smb_fname_src->base_name =
+                           talloc_asprintf(smb_fname_src, "%s/%s",
+                                           fname_src_dir, dname);
+
+                       if (!smb_fname_src->base_name) {
                                TALLOC_FREE(dir_hnd);
                                reply_nterror(req, NT_STATUS_NO_MEMORY);
                                goto out;
                        }
 
-                       if (!resolve_wildcards(ctx,
-                                       fname,newname,&destname)) {
+                       if (!resolve_wildcards(ctx, smb_fname_src->base_name,
+                                              smb_fname_dst->base_name,
+                                              &destname)) {
                                continue;
                        }
                        if (!destname) {
@@ -6845,29 +6898,33 @@ void reply_copy(struct smb_request *req)
                                goto out;
                        }
 
-                       status = check_name(conn, fname);
+                       TALLOC_FREE(smb_fname_dst->base_name);
+                       smb_fname_dst->base_name = destname;
+
+                       status = check_name(conn, smb_fname_src->base_name);
                        if (!NT_STATUS_IS_OK(status)) {
                                TALLOC_FREE(dir_hnd);
                                reply_nterror(req, status);
                                goto out;
                        }
 
-                       status = check_name(conn, destname);
+                       status = check_name(conn, smb_fname_dst->base_name);
                        if (!NT_STATUS_IS_OK(status)) {
                                TALLOC_FREE(dir_hnd);
                                reply_nterror(req, status);
                                goto out;
                        }
 
-                       DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
+                       DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
+                               smb_fname_src->base_name,
+                               smb_fname_dst->base_name));
 
-                       status = copy_file(ctx,conn,fname,destname,ofun,
-                                       count,target_is_directory);
+                       status = copy_file(ctx, conn, smb_fname_src,
+                                          smb_fname_dst, ofun, count,
+                                          target_is_directory);
                        if (NT_STATUS_IS_OK(status)) {
                                count++;
                        }
-                       TALLOC_FREE(fname);
-                       TALLOC_FREE(destname);
                }
                TALLOC_FREE(dir_hnd);
        }
@@ -6887,8 +6944,13 @@ void reply_copy(struct smb_request *req)
        reply_outbuf(req, 1, 0);
        SSVAL(req->outbuf,smb_vwv0,count);
  out:
-       TALLOC_FREE(smb_fname);
-       TALLOC_FREE(smb_fname_new);
+       TALLOC_FREE(smb_fname_src);
+       TALLOC_FREE(smb_fname_dst);
+       TALLOC_FREE(fname_src);
+       TALLOC_FREE(fname_dst);
+       TALLOC_FREE(fname_src_mask);
+       TALLOC_FREE(fname_src_dir);
+
        END_PROFILE(SMBcopy);
        return;
 }
index a36e9f588accb532e06090df8c98909b9c8ab769..dc2544c4e3554c9049da768b53dd19ff7b1bd489 100644 (file)
@@ -7208,23 +7208,17 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
                return;
        }
 
-       status = get_full_smb_filename(ctx, smb_dname, &directory);
-       if (!NT_STATUS_IS_OK(status)) {
-               reply_nterror(req, status);
-               return;
-       }
-
-       status = check_name(conn, directory);
+       status = check_name(conn, smb_dname->base_name);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
                reply_nterror(req, status);
-               return;
+               goto out;
        }
 
        /* Any data in this call is an EA list. */
        if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
                reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
-               return;
+               goto out;
        }
 
        /*
@@ -7236,21 +7230,21 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
        if (total_data != 4) {
                if (total_data < 10) {
                        reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-                       return;
+                       goto out;
                }
 
                if (IVAL(pdata,0) > total_data) {
                        DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
                                IVAL(pdata,0), (unsigned int)total_data));
                        reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-                       return;
+                       goto out;
                }
 
                ea_list = read_ea_list(talloc_tos(), pdata + 4,
                                       total_data - 4);
                if (!ea_list) {
                        reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-                       return;
+                       goto out;
                }
        }
        /* If total_data == 4 Windows doesn't care what values
@@ -7258,19 +7252,19 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
         * The System i QNTC IBM SMB client puts bad values here,
         * so ignore them. */
 
-       status = create_directory(conn, req, directory);
+       status = create_directory(conn, req, smb_dname);
 
        if (!NT_STATUS_IS_OK(status)) {
                reply_nterror(req, status);
-               return;
+               goto out;
        }
 
        /* Try and set any given EA. */
        if (ea_list) {
-               status = set_ea(conn, NULL, directory, ea_list);
+               status = set_ea(conn, NULL, smb_dname->base_name, ea_list);
                if (!NT_STATUS_IS_OK(status)) {
                        reply_nterror(req, status);
-                       return;
+                       goto out;
                }
        }
 
@@ -7278,7 +7272,7 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
        *pparams = (char *)SMB_REALLOC(*pparams,2);
        if(*pparams == NULL) {
                reply_nterror(req, NT_STATUS_NO_MEMORY);
-               return;
+               goto out;
        }
        params = *pparams;
 
@@ -7286,6 +7280,8 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
 
        send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
 
+ out:
+       TALLOC_FREE(smb_dname);
        return;
 }
 
index 873e65e4a4a0b56901142ee6cfa0a09bf5f722a6..385454e587f835f564feb98a54a3e70594e792b8 100644 (file)
@@ -382,18 +382,28 @@ bool vfs_object_exist(connection_struct *conn,const char *fname,SMB_STRUCT_STAT
  Check if a file exists in the vfs.
 ********************************************************************/
 
-bool vfs_file_exist(connection_struct *conn, const char *fname,SMB_STRUCT_STAT *sbuf)
+NTSTATUS vfs_file_exist(connection_struct *conn, struct smb_filename *smb_fname)
 {
-       SMB_STRUCT_STAT st;
+       char *fname = NULL;
+       NTSTATUS status;
 
-       if (!sbuf)
-               sbuf = &st;
+       status = get_full_smb_filename(talloc_tos(), smb_fname, &fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto out;
+       }
 
-       ZERO_STRUCTP(sbuf);
+       status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       if (SMB_VFS_STAT(conn, fname, &smb_fname->st) == -1) {
+               goto out;
+       }
 
-       if (SMB_VFS_STAT(conn,fname,sbuf) == -1)
-               return False;
-       return(S_ISREG(sbuf->st_ex_mode));
+       /* Only return OK if stat was successful and S_ISREG */
+       if (S_ISREG(smb_fname->st.st_ex_mode)) {
+               status = NT_STATUS_OK;
+       }
+ out:
+       TALLOC_FREE(fname);
+       return status;
 }
 
 /****************************************************************************