]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
smbd: Simplify call_trans2qfilepathinfo()
authorVolker Lendecke <vl@samba.org>
Fri, 23 Dec 2022 17:20:15 +0000 (18:20 +0100)
committerRalph Boehme <slow@samba.org>
Wed, 4 Jan 2023 08:54:32 +0000 (08:54 +0000)
Move the file/path specific preparations to the respective callers.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
source3/smbd/smb1_trans2.c

index 0d7ffebd0248814e53ec2b48868312aa636adf75..3b10934f565b842b5956325443ea432de0bce05b 100644 (file)
@@ -1933,287 +1933,24 @@ static void call_trans2qpipeinfo(connection_struct *conn,
 static void call_trans2qfilepathinfo(connection_struct *conn,
                                     struct smb_request *req,
                                     unsigned int tran_call,
+                                    uint16_t info_level,
+                                    struct smb_filename *smb_fname,
+                                    struct files_struct *fsp,
+                                    bool delete_pending,
+                                    struct timespec write_time_ts,
                                     char **pparams, int total_params,
                                     char **ppdata, int total_data,
                                     unsigned int max_data_bytes)
 {
        char *params = *pparams;
        char *pdata = *ppdata;
-       uint16_t info_level;
        unsigned int data_size = 0;
        unsigned int param_size = 2;
-       struct smb_filename *smb_fname = NULL;
-       bool delete_pending = False;
-       struct timespec write_time_ts;
-       struct files_struct *dirfsp = NULL;
-       files_struct *fsp = NULL;
-       struct file_id fileid;
        struct ea_list *ea_list = NULL;
        int lock_data_count = 0;
        char *lock_data = NULL;
        size_t fixed_portion;
        NTSTATUS status = NT_STATUS_OK;
-       int ret;
-
-       if (!params) {
-               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-               return;
-       }
-
-       ZERO_STRUCT(write_time_ts);
-
-       if (tran_call == TRANSACT2_QFILEINFO) {
-               if (total_params < 4) {
-                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-                       return;
-               }
-
-               fsp = file_fsp(req, SVAL(params,0));
-               info_level = SVAL(params,2);
-
-               if (IS_IPC(conn)) {
-                       call_trans2qpipeinfo(
-                               conn,
-                               req,
-                               fsp,
-                               info_level,
-                               tran_call,
-                               pparams,
-                               total_params,
-                               ppdata,
-                               total_data,
-                               max_data_bytes);
-                       return;
-               }
-
-               DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
-
-               if (INFO_LEVEL_IS_UNIX(info_level)) {
-                       if (!lp_smb1_unix_extensions()) {
-                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
-                               return;
-                       }
-                       if (!req->posix_pathnames) {
-                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
-                               return;
-                       }
-               }
-
-               /* Initial check for valid fsp ptr. */
-               if (!check_fsp_open(conn, req, fsp)) {
-                       return;
-               }
-
-               smb_fname = fsp->fsp_name;
-
-               if(fsp->fake_file_handle) {
-                       /*
-                        * This is actually for the QUOTA_FAKE_FILE --metze
-                        */
-
-                       /* We know this name is ok, it's already passed the checks. */
-
-               } else if(fsp_get_pathref_fd(fsp) == -1) {
-                       /*
-                        * This is actually a QFILEINFO on a directory
-                        * handle (returned from an NT SMB). NT5.0 seems
-                        * to do this call. JRA.
-                        */
-                       ret = vfs_stat(conn, smb_fname);
-                       if (ret != 0) {
-                               DBG_NOTICE("vfs_stat of %s failed (%s)\n",
-                                        smb_fname_str_dbg(smb_fname),
-                                        strerror(errno));
-                               reply_nterror(req,
-                                       map_nt_error_from_unix(errno));
-                               return;
-                       }
-
-                       if (fsp_getinfo_ask_sharemode(fsp)) {
-                               fileid = vfs_file_id_from_sbuf(
-                                       conn, &smb_fname->st);
-                               get_file_infos(fileid, fsp->name_hash,
-                                              &delete_pending,
-                                              &write_time_ts);
-                       }
-               } else {
-                       /*
-                        * Original code - this is an open file.
-                        */
-                       status = vfs_stat_fsp(fsp);
-                       if (!NT_STATUS_IS_OK(status)) {
-                               DEBUG(3, ("fstat of %s failed (%s)\n",
-                                         fsp_fnum_dbg(fsp), nt_errstr(status)));
-                               reply_nterror(req, status);
-                               return;
-                       }
-                       if (fsp_getinfo_ask_sharemode(fsp)) {
-                               fileid = vfs_file_id_from_sbuf(
-                                       conn, &smb_fname->st);
-                               get_file_infos(fileid, fsp->name_hash,
-                                              &delete_pending,
-                                              &write_time_ts);
-                       }
-               }
-
-       } else {
-               uint32_t name_hash;
-               char *fname = NULL;
-               uint32_t ucf_flags = ucf_flags_from_smb_request(req);
-               NTTIME twrp = 0;
-
-               /* qpathinfo */
-               if (total_params < 7) {
-                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-                       return;
-               }
-
-               info_level = SVAL(params,0);
-
-               DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
-
-               if (INFO_LEVEL_IS_UNIX(info_level)) {
-                       if (!lp_smb1_unix_extensions()) {
-                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
-                               return;
-                       }
-                       if (!req->posix_pathnames) {
-                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
-                               return;
-                       }
-               }
-
-               if (req->posix_pathnames) {
-                       srvstr_get_path_posix(req,
-                               params,
-                               req->flags2,
-                               &fname,
-                               &params[6],
-                               total_params - 6,
-                               STR_TERMINATE,
-                               &status);
-               } else {
-                       srvstr_get_path(req,
-                               params,
-                               req->flags2,
-                               &fname,
-                               &params[6],
-                               total_params - 6,
-                               STR_TERMINATE,
-                               &status);
-               }
-               if (!NT_STATUS_IS_OK(status)) {
-                       reply_nterror(req, status);
-                       return;
-               }
-
-               if (ucf_flags & UCF_GMT_PATHNAME) {
-                       extract_snapshot_token(fname, &twrp);
-               }
-               status = filename_convert_dirfsp(req,
-                                                conn,
-                                                fname,
-                                                ucf_flags,
-                                                twrp,
-                                                &dirfsp,
-                                                &smb_fname);
-               if (!NT_STATUS_IS_OK(status)) {
-                       if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
-                               reply_botherror(req,
-                                               NT_STATUS_PATH_NOT_COVERED,
-                                               ERRSRV, ERRbadpath);
-                               return;
-                       }
-                       reply_nterror(req, status);
-                       return;
-               }
-
-               /*
-                * qpathinfo must operate on an existing file, so we
-                * can exit early if filename_convert_dirfsp() returned the
-                * "new file" NT_STATUS_OK, !VALID_STAT case.
-                */
-
-               if (!VALID_STAT(smb_fname->st)) {
-                       reply_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
-                       return;
-               }
-
-               /*
-                * smb_fname->fsp may be NULL if smb_fname points at a symlink
-                * and we're in POSIX context, so be careful when using fsp
-                * below, it can still be NULL.
-                */
-               fsp = smb_fname->fsp;
-
-               /* If this is a stream, check if there is a delete_pending. */
-               if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
-                   && is_ntfs_stream_smb_fname(smb_fname)) {
-                       struct smb_filename *smb_fname_base;
-
-                       /* Create an smb_filename with stream_name == NULL. */
-                       smb_fname_base = synthetic_smb_fname(
-                                               talloc_tos(),
-                                               smb_fname->base_name,
-                                               NULL,
-                                               NULL,
-                                               smb_fname->twrp,
-                                               smb_fname->flags);
-                       if (smb_fname_base == NULL) {
-                               reply_nterror(req, NT_STATUS_NO_MEMORY);
-                               return;
-                       }
-
-                       ret = vfs_stat(conn, smb_fname_base);
-                       if (ret != 0) {
-                               DBG_NOTICE("vfs_stat of %s failed "
-                                       "(%s)\n",
-                                       smb_fname_str_dbg(smb_fname_base),
-                                       strerror(errno));
-                               TALLOC_FREE(smb_fname_base);
-                               reply_nterror(req,
-                                       map_nt_error_from_unix(errno));
-                               return;
-                       }
-
-                       status = file_name_hash(conn,
-                                       smb_fname_str_dbg(smb_fname_base),
-                                       &name_hash);
-                       if (!NT_STATUS_IS_OK(status)) {
-                               TALLOC_FREE(smb_fname_base);
-                               reply_nterror(req, status);
-                               return;
-                       }
-
-                       fileid = vfs_file_id_from_sbuf(conn,
-                                                      &smb_fname_base->st);
-                       TALLOC_FREE(smb_fname_base);
-                       get_file_infos(fileid, name_hash, &delete_pending, NULL);
-                       if (delete_pending) {
-                               reply_nterror(req, NT_STATUS_DELETE_PENDING);
-                               return;
-                       }
-               }
-
-               status = file_name_hash(conn,
-                               smb_fname_str_dbg(smb_fname),
-                               &name_hash);
-               if (!NT_STATUS_IS_OK(status)) {
-                       reply_nterror(req, status);
-                       return;
-               }
-
-               if (fsp_getinfo_ask_sharemode(fsp)) {
-                       fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
-                       get_file_infos(fileid, name_hash, &delete_pending,
-                                      &write_time_ts);
-               }
-
-               if (delete_pending) {
-                       reply_nterror(req, NT_STATUS_DELETE_PENDING);
-                       return;
-               }
-       }
 
        DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
                 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
@@ -2364,10 +2101,188 @@ static void call_trans2qpathinfo(
        int total_data,
        unsigned int max_data_bytes)
 {
+       char *params = *pparams;
+       uint16_t info_level;
+       struct smb_filename *smb_fname = NULL;
+       bool delete_pending = False;
+       struct timespec write_time_ts = { .tv_sec = 0, };
+       struct files_struct *dirfsp = NULL;
+       files_struct *fsp = NULL;
+       struct file_id fileid;
+       uint32_t name_hash;
+       char *fname = NULL;
+       uint32_t ucf_flags = ucf_flags_from_smb_request(req);
+       NTTIME twrp = 0;
+       NTSTATUS status = NT_STATUS_OK;
+       int ret;
+
+       if (!params) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
+       }
+
+
+       /* qpathinfo */
+       if (total_params < 7) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
+       }
+
+       info_level = SVAL(params,0);
+
+       DBG_NOTICE("TRANSACT2_QPATHINFO: level = %d\n", info_level);
+
+       if (INFO_LEVEL_IS_UNIX(info_level)) {
+               if (!lp_smb1_unix_extensions()) {
+                       reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                       return;
+               }
+               if (!req->posix_pathnames) {
+                       reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                       return;
+               }
+       }
+
+       if (req->posix_pathnames) {
+               srvstr_get_path_posix(req,
+                                     params,
+                                     req->flags2,
+                                     &fname,
+                                     &params[6],
+                                     total_params - 6,
+                                     STR_TERMINATE,
+                                     &status);
+       } else {
+               srvstr_get_path(req,
+                               params,
+                               req->flags2,
+                               &fname,
+                               &params[6],
+                               total_params - 6,
+                               STR_TERMINATE,
+                               &status);
+       }
+       if (!NT_STATUS_IS_OK(status)) {
+               reply_nterror(req, status);
+               return;
+       }
+
+       if (ucf_flags & UCF_GMT_PATHNAME) {
+               extract_snapshot_token(fname, &twrp);
+       }
+       status = filename_convert_dirfsp(req,
+                                        conn,
+                                        fname,
+                                        ucf_flags,
+                                        twrp,
+                                        &dirfsp,
+                                        &smb_fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+                       reply_botherror(req,
+                                       NT_STATUS_PATH_NOT_COVERED,
+                                       ERRSRV, ERRbadpath);
+                       return;
+               }
+               reply_nterror(req, status);
+               return;
+       }
+
+       /*
+        * qpathinfo must operate on an existing file, so we
+        * can exit early if filename_convert_dirfsp() returned the
+        * "new file" NT_STATUS_OK, !VALID_STAT case.
+        */
+
+       if (!VALID_STAT(smb_fname->st)) {
+               reply_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
+               return;
+       }
+
+       /*
+        * smb_fname->fsp may be NULL if smb_fname points at a symlink
+        * and we're in POSIX context, so be careful when using fsp
+        * below, it can still be NULL.
+        */
+       fsp = smb_fname->fsp;
+
+       /* If this is a stream, check if there is a delete_pending. */
+       if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
+           && is_ntfs_stream_smb_fname(smb_fname)) {
+               struct smb_filename *smb_fname_base;
+
+               /* Create an smb_filename with stream_name == NULL. */
+               smb_fname_base = synthetic_smb_fname(
+                       talloc_tos(),
+                       smb_fname->base_name,
+                       NULL,
+                       NULL,
+                       smb_fname->twrp,
+                       smb_fname->flags);
+               if (smb_fname_base == NULL) {
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                       return;
+               }
+
+               ret = vfs_stat(conn, smb_fname_base);
+               if (ret != 0) {
+                       DBG_NOTICE("vfs_stat of %s failed "
+                                  "(%s)\n",
+                                  smb_fname_str_dbg(smb_fname_base),
+                                  strerror(errno));
+                       TALLOC_FREE(smb_fname_base);
+                       reply_nterror(req,
+                                     map_nt_error_from_unix(errno));
+                       return;
+               }
+
+               status = file_name_hash(conn,
+                                       smb_fname_str_dbg(smb_fname_base),
+                                       &name_hash);
+               if (!NT_STATUS_IS_OK(status)) {
+                       TALLOC_FREE(smb_fname_base);
+                       reply_nterror(req, status);
+                       return;
+               }
+
+               fileid = vfs_file_id_from_sbuf(conn,
+                                              &smb_fname_base->st);
+               TALLOC_FREE(smb_fname_base);
+               get_file_infos(fileid, name_hash, &delete_pending, NULL);
+               if (delete_pending) {
+                       reply_nterror(req, NT_STATUS_DELETE_PENDING);
+                       return;
+               }
+       }
+
+       status = file_name_hash(conn,
+                               smb_fname_str_dbg(smb_fname),
+                               &name_hash);
+       if (!NT_STATUS_IS_OK(status)) {
+               reply_nterror(req, status);
+               return;
+       }
+
+       if (fsp_getinfo_ask_sharemode(fsp)) {
+               fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
+               get_file_infos(fileid, name_hash, &delete_pending,
+                              &write_time_ts);
+       }
+
+       if (delete_pending) {
+               reply_nterror(req, NT_STATUS_DELETE_PENDING);
+               return;
+       }
+
        call_trans2qfilepathinfo(
                conn,
                req,
                TRANSACT2_QPATHINFO,
+               info_level,
+               smb_fname,
+               fsp,
+               false,
+               write_time_ts,
                pparams,
                total_params,
                ppdata,
@@ -2384,10 +2299,123 @@ static void call_trans2qfileinfo(
        int total_data,
        unsigned int max_data_bytes)
 {
+       char *params = *pparams;
+       uint16_t info_level;
+       struct smb_filename *smb_fname = NULL;
+       bool delete_pending = False;
+       struct timespec write_time_ts = { .tv_sec = 0, };
+       files_struct *fsp = NULL;
+       struct file_id fileid;
+       NTSTATUS status = NT_STATUS_OK;
+       int ret;
+
+       if (params == NULL) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
+       }
+
+       if (total_params < 4) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
+       }
+
+       fsp = file_fsp(req, SVAL(params,0));
+       info_level = SVAL(params,2);
+
+       if (IS_IPC(conn)) {
+               call_trans2qpipeinfo(
+                       conn,
+                       req,
+                       fsp,
+                       info_level,
+                       TRANSACT2_QFILEINFO,
+                       pparams,
+                       total_params,
+                       ppdata,
+                       total_data,
+                       max_data_bytes);
+               return;
+       }
+
+       DBG_NOTICE("TRANSACT2_QFILEINFO: level = %d\n", info_level);
+
+       if (INFO_LEVEL_IS_UNIX(info_level)) {
+               if (!lp_smb1_unix_extensions()) {
+                       reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                       return;
+               }
+               if (!req->posix_pathnames) {
+                       reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                       return;
+               }
+       }
+
+       /* Initial check for valid fsp ptr. */
+       if (!check_fsp_open(conn, req, fsp)) {
+               return;
+       }
+
+       smb_fname = fsp->fsp_name;
+
+       if(fsp->fake_file_handle) {
+               /*
+                * This is actually for the QUOTA_FAKE_FILE --metze
+                */
+
+               /* We know this name is ok, it's already passed the checks. */
+
+       } else if(fsp_get_pathref_fd(fsp) == -1) {
+               /*
+                * This is actually a QFILEINFO on a directory
+                * handle (returned from an NT SMB). NT5.0 seems
+                * to do this call. JRA.
+                */
+               ret = vfs_stat(conn, smb_fname);
+               if (ret != 0) {
+                       DBG_NOTICE("vfs_stat of %s failed (%s)\n",
+                                  smb_fname_str_dbg(smb_fname),
+                                  strerror(errno));
+                       reply_nterror(req,
+                                     map_nt_error_from_unix(errno));
+                       return;
+               }
+
+               if (fsp_getinfo_ask_sharemode(fsp)) {
+                       fileid = vfs_file_id_from_sbuf(
+                               conn, &smb_fname->st);
+                       get_file_infos(fileid, fsp->name_hash,
+                                      &delete_pending,
+                                      &write_time_ts);
+               }
+       } else {
+               /*
+                * Original code - this is an open file.
+                */
+               status = vfs_stat_fsp(fsp);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(3, ("fstat of %s failed (%s)\n",
+                                 fsp_fnum_dbg(fsp), nt_errstr(status)));
+                       reply_nterror(req, status);
+                       return;
+               }
+               if (fsp_getinfo_ask_sharemode(fsp)) {
+                       fileid = vfs_file_id_from_sbuf(
+                               conn, &smb_fname->st);
+                       get_file_infos(fileid, fsp->name_hash,
+                                      &delete_pending,
+                                      &write_time_ts);
+               }
+       }
+
        call_trans2qfilepathinfo(
                conn,
                req,
                TRANSACT2_QFILEINFO,
+               info_level,
+               smb_fname,
+               fsp,
+               delete_pending,
+               write_time_ts,
                pparams,
                total_params,
                ppdata,