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,
- ¶ms[6],
- total_params - 6,
- STR_TERMINATE,
- &status);
- } else {
- srvstr_get_path(req,
- params,
- req->flags2,
- &fname,
- ¶ms[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),
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,
+ ¶ms[6],
+ total_params - 6,
+ STR_TERMINATE,
+ &status);
+ } else {
+ srvstr_get_path(req,
+ params,
+ req->flags2,
+ &fname,
+ ¶ms[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,
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,