Takes care of the cases where a Windows program is parsing a pathname
component by component and expects 2 different errors.
ERRbadpath - if a component in the path doesn't exist.
ERRbaddirectory - if a component in the path exists but is not a directory.
Extra error code added to smb.h to support this.
Code based on suggestions from "Christian Groessler" <chris@fast-ag.de>.
Jeremy (jallison@whistle.com)
mode_t unix_mode(int cnum,int dosmode);
int dos_mode(int cnum,char *path,struct stat *sbuf);
int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st);
mode_t unix_mode(int cnum,int dosmode);
int dos_mode(int cnum,char *path,struct stat *sbuf);
int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st);
-BOOL unix_convert(char *name,int cnum,pstring saved_last_component);
+BOOL unix_convert(char *name,int cnum,pstring saved_last_component, BOOL *bad_path);
int disk_free(char *path,int *bsize,int *dfree,int *dsize);
int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize);
BOOL check_name(char *name,int cnum);
int disk_free(char *path,int *bsize,int *dfree,int *dsize);
int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize);
BOOL check_name(char *name,int cnum);
#define ERRbadshare 32 /* Share mode on file conflict with open mode */
#define ERRlock 33 /* Lock request conflicts with existing lock */
#define ERRfilexists 80 /* File in operation already exists */
#define ERRbadshare 32 /* Share mode on file conflict with open mode */
#define ERRlock 33 /* Lock request conflicts with existing lock */
#define ERRfilexists 80 /* File in operation already exists */
+#define ERRunknownlevel 124
#define ERRbadpipe 230 /* Named pipe invalid */
#define ERRpipebusy 231 /* All instances of pipe are busy */
#define ERRpipeclosing 232 /* named pipe close in progress */
#define ERRnotconnected 233 /* No process on other end of named pipe */
#define ERRmoredata 234 /* More data to be returned */
#define ERRbadpipe 230 /* Named pipe invalid */
#define ERRpipebusy 231 /* All instances of pipe are busy */
#define ERRpipeclosing 232 /* named pipe close in progress */
#define ERRnotconnected 233 /* No process on other end of named pipe */
#define ERRmoredata 234 /* More data to be returned */
+#define ERRbaddirectory 267 /* Invalid directory name in a path. */
#define ERROR_EAS_DIDNT_FIT 275 /* Extended attributes didn't fit */
#define ERROR_EAS_NOT_SUPPORTED 282 /* Extended attributes not suppored */
#define ERROR_EAS_DIDNT_FIT 275 /* Extended attributes didn't fit */
#define ERROR_EAS_NOT_SUPPORTED 282 /* Extended attributes not suppored */
-#define ERRunknownlevel 124
#define ERRunknownipc 2142
#define ERRunknownipc 2142
/* Size of buffer to use when moving files across filesystems. */
#define COPYBUF_SIZE (8*1024)
/* Size of buffer to use when moving files across filesystems. */
#define COPYBUF_SIZE (8*1024)
+/* Integers used to override error codes. */
+extern int unix_ERR_class;
+extern int unix_ERR_code;
BOOL directory_exist(char *dname,struct stat *st)
{
struct stat st2;
BOOL directory_exist(char *dname,struct stat *st)
{
struct stat st2;
if (!st) st = &st2;
if (sys_stat(dname,st) != 0)
return(False);
if (!st) st = &st2;
if (sys_stat(dname,st) != 0)
return(False);
- return(S_ISDIR(st->st_mode));
+ ret = S_ISDIR(st->st_mode);
+ if(!ret)
+ errno = ENOTDIR;
+ return ret;
}
/*******************************************************************
}
/*******************************************************************
struct stat sbuf;
int smb_action = 0;
int i;
struct stat sbuf;
int smb_action = 0;
int i;
/* XXXX we need to handle passed times, sattr and flags */
strcpy(fname,smb_buf(inbuf));
/* XXXX we need to handle passed times, sattr and flags */
strcpy(fname,smb_buf(inbuf));
Connections[cnum].read_only = 0;
smb_ofun |= 0x10; /* Add Create it not exists flag */
Connections[cnum].read_only = 0;
smb_ofun |= 0x10; /* Add Create it not exists flag */
- unix_convert(fname,cnum,0);
+ unix_convert(fname,cnum,0,&bad_path);
fnum = find_free_file();
if (fnum < 0)
fnum = find_free_file();
if (fnum < 0)
&rmode,&smb_action);
if (!Files[fnum].open)
&rmode,&smb_action);
if (!Files[fnum].open)
+ {
+ /* Change the error code if bad_path was set. */
+ if((errno == ENOENT) && bad_path)
+ {
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadpath;
+ }
return(UNIXERROR(ERRDOS,ERRnoaccess));
return(UNIXERROR(ERRDOS,ERRnoaccess));
if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
close_file(fnum);
if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
close_file(fnum);
int cnum,mode;
pstring name;
BOOL ok = False;
int cnum,mode;
pstring name;
BOOL ok = False;
+ BOOL bad_path = False;
+
cnum = SVAL(inbuf,smb_tid);
strcpy(name,smb_buf(inbuf) + 1);
cnum = SVAL(inbuf,smb_tid);
strcpy(name,smb_buf(inbuf) + 1);
- unix_convert(name,cnum,0);
+ unix_convert(name,cnum,0,&bad_path);
mode = SVAL(inbuf,smb_vwv0);
mode = SVAL(inbuf,smb_vwv0);
ok = directory_exist(name,NULL);
if (!ok)
ok = directory_exist(name,NULL);
if (!ok)
+ {
+ /* 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
+ ERRbadpath, not ERRbadfile.
+ */
+ if(errno == ENOENT)
+ {
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadpath;
+ }
return(UNIXERROR(ERRDOS,ERRbadpath));
return(UNIXERROR(ERRDOS,ERRbadpath));
outsize = set_message(outbuf,0,0,True);
DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode));
outsize = set_message(outbuf,0,0,True);
DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode));
int mode=0;
uint32 size=0;
time_t mtime=0;
int mode=0;
uint32 size=0;
time_t mtime=0;
+ BOOL bad_path = False;
+
cnum = SVAL(inbuf,smb_tid);
strcpy(fname,smb_buf(inbuf) + 1);
cnum = SVAL(inbuf,smb_tid);
strcpy(fname,smb_buf(inbuf) + 1);
- unix_convert(fname,cnum,0);
+ unix_convert(fname,cnum,0,&bad_path);
/* dos smetimes asks for a stat of "" - it returns a "hidden directory"
under WfWg - weird! */
/* dos smetimes asks for a stat of "" - it returns a "hidden directory"
under WfWg - weird! */
}
else
if (check_name(fname,cnum))
}
else
if (check_name(fname,cnum))
+ {
+ if (sys_stat(fname,&sbuf) == 0)
- if (sys_stat(fname,&sbuf) == 0)
- {
- mode = dos_mode(cnum,fname,&sbuf);
- size = sbuf.st_size;
- mtime = sbuf.st_mtime;
- if (mode & aDIR)
- size = 0;
- ok = True;
- }
- else
- DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
+ mode = dos_mode(cnum,fname,&sbuf);
+ size = sbuf.st_size;
+ mtime = sbuf.st_mtime;
+ if (mode & aDIR)
+ size = 0;
+ ok = True;
+ }
+ else
+ DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
+ {
+ if((errno == ENOENT) && bad_path)
+ {
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadpath;
+ }
+
return(UNIXERROR(ERRDOS,ERRbadfile));
return(UNIXERROR(ERRDOS,ERRbadfile));
outsize = set_message(outbuf,10,0,True);
SSVAL(outbuf,smb_vwv0,mode);
outsize = set_message(outbuf,10,0,True);
SSVAL(outbuf,smb_vwv0,mode);
BOOL ok=False;
int mode;
time_t mtime;
BOOL ok=False;
int mode;
time_t mtime;
+ BOOL bad_path = False;
+
cnum = SVAL(inbuf,smb_tid);
strcpy(fname,smb_buf(inbuf) + 1);
cnum = SVAL(inbuf,smb_tid);
strcpy(fname,smb_buf(inbuf) + 1);
- unix_convert(fname,cnum,0);
+ unix_convert(fname,cnum,0,&bad_path);
mode = SVAL(inbuf,smb_vwv0);
mtime = make_unix_date3(inbuf+smb_vwv1);
mode = SVAL(inbuf,smb_vwv0);
mtime = make_unix_date3(inbuf+smb_vwv1);
ok = set_filetime(fname,mtime);
if (!ok)
ok = set_filetime(fname,mtime);
if (!ok)
+ {
+ if((errno == ENOENT) && bad_path)
+ {
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadpath;
+ }
+
return(UNIXERROR(ERRDOS,ERRnoaccess));
return(UNIXERROR(ERRDOS,ERRnoaccess));
outsize = set_message(outbuf,0,0,True);
DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode));
outsize = set_message(outbuf,0,0,True);
DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode));
BOOL check_descend = False;
BOOL expect_close = False;
BOOL can_open = True;
BOOL check_descend = False;
BOOL expect_close = False;
BOOL can_open = True;
*mask = *directory = *fname = 0;
*mask = *directory = *fname = 0;
strcpy(directory,smb_buf(inbuf)+1);
strcpy(dir2,smb_buf(inbuf)+1);
strcpy(directory,smb_buf(inbuf)+1);
strcpy(dir2,smb_buf(inbuf)+1);
- unix_convert(directory,cnum,0);
+ unix_convert(directory,cnum,0,&bad_path);
unix_format(dir2);
if (!check_name(directory,cnum))
unix_format(dir2);
if (!check_name(directory,cnum))
p = strrchr(dir2,'/');
if (p == NULL)
p = strrchr(dir2,'/');
if (p == NULL)
- {strcpy(mask,dir2);*dir2 = 0;}
+ {
+ strcpy(mask,dir2);
+ *dir2 = 0;
+ }
- {*p = 0;strcpy(mask,p+1);}
+ {
+ *p = 0;
+ strcpy(mask,p+1);
+ }
p = strrchr(directory,'/');
if (!p)
p = strrchr(directory,'/');
if (!p)
if (strlen(directory) == 0)
if (strlen(directory) == 0)
- strcpy(directory,"./");
+ strcpy(directory,"./");
bzero(status,21);
CVAL(status,0) = dirtype;
}
bzero(status,21);
CVAL(status,0) = dirtype;
}
if (dptr_num < 0)
{
if(dptr_num == -2)
if (dptr_num < 0)
{
if(dptr_num == -2)
+ {
+ if((errno == ENOENT) && bad_path)
+ {
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadpath;
+ }
return (UNIXERROR(ERRDOS,ERRnofids));
return (UNIXERROR(ERRDOS,ERRnofids));
return(ERROR(ERRDOS,ERRnofids));
}
}
return(ERROR(ERRDOS,ERRnofids));
}
}
int unixmode;
int rmode=0;
struct stat sbuf;
int unixmode;
int rmode=0;
struct stat sbuf;
+ BOOL bad_path = False;
+
cnum = SVAL(inbuf,smb_tid);
share_mode = SVAL(inbuf,smb_vwv0);
strcpy(fname,smb_buf(inbuf)+1);
cnum = SVAL(inbuf,smb_tid);
share_mode = SVAL(inbuf,smb_vwv0);
strcpy(fname,smb_buf(inbuf)+1);
- unix_convert(fname,cnum,0);
+ unix_convert(fname,cnum,0,&bad_path);
fnum = find_free_file();
if (fnum < 0)
return(ERROR(ERRSRV,ERRnofids));
if (!check_name(fname,cnum))
fnum = find_free_file();
if (fnum < 0)
return(ERROR(ERRSRV,ERRnofids));
if (!check_name(fname,cnum))
+ {
+ if((errno == ENOENT) && bad_path)
+ {
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadpath;
+ }
return(UNIXERROR(ERRDOS,ERRnoaccess));
return(UNIXERROR(ERRDOS,ERRnoaccess));
unixmode = unix_mode(cnum,aARCH);
open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,&rmode,NULL);
if (!Files[fnum].open)
unixmode = unix_mode(cnum,aARCH);
open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,&rmode,NULL);
if (!Files[fnum].open)
+ {
+ if((errno == ENOENT) && bad_path)
+ {
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadpath;
+ }
return(UNIXERROR(ERRDOS,ERRnoaccess));
return(UNIXERROR(ERRDOS,ERRnoaccess));
if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
close_file(fnum);
if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
close_file(fnum);
int size=0,fmode=0,mtime=0,rmode=0;
struct stat sbuf;
int smb_action = 0;
int size=0,fmode=0,mtime=0,rmode=0;
struct stat sbuf;
int smb_action = 0;
/* If it's an IPC, pass off the pipe handler. */
if (IS_IPC(cnum))
/* If it's an IPC, pass off the pipe handler. */
if (IS_IPC(cnum))
/* XXXX we need to handle passed times, sattr and flags */
strcpy(fname,smb_buf(inbuf));
/* XXXX we need to handle passed times, sattr and flags */
strcpy(fname,smb_buf(inbuf));
- unix_convert(fname,cnum,0);
+ unix_convert(fname,cnum,0,&bad_path);
fnum = find_free_file();
if (fnum < 0)
return(ERROR(ERRSRV,ERRnofids));
if (!check_name(fname,cnum))
fnum = find_free_file();
if (fnum < 0)
return(ERROR(ERRSRV,ERRnofids));
if (!check_name(fname,cnum))
+ {
+ if((errno == ENOENT) && bad_path)
+ {
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadpath;
+ }
return(UNIXERROR(ERRDOS,ERRnoaccess));
return(UNIXERROR(ERRDOS,ERRnoaccess));
unixmode = unix_mode(cnum,smb_attr | aARCH);
unixmode = unix_mode(cnum,smb_attr | aARCH);
&rmode,&smb_action);
if (!Files[fnum].open)
&rmode,&smb_action);
if (!Files[fnum].open)
+ {
+ if((errno == ENOENT) && bad_path)
+ {
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadpath;
+ }
return(UNIXERROR(ERRDOS,ERRnoaccess));
return(UNIXERROR(ERRDOS,ERRnoaccess));
if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
close_file(fnum);
if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
close_file(fnum);
int createmode;
mode_t unixmode;
int ofun = 0;
int createmode;
mode_t unixmode;
int ofun = 0;
com = SVAL(inbuf,smb_com);
cnum = SVAL(inbuf,smb_tid);
createmode = SVAL(inbuf,smb_vwv0);
strcpy(fname,smb_buf(inbuf)+1);
com = SVAL(inbuf,smb_com);
cnum = SVAL(inbuf,smb_tid);
createmode = SVAL(inbuf,smb_vwv0);
strcpy(fname,smb_buf(inbuf)+1);
- unix_convert(fname,cnum,0);
+ unix_convert(fname,cnum,0,&bad_path);
if (createmode & aVOLID)
{
if (createmode & aVOLID)
{
return(ERROR(ERRSRV,ERRnofids));
if (!check_name(fname,cnum))
return(ERROR(ERRSRV,ERRnofids));
if (!check_name(fname,cnum))
+ {
+ if((errno == ENOENT) && bad_path)
+ {
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadpath;
+ }
return(UNIXERROR(ERRDOS,ERRnoaccess));
return(UNIXERROR(ERRDOS,ERRnoaccess));
open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode, NULL, NULL);
if (!Files[fnum].open)
open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode, NULL, NULL);
if (!Files[fnum].open)
+ {
+ if((errno == ENOENT) && bad_path)
+ {
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadpath;
+ }
return(UNIXERROR(ERRDOS,ERRnoaccess));
return(UNIXERROR(ERRDOS,ERRnoaccess));
outsize = set_message(outbuf,1,0,True);
SSVAL(outbuf,smb_vwv0,fnum);
outsize = set_message(outbuf,1,0,True);
SSVAL(outbuf,smb_vwv0,fnum);
int outsize = 0;
int createmode;
mode_t unixmode;
int outsize = 0;
int createmode;
mode_t unixmode;
+ BOOL bad_path = False;
+
cnum = SVAL(inbuf,smb_tid);
createmode = SVAL(inbuf,smb_vwv0);
sprintf(fname,"%s/TMXXXXXX",smb_buf(inbuf)+1);
cnum = SVAL(inbuf,smb_tid);
createmode = SVAL(inbuf,smb_vwv0);
sprintf(fname,"%s/TMXXXXXX",smb_buf(inbuf)+1);
- unix_convert(fname,cnum,0);
+ unix_convert(fname,cnum,0,&bad_path);
unixmode = unix_mode(cnum,createmode);
unixmode = unix_mode(cnum,createmode);
return(ERROR(ERRSRV,ERRnofids));
if (!check_name(fname,cnum))
return(ERROR(ERRSRV,ERRnofids));
if (!check_name(fname,cnum))
+ {
+ if((errno == ENOENT) && bad_path)
+ {
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadpath;
+ }
return(UNIXERROR(ERRDOS,ERRnoaccess));
return(UNIXERROR(ERRDOS,ERRnoaccess));
strcpy(fname2,(char *)mktemp(fname));
strcpy(fname2,(char *)mktemp(fname));
open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode, NULL, NULL);
if (!Files[fnum].open)
open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode, NULL, NULL);
if (!Files[fnum].open)
+ {
+ if((errno == ENOENT) && bad_path)
+ {
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadpath;
+ }
return(UNIXERROR(ERRDOS,ERRnoaccess));
return(UNIXERROR(ERRDOS,ERRnoaccess));
outsize = set_message(outbuf,1,2 + strlen(fname2),True);
SSVAL(outbuf,smb_vwv0,fnum);
outsize = set_message(outbuf,1,2 + strlen(fname2),True);
SSVAL(outbuf,smb_vwv0,fnum);
int error = ERRnoaccess;
BOOL has_wild;
BOOL exists=False;
int error = ERRnoaccess;
BOOL has_wild;
BOOL exists=False;
DEBUG(3,("reply_unlink : %s\n",name));
DEBUG(3,("reply_unlink : %s\n",name));
- unix_convert(name,cnum,0);
+ unix_convert(name,cnum,0,&bad_path);
p = strrchr(name,'/');
if (!p) {
p = strrchr(name,'/');
if (!p) {
if (exists)
return(ERROR(ERRDOS,error));
else
if (exists)
return(ERROR(ERRDOS,error));
else
+ {
+ if((errno == ENOENT) && bad_path)
+ {
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadpath;
+ }
return(UNIXERROR(ERRDOS,error));
return(UNIXERROR(ERRDOS,error));
}
outsize = set_message(outbuf,0,0,True);
}
outsize = set_message(outbuf,0,0,True);
pstring directory;
int cnum;
int outsize,ret= -1;
pstring directory;
int cnum;
int outsize,ret= -1;
+ BOOL bad_path = False;
+
strcpy(directory,smb_buf(inbuf) + 1);
cnum = SVAL(inbuf,smb_tid);
strcpy(directory,smb_buf(inbuf) + 1);
cnum = SVAL(inbuf,smb_tid);
- unix_convert(directory,cnum,0);
+ unix_convert(directory,cnum,0,&bad_path);
if (check_name(directory,cnum))
ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
if (ret < 0)
if (check_name(directory,cnum))
ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
if (ret < 0)
+ {
+ if((errno == ENOENT) && bad_path)
+ {
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadpath;
+ }
return(UNIXERROR(ERRDOS,ERRnoaccess));
return(UNIXERROR(ERRDOS,ERRnoaccess));
outsize = set_message(outbuf,0,0,True);
DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret));
outsize = set_message(outbuf,0,0,True);
DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret));
int cnum;
int outsize = 0;
BOOL ok = False;
int cnum;
int outsize = 0;
BOOL ok = False;
+ BOOL bad_path = False;
+
cnum = SVAL(inbuf,smb_tid);
strcpy(directory,smb_buf(inbuf) + 1);
cnum = SVAL(inbuf,smb_tid);
strcpy(directory,smb_buf(inbuf) + 1);
- unix_convert(directory,cnum,0);
+ unix_convert(directory,cnum,0,&bad_path);
if (check_name(directory,cnum))
{
if (check_name(directory,cnum))
{
+ {
+ if((errno == ENOENT) && bad_path)
+ {
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadpath;
+ }
return(UNIXERROR(ERRDOS,ERRbadpath));
return(UNIXERROR(ERRDOS,ERRbadpath));
outsize = set_message(outbuf,0,0,True);
DEBUG(3,("%s rmdir %s\n",timestring(),directory));
outsize = set_message(outbuf,0,0,True);
DEBUG(3,("%s rmdir %s\n",timestring(),directory));
int error = ERRnoaccess;
BOOL has_wild;
BOOL exists=False;
int error = ERRnoaccess;
BOOL has_wild;
BOOL exists=False;
+ BOOL bad_path1 = False;
+ BOOL bad_path2 = False;
DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
- unix_convert(name,cnum,0);
- unix_convert(newname,cnum,newname_last_component);
+ unix_convert(name,cnum,0,&bad_path1);
+ unix_convert(newname,cnum,newname_last_component,&bad_path2);
/*
* Split the old name into directory and last component
/*
* Split the old name into directory and last component
if (exists)
return(ERROR(ERRDOS,error));
else
if (exists)
return(ERROR(ERRDOS,error));
else
+ {
+ if((errno == ENOENT) && (bad_path1 || bad_path2))
+ {
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadpath;
+ }
return(UNIXERROR(ERRDOS,error));
return(UNIXERROR(ERRDOS,error));
}
outsize = set_message(outbuf,0,0,True);
}
outsize = set_message(outbuf,0,0,True);
int ofun = SVAL(inbuf,smb_vwv1);
int flags = SVAL(inbuf,smb_vwv2);
BOOL target_is_directory=False;
int ofun = SVAL(inbuf,smb_vwv1);
int flags = SVAL(inbuf,smb_vwv2);
BOOL target_is_directory=False;
+ BOOL bad_path1 = False;
+ BOOL bad_path2 = False;
return(ERROR(ERRSRV,ERRinvdevice));
}
return(ERROR(ERRSRV,ERRinvdevice));
}
- unix_convert(name,cnum,0);
- unix_convert(newname,cnum,0);
+ unix_convert(name,cnum,0,&bad_path1);
+ unix_convert(newname,cnum,0,&bad_path2);
target_is_directory = directory_exist(newname,NULL);
target_is_directory = directory_exist(newname,NULL);
if (exists)
return(ERROR(ERRDOS,error));
else
if (exists)
return(ERROR(ERRDOS,error));
else
+ {
+ if((errno == ENOENT) && (bad_path1 || bad_path2))
+ {
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadpath;
+ }
return(UNIXERROR(ERRDOS,error));
return(UNIXERROR(ERRDOS,error));
}
outsize = set_message(outbuf,1,0,True);
}
outsize = set_message(outbuf,1,0,True);
of the pathname is returned there. This is used in an exceptional
case in reply_mv (so far). If saved_last_component == 0 then nothing
is returned there.
of the pathname is returned there. This is used in an exceptional
case in reply_mv (so far). If saved_last_component == 0 then nothing
is returned there.
+
+The bad_path arg is set to True if the filename walk failed. This is
+used to pick the correct error code to return between ENOENT and ENOTDIR
+as Windows applications depend on ERRbadpath being returned if a component
+of a pathname does not exist.
****************************************************************************/
****************************************************************************/
-BOOL unix_convert(char *name,int cnum,pstring saved_last_component)
+BOOL unix_convert(char *name,int cnum,pstring saved_last_component, BOOL *bad_path)
{
struct stat st;
char *start, *end;
pstring dirpath;
{
struct stat st;
char *start, *end;
pstring dirpath;
if(saved_last_component)
*saved_last_component = 0;
if(saved_last_component)
*saved_last_component = 0;
if (sys_stat(name,&st) == 0)
return(True);
if (sys_stat(name,&st) == 0)
return(True);
DEBUG(5,("unix_convert(%s,%d)\n",name,cnum));
/* a special case - if we don't have any mangling chars and are case
sensitive then searching won't help */
if (case_sensitive && !is_mangled(name) &&
DEBUG(5,("unix_convert(%s,%d)\n",name,cnum));
/* a special case - if we don't have any mangling chars and are case
sensitive then searching won't help */
if (case_sensitive && !is_mangled(name) &&
- !lp_strip_dot() && !use_mangled_map)
+ !lp_strip_dot() && !use_mangled_map && (saved_errno != ENOENT))
return(False);
/* now we need to recursively match the name against the real
return(False);
/* now we need to recursively match the name against the real
if (end) *end = 0;
if(saved_last_component != 0)
if (end) *end = 0;
if(saved_last_component != 0)
- strcpy(saved_last_component, end ? end + 1 : start);
+ strcpy(saved_last_component, end ? end + 1 : start);
/* check if the name exists up to this point */
if (sys_stat(name, &st) == 0)
/* check if the name exists up to this point */
if (sys_stat(name, &st) == 0)
/* an intermediate part of the name can't be found */
DEBUG(5,("Intermediate not found %s\n",start));
*end = '/';
/* an intermediate part of the name can't be found */
DEBUG(5,("Intermediate not found %s\n",start));
*end = '/';
+ /* We need to return the fact that the intermediate
+ name resolution failed. This is used to return an
+ error of ERRbadpath rather than ERRbadfile. Some
+ Windows applications depend on the difference between
+ these two errors.
+ */
+ *bad_path = True;
{EPERM,ERRDOS,ERRnoaccess},
{EACCES,ERRDOS,ERRnoaccess},
{ENOENT,ERRDOS,ERRbadfile},
{EPERM,ERRDOS,ERRnoaccess},
{EACCES,ERRDOS,ERRnoaccess},
{ENOENT,ERRDOS,ERRbadfile},
- {ENOTDIR,ERRDOS,ERRbadpath},
+ {ENOTDIR,ERRDOS,ERRbaddirectory},
{EIO,ERRHRD,ERRgeneral},
{EBADF,ERRSRV,ERRsrverror},
{EINVAL,ERRSRV,ERRsrverror},
{EIO,ERRHRD,ERRgeneral},
{EBADF,ERRSRV,ERRsrverror},
{EINVAL,ERRSRV,ERRsrverror},
int32 inode = 0;
struct stat sbuf;
int smb_action = 0;
int32 inode = 0;
struct stat sbuf;
int smb_action = 0;
StrnCpy(fname,pname,namelen);
StrnCpy(fname,pname,namelen);
/* XXXX we need to handle passed times, sattr and flags */
/* XXXX we need to handle passed times, sattr and flags */
- unix_convert(fname,cnum,0);
+ unix_convert(fname,cnum,0,&bad_path);
fnum = find_free_file();
if (fnum < 0)
return(ERROR(ERRSRV,ERRnofids));
if (!check_name(fname,cnum))
fnum = find_free_file();
if (fnum < 0)
return(ERROR(ERRSRV,ERRnofids));
if (!check_name(fname,cnum))
+ {
+ if((errno == ENOENT) && bad_path)
+ {
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadpath;
+ }
return(UNIXERROR(ERRDOS,ERRnoaccess));
return(UNIXERROR(ERRDOS,ERRnoaccess));
unixmode = unix_mode(cnum,open_attr | aARCH);
unixmode = unix_mode(cnum,open_attr | aARCH);
&rmode,&smb_action);
if (!Files[fnum].open)
&rmode,&smb_action);
if (!Files[fnum].open)
+ {
+ if((errno == ENOENT) && bad_path)
+ {
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadpath;
+ }
return(UNIXERROR(ERRDOS,ERRnoaccess));
return(UNIXERROR(ERRDOS,ERRnoaccess));
if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
close_file(fnum);
if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
close_file(fnum);
BOOL dont_descend = False;
BOOL out_of_space = False;
int space_remaining;
BOOL dont_descend = False;
BOOL out_of_space = False;
int space_remaining;
DEBUG(5,("path=%s\n",directory));
DEBUG(5,("path=%s\n",directory));
- unix_convert(directory,cnum,0);
+ unix_convert(directory,cnum,0,&bad_path);
if(!check_name(directory,cnum)) {
if(!check_name(directory,cnum)) {
+ if((errno == ENOENT) && bad_path)
+ {
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadpath;
+ }
return(ERROR(ERRDOS,ERRbadpath));
}
return(ERROR(ERRDOS,ERRbadpath));
}
if (dptr_num < 0)
{
if(dptr_num == -2)
if (dptr_num < 0)
{
if(dptr_num == -2)
+ {
+ if((errno == ENOENT) && bad_path)
+ {
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadpath;
+ }
return (UNIXERROR(ERRDOS,ERRbadpath));
return (UNIXERROR(ERRDOS,ERRbadpath));
return(ERROR(ERRDOS,ERRbadpath));
}
return(ERROR(ERRDOS,ERRbadpath));
}
char *fname;
char *p;
int l,pos;
char *fname;
char *p;
int l,pos;
if (tran_call == TRANSACT2_QFILEINFO) {
int16 fnum = SVALS(params,0);
if (tran_call == TRANSACT2_QFILEINFO) {
int16 fnum = SVALS(params,0);
info_level = SVAL(params,0);
fname = &fname1[0];
strcpy(fname,¶ms[6]);
info_level = SVAL(params,0);
fname = &fname1[0];
strcpy(fname,¶ms[6]);
- unix_convert(fname,cnum,0);
+ unix_convert(fname,cnum,0,&bad_path);
if (!check_name(fname,cnum) || sys_stat(fname,&sbuf)) {
DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
if (!check_name(fname,cnum) || sys_stat(fname,&sbuf)) {
DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
+ if((errno == ENOENT) && bad_path)
+ {
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadpath;
+ }
return(UNIXERROR(ERRDOS,ERRbadpath));
}
pos = 0;
return(UNIXERROR(ERRDOS,ERRbadpath));
}
pos = 0;
pstring fname1;
char *fname;
int fd = -1;
pstring fname1;
char *fname;
int fd = -1;
if (!CAN_WRITE(cnum))
return(ERROR(ERRSRV,ERRaccess));
if (!CAN_WRITE(cnum))
return(ERROR(ERRSRV,ERRaccess));
info_level = SVAL(params,0);
fname = fname1;
strcpy(fname,¶ms[6]);
info_level = SVAL(params,0);
fname = fname1;
strcpy(fname,¶ms[6]);
- unix_convert(fname,cnum,0);
+ unix_convert(fname,cnum,0,&bad_path);
if(!check_name(fname, cnum))
if(!check_name(fname, cnum))
- return(ERROR(ERRDOS,ERRbadpath));
-
+ {
+ if((errno == ENOENT) && bad_path)
+ {
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadpath;
+ }
+ return(UNIXERROR(ERRDOS,ERRbadpath));
+ }
+
if(sys_stat(fname,&st)!=0) {
DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
if(sys_stat(fname,&st)!=0) {
DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
- return(ERROR(ERRDOS,ERRbadpath));
+ if((errno == ENOENT) && bad_path)
+ {
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadpath;
+ }
+ return(UNIXERROR(ERRDOS,ERRbadpath));
char *params = *pparams;
pstring directory;
int ret = -1;
char *params = *pparams;
pstring directory;
int ret = -1;
if (!CAN_WRITE(cnum))
return(ERROR(ERRSRV,ERRaccess));
if (!CAN_WRITE(cnum))
return(ERROR(ERRSRV,ERRaccess));
DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
- unix_convert(directory,cnum,0);
+ unix_convert(directory,cnum,0,&bad_path);
if (check_name(directory,cnum))
ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
if(ret < 0)
{
DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
if (check_name(directory,cnum))
ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
if(ret < 0)
{
DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
+ if((errno == ENOENT) && bad_path)
+ {
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadpath;
+ }
return(UNIXERROR(ERRDOS,ERRnoaccess));
}
return(UNIXERROR(ERRDOS,ERRnoaccess));
}