diff options
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/filename.c | 83 | ||||
-rw-r--r-- | source3/smbd/nttrans.c | 57 | ||||
-rw-r--r-- | source3/smbd/open.c | 116 | ||||
-rw-r--r-- | source3/smbd/reply.c | 107 | ||||
-rw-r--r-- | source3/smbd/statcache.c | 2 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 58 | ||||
-rw-r--r-- | source3/smbd/vfs.c | 2 |
7 files changed, 199 insertions, 226 deletions
diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 9ac82386f9..5fe4a4c903 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -111,6 +111,11 @@ 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. + +On exit from unix_convert, if *pst was not null, then the file stat +struct will be returned if the file exists and was found, if not this +stat struct will be filled with zeros (and this can be detected by checking +for nlinks = 0, which can never be true for any file). ****************************************************************************/ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, @@ -127,6 +132,13 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, extern char magic_char; #endif + ZERO_STRUCTP(pst); + + *dirpath = 0; + *bad_path = False; + if(saved_last_component) + *saved_last_component = 0; + if (conn->printer) { /* we don't ever use the filenames on a printer share as a filename - so don't convert them */ @@ -135,15 +147,6 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, DEBUG(5, ("unix_convert called on file \"%s\"\n", name)); - *dirpath = 0; - *bad_path = False; - if(pst) { - ZERO_STRUCTP(pst); - } - - if(saved_last_component) - *saved_last_component = 0; - /* * Convert to basic unix format - removing \ chars and cleaning it up. */ @@ -165,7 +168,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * printing share. */ - if (!*name && (!conn -> printer)) { + if (!*name) { name[0] = '.'; name[1] = '\0'; } @@ -202,8 +205,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, pstrcpy(orig_path, name); if(stat_cache_lookup(conn, name, dirpath, &start, &st)) { - if(pst) - *pst = st; + *pst = st; return True; } @@ -211,11 +213,10 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * stat the name - if it exists then we are all done! */ - if (conn->vfs_ops.stat(conn,dos_to_unix(name,False),&st) == 0) { + if (vfs_stat(conn,name,&st) == 0) { stat_cache_add(orig_path, name); DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); - if(pst) - *pst = st; + *pst = st; return(True); } @@ -277,7 +278,8 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * Check if the name exists up to this point. */ - if (conn->vfs_ops.stat(conn,dos_to_unix(name,False), &st) == 0) { + ZERO_STRUCT(st); + if (vfs_stat(conn,name, &st) == 0) { /* * It exists. it must either be a directory or this must be * the last part of the path for it to be OK. @@ -308,8 +310,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, * Try to find this part of the path in the directory. */ - if (ms_has_wild(start) || - !scan_directory(dirpath, start, conn, end?True:False)) { + if (ms_has_wild(start) || !scan_directory(dirpath, start, conn, end?True:False)) { if (end) { /* * An intermediate part of the name can't be found. @@ -392,6 +393,14 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, if(!component_was_mangled && !name_has_wildcard) stat_cache_add(orig_path, name); + /* + * If we ended up resolving the entire path then return a valid + * stat struct if we got one. + */ + + if (VALID_STAT(st) && (strlen(orig_path) == strlen(name))) + *pst = st; + /* * The name has been resolved. */ @@ -426,15 +435,13 @@ BOOL check_name(char *name,connection_struct *conn) University of Geneva */ #ifdef S_ISLNK - if (!lp_symlinks(SNUM(conn))) - { + if (!lp_symlinks(SNUM(conn))) { SMB_STRUCT_STAT statbuf; if ( (conn->vfs_ops.lstat(conn,dos_to_unix(name,False),&statbuf) != -1) && - (S_ISLNK(statbuf.st_mode)) ) - { + (S_ISLNK(statbuf.st_mode)) ) { DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); ret=0; - } + } } #endif @@ -479,33 +486,29 @@ static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL d mangled = !check_mangled_cache( name ); /* open the directory */ - if (!(cur_dir = OpenDir(conn, path, True))) - { + if (!(cur_dir = OpenDir(conn, path, True))) { DEBUG(3,("scan dir didn't open dir [%s]\n",path)); return(False); - } + } /* now scan for matching names */ - while ((dname = ReadDirName(cur_dir))) - { - if (*dname == '.' && - (strequal(dname,".") || strequal(dname,".."))) - continue; + while ((dname = ReadDirName(cur_dir))) { + if (*dname == '.' && (strequal(dname,".") || strequal(dname,".."))) + continue; pstrcpy(name2,dname); if (!name_map_mangle(name2,False,True,SNUM(conn))) continue; - if ((mangled && mangled_equal(name,name2)) - || fname_equal(name, name2)) - { - /* we've found the file, change it's name and return */ - if (docache) DirCacheAdd(path,name,dname,SNUM(conn)); - pstrcpy(name, dname); - CloseDir(cur_dir); - return(True); - } + if ((mangled && mangled_equal(name,name2)) || fname_equal(name, name2)) { + /* we've found the file, change it's name and return */ + if (docache) + DirCacheAdd(path,name,dname,SNUM(conn)); + pstrcpy(name, dname); + CloseDir(cur_dir); + return(True); } + } CloseDir(cur_dir); return(False); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 67f1a1bc9e..f8b6352ba1 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -795,7 +795,7 @@ int reply_ntcreate_and_X(connection_struct *conn, set_posix_case_semantics(file_attributes); - unix_convert(fname,conn,0,&bad_path,NULL); + unix_convert(fname,conn,0,&bad_path,&sbuf); unixmode = unix_mode(conn,smb_attr | aARCH, fname); @@ -806,7 +806,7 @@ int reply_ntcreate_and_X(connection_struct *conn, if(create_options & FILE_DIRECTORY_FILE) { oplock_request = 0; - fsp = open_directory(conn, fname, smb_ofun, unixmode, &smb_action); + fsp = open_directory(conn, fname, &sbuf, smb_ofun, unixmode, &smb_action); restore_case_semantics(file_attributes); @@ -836,7 +836,7 @@ int reply_ntcreate_and_X(connection_struct *conn, * before issuing an oplock break request to * our client. JRA. */ - fsp = open_file_shared(conn,fname,smb_open_mode, + fsp = open_file_shared(conn,fname,&sbuf,smb_open_mode, smb_ofun,unixmode, oplock_request,&rmode,&smb_action); if (!fsp) { @@ -873,7 +873,7 @@ int reply_ntcreate_and_X(connection_struct *conn, } oplock_request = 0; - fsp = open_directory(conn, fname, smb_ofun, unixmode, &smb_action); + fsp = open_directory(conn, fname, &sbuf, smb_ofun, unixmode, &smb_action); if(!fsp) { restore_case_semantics(file_attributes); @@ -896,7 +896,7 @@ int reply_ntcreate_and_X(connection_struct *conn, oplock_request = 0; - fsp = open_file_stat(conn,fname,smb_open_mode,&sbuf,&smb_action); + fsp = open_file_stat(conn,fname,&sbuf,smb_open_mode,&smb_action); if(!fsp) { restore_case_semantics(file_attributes); @@ -919,22 +919,6 @@ int reply_ntcreate_and_X(connection_struct *conn, } } - if(fsp->is_directory) { - if(conn->vfs_ops.stat(conn,dos_to_unix(fsp->fsp_name, False), &sbuf) != 0) { - close_file(fsp,True); - restore_case_semantics(file_attributes); - END_PROFILE(SMBntcreateX); - return(ERROR(ERRDOS,ERRnoaccess)); - } - } else { - if (conn->vfs_ops.fstat(fsp,fsp->fd,&sbuf) != 0) { - close_file(fsp,False); - restore_case_semantics(file_attributes); - END_PROFILE(SMBntcreateX); - return(ERROR(ERRDOS,ERRnoaccess)); - } - } - restore_case_semantics(file_attributes); file_len = sbuf.st_size; @@ -1231,7 +1215,7 @@ static int call_nt_transact_create(connection_struct *conn, RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); - unix_convert(fname,conn,0,&bad_path,NULL); + unix_convert(fname,conn,0,&bad_path,&sbuf); unixmode = unix_mode(conn,smb_attr | aARCH, fname); @@ -1249,7 +1233,7 @@ static int call_nt_transact_create(connection_struct *conn, * CreateDirectory() call. */ - fsp = open_directory(conn, fname, smb_ofun, unixmode, &smb_action); + fsp = open_directory(conn, fname, &sbuf, smb_ofun, unixmode, &smb_action); if(!fsp) { restore_case_semantics(file_attributes); @@ -1260,20 +1244,13 @@ static int call_nt_transact_create(connection_struct *conn, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if(conn->vfs_ops.stat(conn,dos_to_unix(fsp->fsp_name, False), - &sbuf) != 0) { - close_file(fsp,True); - restore_case_semantics(file_attributes); - return(ERROR(ERRDOS,ERRnoaccess)); - } - } else { /* * Ordinary file case. */ - fsp = open_file_shared(conn,fname,smb_open_mode,smb_ofun,unixmode, + fsp = open_file_shared(conn,fname,&sbuf,smb_open_mode,smb_ofun,unixmode, oplock_request,&rmode,&smb_action); if (!fsp) { @@ -1291,7 +1268,7 @@ static int call_nt_transact_create(connection_struct *conn, } oplock_request = 0; - fsp = open_directory(conn, fname, smb_ofun, unixmode, &smb_action); + fsp = open_directory(conn, fname, &sbuf, smb_ofun, unixmode, &smb_action); if(!fsp) { restore_case_semantics(file_attributes); @@ -1314,7 +1291,7 @@ static int call_nt_transact_create(connection_struct *conn, oplock_request = 0; - fsp = open_file_stat(conn,fname,smb_open_mode,&sbuf,&smb_action); + fsp = open_file_stat(conn,fname,&sbuf,smb_open_mode,&smb_action); if(!fsp) { restore_case_semantics(file_attributes); @@ -1333,20 +1310,6 @@ static int call_nt_transact_create(connection_struct *conn, } } - if(fsp->is_directory) { - if(conn->vfs_ops.stat(conn,dos_to_unix(fsp->fsp_name,False), &sbuf) != 0) { - close_file(fsp,True); - restore_case_semantics(file_attributes); - return(ERROR(ERRDOS,ERRnoaccess)); - } - } else { - if (!fsp->stat_open && conn->vfs_ops.fstat(fsp,fsp->fd,&sbuf) != 0) { - close_file(fsp,False); - restore_case_semantics(file_attributes); - return(ERROR(ERRDOS,ERRnoaccess)); - } - } - file_len = sbuf.st_size; fmode = dos_mode(conn,fname,&sbuf); if(fmode == 0) diff --git a/source3/smbd/open.c b/source3/smbd/open.c index edd94bd865..12f6d12948 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -88,12 +88,11 @@ static void check_for_pipe(char *fname) ****************************************************************************/ static BOOL open_file(files_struct *fsp,connection_struct *conn, - char *fname1,int flags,mode_t mode) + char *fname1,SMB_STRUCT_STAT *psbuf,int flags,mode_t mode) { extern struct current_user current_user; pstring fname; int accmode = (flags & O_ACCMODE); - SMB_STRUCT_STAT sbuf; fsp->fd = -1; fsp->oplock_type = NO_OPLOCK; @@ -138,10 +137,12 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, return False; } - if (conn->vfs_ops.fstat(fsp,fsp->fd, &sbuf) == -1) { - DEBUG(0,("Error doing fstat on open file %s (%s)\n", fname,strerror(errno) )); - fd_close(conn, fsp); - return False; + if (!VALID_STAT(*psbuf)) { + if (vfs_fstat(fsp,fsp->fd,psbuf) == -1) { + DEBUG(0,("Error doing fstat on open file %s (%s)\n", fname,strerror(errno) )); + fd_close(conn, fsp); + return False; + } } /* @@ -150,18 +151,18 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, * so catch a directory open and return an EISDIR. JRA. */ - if(S_ISDIR(sbuf.st_mode)) { + if(S_ISDIR(psbuf->st_mode)) { fd_close(conn, fsp); errno = EISDIR; return False; } - fsp->mode = sbuf.st_mode; - fsp->inode = sbuf.st_ino; - fsp->dev = sbuf.st_dev; + fsp->mode = psbuf->st_mode; + fsp->inode = psbuf->st_ino; + fsp->dev = psbuf->st_dev; GetTimeOfDay(&fsp->open_time); fsp->vuid = current_user.vuid; - fsp->size = 0; + fsp->size = psbuf->st_size; fsp->pos = -1; fsp->can_lock = True; fsp->can_read = ((flags & O_WRONLY)==0); @@ -513,17 +514,17 @@ static void kernel_flock(files_struct *fsp, int deny_mode) /**************************************************************************** - Open a file with a share mode. + Open a file with a share mode. On output from this open we are guarenteeing + that ****************************************************************************/ -files_struct *open_file_shared(connection_struct *conn,char *fname,int share_mode,int ofun, - mode_t mode,int oplock_request, int *Access,int *action) +files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_STAT *psbuf, + int share_mode,int ofun, mode_t mode,int oplock_request, int *Access,int *action) { int flags=0; int flags2=0; int deny_mode = GET_DENY_MODE(share_mode); BOOL allow_share_delete = GET_ALLOW_SHARE_DELETE(share_mode); - SMB_STRUCT_STAT sbuf; - BOOL file_existed = vfs_file_exist(conn, fname, &sbuf); + BOOL file_existed = VALID_STAT(*psbuf); BOOL fcbopen = False; SMB_DEV_T dev = 0; SMB_INO_T inode = 0; @@ -619,7 +620,7 @@ files_struct *open_file_shared(connection_struct *conn,char *fname,int share_mod #endif /* O_SYNC */ if (flags != O_RDONLY && file_existed && - (!CAN_WRITE(conn) || IS_DOS_READONLY(dos_mode(conn,fname,&sbuf)))) { + (!CAN_WRITE(conn) || IS_DOS_READONLY(dos_mode(conn,fname,psbuf)))) { if (!fcbopen) { DEBUG(5,("open_file_shared: read/write access requested for file %s on read only %s\n", fname, !CAN_WRITE(conn) ? "share" : "file" )); @@ -638,8 +639,9 @@ files_struct *open_file_shared(connection_struct *conn,char *fname,int share_mod } if (file_existed) { - dev = sbuf.st_dev; - inode = sbuf.st_ino; + + dev = psbuf->st_dev; + inode = psbuf->st_ino; lock_share_entry(conn, dev, inode); @@ -659,10 +661,10 @@ files_struct *open_file_shared(connection_struct *conn,char *fname,int share_mod DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", flags,flags2,(int)mode)); - fsp_open = open_file(fsp,conn,fname,flags|(flags2&~(O_TRUNC)),mode); + fsp_open = open_file(fsp,conn,fname,psbuf,flags|(flags2&~(O_TRUNC)),mode); if (!fsp_open && (flags == O_RDWR) && (errno != ENOENT) && fcbopen) { - if((fsp_open = open_file(fsp,conn,fname,O_RDONLY,mode)) == True) + if((fsp_open = open_file(fsp,conn,fname,psbuf,O_RDONLY,mode)) == True) flags = O_RDONLY; } @@ -717,11 +719,16 @@ files_struct *open_file_shared(connection_struct *conn,char *fname,int share_mod * If requested, truncate the file. */ - if ((flags2&O_TRUNC) && (truncate_unless_locked(conn,fsp) == -1)) { - unlock_share_entry_fsp(fsp); - fd_close(conn,fsp); - file_free(fsp); - return NULL; + if (flags2&O_TRUNC) { + /* + * We are modifing the file after open - update the stat struct.. + */ + if ((truncate_unless_locked(conn,fsp) == -1) || (vfs_fstat(fsp,fsp->fd,psbuf)==-1)) { + unlock_share_entry_fsp(fsp); + fd_close(conn,fsp); + file_free(fsp); + return NULL; + } } switch (flags) { @@ -783,28 +790,26 @@ files_struct *open_file_shared(connection_struct *conn,char *fname,int share_mod with the 'stat_open' flag set ****************************************************************************/ -files_struct *open_file_stat(connection_struct *conn, - char *fname, int smb_ofun, SMB_STRUCT_STAT *pst, int *action) +files_struct *open_file_stat(connection_struct *conn, char *fname, + SMB_STRUCT_STAT *psbuf, int smb_ofun, int *action) { extern struct current_user current_user; - files_struct *fsp = file_new(); - - if(!fsp) - return NULL; + files_struct *fsp = NULL; - if(conn->vfs_ops.stat(conn,dos_to_unix(fname, False), pst) < 0) { - DEBUG(0,("open_file_stat: unable to stat name = %s. Error was %s\n", - fname, strerror(errno) )); - file_free(fsp); + if (!VALID_STAT(*psbuf)) { + DEBUG(0,("open_file_stat: unable to stat name = %s. Error was %s\n", fname, strerror(errno) )); return NULL; } - if(S_ISDIR(pst->st_mode)) { + if(S_ISDIR(psbuf->st_mode)) { DEBUG(0,("open_file_stat: %s is a directory !\n", fname )); - file_free(fsp); return NULL; } + fsp = file_new(); + if(!fsp) + return NULL; + *action = FILE_WAS_OPENED; DEBUG(5,("open_file_stat: opening file %s as a stat entry\n", fname)); @@ -814,10 +819,12 @@ files_struct *open_file_stat(connection_struct *conn, */ fsp->fd = -1; - fsp->mode = 0; + fsp->mode = psbuf->st_mode; + fsp->inode = psbuf->st_ino; + fsp->dev = psbuf->st_dev; GetTimeOfDay(&fsp->open_time); + fsp->size = psbuf->st_size; fsp->vuid = current_user.vuid; - fsp->size = 0; fsp->pos = -1; fsp->can_lock = False; fsp->can_read = False; @@ -851,20 +858,18 @@ files_struct *open_file_stat(connection_struct *conn, Open a directory from an NT SMB call. ****************************************************************************/ -files_struct *open_directory(connection_struct *conn, - char *fname, int smb_ofun, mode_t unixmode, int *action) +files_struct *open_directory(connection_struct *conn, char *fname, + SMB_STRUCT_STAT *psbuf, int smb_ofun, mode_t unixmode, int *action) { extern struct current_user current_user; - SMB_STRUCT_STAT st; BOOL got_stat = False; files_struct *fsp = file_new(); if(!fsp) return NULL; - if(conn->vfs_ops.stat(conn,dos_to_unix(fname, False), &st) == 0) { + if (VALID_STAT(*psbuf)) got_stat = True; - } if (got_stat && (GET_FILE_OPEN_DISPOSITION(smb_ofun) == FILE_EXISTS_FAIL)) { file_free(fsp); @@ -876,7 +881,7 @@ files_struct *open_directory(connection_struct *conn, if (got_stat) { - if(!S_ISDIR(st.st_mode)) { + if(!S_ISDIR(psbuf->st_mode)) { DEBUG(0,("open_directory: %s is not a directory !\n", fname )); file_free(fsp); errno = EACCES; @@ -903,6 +908,12 @@ files_struct *open_directory(connection_struct *conn, file_free(fsp); return NULL; } + + if(vfs_stat(conn,fname, psbuf) != 0) { + file_free(fsp); + return NULL; + } + *action = FILE_WAS_CREATED; } @@ -919,7 +930,7 @@ files_struct *open_directory(connection_struct *conn, return NULL; } - if(!S_ISDIR(st.st_mode)) { + if(!S_ISDIR(psbuf->st_mode)) { DEBUG(0,("open_directory: %s is not a directory !\n", fname )); file_free(fsp); return NULL; @@ -928,18 +939,19 @@ files_struct *open_directory(connection_struct *conn, *action = FILE_WAS_OPENED; } - DEBUG(5,("open_directory: opening directory %s\n", - fname)); + DEBUG(5,("open_directory: opening directory %s\n", fname)); /* * Setup the files_struct for it. */ fsp->fd = -1; - fsp->mode = 0; + fsp->mode = psbuf->st_mode; + fsp->inode = psbuf->st_ino; + fsp->dev = psbuf->st_dev; GetTimeOfDay(&fsp->open_time); + fsp->size = psbuf->st_size; fsp->vuid = current_user.vuid; - fsp->size = 0; fsp->pos = -1; fsp->can_lock = True; fsp->can_read = False; @@ -983,7 +995,7 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) SMB_DEV_T dev; SMB_INO_T inode; - if (conn->vfs_ops.stat(conn,dos_to_unix(fname,False),&sbuf) == -1) + if (vfs_stat(conn,fname,&sbuf) == -1) return(True); dev = sbuf.st_dev; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index efd18799a2..4fd9f9c42d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1033,22 +1033,20 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size pstring name; BOOL ok = False; BOOL bad_path = False; - SMB_STRUCT_STAT st; + SMB_STRUCT_STAT sbuf; START_PROFILE(SMBchkpth); pstrcpy(name,smb_buf(inbuf) + 1); RESOLVE_DFSPATH(name, conn, inbuf, outbuf); - unix_convert(name,conn,0,&bad_path,&st); + unix_convert(name,conn,0,&bad_path,&sbuf); mode = SVAL(inbuf,smb_vwv0); if (check_name(name,conn)) { - if(VALID_STAT(st)) - ok = S_ISDIR(st.st_mode); - else - ok = vfs_directory_exist(conn,name,NULL); + if(VALID_STAT(sbuf)) + ok = S_ISDIR(sbuf.st_mode); } if (!ok) @@ -1182,17 +1180,17 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size BOOL ok=False; int mode; time_t mtime; - SMB_STRUCT_STAT st; + SMB_STRUCT_STAT sbuf; BOOL bad_path = False; START_PROFILE(SMBsetatr); pstrcpy(fname,smb_buf(inbuf) + 1); - unix_convert(fname,conn,0,&bad_path,&st); + unix_convert(fname,conn,0,&bad_path,&sbuf); mode = SVAL(inbuf,smb_vwv0); mtime = make_unix_date3(inbuf+smb_vwv1); - if (VALID_STAT_OF_DIR(st) || vfs_directory_exist(conn, fname, NULL)) + if (VALID_STAT_OF_DIR(sbuf)) mode |= aDIR; if (check_name(fname,conn)) ok = (file_chmod(conn,fname,mode,NULL) == 0); @@ -1292,11 +1290,12 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (status_len == 0) { + SMB_STRUCT_STAT sbuf; pstring dir2; pstrcpy(directory,smb_buf(inbuf)+1); pstrcpy(dir2,smb_buf(inbuf)+1); - unix_convert(directory,conn,0,&bad_path,NULL); + unix_convert(directory,conn,0,&bad_path,&sbuf); unix_format(dir2); if (!check_name(directory,conn)) @@ -1517,11 +1516,11 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); - unix_convert(fname,conn,0,&bad_path,NULL); + unix_convert(fname,conn,0,&bad_path,&sbuf); unixmode = unix_mode(conn,aARCH,fname); - fsp = open_file_shared(conn,fname,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), + fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), unixmode, oplock_request,&rmode,NULL); if (!fsp) @@ -1535,12 +1534,6 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (vfs_fstat(fsp,fsp->fd,&sbuf) != 0) { - close_file(fsp,False); - END_PROFILE(SMBopen); - return(ERROR(ERRDOS,ERRnoaccess)); - } - size = sbuf.st_size; fmode = dos_mode(conn,fname,&sbuf); mtime = sbuf.st_mtime; @@ -1618,11 +1611,11 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); - unix_convert(fname,conn,0,&bad_path,NULL); + unix_convert(fname,conn,0,&bad_path,&sbuf); unixmode = unix_mode(conn,smb_attr | aARCH, fname); - fsp = open_file_shared(conn,fname,smb_mode,smb_ofun,unixmode, + fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode, oplock_request, &rmode,&smb_action); if (!fsp) @@ -1636,12 +1629,6 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (vfs_fstat(fsp,fsp->fd,&sbuf) != 0) { - close_file(fsp,False); - END_PROFILE(SMBopenX); - return(ERROR(ERRDOS,ERRnoaccess)); - } - size = sbuf.st_size; fmode = dos_mode(conn,fname,&sbuf); mtime = sbuf.st_mtime; @@ -1737,6 +1724,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, BOOL bad_path = False; files_struct *fsp; int oplock_request = CORE_OPLOCK_REQUEST(inbuf); + SMB_STRUCT_STAT sbuf; START_PROFILE(SMBcreate); com = SVAL(inbuf,smb_com); @@ -1746,12 +1734,11 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); - unix_convert(fname,conn,0,&bad_path,NULL); + unix_convert(fname,conn,0,&bad_path,&sbuf); - if (createmode & aVOLID) - { + if (createmode & aVOLID) { DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname)); - } + } unixmode = unix_mode(conn,createmode,fname); @@ -1767,7 +1754,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, } /* Open file in dos compatibility share mode. */ - fsp = open_file_shared(conn,fname,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), + fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), ofun, unixmode, oplock_request, NULL, NULL); if (!fsp) @@ -1813,23 +1800,27 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, BOOL bad_path = False; files_struct *fsp; int oplock_request = CORE_OPLOCK_REQUEST(inbuf); + SMB_STRUCT_STAT sbuf; START_PROFILE(SMBctemp); - + createmode = SVAL(inbuf,smb_vwv0); pstrcpy(fname,smb_buf(inbuf)+1); pstrcat(fname,"/TMXXXXXX"); RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); - unix_convert(fname,conn,0,&bad_path,NULL); + unix_convert(fname,conn,0,&bad_path,&sbuf); unixmode = unix_mode(conn,createmode,fname); pstrcpy(fname2,(char *)smbd_mktemp(fname)); + /* This file should not exist. */ + ZERO_STRUCT(sbuf); + vfs_stat(conn,fname2,&sbuf); /* Open file in dos compatibility share mode. */ /* We should fail if file exists. */ - fsp = open_file_shared(conn,fname2,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), + fsp = open_file_shared(conn,fname2,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unixmode, oplock_request, NULL, NULL); if (!fsp) @@ -1904,6 +1895,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size BOOL exists=False; BOOL bad_path = False; BOOL rc = True; + SMB_STRUCT_STAT sbuf; START_PROFILE(SMBunlink); *directory = *mask = 0; @@ -1916,7 +1908,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size DEBUG(3,("reply_unlink : %s\n",name)); - rc = unix_convert(name,conn,0,&bad_path,NULL); + rc = unix_convert(name,conn,0,&bad_path,&sbuf); p = strrchr(name,'/'); if (!p) { @@ -1948,7 +1940,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (can_delete(directory,conn,dirtype) && !vfs_unlink(conn,directory)) count++; if (!count) - exists = vfs_file_exist(conn,directory,NULL); + exists = vfs_file_exist(conn,directory,&sbuf); } else { void *dirptr = NULL; char *dname; @@ -3281,9 +3273,10 @@ int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_ int mkdir_internal(connection_struct *conn, char *inbuf, char *outbuf, pstring directory) { BOOL bad_path = False; + SMB_STRUCT_STAT sbuf; int ret= -1; - unix_convert(directory,conn,0,&bad_path,NULL); + unix_convert(directory,conn,0,&bad_path,&sbuf); if (check_name(directory, conn)) ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory)); @@ -3482,13 +3475,14 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int outsize = 0; BOOL ok = False; BOOL bad_path = False; + SMB_STRUCT_STAT sbuf; START_PROFILE(SMBrmdir); pstrcpy(directory,smb_buf(inbuf) + 1); RESOLVE_DFSPATH(directory, conn, inbuf, outbuf) - unix_convert(directory,conn, NULL,&bad_path,NULL); + unix_convert(directory,conn, NULL,&bad_path,&sbuf); if (check_name(directory,conn)) { @@ -3614,12 +3608,13 @@ int rename_internals(connection_struct *conn, int error = ERRnoaccess; BOOL exists=False; BOOL rc = True; - pstring zdirectory; + SMB_STRUCT_STAT sbuf1, sbuf2; + pstring zdirectory; *directory = *mask = 0; - rc = unix_convert(name,conn,0,&bad_path1,NULL); - unix_convert(newname,conn,newname_last_component,&bad_path2,NULL); + rc = unix_convert(name,conn,0,&bad_path1,&sbuf1); + unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2); /* * Split the old name into directory and last component @@ -3855,7 +3850,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, int count,BOOL target_is_directory, int *err_ret) { int Access,action; - SMB_STRUCT_STAT st; + SMB_STRUCT_STAT src_sbuf, sbuf2; SMB_OFF_T ret=-1; files_struct *fsp1,*fsp2; pstring dest; @@ -3873,10 +3868,10 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, pstrcat(dest,p); } - if (!vfs_file_exist(conn,src,&st)) + if (!vfs_file_exist(conn,src,&src_sbuf)) return(False); - fsp1 = open_file_shared(conn,src,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY), + fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action); if (!fsp1) { @@ -3884,10 +3879,11 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, } if (!target_is_directory && count) - ofun = 1; + ofun = FILE_EXISTS_OPEN; - fsp2 = open_file_shared(conn,dest,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY), - ofun,st.st_mode,0,&Access,&action); + vfs_stat(conn,dest,&sbuf2); + fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY), + ofun,src_sbuf.st_mode,0,&Access,&action); if (!fsp2) { close_file(fsp1,False); @@ -3902,12 +3898,12 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, * Stop the copy from occurring. */ ret = -1; - st.st_size = 0; + src_sbuf.st_size = 0; } } - if (st.st_size) - ret = vfs_transfer_file(-1, fsp1, -1, fsp2, st.st_size, NULL, 0, 0); + if (src_sbuf.st_size) + ret = vfs_transfer_file(-1, fsp1, -1, fsp2, src_sbuf.st_size, NULL, 0, 0); close_file(fsp1,False); /* @@ -3918,7 +3914,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, */ *err_ret = close_file(fsp2,False); - return(ret == (SMB_OFF_T)st.st_size); + return(ret == (SMB_OFF_T)src_sbuf.st_size); } @@ -3945,6 +3941,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, BOOL bad_path1 = False; BOOL bad_path2 = False; BOOL rc = True; + SMB_STRUCT_STAT sbuf1, sbuf2; START_PROFILE(SMBcopy); *directory = *mask = 0; @@ -3964,10 +3961,10 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, RESOLVE_DFSPATH(name, conn, inbuf, outbuf); RESOLVE_DFSPATH(newname, conn, inbuf, outbuf); - rc = unix_convert(name,conn,0,&bad_path1,NULL); - unix_convert(newname,conn,0,&bad_path2,NULL); + rc = unix_convert(name,conn,0,&bad_path1,&sbuf1); + unix_convert(newname,conn,0,&bad_path2,&sbuf2); - target_is_directory = vfs_directory_exist(conn,False,NULL); + target_is_directory = VALID_STAT_OF_DIR(sbuf2); if ((flags&1) && target_is_directory) { END_PROFILE(SMBcopy); @@ -3979,7 +3976,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(ERROR(ERRDOS,ERRbadpath)); } - if ((flags&(1<<5)) && vfs_directory_exist(conn,name,NULL)) { + if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) { /* wants a tree copy! XXXX */ DEBUG(3,("Rejecting tree copy\n")); END_PROFILE(SMBcopy); diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 8d756a1d46..8200c277b3 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -193,7 +193,7 @@ BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath, scp = (stat_cache_entry *)(hash_elem->value); DO_PROFILE_INC(statcache_hits); trans_name = scp->names+scp->name_len+1; - if(conn->vfs_ops.stat(conn,dos_to_unix(trans_name,False), pst) != 0) { + if(vfs_stat(conn,trans_name, pst) != 0) { /* Discard this entry - it doesn't exist in the filesystem. */ hash_remove(&stat_cache, hash_elem); return False; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 7e2c25109a..17a362fb5c 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -224,7 +224,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, /* XXXX we need to handle passed times, sattr and flags */ - unix_convert(fname,conn,0,&bad_path,NULL); + unix_convert(fname,conn,0,&bad_path,&sbuf); if (!check_name(fname,conn)) { @@ -238,7 +238,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, unixmode = unix_mode(conn,open_attr | aARCH, fname); - fsp = open_file_shared(conn,fname,open_mode,open_ofun,unixmode, + fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,unixmode, oplock_request, &rmode,&smb_action); if (!fsp) @@ -251,11 +251,6 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (fsp->conn->vfs_ops.fstat(fsp,fsp->fd,&sbuf) != 0) { - close_file(fsp,False); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - size = sbuf.st_size; fmode = dos_mode(conn,fname,&sbuf); mtime = sbuf.st_mtime; @@ -407,7 +402,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, if(needslash) pstrcat(pathreal,"/"); pstrcat(pathreal,dname); - if (conn->vfs_ops.stat(conn,dos_to_unix(pathreal,False),&sbuf) != 0) + if (vfs_stat(conn,pathreal,&sbuf) != 0) { /* Needed to show the msdfs symlinks as directories */ if(!lp_host_msdfs() || !lp_msdfs_root(SNUM(conn)) @@ -657,6 +652,7 @@ static int call_trans2findfirst(connection_struct *conn, BOOL out_of_space = False; int space_remaining; BOOL bad_path = False; + SMB_STRUCT_STAT sbuf; *directory = *mask = 0; @@ -686,7 +682,7 @@ static int call_trans2findfirst(connection_struct *conn, DEBUG(5,("path=%s\n",directory)); - unix_convert(directory,conn,0,&bad_path,NULL); + unix_convert(directory,conn,0,&bad_path,&sbuf); if(!check_name(directory,conn)) { if((errno == ENOENT) && bad_path) { @@ -1112,7 +1108,7 @@ static int call_trans2qfsinfo(connection_struct *conn, DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level)); - if(conn->vfs_ops.stat(conn,".",&st)!=0) { + if(vfs_stat(conn,".",&st)!=0) { DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno))); return (ERROR(ERRSRV,ERRinvdevice)); } @@ -1308,7 +1304,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, fname = fsp->fsp_name; unix_convert(fname,conn,0,&bad_path,&sbuf); if (!check_name(fname,conn) || - (!VALID_STAT(sbuf) && conn->vfs_ops.stat(conn,dos_to_unix(fname,False),&sbuf))) { + (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf))) { DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); if((errno == ENOENT) && bad_path) { @@ -1328,7 +1324,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, CHECK_ERROR(fsp); fname = fsp->fsp_name; - if (fsp->conn->vfs_ops.fstat(fsp,fsp->fd,&sbuf) != 0) { + if (vfs_fstat(fsp,fsp->fd,&sbuf) != 0) { DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); return(UNIXERROR(ERRDOS,ERRbadfid)); } @@ -1350,7 +1346,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, unix_convert(fname,conn,0,&bad_path,&sbuf); if (!check_name(fname,conn) || - (!VALID_STAT(sbuf) && conn->vfs_ops.stat(conn,dos_to_unix(fname,False),&sbuf))) { + (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf))) { DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); if((errno == ENOENT) && bad_path) { @@ -1567,7 +1563,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, int mode=0; SMB_OFF_T size=0; struct utimbuf tvs; - SMB_STRUCT_STAT st; + SMB_STRUCT_STAT sbuf; pstring fname1; char *fname; int fd = -1; @@ -1588,9 +1584,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, * to do this call. JRA. */ fname = fsp->fsp_name; - unix_convert(fname,conn,0,&bad_path,&st); - if (!check_name(fname,conn) || - (!VALID_STAT(st) && conn->vfs_ops.stat(conn,dos_to_unix(fname,False),&st))) { + unix_convert(fname,conn,0,&bad_path,&sbuf); + if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) { DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); if((errno == ENOENT) && bad_path) { @@ -1609,7 +1604,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, fname = fsp->fsp_name; fd = fsp->fd; - if (fsp->conn->vfs_ops.fstat(fsp,fd,&st) != 0) { + if (vfs_fstat(fsp,fd,&sbuf) != 0) { DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); return(UNIXERROR(ERRDOS,ERRbadfid)); } @@ -1619,7 +1614,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, info_level = SVAL(params,0); fname = fname1; pstrcpy(fname,¶ms[6]); - unix_convert(fname,conn,0,&bad_path,&st); + unix_convert(fname,conn,0,&bad_path,&sbuf); if(!check_name(fname, conn)) { if((errno == ENOENT) && bad_path) @@ -1630,7 +1625,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, return(UNIXERROR(ERRDOS,ERRbadpath)); } - if(!VALID_STAT(st) && conn->vfs_ops.stat(conn,dos_to_unix(fname,False),&st)!=0) { + if(!VALID_STAT(sbuf)) { DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno))); if((errno == ENOENT) && bad_path) { @@ -1651,10 +1646,10 @@ static int call_trans2setfilepathinfo(connection_struct *conn, SSVAL(params,0,0); - size = st.st_size; - tvs.modtime = st.st_mtime; - tvs.actime = st.st_atime; - mode = dos_mode(conn,fname,&st); + size = sbuf.st_size; + tvs.modtime = sbuf.st_mtime; + tvs.actime = sbuf.st_atime; + mode = dos_mode(conn,fname,&sbuf); if (total_data > 0 && IVAL(pdata,0) == total_data) { /* uggh, EAs for OS2 */ @@ -1908,10 +1903,10 @@ dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode)) /* get some defaults (no modifications) if any info is zero or -1. */ if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1) - tvs.actime = st.st_atime; + tvs.actime = sbuf.st_atime; if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1) - tvs.modtime = st.st_mtime; + tvs.modtime = sbuf.st_mtime; DEBUG(6,("actime: %s " , ctime(&tvs.actime))); DEBUG(6,("modtime: %s ", ctime(&tvs.modtime))); @@ -1925,13 +1920,13 @@ dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode)) * changing the size of a file. */ if (!size) - size = st.st_size; + size = sbuf.st_size; } /* Try and set the times, size and mode of this file - if they are different from the current values */ - if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime) { + if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) { if(fsp != NULL) { /* * This was a setfileinfo on an open file. @@ -1957,7 +1952,7 @@ dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode)) } /* check the mode isn't different, before changing it */ - if ((mode != 0) && (mode != dos_mode(conn, fname, &st))) { + if ((mode != 0) && (mode != dos_mode(conn, fname, &sbuf))) { DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, mode )); @@ -1968,7 +1963,7 @@ dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode)) } } - if(size != st.st_size) { + if(size != sbuf.st_size) { DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n", fname, (double)size )); @@ -2004,6 +1999,7 @@ static int call_trans2mkdir(connection_struct *conn, char *params = *pparams; pstring directory; int ret = -1; + SMB_STRUCT_STAT sbuf; BOOL bad_path = False; if (!CAN_WRITE(conn)) @@ -2013,7 +2009,7 @@ static int call_trans2mkdir(connection_struct *conn, DEBUG(3,("call_trans2mkdir : name = %s\n", directory)); - unix_convert(directory,conn,0,&bad_path,NULL); + unix_convert(directory,conn,0,&bad_path,&sbuf); if (check_name(directory,conn)) ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory)); diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 467f3e47a2..2f984aee4f 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -323,6 +323,8 @@ BOOL vfs_file_exist(connection_struct *conn,char *fname,SMB_STRUCT_STAT *sbuf) if (!sbuf) sbuf = &st; + + ZERO_STRUCTP(sbuf); if (vfs_stat(conn,fname,sbuf) != 0) return(False); |