1
0
mirror of https://github.com/samba-team/samba.git synced 2025-03-27 22:50:26 +03:00

Use a common function to parse all pathnames from the wire. This allows

much closer emulation of Win2k3 error return codes.
Jeremy.
(This used to be commit c9f31fafeda6ad79e590276f36e03ecd2e93f818)
This commit is contained in:
Jeremy Allison 2004-03-03 20:55:59 +00:00
parent 7ac1750de2
commit fba5a72249
9 changed files with 383 additions and 136 deletions

View File

@ -577,9 +577,13 @@ static int cmd_dir(void)
int rc;
dir_total = 0;
pstrcpy(mask,cur_dir);
if(mask[strlen(mask)-1]!='\\')
pstrcat(mask,"\\");
if (strcmp(cur_dir, "\\") != 0) {
pstrcpy(mask,cur_dir);
if(mask[strlen(mask)-1]!='\\')
pstrcat(mask,"\\");
} else {
*mask = '\0';
}
if (next_token_nr(NULL,buf,NULL,sizeof(buf))) {
dos_format(p);
@ -1769,6 +1773,38 @@ static int cmd_rename(void)
return 0;
}
#if 0
This will become a hard link call. JRA.
/****************************************************************************
Rename some file using the NT call.
****************************************************************************/
static int cmd_ntrename(void)
{
pstring src,dest;
fstring buf,buf2;
pstrcpy(src,cur_dir);
pstrcpy(dest,cur_dir);
if (!next_token_nr(NULL,buf,NULL,sizeof(buf)) ||
!next_token_nr(NULL,buf2,NULL, sizeof(buf2))) {
d_printf("ntrename <src> <dest>\n");
return 1;
}
pstrcat(src,buf);
pstrcat(dest,buf2);
if (!cli_ntrename(cli, src, dest)) {
d_printf("%s doing an NT rename of files\n",cli_errstr(cli));
return 1;
}
return 0;
}
#endif
/****************************************************************************
Toggle the prompt flag.
****************************************************************************/
@ -2168,6 +2204,10 @@ static struct
{"more",cmd_more,"<remote name> view a remote file with your pager",{COMPL_REMOTE,COMPL_NONE}},
{"mput",cmd_mput,"<mask> put all matching files",{COMPL_REMOTE,COMPL_NONE}},
{"newer",cmd_newer,"<file> only mget files newer than the specified local file",{COMPL_LOCAL,COMPL_NONE}},
#if 0
/* This call will eventually morph into a hard link call. JRA */
{"ntrename",cmd_ntrename,"<src> <dest> NT rename some files",{COMPL_REMOTE,COMPL_REMOTE}},
#endif
{"open",cmd_open,"<mask> open a file",{COMPL_REMOTE,COMPL_NONE}},
{"print",cmd_print,"<file name> print a file",{COMPL_NONE,COMPL_NONE}},
{"printmode",cmd_printmode,"<graphics or text> set the print mode",{COMPL_NONE,COMPL_NONE}},

View File

@ -1151,6 +1151,12 @@ struct bitmap {
/* Flag for NT transact rename call. */
#define RENAME_REPLACE_IF_EXISTS 1
/* flags for SMBntrename call (from Samba4) */
#define RENAME_FLAG_MOVE_CLUSTER_INFORMATION 0x102 /* ???? */
#define RENAME_FLAG_HARD_LINK 0x103
#define RENAME_FLAG_RENAME 0x104
#define RENAME_FLAG_COPY 0x105
/* Filesystem Attributes. */
#define FILE_CASE_SENSITIVE_SEARCH 0x00000001
#define FILE_CASE_PRESERVED_NAMES 0x00000002

View File

@ -245,6 +245,7 @@ copy an IP address from one buffer to another
Make a filename into unix format.
****************************************************************************/
#define IS_DIRECTORY_SEP(c) ((c) == '\\' || (c) == '/')
#define unix_format(fname) string_replace(fname,'\\','/')
#define unix_format_w(fname) string_replace_w(fname, UCS2_CHAR('\\'), UCS2_CHAR('/'))

View File

@ -223,6 +223,44 @@ BOOL cli_rename(struct cli_state *cli, const char *fname_src, const char *fname_
return True;
}
/****************************************************************************
NT Rename a file.
****************************************************************************/
BOOL cli_ntrename(struct cli_state *cli, const char *fname_src, const char *fname_dst)
{
char *p;
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
set_message(cli->outbuf, 4, 0, True);
SCVAL(cli->outbuf,smb_com,SMBntrename);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN | aDIR);
SSVAL(cli->outbuf,smb_vwv1, RENAME_FLAG_RENAME);
p = smb_buf(cli->outbuf);
*p++ = 4;
p += clistr_push(cli, p, fname_src, -1, STR_TERMINATE);
*p++ = 4;
p += clistr_push(cli, p, fname_dst, -1, STR_TERMINATE);
cli_setup_bcc(cli, p);
cli_send_smb(cli);
if (!cli_receive_smb(cli))
return False;
if (cli_is_error(cli))
return False;
return True;
}
/****************************************************************************
Delete a file.
****************************************************************************/

View File

@ -1480,7 +1480,7 @@ BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
NTSTATUS status;
status = rename_internals(conn, new_name, old_name, True);
status = rename_internals(conn, new_name, old_name, 0, True);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
new_name, old_name));
@ -1499,7 +1499,7 @@ BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
NTSTATUS status;
status = rename_internals(conn, new_name, old_name, True);
status = rename_internals(conn, new_name, old_name, 0, True);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
new_name, old_name));
@ -1520,7 +1520,7 @@ BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
NTSTATUS status;
status = rename_internals(conn, new_name, old_name, True);
status = rename_internals(conn, new_name, old_name, 0, True);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
new_name, old_name));
@ -1542,7 +1542,7 @@ BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
NTSTATUS status;
status = rename_internals(conn, new_name, old_name, True);
status = rename_internals(conn, new_name, old_name, 0, True);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
new_name, old_name));
@ -1573,7 +1573,7 @@ BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
NTSTATUS status;
status = rename_internals(conn, new_name, old_name, True);
status = rename_internals(conn, new_name, old_name, 0, True);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
new_name, old_name));

View File

@ -114,29 +114,30 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
DEBUG(5, ("unix_convert called on file \"%s\"\n", name));
/*
* Convert to basic unix format - removing \ chars and cleaning it up.
* Conversion to basic unix format is already done in check_path_syntax().
*/
unix_format(name);
unix_clean_name(name);
/*
* Names must be relative to the root of the service - trim any leading /.
* also trim trailing /'s.
* Names must be relative to the root of the service - any leading /.
* and trailing /'s should have been trimmed by check_path_syntax().
*/
trim_char(name,'/','/');
#ifdef DEVELOPER
SMB_ASSERT(*name != '/');
#endif
/*
* If we trimmed down to a single '\0' character
* then we should use the "." directory to avoid
* searching the cache, but not if we are in a
* printing share.
* As we know this is valid we can return true here.
*/
if (!*name) {
name[0] = '.';
name[1] = '\0';
return(True);
}
/*
@ -154,19 +155,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
if (!case_sensitive && (!case_preserve || (mangle_is_8_3(name, False) && !short_case_preserve)))
strnorm(name);
/*
* If we trimmed down to a single '\0' character
* then we will be using the "." directory.
* As we know this is valid we can return true here.
*/
if(!*name)
return(True);
start = name;
while (start[0] == '.' && start[1] == '/')
start += 2;
pstrcpy(orig_path, name);
if(!case_sensitive && stat_cache_lookup(conn, name, dirpath, &start, &st)) {

View File

@ -537,7 +537,7 @@ static int do_ntcreate_pipe_open(connection_struct *conn,
char *p = NULL;
NTSTATUS status;
srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE,&status);
srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status))
return ERROR_NT(status);
@ -658,7 +658,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
if(!dir_fsp->is_directory) {
srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE,&status);
srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBntcreateX);
return ERROR_NT(status);
@ -700,13 +700,13 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
dir_name_len++;
}
srvstr_get_path(inbuf, &fname[dir_name_len], smb_buf(inbuf), sizeof(fname)-dir_name_len, STR_TERMINATE,&status);
srvstr_get_path(inbuf, &fname[dir_name_len], smb_buf(inbuf), sizeof(fname)-dir_name_len, 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBntcreateX);
return ERROR_NT(status);
}
} else {
srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE,&status);
srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBntcreateX);
return ERROR_NT(status);
@ -1018,8 +1018,7 @@ static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, cha
return ERROR_DOS(ERRDOS,ERRnoaccess);
}
srvstr_pull(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE);
status = check_path_syntax(fname);
srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
@ -1160,7 +1159,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
int smb_open_mode;
int smb_attr;
time_t c_time;
NTSTATUS nt_status;
NTSTATUS status;
DEBUG(5,("call_nt_transact_create\n"));
@ -1226,11 +1225,9 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
return ERROR_DOS(ERRDOS,ERRbadfid);
if(!dir_fsp->is_directory) {
srvstr_pull(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE);
nt_status = check_path_syntax(fname);
if (!NT_STATUS_IS_OK(nt_status)) {
return ERROR_NT(nt_status);
srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
/*
@ -1259,17 +1256,18 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
dir_name_len++;
}
srvstr_pull(inbuf, &fname[dir_name_len], params+53, sizeof(fname)-dir_name_len,
parameter_count-53, STR_TERMINATE);
nt_status = check_path_syntax(fname);
if (!NT_STATUS_IS_OK(nt_status)) {
return ERROR_NT(nt_status);
{
pstring tmpname;
srvstr_get_path(inbuf, tmpname, params+53, sizeof(tmpname), parameter_count-53, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
pstrcat(fname, tmpname);
}
} else {
srvstr_pull(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE);
nt_status = check_path_syntax(fname);
if (!NT_STATUS_IS_OK(nt_status)) {
return ERROR_NT(nt_status);
srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
/*
@ -1395,10 +1393,10 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
* Now try and apply the desired SD.
*/
if (sd_len && !NT_STATUS_IS_OK(nt_status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION))) {
if (sd_len && !NT_STATUS_IS_OK(status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION))) {
close_file(fsp,False);
restore_case_semantics(file_attributes);
return ERROR_NT(nt_status);
return ERROR_NT(status);
}
restore_case_semantics(file_attributes);
@ -1518,17 +1516,31 @@ int reply_ntrename(connection_struct *conn,
pstring newname;
char *p;
NTSTATUS status;
uint16 attrs = SVAL(inbuf,smb_vwv0);
uint16 rename_type = SVAL(inbuf,smb_vwv1);
START_PROFILE(SMBntrename);
if (rename_type != RENAME_FLAG_RENAME) {
END_PROFILE(SMBntrename);
return ERROR_NT(NT_STATUS_ACCESS_DENIED);
}
p = smb_buf(inbuf) + 1;
p += srvstr_get_path(inbuf, name, p, sizeof(name), STR_TERMINATE,&status);
p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBntrename);
return ERROR_NT(status);
}
if( strchr_m(name, ':')) {
/* Can't rename a stream. */
END_PROFILE(SMBntrename);
return ERROR_NT(NT_STATUS_ACCESS_DENIED);
}
p++;
p += srvstr_get_path(inbuf, newname, p, sizeof(newname), STR_TERMINATE,&status);
p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBntrename);
return ERROR_NT(status);
@ -1539,7 +1551,7 @@ int reply_ntrename(connection_struct *conn,
DEBUG(3,("reply_ntrename : %s -> %s\n",name,newname));
status = rename_internals(conn, name, newname, False);
status = rename_internals(conn, name, newname, attrs, False);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBntrename);
return ERROR_NT(status);
@ -1627,14 +1639,13 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o
fsp = file_fsp(params, 0);
replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False;
CHECK_FSP(fsp, conn);
srvstr_pull(inbuf, new_name, params+4, sizeof(new_name), -1, STR_TERMINATE);
status = check_path_syntax(new_name);
srvstr_get_path(inbuf, new_name, params+4, sizeof(new_name), -1, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = rename_internals(conn, fsp->fsp_name,
new_name, replace_if_exists);
new_name, 0, replace_if_exists);
if (!NT_STATUS_IS_OK(status))
return ERROR_NT(status);

View File

@ -40,28 +40,117 @@ extern BOOL global_encrypted_passwords_negotiated;
/****************************************************************************
Ensure we check the path in *exactly* the same way as W2K.
We're assuming here that '/' is not the second byte in any multibyte char
set (a safe assumption). '\\' *may* be the second byte in a multibyte char
set.
****************************************************************************/
NTSTATUS check_path_syntax(const char *name)
static NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
{
while (*name == '\\' || *name == '/')
name++;
if (name[0] == '.' && name[1] == '\0')
return NT_STATUS_OBJECT_NAME_INVALID;
else if (name[0] == '.' && name[1] == '.' &&
(name[2] == '\\' || name [2] == '/' || name[2] == '\0'))
return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
return NT_STATUS_OK;
char *d = destname;
const char *s = srcname;
NTSTATUS ret = NT_STATUS_OK;
while (*s) {
if (IS_DIRECTORY_SEP(*s)) {
/*
* Safe to assume is not the second part of a mb char as this is handled below.
*/
/* Eat multiple '/' or '\\' */
while (IS_DIRECTORY_SEP(*s)) {
s++;
}
if ((d != destname) && (*s != '\0')) {
/* We only care about non-leading or trailing '/' or '\\' */
*d++ = '/';
}
} else if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
/* Uh oh - "../" or "..\\" or "..\0" ! */
/*
* No mb char starts with '.' so we're safe checking the directory separator here.
*/
/* If we just added a '/', delete it. */
if ((d > destname) && (*(d-1) == '/')) {
*(d-1) = '\0';
if (d == (destname + 1)) {
d--;
} else {
d -= 2;
}
}
/* Are we at the start ? Can't go back further if so. */
if (d == destname) {
return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
}
/* Go back one level... */
while (d > destname) {
if (*d == '/')
break;
d--;
}
s += 3;
} else if ((s[0] == '.') && IS_DIRECTORY_SEP(s[1])) {
/*
* No mb char starts with '.' so we're safe checking the directory separator here.
*/
/* "./" or ".\\" fails with a different error depending on where it is... */
if (s == srcname) {
ret = NT_STATUS_OBJECT_NAME_INVALID;
} else {
if (s[2] == '\0') {
return NT_STATUS_INVALID_PARAMETER;
}
ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
}
s++;
} else {
if ((*s & 0x80) && IS_DIRECTORY_SEP(s[1])) {
/*
* Potential mb char with second char a directory separator.
* All the encodings we care about are 2 byte only, so do a
* conversion to unicode. If the 2 byte char won't convert then
* it's probably a one byte char with a real directory separator
* following, so only copy one byte. If it will convert then
* copy both bytes.
*/
uint16 ucs2_val;
if (convert_string(CH_UNIX, CH_UCS2, s, 2, &ucs2_val, 2) == 2) {
*d++ = *s++;
}
}
/* Just copy the char (or the second byte of the mb char). */
*d++ = *s++;
}
}
*d = '\0';
return ret;
}
/****************************************************************************
Pull a string and check the path - provide for error return.
****************************************************************************/
size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, int flags, NTSTATUS *err)
size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err)
{
size_t ret = srvstr_pull_buf( inbuf, dest, src, dest_len, flags);
*err = check_path_syntax(dest);
pstring tmppath;
char *tmppath_ptr = tmppath;
#ifdef DEVELOPER
SMB_ASSERT(dest_len == sizeof(pstring));
#endif
size_t ret;
if (src_len == 0) {
ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
} else {
ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
}
*err = check_path_syntax(dest, tmppath);
return ret;
}
@ -414,7 +503,7 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
START_PROFILE(SMBchkpth);
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE, &status);
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBchkpth);
return ERROR_NT(status);
@ -492,7 +581,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
START_PROFILE(SMBgetatr);
p = smb_buf(inbuf) + 1;
p += srvstr_get_path(inbuf, fname, p, sizeof(fname), STR_TERMINATE,&status);
p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBgetatr);
return ERROR_NT(status);
@ -567,7 +656,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
START_PROFILE(SMBsetatr);
p = smb_buf(inbuf) + 1;
p += srvstr_get_path(inbuf, fname, p, sizeof(fname), STR_TERMINATE,&status);
p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBsetatr);
return ERROR_NT(status);
@ -695,7 +784,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
maxentries = SVAL(inbuf,smb_vwv0);
dirtype = SVAL(inbuf,smb_vwv1);
p = smb_buf(inbuf) + 1;
p += srvstr_get_path(inbuf, path, p, sizeof(path), STR_TERMINATE,&nt_status);
p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status);
if (!NT_STATUS_IS_OK(nt_status)) {
END_PROFILE(SMBsearch);
return ERROR_NT(nt_status);
@ -873,7 +962,7 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
outsize = set_message(outbuf,1,0,True);
p = smb_buf(inbuf) + 1;
p += srvstr_get_path(inbuf, path, p, sizeof(path), STR_TERMINATE,&err);
p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err);
if (!NT_STATUS_IS_OK(err)) {
END_PROFILE(SMBfclose);
return ERROR_NT(err);
@ -925,7 +1014,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
share_mode = SVAL(inbuf,smb_vwv0);
srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE,&status);
srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBopen);
return ERROR_NT(status);
@ -1017,7 +1106,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
}
/* XXXX we need to handle passed times, sattr and flags */
srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE,&status);
srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBopenX);
return ERROR_NT(status);
@ -1133,7 +1222,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
com = SVAL(inbuf,smb_com);
createmode = SVAL(inbuf,smb_vwv0);
srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), STR_TERMINATE,&status);
srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBcreate);
return ERROR_NT(status);
@ -1202,7 +1291,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
START_PROFILE(SMBctemp);
createmode = SVAL(inbuf,smb_vwv0);
srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE,&status);
srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBctemp);
return ERROR_NT(status);
@ -1456,17 +1545,27 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
while ((dname = ReadDirName(dirptr))) {
pstring fname;
pstrcpy(fname,dname);
BOOL sys_direntry = False;
/* Quick check for "." and ".." */
if (fname[0] == '.') {
if (!fname[1] || (fname[1] == '.' && !fname[2])) {
continue;
if ((dirtype & aDIR)) {
sys_direntry = True;
} else {
continue;
}
}
}
if(!mask_match(fname, mask, case_sensitive))
continue;
if (sys_direntry) {
error = NT_STATUS_OBJECT_NAME_INVALID;
continue;
}
slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
error = can_delete(fname,conn,dirtype,bad_path);
if (!NT_STATUS_IS_OK(error))
@ -1501,7 +1600,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
dirtype = SVAL(inbuf,smb_vwv0);
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE,&status);
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBunlink);
return ERROR_NT(status);
@ -3054,7 +3153,7 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
NTSTATUS status;
START_PROFILE(SMBmkdir);
srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE,&status);
srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBmkdir);
return ERROR_NT(status);
@ -3224,7 +3323,7 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
NTSTATUS status;
START_PROFILE(SMBrmdir);
srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE,&status);
srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBrmdir);
return ERROR_NT(status);
@ -3464,15 +3563,16 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *
code.
****************************************************************************/
NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BOOL replace_if_exists)
NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
{
pstring directory;
pstring mask;
pstring newname_last_component;
pstring last_component_src;
pstring last_component_dest;
char *p;
BOOL has_wild;
BOOL bad_path1 = False;
BOOL bad_path2 = False;
BOOL bad_path_src = False;
BOOL bad_path_dest = False;
int count=0;
NTSTATUS error = NT_STATUS_OK;
BOOL rc = True;
@ -3483,8 +3583,29 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BO
ZERO_STRUCT(sbuf1);
ZERO_STRUCT(sbuf2);
rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
rcdest = unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
if (!rc && bad_path_src) {
if (ms_has_wild(last_component_src))
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
return NT_STATUS_OBJECT_PATH_NOT_FOUND;
}
/* Quick check for "." and ".." */
if (last_component_src[0] == '.') {
if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
return NT_STATUS_OBJECT_NAME_INVALID;
}
}
rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
/* Quick check for "." and ".." */
if (last_component_dest[0] == '.') {
if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
return NT_STATUS_OBJECT_NAME_INVALID;
}
}
/*
* Split the old name into directory and last component
@ -3540,9 +3661,9 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BO
}
DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
case_sensitive, case_preserve, short_case_preserve, directory,
newname, newname_last_component, is_short_name));
newname, last_component_dest, is_short_name));
/*
* Check for special case with case preserving and not
@ -3558,7 +3679,7 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
((short_case_preserve == True) &&
(is_short_name == True))) &&
strcsequal(directory, newname)) {
pstring newname_modified_last_component;
pstring modified_last_component;
/*
* Get the last component of the modified name.
@ -3566,15 +3687,15 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
* character above.
*/
p = strrchr_m(newname,'/');
pstrcpy(newname_modified_last_component,p+1);
pstrcpy(modified_last_component,p+1);
if(strcsequal(newname_modified_last_component,
newname_last_component) == False) {
if(strcsequal(modified_last_component,
last_component_dest) == False) {
/*
* Replace the modified last component with
* the original.
*/
pstrcpy(p+1, newname_last_component);
pstrcpy(p+1, last_component_dest);
}
}
@ -3609,14 +3730,9 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
return error;
}
/* Quick check for "." and ".." */
if (!bad_path2 && newname_last_component[0] == '.') {
if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
DEBUG(10,("rename_internals: newname_last_component = '.' or '..'\n"));
return NT_STATUS_ACCESS_DENIED;
}
}
if (!rcdest && bad_path2) {
if (!rcdest && bad_path_dest) {
if (ms_has_wild(last_component_dest))
return NT_STATUS_OBJECT_NAME_INVALID;
return NT_STATUS_OBJECT_PATH_NOT_FOUND;
}
@ -3669,17 +3785,6 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
const char *dname;
pstring destname;
/* Quick check for "." and ".." */
if (!bad_path2 && newname_last_component[0] == '.') {
if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
DEBUG(10,("rename_internals: newname_last_component = '.' or '..'\n"));
return NT_STATUS_ACCESS_DENIED;
}
}
if (!rcdest && bad_path2) {
return NT_STATUS_OBJECT_PATH_NOT_FOUND;
}
if (check_name(directory,conn))
dirptr = OpenDir(conn, directory, True);
@ -3692,19 +3797,29 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
while ((dname = ReadDirName(dirptr))) {
pstring fname;
BOOL sysdir_entry = False;
pstrcpy(fname,dname);
/* Quick check for "." and ".." */
if (fname[0] == '.') {
if (!fname[1] || (fname[1] == '.' && !fname[2])) {
continue;
if (attrs & aDIR) {
sysdir_entry = True;
} else {
continue;
}
}
}
if(!mask_match(fname, mask, case_sensitive))
continue;
if (sysdir_entry) {
error = NT_STATUS_OBJECT_NAME_INVALID;
continue;
}
error = NT_STATUS_ACCESS_DENIED;
slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
if (!vfs_object_exist(conn, fname, &sbuf1)) {
@ -3735,11 +3850,20 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
if (!SMB_VFS_RENAME(conn,fname,destname)) {
rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
count++;
error = NT_STATUS_OK;
}
DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
}
CloseDir(dirptr);
}
if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
if (!rcdest && bad_path_dest) {
if (ms_has_wild(last_component_dest))
return NT_STATUS_OBJECT_NAME_INVALID;
return NT_STATUS_OBJECT_PATH_NOT_FOUND;
}
}
}
if (count == 0 && NT_STATUS_IS_OK(error)) {
@ -3760,18 +3884,19 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
pstring name;
pstring newname;
char *p;
uint16 attrs = SVAL(inbuf,smb_vwv0);
NTSTATUS status;
START_PROFILE(SMBmv);
p = smb_buf(inbuf) + 1;
p += srvstr_get_path(inbuf, name, p, sizeof(name), STR_TERMINATE,&status);
p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBmv);
return ERROR_NT(status);
}
p++;
p += srvstr_get_path(inbuf, newname, p, sizeof(newname), STR_TERMINATE,&status);
p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBmv);
return ERROR_NT(status);
@ -3782,7 +3907,7 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
status = rename_internals(conn, name, newname, False);
status = rename_internals(conn, name, newname, attrs, False);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBmv);
return ERROR_NT(status);
@ -3909,12 +4034,12 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
*directory = *mask = 0;
p = smb_buf(inbuf);
p += srvstr_get_path(inbuf, name, p, sizeof(name), STR_TERMINATE,&status);
p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBcopy);
return ERROR_NT(status);
}
p += srvstr_get_path(inbuf, newname, p, sizeof(newname), STR_TERMINATE,&status);
p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBcopy);
return ERROR_NT(status);
@ -4074,7 +4199,7 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
return ERROR_DOS(ERRDOS,ERRnoaccess);
}
srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE,&status);
srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(pathworks_setdir);
return ERROR_NT(status);

View File

@ -228,6 +228,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
int smb_action = 0;
BOOL bad_path = False;
files_struct *fsp;
NTSTATUS status;
/*
* Ensure we have enough parameters to perform the operation.
@ -248,7 +249,10 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
open_size = IVAL(params,14);
pname = &params[28];
srvstr_pull(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE);
srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
fname,open_mode, open_attr, open_ofun, open_size));
@ -939,6 +943,7 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb
int space_remaining;
BOOL bad_path = False;
SMB_STRUCT_STAT sbuf;
NTSTATUS ntstatus = NT_STATUS_OK;
if (total_params < 12)
return(ERROR_DOS(ERRDOS,ERRinvalidparam));
@ -968,7 +973,10 @@ close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n",
return(ERROR_DOS(ERRDOS,ERRunknownlevel));
}
srvstr_pull(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE);
srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus);
if (!NT_STATUS_IS_OK(ntstatus)) {
return ERROR_NT(ntstatus);
}
RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
@ -1151,13 +1159,17 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu
BOOL dont_descend = False;
BOOL out_of_space = False;
int space_remaining;
NTSTATUS ntstatus = NT_STATUS_OK;
if (total_params < 12)
return(ERROR_DOS(ERRDOS,ERRinvalidparam));
*mask = *directory = *resume_name = 0;
srvstr_pull(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE);
srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus);
if (!NT_STATUS_IS_OK(ntstatus)) {
return ERROR_NT(ntstatus);
}
DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
close_after_request=%d, close_if_end = %d requires_resume_key = %d \
@ -1909,6 +1921,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
desired_access = fsp->desired_access;
}
} else {
NTSTATUS status = NT_STATUS_OK;
/* qpathinfo */
if (total_params < 6)
return(ERROR_DOS(ERRDOS,ERRinvalidparam));
@ -1917,7 +1931,10 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
srvstr_pull(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE);
srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
@ -2483,6 +2500,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
mode_t unixmode = 0;
NTSTATUS status = NT_STATUS_OK;
if (!params)
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
@ -2540,7 +2558,10 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
return(ERROR_DOS(ERRDOS,ERRinvalidparam));
info_level = SVAL(params,0);
srvstr_pull(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE);
srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
unix_convert(fname,conn,0,&bad_path,&sbuf);
/*
@ -2761,7 +2782,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
{
BOOL delete_on_close;
NTSTATUS status;
if (total_data < 1)
return(ERROR_DOS(ERRDOS,ERRinvalidparam));
@ -2948,7 +2968,10 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
if (VALID_STAT(sbuf))
return(ERROR_DOS(ERRDOS,ERRbadpath));
srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
srvstr_get_path(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
return(UNIXERROR(ERRDOS,ERRnoaccess));
@ -2973,7 +2996,10 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
if (VALID_STAT(sbuf))
return(ERROR_DOS(ERRDOS,ERRbadpath));
srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
srvstr_get_path(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
return(UNIXERROR(ERRDOS,ERRnoaccess));
@ -2996,7 +3022,6 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
pstring newname;
pstring base_name;
char *p;
NTSTATUS status;
if (total_data < 12)
return(ERROR_DOS(ERRDOS,ERRinvalidparam));
@ -3004,10 +3029,13 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
overwrite = (CVAL(pdata,0) ? True : False);
root_fid = IVAL(pdata,4);
len = IVAL(pdata,8);
srvstr_pull(inbuf, newname, &pdata[12], sizeof(newname), len, 0);
srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
/* Check the new name has no '\' characters. */
if (strchr_m(newname, '\\') || strchr_m(newname, '/'))
/* Check the new name has no '/' characters. */
if (strchr_m(newname, '/'))
return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
@ -3028,10 +3056,11 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
} else {
DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
fname, newname ));
status = rename_internals(conn, fname, base_name, overwrite);
status = rename_internals(conn, fname, base_name, 0, overwrite);
}
if (!NT_STATUS_IS_OK(status))
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
process_pending_change_notify_queue((time_t)0);
SSVAL(params,0,0);
send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
@ -3171,6 +3200,7 @@ static int call_trans2mkdir(connection_struct *conn,
int ret = -1;
SMB_STRUCT_STAT sbuf;
BOOL bad_path = False;
NTSTATUS status = NT_STATUS_OK;
if (!CAN_WRITE(conn))
return ERROR_DOS(ERRSRV,ERRaccess);
@ -3178,7 +3208,10 @@ static int call_trans2mkdir(connection_struct *conn,
if (total_params < 4)
return(ERROR_DOS(ERRDOS,ERRinvalidparam));
srvstr_pull(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE);
srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
@ -3290,6 +3323,7 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
pstring pathname;
int reply_size = 0;
int max_referral_level;
NTSTATUS status = NT_STATUS_OK;
DEBUG(10,("call_trans2getdfsreferral\n"));
@ -3301,7 +3335,10 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
if(!lp_host_msdfs())
return ERROR_DOS(ERRDOS,ERRbadfunc);
srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
srvstr_get_path(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
return UNIXERROR(ERRDOS,ERRbadfile);