return;
}
- status = resolve_dfspath(ctx, conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
- name,
- &name);
+ DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
+
+ status = filename_convert(ctx,
+ conn,
+ req->flags2 & FLAGS2_DFS_PATHNAMES,
+ name,
+ &smb_fname,
+ &name);
+
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
goto path_err;
}
- DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
-
- status = unix_convert(ctx, conn, name, &smb_fname, 0);
- if (!NT_STATUS_IS_OK(status)) {
- goto path_err;
- }
-
- status = get_full_smb_filename(ctx, smb_fname, &name);
- if (!NT_STATUS_IS_OK(status)) {
- goto path_err;
- }
-
- status = check_name(conn, name);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
- goto path_err;
- }
-
if (!VALID_STAT(smb_fname->st) &&
- (SMB_VFS_STAT(conn, name, &smb_fname->st) != 0)) {
- DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
+ (SMB_VFS_STAT(conn, smb_fname) != 0)) {
+ DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
+ smb_fname_str_dbg(smb_fname), strerror(errno)));
status = map_nt_error_from_unix(errno);
goto path_err;
}
}
reply_outbuf(req, 0, 0);
- out:
- TALLOC_FREE(smb_fname);
- END_PROFILE(SMBcheckpath);
- return;
path_err:
-
- TALLOC_FREE(smb_fname);
-
- END_PROFILE(SMBcheckpath);
-
/* We special case this - as when a Windows machine
is parsing a path is steps through the components
one at a time - if a component fails it expects
*/
reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
ERRDOS, ERRbadpath);
- return;
+ goto out;
}
reply_nterror(req, status);
+
+ out:
+ TALLOC_FREE(smb_fname);
+ END_PROFILE(SMBcheckpath);
+ return;
}
/****************************************************************************
goto out;
}
- status = resolve_dfspath(ctx, conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
- fname,
- &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);
- goto out;
- }
- reply_nterror(req, status);
- goto out;
- }
-
/* dos smetimes asks for a stat of "" - it returns a "hidden directory"
under WfWg - weird! */
if (*fname == '\0') {
size = 0;
mtime = 0;
} else {
- status = unix_convert(ctx, conn, fname, &smb_fname, 0);
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- goto out;
- }
- status = get_full_smb_filename(ctx, smb_fname, &fname);
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- goto out;
- }
- status = check_name(conn, fname);
+ status = filename_convert(ctx,
+ conn,
+ req->flags2 & FLAGS2_DFS_PATHNAMES,
+ fname,
+ &smb_fname,
+ &fname);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
+ ERRSRV, ERRbadpath);
+ goto out;
+ }
reply_nterror(req, status);
goto out;
}
if (!VALID_STAT(smb_fname->st) &&
- (SMB_VFS_STAT(conn, fname, &smb_fname->st) != 0)) {
- DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
+ (SMB_VFS_STAT(conn, smb_fname) != 0)) {
+ DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
+ smb_fname_str_dbg(smb_fname),
+ strerror(errno)));
reply_unixerror(req, ERRDOS,ERRbadfile);
goto out;
}
SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
}
- DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
+ DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
+ smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
out:
TALLOC_FREE(smb_fname);
+ TALLOC_FREE(fname);
END_PROFILE(SMBgetatr);
return;
}
goto out;
}
- status = resolve_dfspath(ctx, conn,
+ status = filename_convert(ctx,
+ conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
fname,
+ &smb_fname,
&fname);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
goto out;
}
- status = unix_convert(ctx, conn, fname, &smb_fname, 0);
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- goto out;
- }
-
- status = get_full_smb_filename(ctx, smb_fname, &fname);
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- goto out;
- }
-
- status = check_name(conn, fname);
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- goto out;
- }
-
if (fname[0] == '.' && fname[1] == '\0') {
/*
* Not sure here is the right place to catch this
return;
}
+/*
+ * Utility function to split the filename from the directory.
+ */
+static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
+ char **fname_dir_out,
+ char **fname_mask_out)
+{
+ const char *p = NULL;
+ char *fname_dir = NULL;
+ char *fname_mask = NULL;
+
+ p = strrchr_m(fname_in, '/');
+ if (!p) {
+ fname_dir = talloc_strdup(ctx, ".");
+ fname_mask = talloc_strdup(ctx, fname_in);
+ } else {
+ fname_dir = talloc_strndup(ctx, fname_in,
+ PTR_DIFF(p, fname_in));
+ fname_mask = talloc_strdup(ctx, p+1);
+ }
+
+ if (!fname_dir || !fname_mask) {
+ TALLOC_FREE(fname_dir);
+ TALLOC_FREE(fname_mask);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ *fname_dir_out = fname_dir;
+ *fname_mask_out = fname_mask;
+ return NT_STATUS_OK;
+}
+
/****************************************************************************
Reply to a search.
Can be called from SMBsearch, SMBffirst or SMBfunique.
void reply_search(struct smb_request *req)
{
connection_struct *conn = req->conn;
+ char *path = NULL;
const char *mask = NULL;
char *directory = NULL;
char *fname = NULL;
bool finished = False;
const char *p;
int status_len;
- char *path = NULL;
char status[21];
int dptr_num= -1;
bool check_descend = False;
return;
}
- nt_status = resolve_dfspath_wcard(ctx, conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
- path,
- &path,
- &mask_contains_wcard);
- if (!NT_STATUS_IS_OK(nt_status)) {
- if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
- reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
- ERRSRV, ERRbadpath);
- END_PROFILE(SMBsearch);
- return;
- }
- reply_nterror(req, nt_status);
- END_PROFILE(SMBsearch);
- return;
- }
-
p++;
status_len = SVAL(p, 0);
p += 2;
if (status_len == 0) {
struct smb_filename *smb_fname = NULL;
+ nt_status = resolve_dfspath_wcard(ctx, conn,
+ req->flags2 & FLAGS2_DFS_PATHNAMES,
+ path,
+ &path,
+ &mask_contains_wcard);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
+ reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
+ ERRSRV, ERRbadpath);
+ END_PROFILE(SMBsearch);
+ return;
+ }
+ reply_nterror(req, nt_status);
+ END_PROFILE(SMBsearch);
+ return;
+ }
+
nt_status = unix_convert(ctx, conn, path, &smb_fname,
UCF_ALLOW_WCARD_LCOMP);
if (!NT_STATUS_IS_OK(nt_status)) {
void reply_open(struct smb_request *req)
{
connection_struct *conn = req->conn;
+ struct smb_filename *smb_fname = NULL;
char *fname = NULL;
uint32 fattr=0;
SMB_OFF_T size = 0;
time_t mtime=0;
int info;
- SMB_STRUCT_STAT sbuf;
files_struct *fsp;
int oplock_request;
int deny_mode;
START_PROFILE(SMBopen);
- SET_STAT_INVALID(sbuf);
-
if (req->wct < 2) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- END_PROFILE(SMBopen);
- return;
+ goto out;
}
oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- END_PROFILE(SMBopen);
- return;
+ goto out;
+ }
+
+ status = filename_convert(ctx,
+ conn,
+ req->flags2 & FLAGS2_DFS_PATHNAMES,
+ fname,
+ &smb_fname,
+ &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);
+ goto out;
+ }
+ reply_nterror(req, status);
+ goto out;
}
if (!map_open_params_to_ntcreate(
fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask,
&share_mode, &create_disposition, &create_options)) {
reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
- END_PROFILE(SMBopen);
- return;
+ goto out;
}
status = SMB_VFS_CREATE_FILE(
conn, /* conn */
req, /* req */
0, /* root_dir_fid */
- fname, /* fname */
- CFF_DOS_PATH, /* create_file_flags */
+ smb_fname, /* fname */
access_mask, /* access_mask */
share_mode, /* share_access */
create_disposition, /* create_disposition*/
NULL, /* sd */
NULL, /* ea_list */
&fsp, /* result */
- &info, /* pinfo */
- &sbuf); /* psbuf */
+ &info); /* pinfo */
if (!NT_STATUS_IS_OK(status)) {
if (open_was_deferred(req->mid)) {
/* We have re-scheduled this call. */
- END_PROFILE(SMBopen);
- return;
+ goto out;
}
reply_openerror(req, status);
- END_PROFILE(SMBopen);
- return;
+ goto out;
}
- size = sbuf.st_ex_size;
- fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
- mtime = convert_timespec_to_time_t(sbuf.st_ex_mtime);
+ size = smb_fname->st.st_ex_size;
+ fattr = dos_mode(conn,fsp->fsp_name,&smb_fname->st);
+ mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
if (fattr & aDIR) {
DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name));
close_file(req, fsp, ERROR_CLOSE);
reply_doserror(req, ERRDOS,ERRnoaccess);
- END_PROFILE(SMBopen);
- return;
+ goto out;
}
reply_outbuf(req, 7, 0);
SCVAL(req->outbuf,smb_flg,
CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
}
+ out:
+ TALLOC_FREE(smb_fname);
END_PROFILE(SMBopen);
return;
}
void reply_open_and_X(struct smb_request *req)
{
connection_struct *conn = req->conn;
+ struct smb_filename *smb_fname = NULL;
char *fname = NULL;
uint16 open_flags;
int deny_mode;
int smb_ofun;
uint32 fattr=0;
int mtime=0;
- SMB_STRUCT_STAT sbuf;
int smb_action = 0;
files_struct *fsp;
NTSTATUS status;
if (req->wct < 15) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- END_PROFILE(SMBopenX);
- return;
+ goto out;
}
- SET_STAT_INVALID(sbuf);
-
open_flags = SVAL(req->vwv+2, 0);
deny_mode = SVAL(req->vwv+3, 0);
smb_attr = SVAL(req->vwv+5, 0);
} else {
reply_doserror(req, ERRSRV, ERRaccess);
}
- END_PROFILE(SMBopenX);
- return;
+ goto out;
}
/* XXXX we need to handle passed times, sattr and flags */
STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- END_PROFILE(SMBopenX);
- return;
+ goto out;
+ }
+
+ status = filename_convert(ctx,
+ conn,
+ req->flags2 & FLAGS2_DFS_PATHNAMES,
+ fname,
+ &smb_fname,
+ &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);
+ goto out;
+ }
+ reply_nterror(req, status);
+ goto out;
}
if (!map_open_params_to_ntcreate(
fname, deny_mode, smb_ofun, &access_mask,
&share_mode, &create_disposition, &create_options)) {
reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
- END_PROFILE(SMBopenX);
- return;
+ goto out;
}
status = SMB_VFS_CREATE_FILE(
conn, /* conn */
req, /* req */
0, /* root_dir_fid */
- fname, /* fname */
- CFF_DOS_PATH, /* create_file_flags */
+ smb_fname, /* fname */
access_mask, /* access_mask */
share_mode, /* share_access */
create_disposition, /* create_disposition*/
NULL, /* sd */
NULL, /* ea_list */
&fsp, /* result */
- &smb_action, /* pinfo */
- &sbuf); /* psbuf */
+ &smb_action); /* pinfo */
if (!NT_STATUS_IS_OK(status)) {
- END_PROFILE(SMBopenX);
if (open_was_deferred(req->mid)) {
/* We have re-scheduled this call. */
- return;
+ goto out;
}
reply_openerror(req, status);
- return;
+ goto out;
}
/* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
close_file(req, fsp, ERROR_CLOSE);
reply_nterror(req, NT_STATUS_DISK_FULL);
- END_PROFILE(SMBopenX);
- return;
+ goto out;
}
retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
if (retval < 0) {
close_file(req, fsp, ERROR_CLOSE);
reply_nterror(req, NT_STATUS_DISK_FULL);
- END_PROFILE(SMBopenX);
- return;
+ goto out;
}
- sbuf.st_ex_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
+ smb_fname->st.st_ex_size =
+ SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st);
}
- fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
- mtime = convert_timespec_to_time_t(sbuf.st_ex_mtime);
+ fattr = dos_mode(conn,fsp->fsp_name,&smb_fname->st);
+ mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
if (fattr & aDIR) {
close_file(req, fsp, ERROR_CLOSE);
reply_doserror(req, ERRDOS, ERRnoaccess);
- END_PROFILE(SMBopenX);
- return;
+ goto out;
}
/* If the caller set the extended oplock request bit
} else {
srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
}
- SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_ex_size);
+ SIVAL(req->outbuf,smb_vwv6,(uint32)smb_fname->st.st_ex_size);
SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
SSVAL(req->outbuf,smb_vwv11,smb_action);
SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
}
- END_PROFILE(SMBopenX);
chain_reply(req);
+ out:
+ TALLOC_FREE(smb_fname);
+ END_PROFILE(SMBopenX);
return;
}
void reply_mknew(struct smb_request *req)
{
connection_struct *conn = req->conn;
+ struct smb_filename *smb_fname = NULL;
char *fname = NULL;
uint32 fattr = 0;
struct smb_file_time ft;
files_struct *fsp;
int oplock_request = 0;
- SMB_STRUCT_STAT sbuf;
NTSTATUS status;
uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
START_PROFILE(SMBcreate);
ZERO_STRUCT(ft);
- SET_STAT_INVALID(sbuf);
if (req->wct < 3) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- END_PROFILE(SMBcreate);
- return;
+ goto out;
}
fattr = SVAL(req->vwv+0, 0);
STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- END_PROFILE(SMBcreate);
- return;
+ goto out;
+ }
+
+ status = filename_convert(ctx,
+ conn,
+ req->flags2 & FLAGS2_DFS_PATHNAMES,
+ fname,
+ &smb_fname,
+ &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);
+ goto out;
+ }
+ reply_nterror(req, status);
+ goto out;
}
if (fattr & aVOLID) {
conn, /* conn */
req, /* req */
0, /* root_dir_fid */
- fname, /* fname */
- CFF_DOS_PATH, /* create_file_flags */
+ smb_fname, /* fname */
access_mask, /* access_mask */
share_mode, /* share_access */
create_disposition, /* create_disposition*/
NULL, /* sd */
NULL, /* ea_list */
&fsp, /* result */
- NULL, /* pinfo */
- &sbuf); /* psbuf */
+ NULL); /* pinfo */
if (!NT_STATUS_IS_OK(status)) {
- END_PROFILE(SMBcreate);
if (open_was_deferred(req->mid)) {
/* We have re-scheduled this call. */
- return;
+ goto out;
}
reply_openerror(req, status);
- return;
+ goto out;
}
- ft.atime = sbuf.st_ex_atime; /* atime. */
- status = smb_set_file_time(conn, fsp, fsp->fsp_name, &sbuf, &ft, true);
+ ft.atime = smb_fname->st.st_ex_atime; /* atime. */
+ status = smb_set_file_time(conn, fsp, fsp->fsp_name, &smb_fname->st,
+ &ft, true);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBcreate);
- reply_openerror(req, status);
- return;
+ goto out;
}
reply_outbuf(req, 1, 0);
DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
fsp->fsp_name, fsp->fh->fd, (unsigned int)fattr ) );
+ out:
+ TALLOC_FREE(smb_fname);
END_PROFILE(SMBcreate);
return;
}
goto out;
}
- status = resolve_dfspath(ctx, conn,
+ status = filename_convert(ctx, conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
fname,
+ &smb_fname,
&fname);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
goto out;
}
- status = unix_convert(ctx, conn, fname, &smb_fname, 0);
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- goto out;
- }
-
- status = get_full_smb_filename(ctx, smb_fname, &fname);
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- goto out;
- }
-
- status = check_name(conn, fname);
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- goto out;
- }
-
- tmpfd = mkstemp(fname);
+ tmpfd = mkstemp(smb_fname->base_name);
if (tmpfd == -1) {
reply_unixerror(req, ERRDOS, ERRnoaccess);
goto out;
}
- SET_STAT_INVALID(smb_fname->st);
- SMB_VFS_STAT(conn, fname, &smb_fname->st);
+ SMB_VFS_STAT(conn, smb_fname);
/* We should fail if file does not exist. */
status = SMB_VFS_CREATE_FILE(
conn, /* conn */
req, /* req */
0, /* root_dir_fid */
- fname, /* fname */
- 0, /* create_file_flags */
+ smb_fname, /* fname */
FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
FILE_OPEN, /* create_disposition*/
NULL, /* sd */
NULL, /* ea_list */
&fsp, /* result */
- NULL, /* pinfo */
- &smb_fname->st); /* psbuf */
+ NULL); /* pinfo */
/* close fd from mkstemp() */
close(tmpfd);
static NTSTATUS do_unlink(connection_struct *conn,
struct smb_request *req,
- const char *fname,
+ struct smb_filename *smb_fname,
uint32 dirtype)
{
- SMB_STRUCT_STAT sbuf;
+ char *fname = NULL;
uint32 fattr;
files_struct *fsp;
uint32 dirtype_orig = dirtype;
return NT_STATUS_MEDIA_WRITE_PROTECTED;
}
- if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
+ if (SMB_VFS_LSTAT(conn, smb_fname) != 0) {
return map_nt_error_from_unix(errno);
}
- fattr = dos_mode(conn,fname,&sbuf);
+ status = get_full_smb_filename(smb_fname, smb_fname, &fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ fattr = dos_mode(conn, fname, &smb_fname->st);
+ TALLOC_FREE(fname);
if (dirtype & FILE_ATTRIBUTE_NORMAL) {
dirtype = aDIR|aARCH|aRONLY;
(conn, /* conn */
req, /* req */
0, /* root_dir_fid */
- fname, /* fname */
- 0, /* create_file_flags */
+ smb_fname, /* fname */
DELETE_ACCESS, /* access_mask */
FILE_SHARE_NONE, /* share_access */
FILE_OPEN, /* create_disposition*/
NULL, /* sd */
NULL, /* ea_list */
&fsp, /* result */
- NULL, /* pinfo */
- &sbuf); /* psbuf */
+ NULL); /* pinfo */
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
uint32 dirtype, const char *name_in, bool has_wild)
{
struct smb_filename *smb_fname = NULL;
- const char *directory = NULL;
- char *mask = NULL;
- char *name = NULL;
- char *p = NULL;
+ char *fname_dir = NULL;
+ char *fname_mask = NULL;
int count=0;
NTSTATUS status = NT_STATUS_OK;
- SMB_STRUCT_STAT st;
TALLOC_CTX *ctx = talloc_tos();
status = unix_convert(ctx, conn, name_in, &smb_fname,
has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
if (!NT_STATUS_IS_OK(status)) {
- return status;
+ goto out;
}
- status = get_full_smb_filename(ctx, smb_fname, &name);
+ /* Split up the directory from the filename/mask. */
+ status = split_fname_dir_mask(ctx, smb_fname->base_name,
+ &fname_dir, &fname_mask);
if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(smb_fname);
- return status;
- }
-
- p = strrchr_m(name,'/');
- if (!p) {
- directory = talloc_strdup(ctx, ".");
- if (!directory) {
- TALLOC_FREE(smb_fname);
- return NT_STATUS_NO_MEMORY;
- }
- mask = name;
- } else {
- *p = 0;
- directory = name;
- mask = p+1;
+ goto out;
}
/*
* Tine Smukavec <valentin.smukavec@hermes.si>.
*/
- if (!VALID_STAT(smb_fname->st) && mangle_is_mangled(mask,conn->params)) {
+ if (!VALID_STAT(smb_fname->st) &&
+ mangle_is_mangled(fname_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_mask,
+ &new_mask, conn->params);
if (new_mask) {
- mask = new_mask;
+ TALLOC_FREE(fname_mask);
+ fname_mask = new_mask;
}
}
- TALLOC_FREE(smb_fname);
if (!has_wild) {
- directory = talloc_asprintf(ctx,
- "%s/%s",
- directory,
- mask);
- if (!directory) {
- return NT_STATUS_NO_MEMORY;
+
+ /*
+ * Only one file needs to be unlinked. Append the mask back
+ * onto the directory.
+ */
+ TALLOC_FREE(smb_fname->base_name);
+ smb_fname->base_name = talloc_asprintf(smb_fname,
+ "%s/%s",
+ fname_dir,
+ fname_mask);
+ if (!smb_fname->base_name) {
+ status = NT_STATUS_NO_MEMORY;
+ goto out;
}
if (dirtype == 0) {
dirtype = FILE_ATTRIBUTE_NORMAL;
}
- status = check_name(conn, directory);
+ status = check_name(conn, smb_fname->base_name);
if (!NT_STATUS_IS_OK(status)) {
- return status;
+ goto out;
}
- status = do_unlink(conn, req, directory, dirtype);
+ status = do_unlink(conn, req, smb_fname, dirtype);
if (!NT_STATUS_IS_OK(status)) {
- return status;
+ goto out;
}
count++;
const char *dname;
if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
- return NT_STATUS_OBJECT_NAME_INVALID;
+ status = NT_STATUS_OBJECT_NAME_INVALID;
+ goto out;
}
- if (strequal(mask,"????????.???")) {
- mask[0] = '*';
- mask[1] = '\0';
+ if (strequal(fname_mask,"????????.???")) {
+ TALLOC_FREE(fname_mask);
+ fname_mask = talloc_strdup(ctx, "*");
+ if (!fname_mask) {
+ status = NT_STATUS_NO_MEMORY;
+ goto out;
+ }
}
- status = check_name(conn, directory);
+ status = check_name(conn, fname_dir);
if (!NT_STATUS_IS_OK(status)) {
- return status;
+ goto out;
}
- dir_hnd = OpenDir(talloc_tos(), conn, directory, mask,
+ dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
dirtype);
if (dir_hnd == NULL) {
- return map_nt_error_from_unix(errno);
+ status = map_nt_error_from_unix(errno);
+ goto out;
}
/* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
status = NT_STATUS_NO_SUCH_FILE;
- while ((dname = ReadDirName(dir_hnd, &offset, &st))) {
- char *fname = NULL;
-
- if (!is_visible_file(conn, directory, dname, &st,
- true))
- {
+ while ((dname = ReadDirName(dir_hnd, &offset,
+ &smb_fname->st))) {
+ if (!is_visible_file(conn, fname_dir, dname,
+ &smb_fname->st, true)) {
continue;
}
continue;
}
- if(!mask_match(dname, mask, conn->case_sensitive)) {
+ if(!mask_match(dname, fname_mask,
+ conn->case_sensitive)) {
continue;
}
- fname = talloc_asprintf(ctx, "%s/%s",
- directory,
- dname);
- if (!fname) {
- return NT_STATUS_NO_MEMORY;
+ TALLOC_FREE(smb_fname->base_name);
+ smb_fname->base_name =
+ talloc_asprintf(smb_fname, "%s/%s",
+ fname_dir, dname);
+
+ if (!smb_fname->base_name) {
+ TALLOC_FREE(dir_hnd);
+ status = NT_STATUS_NO_MEMORY;
+ goto out;
}
- status = check_name(conn, fname);
+ status = check_name(conn, smb_fname->base_name);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(dir_hnd);
- return status;
+ goto out;
}
- status = do_unlink(conn, req, fname, dirtype);
+ status = do_unlink(conn, req, smb_fname, dirtype);
if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(fname);
continue;
}
count++;
DEBUG(3,("unlink_internals: successful unlink [%s]\n",
- fname));
-
- TALLOC_FREE(fname);
+ smb_fname->base_name));
}
TALLOC_FREE(dir_hnd);
}
status = map_nt_error_from_unix(errno);
}
+ out:
+ TALLOC_FREE(smb_fname);
+ TALLOC_FREE(fname_dir);
+ TALLOC_FREE(fname_mask);
return status;
}
goto out;
}
- status = resolve_dfspath(ctx, conn,
+ status = filename_convert(ctx, conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
directory,
+ &smb_dname,
&directory);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
goto out;
}
- status = unix_convert(ctx, conn, directory, &smb_dname, 0);
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- 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);
- 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)));
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);
while((dname = ReadDirName(dir_hnd, &offset, &st))) {
char *fullname = NULL;
+ struct smb_filename *smb_fname = NULL;
+ NTSTATUS status;
if (ISDOT(dname) || ISDOTDOT(dname)) {
continue;
dname);
if (!fullname) {
errno = ENOMEM;
- ret = False;
- break;
+ goto err_break;
}
- if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
- ret = False;
- break;
+ status = create_synthetic_smb_fname(talloc_tos(), fullname,
+ NULL, NULL, &smb_fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto err_break;
+ }
+
+ if(SMB_VFS_LSTAT(conn, smb_fname) != 0) {
+ goto err_break;
}
- if(st.st_ex_mode & S_IFDIR) {
+ if(smb_fname->st.st_ex_mode & S_IFDIR) {
if(!recursive_rmdir(ctx, conn, fullname)) {
- ret = False;
- break;
+ goto err_break;
}
if(SMB_VFS_RMDIR(conn,fullname) != 0) {
- ret = False;
- break;
+ goto err_break;
}
} else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
- ret = False;
- break;
+ goto err_break;
}
+ TALLOC_FREE(smb_fname);
+ TALLOC_FREE(fullname);
+ continue;
+ err_break:
+ TALLOC_FREE(smb_fname);
TALLOC_FREE(fullname);
+ ret = false;
+ break;
}
TALLOC_FREE(dir_hnd);
return ret;
SMB_STRUCT_STAT st;
/* Might be a symlink. */
- if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
+ if(vfs_lstat_smb_fname(conn, directory, &st) != 0) {
return map_nt_error_from_unix(errno);
}
if (S_ISLNK(st.st_ex_mode)) {
/* Is what it points to a directory ? */
- if(SMB_VFS_STAT(conn, directory, &st) != 0) {
+ if(vfs_stat_smb_fname(conn, directory, &st) != 0) {
return map_nt_error_from_unix(errno);
}
if (!(S_ISDIR(st.st_ex_mode))) {
break;
}
- if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
+ if(vfs_lstat_smb_fname(conn,fullname, &st) != 0) {
break;
}
if(st.st_ex_mode & S_IFDIR) {
goto out;
}
- status = resolve_dfspath(ctx, conn,
+ status = filename_convert(ctx, conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
directory,
+ &smb_dname,
&directory);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
goto out;
}
- status = unix_convert(ctx, conn, directory, &smb_dname, 0);
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- 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);
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- goto out;
- }
-
dptr_closepath(directory, req->smbpid);
status = rmdir_internals(ctx, conn, directory);
if (!NT_STATUS_IS_OK(status)) {
return NT_STATUS_INVALID_PARAMETER;
}
- /*
- * Have vfs_object_exist also fill sbuf1
- */
- dst_exists = vfs_object_exist(conn, newname, &sbuf1);
+ dst_exists = vfs_stat_smb_fname(conn, newname, &sbuf1) == 0;
if(!replace_if_exists && dst_exists) {
DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
} else {
int ret = -1;
if (fsp->posix_open) {
- ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf);
+ ret = vfs_lstat_smb_fname(conn,fsp->fsp_name,&sbuf);
} else {
- ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf);
+
+ ret = vfs_stat_smb_fname(conn,fsp->fsp_name,&sbuf);
}
if (ret == -1) {
return map_nt_error_from_unix(errno);
bool dest_has_wild,
uint32_t access_mask)
{
- struct smb_filename *smb_fname = NULL;
- struct smb_filename *smb_fname_new = NULL;
- char *directory = NULL;
- char *mask = NULL;
- char *name = NULL;
- char *newname = NULL;
- char *p;
+ struct smb_filename *smb_fname_src = NULL;
+ struct smb_filename *smb_fname_dst = NULL;
+ char *fname_src_dir = NULL;
+ char *fname_src_mask = NULL;
int count=0;
NTSTATUS status = NT_STATUS_OK;
struct smb_Dir *dir_hnd = NULL;
int create_options = 0;
bool posix_pathnames = lp_posix_pathnames();
- status = unix_convert(ctx, conn, name_in, &smb_fname,
+ status = unix_convert(ctx, conn, name_in, &smb_fname_src,
src_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
if (!NT_STATUS_IS_OK(status)) {
goto out;
}
- status = get_full_smb_filename(ctx, smb_fname, &name);
- if (!NT_STATUS_IS_OK(status)) {
- goto out;
- }
-
- status = unix_convert(ctx, conn, newname_in, &smb_fname_new,
+ status = unix_convert(ctx, conn, newname_in, &smb_fname_dst,
(UCF_SAVE_LCOMP |
(dest_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0)));
if (!NT_STATUS_IS_OK(status)) {
goto out;
}
- status = get_full_smb_filename(ctx, smb_fname_new, &newname);
- if (!NT_STATUS_IS_OK(status)) {
- goto out;
- }
-
/*
* Split the old name into directory and last component
* strings. Note that unix_convert may have stripped off a
* as this is checked in resolve_wildcards().
*/
- p = strrchr_m(name,'/');
- if (!p) {
- directory = talloc_strdup(ctx, ".");
- if (!directory) {
- status = NT_STATUS_NO_MEMORY;
- goto out;
- }
- mask = name;
- } else {
- *p = 0;
- directory = talloc_strdup(ctx, name);
- if (!directory) {
- status = NT_STATUS_NO_MEMORY;
- goto out;
- }
- mask = p+1;
- *p = '/'; /* Replace needed for exceptional test below. */
+ /* Split up the directory from the filename/mask. */
+ status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
+ &fname_src_dir, &fname_src_mask);
+ if (!NT_STATUS_IS_OK(status)) {
+ status = NT_STATUS_NO_MEMORY;
+ goto out;
}
/*
* 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);
if (new_mask) {
- mask = new_mask;
+ TALLOC_FREE(fname_src_mask);
+ fname_src_mask = new_mask;
}
}
if (!src_has_wild) {
files_struct *fsp;
+ char *fname_dst = NULL;
/*
- * No wildcards - just process the one file.
+ * Only one file needs to be renamied. Append the mask back
+ * onto the directory.
*/
- /* Add a terminating '/' to the directory name. */
- directory = talloc_asprintf_append(directory,
- "/%s",
- mask);
- if (!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) {
status = NT_STATUS_NO_MEMORY;
goto out;
}
- /* Ensure newname contains a '/' also */
- if(strrchr_m(newname,'/') == 0) {
- newname = talloc_asprintf(ctx,
- "./%s",
- newname);
- if (!newname) {
+ /* Ensure dst fname contains a '/' also */
+ if(strrchr_m(smb_fname_dst->base_name, '/') == 0) {
+ char *tmp;
+ tmp = talloc_asprintf(smb_fname_dst, "./%s",
+ smb_fname_dst->base_name);
+ if (!tmp) {
status = NT_STATUS_NO_MEMORY;
goto out;
}
+ TALLOC_FREE(smb_fname_dst->base_name);
+ smb_fname_dst->base_name = tmp;
}
DEBUG(3, ("rename_internals: case_sensitive = %d, "
"directory = %s, newname = %s, "
"last_component_dest = %s\n",
conn->case_sensitive, conn->case_preserve,
- conn->short_case_preserve, directory,
- newname, smb_fname_new->original_lcomp));
+ conn->short_case_preserve,
+ smb_fname_str_dbg(smb_fname_src),
+ smb_fname_str_dbg(smb_fname_dst),
+ smb_fname_dst->original_lcomp));
/* The dest name still may have wildcards. */
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)) {
DEBUG(6, ("rename_internals: resolve_wildcards "
- "%s %s failed\n",
- directory,
- newname));
+ "%s %s failed\n",
+ smb_fname_src->base_name,
+ smb_fname_dst->base_name));
status = NT_STATUS_NO_MEMORY;
goto out;
}
- newname = mod_newname;
+ TALLOC_FREE(smb_fname_dst->base_name);
+ smb_fname_dst->base_name = fname_dst_mod;
}
- ZERO_STRUCT(smb_fname->st);
+ ZERO_STRUCT(smb_fname_src->st);
if (posix_pathnames) {
- SMB_VFS_LSTAT(conn, directory, &smb_fname->st);
+ SMB_VFS_LSTAT(conn, smb_fname_src);
} else {
- SMB_VFS_STAT(conn, directory, &smb_fname->st);
+ SMB_VFS_STAT(conn, smb_fname_src);
}
- if (S_ISDIR(smb_fname->st.st_ex_mode)) {
+ if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
create_options |= FILE_DIRECTORY_FILE;
}
conn, /* conn */
req, /* req */
0, /* root_dir_fid */
- directory, /* fname */
- 0, /* create_file_flags */
+ smb_fname_src, /* fname */
access_mask, /* access_mask */
(FILE_SHARE_READ | /* share_access */
FILE_SHARE_WRITE),
NULL, /* sd */
NULL, /* ea_list */
&fsp, /* result */
- NULL, /* pinfo */
- &smb_fname->st); /* psbuf */
+ NULL); /* pinfo */
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3, ("Could not open rename source %s: %s\n",
- directory, nt_errstr(status)));
+ smb_fname_str_dbg(smb_fname_src),
+ nt_errstr(status)));
goto out;
}
- status = rename_internals_fsp(conn, fsp, newname,
- smb_fname_new->original_lcomp,
+ status = get_full_smb_filename(ctx, smb_fname_dst, &fname_dst);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto out;
+ }
+
+ status = rename_internals_fsp(conn, fsp, fname_dst,
+ smb_fname_dst->original_lcomp,
attrs, replace_if_exists);
+ TALLOC_FREE(fname_dst);
+
close_file(req, fsp, NORMAL_CLOSE);
DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
- nt_errstr(status), directory,newname));
+ nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
+ smb_fname_str_dbg(smb_fname_dst)));
goto out;
}
/*
* Wildcards - process each file that matches.
*/
- if (strequal(mask,"????????.???")) {
- mask[0] = '*';
- mask[1] = '\0';
+ if (strequal(fname_src_mask, "????????.???")) {
+ TALLOC_FREE(fname_src_mask);
+ fname_src_mask = talloc_strdup(ctx, "*");
+ if (!fname_src_mask) {
+ status = NT_STATUS_NO_MEMORY;
+ goto out;
+ }
}
- status = check_name(conn, directory);
+ status = check_name(conn, fname_src_dir);
if (!NT_STATUS_IS_OK(status)) {
goto out;
}
- dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, attrs);
+ dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
+ attrs);
if (dir_hnd == NULL) {
status = map_nt_error_from_unix(errno);
goto out;
* - gentest fix. JRA
*/
- while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname->st))) {
+ while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st))) {
files_struct *fsp = NULL;
- char *fname = NULL;
+ char *fname_dst = NULL;
char *destname = NULL;
bool sysdir_entry = False;
}
}
- 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;
}
break;
}
- fname = talloc_asprintf(ctx,
- "%s/%s",
- directory,
- dname);
- if (!fname) {
+ 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) {
status = 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)) {
DEBUG(6, ("resolve_wildcards %s %s failed\n",
- fname, destname));
- TALLOC_FREE(fname);
+ smb_fname_src->base_name, destname));
continue;
}
if (!destname) {
goto out;
}
- ZERO_STRUCT(smb_fname->st);
+ TALLOC_FREE(smb_fname_dst->base_name);
+ smb_fname_dst->base_name = destname;
+
+ ZERO_STRUCT(smb_fname_src->st);
if (posix_pathnames) {
- SMB_VFS_LSTAT(conn, fname, &smb_fname->st);
+ SMB_VFS_LSTAT(conn, smb_fname_src);
} else {
- SMB_VFS_STAT(conn, fname, &smb_fname->st);
+ SMB_VFS_STAT(conn, smb_fname_src);
}
create_options = 0;
- if (S_ISDIR(smb_fname->st.st_ex_mode)) {
+ if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
create_options |= FILE_DIRECTORY_FILE;
}
conn, /* conn */
req, /* req */
0, /* root_dir_fid */
- fname, /* fname */
- 0, /* create_file_flags */
+ smb_fname_src, /* fname */
access_mask, /* access_mask */
(FILE_SHARE_READ | /* share_access */
FILE_SHARE_WRITE),
NULL, /* sd */
NULL, /* ea_list */
&fsp, /* result */
- NULL, /* pinfo */
- &smb_fname->st); /* psbuf */
+ NULL); /* pinfo */
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
"returned %s rename %s -> %s\n",
- nt_errstr(status), directory, newname));
+ nt_errstr(status),
+ smb_fname_str_dbg(smb_fname_src),
+ smb_fname_str_dbg(smb_fname_dst)));
break;
}
- status = rename_internals_fsp(conn, fsp, destname, dname,
+ status = get_full_smb_filename(ctx, smb_fname_dst, &fname_dst);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto out;
+ }
+
+ status = rename_internals_fsp(conn, fsp, fname_dst, dname,
attrs, replace_if_exists);
+ TALLOC_FREE(fname_dst);
+
close_file(req, fsp, NORMAL_CLOSE);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3, ("rename_internals_fsp returned %s for "
"rename %s -> %s\n", nt_errstr(status),
- directory, newname));
+ smb_fname_str_dbg(smb_fname_src),
+ smb_fname_str_dbg(smb_fname_dst)));
break;
}
count++;
DEBUG(3,("rename_internals: doing rename on %s -> "
- "%s\n",fname,destname));
+ "%s\n", smb_fname_str_dbg(smb_fname_src),
+ smb_fname_str_dbg(smb_fname_src)));
- TALLOC_FREE(fname);
- TALLOC_FREE(destname);
}
TALLOC_FREE(dir_hnd);
}
out:
- TALLOC_FREE(smb_fname);
- TALLOC_FREE(smb_fname_new);
+ TALLOC_FREE(smb_fname_src);
+ TALLOC_FREE(smb_fname_dst);
+ TALLOC_FREE(fname_src_dir);
+ TALLOC_FREE(fname_src_mask);
return status;
}
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;
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;
}
}
+ /* Open the src file for reading. */
status = SMB_VFS_CREATE_FILE(
conn, /* conn */
NULL, /* req */
0, /* root_dir_fid */
- src, /* fname */
- 0, /* create_file_flags */
+ smb_fname_src, /* fname */
FILE_GENERIC_READ, /* access_mask */
FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
FILE_OPEN, /* create_disposition*/
NULL, /* sd */
NULL, /* ea_list */
&fsp1, /* result */
- NULL, /* pinfo */
- &src_sbuf); /* psbuf */
+ NULL); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(dest);
- return status;
+ goto out;
}
- dosattrs = dos_mode(conn, src, &src_sbuf);
- if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
- ZERO_STRUCTP(&sbuf2);
+ status = get_full_smb_filename(talloc_tos(), smb_fname_src, &fname_src);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto out;
+ }
+
+ dosattrs = dos_mode(conn, fname_src, &smb_fname_src->st);
+
+ TALLOC_FREE(fname_src);
+
+ if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -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 */
- 0, /* create_file_flags */
+ smb_fname_dst, /* fname */
FILE_GENERIC_WRITE, /* access_mask */
FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
new_create_disposition, /* create_disposition*/
NULL, /* sd */
NULL, /* ea_list */
&fsp2, /* result */
- NULL, /* pinfo */
- &sbuf2); /* psbuf */
-
- TALLOC_FREE(dest);
+ NULL); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
close_file(NULL, fsp1, ERROR_CLOSE);
- return status;
+ goto out;
}
if ((ofun&3) == 1) {
* 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
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);
+ return status;
}
/****************************************************************************
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;
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 */
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)) {
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)) {
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);
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,'/');
- if (p != NULL) {
- directory = talloc_strndup(ctx, name, PTR_DIFF(p, name));
- mask = p+1;
- } else {
- directory = talloc_strdup(ctx, "./");
- mask = name;
- }
-
- if (!directory) {
+ /* Split up the directory from the filename/mask. */
+ status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
+ &fname_src_dir, &fname_src_mask);
+ if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
goto out;
}
* 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);
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);
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) {
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);
}
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;
}
int ret = -1;
if (fsp->posix_open) {
- ret = SMB_VFS_LSTAT(conn, fsp->fsp_name, &sbuf);
+ ret = vfs_lstat_smb_fname(conn, fsp->fsp_name, &sbuf);
} else {
- ret = SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf);
+ ret = vfs_stat_smb_fname(conn, fsp->fsp_name, &sbuf);
}
if (ret == -1) {
status = map_nt_error_from_unix(errno);