mirror of
https://github.com/samba-team/samba.git
synced 2024-12-24 21:34:56 +03:00
Restructuring of the code to remove dos_ChDir/dos_GetWd and re-vector them
through the VFS. All file access/directory access code in smbd should now
go via the vfs. Added vfs_chown/vfs_chmod calls. Still looking at vfs_get_nt_acl()
vfs_set_nt_acl() call API design.
Jeremy.
(This used to be commit f96625ec12
)
This commit is contained in:
parent
8c93ddf3e0
commit
b43b2e4f8a
@ -90,8 +90,6 @@ BOOL dos_file_exist(char *fname,SMB_STRUCT_STAT *sbuf);
|
||||
BOOL dos_directory_exist(char *dname,SMB_STRUCT_STAT *st);
|
||||
time_t dos_file_modtime(char *fname);
|
||||
SMB_OFF_T dos_file_size(char *file_name);
|
||||
int dos_ChDir(char *path);
|
||||
char *dos_GetWd(char *path);
|
||||
|
||||
/*The following definitions come from lib/error.c */
|
||||
|
||||
@ -339,7 +337,6 @@ void smb_setlen(char *buf,int len);
|
||||
int set_message(char *buf,int num_words,int num_bytes,BOOL zero);
|
||||
void dos_clean_name(char *s);
|
||||
void unix_clean_name(char *s);
|
||||
BOOL reduce_name(char *s,char *dir,BOOL widelinks);
|
||||
void make_dir_struct(char *buf,char *mask,char *fname,SMB_OFF_T size,int mode,time_t date);
|
||||
void close_low_fds(void);
|
||||
int set_blocking(int fd, BOOL set);
|
||||
@ -3854,23 +3851,35 @@ int vfswrap_lstat(char *path,
|
||||
SMB_STRUCT_STAT *sbuf);
|
||||
int vfswrap_unlink(char *path);
|
||||
int vfswrap_chmod(char *path, mode_t mode);
|
||||
int vfswrap_chown(char *path, uid_t uid, gid_t gid);
|
||||
int vfswrap_chdir(char *path);
|
||||
char *vfswrap_getwd(char *path);
|
||||
int vfswrap_utime(char *path, struct utimbuf *times);
|
||||
int vfswrap_ftruncate(int fd, SMB_OFF_T offset);
|
||||
BOOL vfswrap_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type);
|
||||
size_t vfswrap_get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc);
|
||||
BOOL vfswrap_set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd);
|
||||
|
||||
/*The following definitions come from smbd/vfs.c */
|
||||
|
||||
int vfs_init_default(connection_struct *conn);
|
||||
BOOL vfs_init_custom(connection_struct *conn);
|
||||
BOOL vfs_directory_exist(connection_struct *conn, char *dname,
|
||||
SMB_STRUCT_STAT *st);
|
||||
int vfs_stat(connection_struct *conn, char *fname, SMB_STRUCT_STAT *st);
|
||||
BOOL vfs_directory_exist(connection_struct *conn, char *dname, SMB_STRUCT_STAT *st);
|
||||
int vfs_unlink(connection_struct *conn, char *fname);
|
||||
int vfs_chmod(connection_struct *conn, char *fname,mode_t mode);
|
||||
int vfs_chown(connection_struct *conn, char *fname, uid_t uid, gid_t gid);
|
||||
int vfs_chdir(connection_struct *conn, char *fname);
|
||||
char *vfs_getwd(connection_struct *conn, char *unix_path);
|
||||
BOOL vfs_file_exist(connection_struct *conn,char *fname,SMB_STRUCT_STAT *sbuf);
|
||||
ssize_t vfs_write_data(files_struct *fsp,char *buffer,size_t N);
|
||||
SMB_OFF_T vfs_transfer_file(int in_fd, files_struct *in_fsp,
|
||||
int out_fd, files_struct *out_fsp,
|
||||
SMB_OFF_T n, char *header, int headlen, int align);
|
||||
char *vfs_readdirname(connection_struct *conn, void *p);
|
||||
int vfs_ChDir(connection_struct *conn, char *path);
|
||||
char *vfs_GetWd(connection_struct *conn, char *path);
|
||||
BOOL reduce_name(connection_struct *conn, char *s,char *dir,BOOL widelinks);
|
||||
|
||||
/*The following definitions come from smbwrapper/realcalls.c */
|
||||
|
||||
|
@ -184,9 +184,16 @@ struct vfs_ops {
|
||||
int (*lstat)(char *path, SMB_STRUCT_STAT *sbuf);
|
||||
int (*unlink)(char *path);
|
||||
int (*chmod)(char *path, mode_t mode);
|
||||
int (*chown)(char *path, uid_t uid, gid_t gid);
|
||||
int (*chdir)(char *path);
|
||||
char *(*getwd)(char *buf);
|
||||
int (*utime)(char *path, struct utimbuf *times);
|
||||
int (*ftruncate)(int fd, SMB_OFF_T offset);
|
||||
BOOL (*lock)(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type);
|
||||
#if 0
|
||||
size_t (*get_nt_acl)(files_struct *fsp, SEC_DESC **ppdesc);
|
||||
BOOL (*set_nt_acl)(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd);
|
||||
#endif
|
||||
};
|
||||
|
||||
struct vfs_options {
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
extern int DEBUGLEVEL;
|
||||
|
||||
#if 0 /* Use vfs_unlink. */
|
||||
/*******************************************************************
|
||||
Unlink wrapper that calls dos_to_unix.
|
||||
********************************************************************/
|
||||
@ -41,6 +42,7 @@ int dos_unlink(char *fname)
|
||||
{
|
||||
return(unlink(dos_to_unix(fname,False)));
|
||||
}
|
||||
#endif
|
||||
|
||||
/*******************************************************************
|
||||
Open() wrapper that calls dos_to_unix.
|
||||
@ -85,10 +87,12 @@ char *dos_readdirname(DIR *p)
|
||||
A chown() wrapper that calls dos_to_unix.
|
||||
********************************************************************/
|
||||
|
||||
#if 0 /* Use vfs_chown. */
|
||||
int dos_chown(char *fname, uid_t uid, gid_t gid)
|
||||
{
|
||||
return(sys_chown(dos_to_unix(fname,False),uid,gid));
|
||||
}
|
||||
#endif
|
||||
|
||||
/*******************************************************************
|
||||
A stat() wrapper that calls dos_to_unix.
|
||||
@ -134,6 +138,7 @@ int dos_rmdir(char *dname)
|
||||
return(rmdir(dos_to_unix(dname,False)));
|
||||
}
|
||||
|
||||
#if 0 /* VFS */
|
||||
/*******************************************************************
|
||||
chdir() - call dos_to_unix.
|
||||
********************************************************************/
|
||||
@ -142,6 +147,7 @@ int dos_chdir(char *dname)
|
||||
{
|
||||
return(chdir(dos_to_unix(dname,False)));
|
||||
}
|
||||
#endif
|
||||
|
||||
/*******************************************************************
|
||||
Utime() - call dos_to_unix.
|
||||
@ -282,6 +288,7 @@ int dos_chmod(char *fname,mode_t mode)
|
||||
return(chmod(dos_to_unix(fname,False),mode));
|
||||
}
|
||||
|
||||
#if 0 /* VFS */
|
||||
/*******************************************************************
|
||||
Getwd - takes a UNIX directory name and returns the name
|
||||
in dos format.
|
||||
@ -295,6 +302,7 @@ char *dos_getwd(char *unix_path)
|
||||
unix_to_dos(wd, True);
|
||||
return wd;
|
||||
}
|
||||
#endif /* VFS */
|
||||
|
||||
/*******************************************************************
|
||||
Check if a DOS file exists. Use vfs_file_exist function instead.
|
||||
@ -333,164 +341,3 @@ SMB_OFF_T dos_file_size(char *file_name)
|
||||
{
|
||||
return get_file_size(dos_to_unix(file_name, False));
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
A wrapper for dos_chdir().
|
||||
********************************************************************/
|
||||
|
||||
int dos_ChDir(char *path)
|
||||
{
|
||||
int res;
|
||||
static pstring LastDir="";
|
||||
|
||||
if (strcsequal(path,"."))
|
||||
return(0);
|
||||
|
||||
if (*path == '/' && strcsequal(LastDir,path))
|
||||
return(0);
|
||||
|
||||
DEBUG(3,("dos_ChDir to %s\n",path));
|
||||
|
||||
res = dos_chdir(path);
|
||||
if (!res)
|
||||
pstrcpy(LastDir,path);
|
||||
return(res);
|
||||
}
|
||||
|
||||
/* number of list structures for a caching GetWd function. */
|
||||
#define MAX_GETWDCACHE (50)
|
||||
|
||||
struct
|
||||
{
|
||||
SMB_DEV_T dev; /* These *must* be compatible with the types returned in a stat() call. */
|
||||
SMB_INO_T inode; /* These *must* be compatible with the types returned in a stat() call. */
|
||||
char *dos_path; /* The pathname in DOS format. */
|
||||
BOOL valid;
|
||||
} ino_list[MAX_GETWDCACHE];
|
||||
|
||||
BOOL use_getwd_cache=True;
|
||||
|
||||
/****************************************************************************
|
||||
Prompte a ptr (to make it recently used)
|
||||
****************************************************************************/
|
||||
|
||||
static void array_promote(char *array,int elsize,int element)
|
||||
{
|
||||
char *p;
|
||||
if (element == 0)
|
||||
return;
|
||||
|
||||
p = (char *)malloc(elsize);
|
||||
|
||||
if (!p)
|
||||
{
|
||||
DEBUG(5,("Ahh! Can't malloc\n"));
|
||||
return;
|
||||
}
|
||||
memcpy(p,array + element * elsize, elsize);
|
||||
memmove(array + elsize,array,elsize*element);
|
||||
memcpy(array,p,elsize);
|
||||
free(p);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
Return the absolute current directory path - given a UNIX pathname.
|
||||
Note that this path is returned in DOS format, not UNIX
|
||||
format.
|
||||
********************************************************************/
|
||||
|
||||
char *dos_GetWd(char *path)
|
||||
{
|
||||
pstring s;
|
||||
static BOOL getwd_cache_init = False;
|
||||
SMB_STRUCT_STAT st, st2;
|
||||
int i;
|
||||
|
||||
*s = 0;
|
||||
|
||||
if (!use_getwd_cache)
|
||||
return(dos_getwd(path));
|
||||
|
||||
/* init the cache */
|
||||
if (!getwd_cache_init)
|
||||
{
|
||||
getwd_cache_init = True;
|
||||
for (i=0;i<MAX_GETWDCACHE;i++)
|
||||
{
|
||||
string_set(&ino_list[i].dos_path,"");
|
||||
ino_list[i].valid = False;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the inode of the current directory, if this doesn't work we're
|
||||
in trouble :-) */
|
||||
|
||||
if (sys_stat(".",&st) == -1)
|
||||
{
|
||||
DEBUG(0,("Very strange, couldn't stat \".\" path=%s\n", path));
|
||||
return(dos_getwd(path));
|
||||
}
|
||||
|
||||
|
||||
for (i=0; i<MAX_GETWDCACHE; i++)
|
||||
if (ino_list[i].valid)
|
||||
{
|
||||
|
||||
/* If we have found an entry with a matching inode and dev number
|
||||
then find the inode number for the directory in the cached string.
|
||||
If this agrees with that returned by the stat for the current
|
||||
directory then all is o.k. (but make sure it is a directory all
|
||||
the same...) */
|
||||
|
||||
if (st.st_ino == ino_list[i].inode &&
|
||||
st.st_dev == ino_list[i].dev)
|
||||
{
|
||||
if (dos_stat(ino_list[i].dos_path,&st2) == 0)
|
||||
{
|
||||
if (st.st_ino == st2.st_ino &&
|
||||
st.st_dev == st2.st_dev &&
|
||||
(st2.st_mode & S_IFMT) == S_IFDIR)
|
||||
{
|
||||
pstrcpy (path, ino_list[i].dos_path);
|
||||
|
||||
/* promote it for future use */
|
||||
array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
|
||||
return (path);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If the inode is different then something's changed,
|
||||
scrub the entry and start from scratch. */
|
||||
ino_list[i].valid = False;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* We don't have the information to hand so rely on traditional methods.
|
||||
The very slow getcwd, which spawns a process on some systems, or the
|
||||
not quite so bad getwd. */
|
||||
|
||||
if (!dos_getwd(s))
|
||||
{
|
||||
DEBUG(0,("dos_GetWd: dos_getwd call failed, errno %s\n",strerror(errno)));
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
pstrcpy(path,s);
|
||||
|
||||
DEBUG(5,("dos_GetWd %s, inode %.0f, dev %.0f\n",s,(double)st.st_ino,(double)st.st_dev));
|
||||
|
||||
/* add it to the cache */
|
||||
i = MAX_GETWDCACHE - 1;
|
||||
string_set(&ino_list[i].dos_path,s);
|
||||
ino_list[i].dev = st.st_dev;
|
||||
ino_list[i].inode = st.st_ino;
|
||||
ino_list[i].valid = True;
|
||||
|
||||
/* put it at the top of the list */
|
||||
array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
|
||||
|
||||
return (path);
|
||||
}
|
||||
|
@ -410,137 +410,6 @@ void unix_clean_name(char *s)
|
||||
trim_string(s,NULL,"/..");
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
reduce a file name, removing .. elements and checking that
|
||||
it is below dir in the heirachy. This uses dos_GetWd() and so must be run
|
||||
on the system that has the referenced file system.
|
||||
|
||||
widelinks are allowed if widelinks is true
|
||||
********************************************************************/
|
||||
|
||||
BOOL reduce_name(char *s,char *dir,BOOL widelinks)
|
||||
{
|
||||
#ifndef REDUCE_PATHS
|
||||
return True;
|
||||
#else
|
||||
pstring dir2;
|
||||
pstring wd;
|
||||
pstring base_name;
|
||||
pstring newname;
|
||||
char *p=NULL;
|
||||
BOOL relative = (*s != '/');
|
||||
|
||||
*dir2 = *wd = *base_name = *newname = 0;
|
||||
|
||||
if (widelinks)
|
||||
{
|
||||
unix_clean_name(s);
|
||||
/* can't have a leading .. */
|
||||
if (strncmp(s,"..",2) == 0 && (s[2]==0 || s[2]=='/'))
|
||||
{
|
||||
DEBUG(3,("Illegal file name? (%s)\n",s));
|
||||
return(False);
|
||||
}
|
||||
|
||||
if (strlen(s) == 0)
|
||||
pstrcpy(s,"./");
|
||||
|
||||
return(True);
|
||||
}
|
||||
|
||||
DEBUG(3,("reduce_name [%s] [%s]\n",s,dir));
|
||||
|
||||
/* remove any double slashes */
|
||||
all_string_sub(s,"//","/",0);
|
||||
|
||||
pstrcpy(base_name,s);
|
||||
p = strrchr(base_name,'/');
|
||||
|
||||
if (!p)
|
||||
return(True);
|
||||
|
||||
if (!dos_GetWd(wd))
|
||||
{
|
||||
DEBUG(0,("couldn't getwd for %s %s\n",s,dir));
|
||||
return(False);
|
||||
}
|
||||
|
||||
if (dos_ChDir(dir) != 0)
|
||||
{
|
||||
DEBUG(0,("couldn't chdir to %s\n",dir));
|
||||
return(False);
|
||||
}
|
||||
|
||||
if (!dos_GetWd(dir2))
|
||||
{
|
||||
DEBUG(0,("couldn't getwd for %s\n",dir));
|
||||
dos_ChDir(wd);
|
||||
return(False);
|
||||
}
|
||||
|
||||
if (p && (p != base_name))
|
||||
{
|
||||
*p = 0;
|
||||
if (strcmp(p+1,".")==0)
|
||||
p[1]=0;
|
||||
if (strcmp(p+1,"..")==0)
|
||||
*p = '/';
|
||||
}
|
||||
|
||||
if (dos_ChDir(base_name) != 0)
|
||||
{
|
||||
dos_ChDir(wd);
|
||||
DEBUG(3,("couldn't chdir for %s %s basename=%s\n",s,dir,base_name));
|
||||
return(False);
|
||||
}
|
||||
|
||||
if (!dos_GetWd(newname))
|
||||
{
|
||||
dos_ChDir(wd);
|
||||
DEBUG(2,("couldn't get wd for %s %s\n",s,dir2));
|
||||
return(False);
|
||||
}
|
||||
|
||||
if (p && (p != base_name))
|
||||
{
|
||||
pstrcat(newname,"/");
|
||||
pstrcat(newname,p+1);
|
||||
}
|
||||
|
||||
{
|
||||
size_t l = strlen(dir2);
|
||||
if (dir2[l-1] == '/')
|
||||
l--;
|
||||
|
||||
if (strncmp(newname,dir2,l) != 0)
|
||||
{
|
||||
dos_ChDir(wd);
|
||||
DEBUG(2,("Bad access attempt? s=%s dir=%s newname=%s l=%d\n",s,dir2,newname,(int)l));
|
||||
return(False);
|
||||
}
|
||||
|
||||
if (relative)
|
||||
{
|
||||
if (newname[l] == '/')
|
||||
pstrcpy(s,newname + l + 1);
|
||||
else
|
||||
pstrcpy(s,newname+l);
|
||||
}
|
||||
else
|
||||
pstrcpy(s,newname);
|
||||
}
|
||||
|
||||
dos_ChDir(wd);
|
||||
|
||||
if (strlen(s) == 0)
|
||||
pstrcpy(s,"./");
|
||||
|
||||
DEBUG(3,("reduced to %s\n",s));
|
||||
return(True);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
make a dir struct
|
||||
****************************************************************************/
|
||||
|
@ -92,7 +92,7 @@ pstring global_scope = "";
|
||||
#define VALID(i) iSERVICE(i).valid
|
||||
|
||||
int keepalive = DEFAULT_KEEPALIVE;
|
||||
extern BOOL use_getwd_cache;
|
||||
BOOL use_getwd_cache;
|
||||
|
||||
extern int extra_time_offset;
|
||||
|
||||
|
@ -61,7 +61,7 @@ mode_t unix_mode(connection_struct *conn,int dosmode,const char *fname)
|
||||
|
||||
dname = parent_dirname(fname);
|
||||
DEBUG(2,("unix_mode(%s) inheriting from %s\n",fname,dname));
|
||||
if (dos_stat(dname,&sbuf) != 0) {
|
||||
if (vfs_stat(conn,dname,&sbuf) != 0) {
|
||||
DEBUG(4,("unix_mode(%s) failed, [dir %s]: %s\n",fname,dname,strerror(errno)));
|
||||
return(0); /* *** shouldn't happen! *** */
|
||||
}
|
||||
@ -191,7 +191,7 @@ int file_chmod(connection_struct *conn,char *fname,int dosmode,SMB_STRUCT_STAT *
|
||||
|
||||
if (!st) {
|
||||
st = &st1;
|
||||
if (conn->vfs_ops.stat(dos_to_unix(fname,False),st)) return(-1);
|
||||
if (vfs_stat(conn,fname,st)) return(-1);
|
||||
}
|
||||
|
||||
if (S_ISDIR(st->st_mode)) dosmode |= aDIR;
|
||||
@ -227,7 +227,7 @@ int file_chmod(connection_struct *conn,char *fname,int dosmode,SMB_STRUCT_STAT *
|
||||
unixmode |= (st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH));
|
||||
}
|
||||
|
||||
return(conn->vfs_ops.chmod(dos_to_unix(fname,False),unixmode));
|
||||
return(vfs_chmod(conn,fname,unixmode));
|
||||
}
|
||||
|
||||
|
||||
@ -258,7 +258,7 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times)
|
||||
(as DOS does).
|
||||
*/
|
||||
|
||||
if(conn->vfs_ops.stat(dos_to_unix(fname,False),&sb) != 0)
|
||||
if(vfs_stat(conn,fname,&sb) != 0)
|
||||
return -1;
|
||||
|
||||
/* Check if we have write access. */
|
||||
|
@ -419,7 +419,7 @@ BOOL check_name(char *name,connection_struct *conn)
|
||||
return(0);
|
||||
}
|
||||
|
||||
ret = reduce_name(name,conn->connectpath,lp_widelinks(SNUM(conn)));
|
||||
ret = reduce_name(conn,name,conn->connectpath,lp_widelinks(SNUM(conn)));
|
||||
|
||||
/* Check if we are allowing users to follow symlinks */
|
||||
/* Patch from David Clerc <David.Clerc@cui.unige.ch>
|
||||
|
@ -51,7 +51,7 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags,
|
||||
|
||||
ZERO_STRUCTP(data);
|
||||
|
||||
if(dos_stat(path, &st) == -1) return False;
|
||||
if(vfs_stat(conn,path, &st) == -1) return False;
|
||||
|
||||
data->modify_time = st.st_mtime;
|
||||
data->status_time = st.st_ctime;
|
||||
@ -102,7 +102,7 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags,
|
||||
/*
|
||||
* Do the stat - but ignore errors.
|
||||
*/
|
||||
dos_stat(full_name, &st);
|
||||
vfs_stat(conn,full_name, &st);
|
||||
data->total_time += (st.st_mtime + st.st_ctime);
|
||||
}
|
||||
|
||||
|
@ -732,7 +732,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval, B
|
||||
*/
|
||||
saved_conn = fsp->conn;
|
||||
saved_vuid = current_user.vuid;
|
||||
dos_GetWd(saved_dir);
|
||||
vfs_GetWd(saved_conn,saved_dir);
|
||||
unbecome_user();
|
||||
/* Save the chain fnum. */
|
||||
file_chain_save();
|
||||
@ -814,7 +814,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval, B
|
||||
exit_server("unable to re-become user");
|
||||
}
|
||||
/* Including the directory. */
|
||||
dos_ChDir(saved_dir);
|
||||
vfs_ChDir(saved_conn,saved_dir);
|
||||
|
||||
/* Restore the chain fnum. */
|
||||
file_chain_restore();
|
||||
|
@ -1100,7 +1100,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
|
||||
unix_convert(fname,conn,0,&bad_path,&sbuf);
|
||||
if (check_name(fname,conn))
|
||||
{
|
||||
if (VALID_STAT(sbuf) || dos_stat(fname,&sbuf) == 0)
|
||||
if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0)
|
||||
{
|
||||
mode = dos_mode(conn,fname,&sbuf);
|
||||
size = sbuf.st_size;
|
||||
|
@ -56,8 +56,8 @@ BOOL become_service(connection_struct *conn,BOOL do_chdir)
|
||||
snum = SNUM(conn);
|
||||
|
||||
if (do_chdir &&
|
||||
dos_ChDir(conn->connectpath) != 0 &&
|
||||
dos_ChDir(conn->origpath) != 0) {
|
||||
vfs_ChDir(conn,conn->connectpath) != 0 &&
|
||||
vfs_ChDir(conn,conn->origpath) != 0) {
|
||||
DEBUG(0,("chdir (%s) failed\n",
|
||||
conn->connectpath));
|
||||
return(False);
|
||||
@ -575,7 +575,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dos_ChDir(conn->connectpath) != 0) {
|
||||
if (vfs_ChDir(conn,conn->connectpath) != 0) {
|
||||
DEBUG(0,("Can't change directory to %s (%s)\n",
|
||||
conn->connectpath,strerror(errno)));
|
||||
unbecome_user();
|
||||
@ -598,9 +598,9 @@ connection_struct *make_connection(char *service,char *user,char *password, int
|
||||
{
|
||||
pstring s;
|
||||
pstrcpy(s,conn->connectpath);
|
||||
dos_GetWd(s);
|
||||
vfs_GetWd(conn,s);
|
||||
string_set(&conn->connectpath,s);
|
||||
dos_ChDir(conn->connectpath);
|
||||
vfs_ChDir(conn,conn->connectpath);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -146,8 +146,6 @@ static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *p
|
||||
DOM_SID grp_sid;
|
||||
DOM_SID file_owner_sid;
|
||||
DOM_SID file_grp_sid;
|
||||
uint32 owner_rid;
|
||||
uint32 grp_rid;
|
||||
SEC_ACL *dacl = psd->dacl;
|
||||
BOOL all_aces_are_inherit_only = (is_directory ? True : False);
|
||||
int i;
|
||||
@ -353,7 +351,7 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc)
|
||||
} else {
|
||||
|
||||
if(fsp->is_directory || fsp->fd == -1) {
|
||||
if(dos_stat(fsp->fsp_name, &sbuf) != 0) {
|
||||
if(vfs_stat(fsp->conn,fsp->fsp_name, &sbuf) != 0) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
@ -458,14 +456,14 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
|
||||
*/
|
||||
|
||||
if(fsp->is_directory) {
|
||||
if(dos_stat(fsp->fsp_name, &sbuf) != 0)
|
||||
if(vfs_stat(fsp->conn,fsp->fsp_name, &sbuf) != 0)
|
||||
return False;
|
||||
} else {
|
||||
|
||||
int ret;
|
||||
|
||||
if(fsp->fd == -1)
|
||||
ret = conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name,False), &sbuf);
|
||||
ret = vfs_stat(fsp->conn,fsp->fsp_name,&sbuf);
|
||||
else
|
||||
ret = conn->vfs_ops.fstat(fsp->fd,&sbuf);
|
||||
|
||||
@ -492,7 +490,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
|
||||
DEBUG(3,("call_nt_transact_set_security_desc: chown %s. uid = %u, gid = %u.\n",
|
||||
fsp->fsp_name, (unsigned int)user, (unsigned int)grp ));
|
||||
|
||||
if(dos_chown( fsp->fsp_name, user, grp) == -1) {
|
||||
if(vfs_chown( fsp->conn, fsp->fsp_name, user, grp) == -1) {
|
||||
DEBUG(3,("call_nt_transact_set_security_desc: chown %s, %u, %u failed. Error = %s.\n",
|
||||
fsp->fsp_name, (unsigned int)user, (unsigned int)grp, strerror(errno) ));
|
||||
return False;
|
||||
@ -504,7 +502,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
|
||||
*/
|
||||
|
||||
if(fsp->is_directory) {
|
||||
if(dos_stat(fsp->fsp_name, &sbuf) != 0) {
|
||||
if(vfs_stat(fsp->conn, fsp->fsp_name, &sbuf) != 0) {
|
||||
return False;
|
||||
}
|
||||
} else {
|
||||
@ -512,7 +510,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
|
||||
int ret;
|
||||
|
||||
if(fsp->fd == -1)
|
||||
ret = conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name,False), &sbuf);
|
||||
ret = vfs_stat(fsp->conn, fsp->fsp_name, &sbuf);
|
||||
else
|
||||
ret = conn->vfs_ops.fstat(fsp->fd,&sbuf);
|
||||
|
||||
|
@ -284,6 +284,42 @@ int vfswrap_chmod(char *path, mode_t mode)
|
||||
return result;
|
||||
}
|
||||
|
||||
int vfswrap_chown(char *path, uid_t uid, gid_t gid)
|
||||
{
|
||||
int result;
|
||||
|
||||
#ifdef VFS_CHECK_NULL
|
||||
if (path == NULL) {
|
||||
smb_panic("NULL pointer passed to vfswrap_chown()\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
result = sys_chown(path, uid, gid);
|
||||
return result;
|
||||
}
|
||||
|
||||
int vfswrap_chdir(char *path)
|
||||
{
|
||||
#ifdef VFS_CHECK_NULL
|
||||
if (path == NULL) {
|
||||
smb_panic("NULL pointer passed to vfswrap_chdir()\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
return chdir(path);
|
||||
}
|
||||
|
||||
char *vfswrap_getwd(char *path)
|
||||
{
|
||||
#ifdef VFS_CHECK_NULL
|
||||
if (path == NULL) {
|
||||
smb_panic("NULL pointer passed to vfswrap_getwd()\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
return sys_getwd(path);
|
||||
}
|
||||
|
||||
int vfswrap_utime(char *path, struct utimbuf *times)
|
||||
{
|
||||
int result;
|
||||
@ -310,3 +346,13 @@ BOOL vfswrap_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
|
||||
{
|
||||
return fcntl_lock(fd, op, offset, count,type);
|
||||
}
|
||||
|
||||
#if 0
|
||||
size_t vfswrap_get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc)
|
||||
{
|
||||
}
|
||||
|
||||
BOOL vfswrap_set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
@ -64,9 +64,16 @@ struct vfs_ops default_vfs_ops = {
|
||||
vfswrap_lstat,
|
||||
vfswrap_unlink,
|
||||
vfswrap_chmod,
|
||||
vfswrap_chown,
|
||||
vfswrap_chdir,
|
||||
vfswrap_getwd,
|
||||
vfswrap_utime,
|
||||
vfswrap_ftruncate,
|
||||
vfswrap_lock
|
||||
vfswrap_lock,
|
||||
#if 0
|
||||
vfswrap_get_nt_acl,
|
||||
vfswrap_set_nt_acl
|
||||
#endif
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
@ -208,6 +215,10 @@ BOOL vfs_init_custom(connection_struct *conn)
|
||||
conn->vfs_ops.chmod = default_vfs_ops.chmod;
|
||||
}
|
||||
|
||||
if (conn->vfs_ops.chown == NULL) {
|
||||
conn->vfs_ops.chown = default_vfs_ops.chown;
|
||||
}
|
||||
|
||||
if (conn->vfs_ops.utime == NULL) {
|
||||
conn->vfs_ops.utime = default_vfs_ops.utime;
|
||||
}
|
||||
@ -224,20 +235,33 @@ BOOL vfs_init_custom(connection_struct *conn)
|
||||
}
|
||||
#endif
|
||||
|
||||
BOOL vfs_directory_exist(connection_struct *conn, char *dname,
|
||||
SMB_STRUCT_STAT *st)
|
||||
/*******************************************************************
|
||||
vfs stat wrapper that calls dos_to_unix.
|
||||
********************************************************************/
|
||||
|
||||
int vfs_stat(connection_struct *conn, char *fname, SMB_STRUCT_STAT *st)
|
||||
{
|
||||
SMB_STRUCT_STAT st2;
|
||||
BOOL ret;
|
||||
return(conn->vfs_ops.stat(dos_to_unix(fname,False),st));
|
||||
}
|
||||
|
||||
if (!st) st = &st2;
|
||||
/*******************************************************************
|
||||
Check if directory exists.
|
||||
********************************************************************/
|
||||
|
||||
if (conn->vfs_ops.stat(dos_to_unix(dname,False),st) != 0)
|
||||
return(False);
|
||||
BOOL vfs_directory_exist(connection_struct *conn, char *dname, SMB_STRUCT_STAT *st)
|
||||
{
|
||||
SMB_STRUCT_STAT st2;
|
||||
BOOL ret;
|
||||
|
||||
ret = S_ISDIR(st->st_mode);
|
||||
if(!ret)
|
||||
errno = ENOTDIR;
|
||||
if (!st)
|
||||
st = &st2;
|
||||
|
||||
if (vfs_stat(conn,dname,st) != 0)
|
||||
return(False);
|
||||
|
||||
ret = S_ISDIR(st->st_mode);
|
||||
if(!ret)
|
||||
errno = ENOTDIR;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -248,26 +272,70 @@ BOOL vfs_directory_exist(connection_struct *conn, char *dname,
|
||||
|
||||
int vfs_unlink(connection_struct *conn, char *fname)
|
||||
{
|
||||
return(conn->vfs_ops.unlink(dos_to_unix(fname,False)));
|
||||
return(conn->vfs_ops.unlink(dos_to_unix(fname,False)));
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
check if a vfs file exists
|
||||
vfs chmod wrapper that calls dos_to_unix.
|
||||
********************************************************************/
|
||||
|
||||
int vfs_chmod(connection_struct *conn, char *fname,mode_t mode)
|
||||
{
|
||||
return(conn->vfs_ops.chmod(dos_to_unix(fname,False), mode));
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
vfs chown wrapper that calls dos_to_unix.
|
||||
********************************************************************/
|
||||
|
||||
int vfs_chown(connection_struct *conn, char *fname, uid_t uid, gid_t gid)
|
||||
{
|
||||
return(conn->vfs_ops.chown(dos_to_unix(fname,False), uid, gid));
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
A wrapper for vfs_chdir().
|
||||
********************************************************************/
|
||||
|
||||
int vfs_chdir(connection_struct *conn, char *fname)
|
||||
{
|
||||
return(conn->vfs_ops.chdir(dos_to_unix(fname,False)));
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
vfs getwd wrapper that calls dos_to_unix.
|
||||
********************************************************************/
|
||||
|
||||
char *vfs_getwd(connection_struct *conn, char *unix_path)
|
||||
{
|
||||
char *wd;
|
||||
wd = conn->vfs_ops.getwd(unix_path);
|
||||
if (wd)
|
||||
unix_to_dos(wd, True);
|
||||
return wd;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
Check if a vfs file exists.
|
||||
********************************************************************/
|
||||
|
||||
BOOL vfs_file_exist(connection_struct *conn,char *fname,SMB_STRUCT_STAT *sbuf)
|
||||
{
|
||||
SMB_STRUCT_STAT st;
|
||||
if (!sbuf) sbuf = &st;
|
||||
|
||||
if (conn->vfs_ops.stat(dos_to_unix(fname,False),sbuf) != 0)
|
||||
return(False);
|
||||
SMB_STRUCT_STAT st;
|
||||
|
||||
return(S_ISREG(sbuf->st_mode));
|
||||
if (!sbuf)
|
||||
sbuf = &st;
|
||||
|
||||
if (vfs_stat(conn,fname,sbuf) != 0)
|
||||
return(False);
|
||||
|
||||
return(S_ISREG(sbuf->st_mode));
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
write data to a fd on the vfs
|
||||
Write data to a fd on the vfs.
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t vfs_write_data(files_struct *fsp,char *buffer,size_t N)
|
||||
{
|
||||
size_t total=0;
|
||||
@ -286,8 +354,9 @@ ssize_t vfs_write_data(files_struct *fsp,char *buffer,size_t N)
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
transfer some data between two file_struct's
|
||||
Transfer some data between two file_struct's.
|
||||
****************************************************************************/
|
||||
|
||||
SMB_OFF_T vfs_transfer_file(int in_fd, files_struct *in_fsp,
|
||||
int out_fd, files_struct *out_fsp,
|
||||
SMB_OFF_T n, char *header, int headlen, int align)
|
||||
@ -376,22 +445,26 @@ SMB_OFF_T vfs_transfer_file(int in_fd, files_struct *in_fsp,
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
a vfs_readdir wrapper which just returns the file name
|
||||
A vfs_readdir wrapper which just returns the file name.
|
||||
********************************************************************/
|
||||
|
||||
char *vfs_readdirname(connection_struct *conn, void *p)
|
||||
{
|
||||
struct dirent *ptr;
|
||||
char *dname;
|
||||
|
||||
if (!p) return(NULL);
|
||||
if (!p)
|
||||
return(NULL);
|
||||
|
||||
ptr = (struct dirent *)conn->vfs_ops.readdir(p);
|
||||
if (!ptr) return(NULL);
|
||||
if (!ptr)
|
||||
return(NULL);
|
||||
|
||||
dname = ptr->d_name;
|
||||
|
||||
#ifdef NEXT2
|
||||
if (telldir(p) < 0) return(NULL);
|
||||
if (telldir(p) < 0)
|
||||
return(NULL);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_BROKEN_READDIR
|
||||
@ -474,3 +547,293 @@ static BOOL handle_vfs_option(char *pszParmValue, char **ptr)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
A wrapper for vfs_chdir().
|
||||
********************************************************************/
|
||||
|
||||
int vfs_ChDir(connection_struct *conn, char *path)
|
||||
{
|
||||
int res;
|
||||
static pstring LastDir="";
|
||||
|
||||
if (strcsequal(path,"."))
|
||||
return(0);
|
||||
|
||||
if (*path == '/' && strcsequal(LastDir,path))
|
||||
return(0);
|
||||
|
||||
DEBUG(3,("vfs_ChDir to %s\n",path));
|
||||
|
||||
res = vfs_chdir(conn,path);
|
||||
if (!res)
|
||||
pstrcpy(LastDir,path);
|
||||
return(res);
|
||||
}
|
||||
|
||||
/* number of list structures for a caching GetWd function. */
|
||||
#define MAX_GETWDCACHE (50)
|
||||
|
||||
struct
|
||||
{
|
||||
SMB_DEV_T dev; /* These *must* be compatible with the types returned in a stat() call. */
|
||||
SMB_INO_T inode; /* These *must* be compatible with the types returned in a stat() call. */
|
||||
char *dos_path; /* The pathname in DOS format. */
|
||||
BOOL valid;
|
||||
} ino_list[MAX_GETWDCACHE];
|
||||
|
||||
extern BOOL use_getwd_cache;
|
||||
|
||||
/****************************************************************************
|
||||
Prompte a ptr (to make it recently used)
|
||||
****************************************************************************/
|
||||
|
||||
static void array_promote(char *array,int elsize,int element)
|
||||
{
|
||||
char *p;
|
||||
if (element == 0)
|
||||
return;
|
||||
|
||||
p = (char *)malloc(elsize);
|
||||
|
||||
if (!p) {
|
||||
DEBUG(5,("array_promote: malloc fail\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(p,array + element * elsize, elsize);
|
||||
memmove(array + elsize,array,elsize*element);
|
||||
memcpy(array,p,elsize);
|
||||
free(p);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
Return the absolute current directory path - given a UNIX pathname.
|
||||
Note that this path is returned in DOS format, not UNIX
|
||||
format. Note this can be called with conn == NULL.
|
||||
********************************************************************/
|
||||
|
||||
char *vfs_GetWd(connection_struct *conn, char *path)
|
||||
{
|
||||
pstring s;
|
||||
static BOOL getwd_cache_init = False;
|
||||
SMB_STRUCT_STAT st, st2;
|
||||
int i;
|
||||
|
||||
*s = 0;
|
||||
|
||||
if (!use_getwd_cache)
|
||||
return(vfs_getwd(conn,path));
|
||||
|
||||
/* init the cache */
|
||||
if (!getwd_cache_init)
|
||||
{
|
||||
getwd_cache_init = True;
|
||||
for (i=0;i<MAX_GETWDCACHE;i++)
|
||||
{
|
||||
string_set(&ino_list[i].dos_path,"");
|
||||
ino_list[i].valid = False;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the inode of the current directory, if this doesn't work we're
|
||||
in trouble :-) */
|
||||
|
||||
if (vfs_stat(conn, ".",&st) == -1)
|
||||
{
|
||||
DEBUG(0,("Very strange, couldn't stat \".\" path=%s\n", path));
|
||||
return(vfs_getwd(conn,path));
|
||||
}
|
||||
|
||||
|
||||
for (i=0; i<MAX_GETWDCACHE; i++)
|
||||
if (ino_list[i].valid)
|
||||
{
|
||||
|
||||
/* If we have found an entry with a matching inode and dev number
|
||||
then find the inode number for the directory in the cached string.
|
||||
If this agrees with that returned by the stat for the current
|
||||
directory then all is o.k. (but make sure it is a directory all
|
||||
the same...) */
|
||||
|
||||
if (st.st_ino == ino_list[i].inode &&
|
||||
st.st_dev == ino_list[i].dev)
|
||||
{
|
||||
if (vfs_stat(conn,ino_list[i].dos_path,&st2) == 0)
|
||||
{
|
||||
if (st.st_ino == st2.st_ino &&
|
||||
st.st_dev == st2.st_dev &&
|
||||
(st2.st_mode & S_IFMT) == S_IFDIR)
|
||||
{
|
||||
pstrcpy (path, ino_list[i].dos_path);
|
||||
|
||||
/* promote it for future use */
|
||||
array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
|
||||
return (path);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If the inode is different then something's changed,
|
||||
scrub the entry and start from scratch. */
|
||||
ino_list[i].valid = False;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* We don't have the information to hand so rely on traditional methods.
|
||||
The very slow getcwd, which spawns a process on some systems, or the
|
||||
not quite so bad getwd. */
|
||||
|
||||
if (!vfs_getwd(conn,s))
|
||||
{
|
||||
DEBUG(0,("vfs_GetWd: vfs_getwd call failed, errno %s\n",strerror(errno)));
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
pstrcpy(path,s);
|
||||
|
||||
DEBUG(5,("vfs_GetWd %s, inode %.0f, dev %.0f\n",s,(double)st.st_ino,(double)st.st_dev));
|
||||
|
||||
/* add it to the cache */
|
||||
i = MAX_GETWDCACHE - 1;
|
||||
string_set(&ino_list[i].dos_path,s);
|
||||
ino_list[i].dev = st.st_dev;
|
||||
ino_list[i].inode = st.st_ino;
|
||||
ino_list[i].valid = True;
|
||||
|
||||
/* put it at the top of the list */
|
||||
array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
|
||||
|
||||
return (path);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
Reduce a file name, removing .. elements and checking that
|
||||
it is below dir in the heirachy. This uses vfs_GetWd() and so must be run
|
||||
on the system that has the referenced file system.
|
||||
Widelinks are allowed if widelinks is true.
|
||||
********************************************************************/
|
||||
|
||||
BOOL reduce_name(connection_struct *conn, char *s,char *dir,BOOL widelinks)
|
||||
{
|
||||
#ifndef REDUCE_PATHS
|
||||
return True;
|
||||
#else
|
||||
pstring dir2;
|
||||
pstring wd;
|
||||
pstring base_name;
|
||||
pstring newname;
|
||||
char *p=NULL;
|
||||
BOOL relative = (*s != '/');
|
||||
|
||||
*dir2 = *wd = *base_name = *newname = 0;
|
||||
|
||||
if (widelinks)
|
||||
{
|
||||
unix_clean_name(s);
|
||||
/* can't have a leading .. */
|
||||
if (strncmp(s,"..",2) == 0 && (s[2]==0 || s[2]=='/'))
|
||||
{
|
||||
DEBUG(3,("Illegal file name? (%s)\n",s));
|
||||
return(False);
|
||||
}
|
||||
|
||||
if (strlen(s) == 0)
|
||||
pstrcpy(s,"./");
|
||||
|
||||
return(True);
|
||||
}
|
||||
|
||||
DEBUG(3,("reduce_name [%s] [%s]\n",s,dir));
|
||||
|
||||
/* remove any double slashes */
|
||||
all_string_sub(s,"//","/",0);
|
||||
|
||||
pstrcpy(base_name,s);
|
||||
p = strrchr(base_name,'/');
|
||||
|
||||
if (!p)
|
||||
return(True);
|
||||
|
||||
if (!vfs_GetWd(conn,wd))
|
||||
{
|
||||
DEBUG(0,("couldn't vfs_GetWd for %s %s\n",s,dir));
|
||||
return(False);
|
||||
}
|
||||
|
||||
if (vfs_ChDir(conn,dir) != 0)
|
||||
{
|
||||
DEBUG(0,("couldn't vfs_ChDir to %s\n",dir));
|
||||
return(False);
|
||||
}
|
||||
|
||||
if (!vfs_GetWd(conn,dir2))
|
||||
{
|
||||
DEBUG(0,("couldn't vfs_GetWd for %s\n",dir));
|
||||
vfs_ChDir(conn,wd);
|
||||
return(False);
|
||||
}
|
||||
|
||||
if (p && (p != base_name))
|
||||
{
|
||||
*p = 0;
|
||||
if (strcmp(p+1,".")==0)
|
||||
p[1]=0;
|
||||
if (strcmp(p+1,"..")==0)
|
||||
*p = '/';
|
||||
}
|
||||
|
||||
if (vfs_ChDir(conn,base_name) != 0)
|
||||
{
|
||||
vfs_ChDir(conn,wd);
|
||||
DEBUG(3,("couldn't vfs_ChDir for %s %s basename=%s\n",s,dir,base_name));
|
||||
return(False);
|
||||
}
|
||||
|
||||
if (!vfs_GetWd(conn,newname))
|
||||
{
|
||||
vfs_ChDir(conn,wd);
|
||||
DEBUG(2,("couldn't get vfs_GetWd for %s %s\n",s,dir2));
|
||||
return(False);
|
||||
}
|
||||
|
||||
if (p && (p != base_name))
|
||||
{
|
||||
pstrcat(newname,"/");
|
||||
pstrcat(newname,p+1);
|
||||
}
|
||||
|
||||
{
|
||||
size_t l = strlen(dir2);
|
||||
if (dir2[l-1] == '/')
|
||||
l--;
|
||||
|
||||
if (strncmp(newname,dir2,l) != 0)
|
||||
{
|
||||
vfs_ChDir(conn,wd);
|
||||
DEBUG(2,("Bad access attempt? s=%s dir=%s newname=%s l=%d\n",s,dir2,newname,(int)l));
|
||||
return(False);
|
||||
}
|
||||
|
||||
if (relative)
|
||||
{
|
||||
if (newname[l] == '/')
|
||||
pstrcpy(s,newname + l + 1);
|
||||
else
|
||||
pstrcpy(s,newname+l);
|
||||
}
|
||||
else
|
||||
pstrcpy(s,newname);
|
||||
}
|
||||
|
||||
vfs_ChDir(conn,wd);
|
||||
|
||||
if (strlen(s) == 0)
|
||||
pstrcpy(s,"./");
|
||||
|
||||
DEBUG(3,("reduced to %s\n",s));
|
||||
return(True);
|
||||
#endif
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user