diff options
author | Jeremy Allison <jra@samba.org> | 1998-07-17 22:21:24 +0000 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 1998-07-17 22:21:24 +0000 |
commit | 471087c9d28a4058efc16f98784cb179ffc1e4c4 (patch) | |
tree | accca93b43b77c8a46b2b78891d64a822ec3a403 /source3/smbd/nttrans.c | |
parent | 18067a7f0c7153d5298ab1e6530ace4f25f926e7 (diff) | |
download | samba-471087c9d28a4058efc16f98784cb179ffc1e4c4.tar.gz samba-471087c9d28a4058efc16f98784cb179ffc1e4c4.tar.xz samba-471087c9d28a4058efc16f98784cb179ffc1e4c4.zip |
Code added to fix the renaming of a directory under NT SMB calls.
local.h: Changed MAXDIR to MAX_OPEN_DIRECTORIES - shmem size also tuned by this.
dir.c: Use MAX_OPEN_DIRECTORIES.
nttrans.c: Allow opening of a directory to succeed. Doesn't actually open
a file descriptor but takes a files_struct slot marked as an
fd.
reply.c: Changed to close any outstanding is_directory files.
reply_close changed to understand directory files.
server.c: Added open_directory(), close_directory() calls.
smb.h: Added is_directory to files_struct.
Changed OPEN_FNUM to check that target is !is_directory (this
prevents the normal file calls from processing a directory
files_struct.
Jeremy.
(This used to be commit e01ce693f47e75e277f3440d46e32b0bd866b550)
Diffstat (limited to 'source3/smbd/nttrans.c')
-rw-r--r-- | source3/smbd/nttrans.c | 81 |
1 files changed, 59 insertions, 22 deletions
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 8f7f40b4f99..672e2c0802a 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -476,12 +476,14 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) return(ERROR(ERRSRV,ERRnofids)); } + fsp = &Files[fnum]; + if (!check_name(fname,cnum)) { if((errno == ENOENT) && bad_path) { unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - Files[fnum].reserved = False; + fsp->reserved = False; restore_case_semantics(file_attributes); @@ -493,39 +495,72 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; + /* + * NB. We have a potential bug here. If we cause an oplock + * break to ourselves, then we could end up processing filename + * related SMB requests whilst we await the oplock break + * response. As we may have changed the filename case + * semantics to be POSIX-like, this could mean a filename + * request could fail when it should succeed. This is a + * rare condition, but eventually we must arrange to restore + * the correct case semantics before issuing an oplock break + * request to our client. JRA. + */ + open_file_shared(fnum,cnum,fname,smb_open_mode,smb_ofun,unixmode, oplock_request,&rmode,&smb_action); - fsp = &Files[fnum]; - - if (!fsp->open) { - if((errno == ENOENT) && bad_path) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - Files[fnum].reserved = False; + restore_case_semantics(file_attributes); - restore_case_semantics(file_attributes); + if (!fsp->open) { + /* + * We cheat here. The only case we care about is a directory + * rename, where the NT client will attempt to open the source + * directory for DELETE access. Note that when the NT client + * does this it does *not* set the directory bit in the + * request packet. This is translated into a read/write open + * request. POSIX states that any open for write request on a directory + * will generate an EISDIR error, so we can catch this here and open + * a pseudo handle that is flagged as a directory. JRA. + */ - return(UNIXERROR(ERRDOS,ERRnoaccess)); + if(errno == EISDIR) { + oplock_request = 0; + open_directory(fnum, cnum, fname, &smb_action); + + if(!fsp->open) { + fsp->reserved = False; + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + } else { + if((errno == ENOENT) && bad_path) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } + + fsp->reserved = False; + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } } - if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { - close_file(fnum,False); - - restore_case_semantics(file_attributes); - - return(ERROR(ERRDOS,ERRnoaccess)); - } + if(fsp->is_directory) { + if(stat(fsp->name, &sbuf) != 0) { + close_directory(fnum); + return(ERROR(ERRDOS,ERRnoaccess)); + } + } else { + if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + close_file(fnum,False); + return(ERROR(ERRDOS,ERRnoaccess)); + } + } - restore_case_semantics(file_attributes); - file_len = sbuf.st_size; fmode = dos_mode(cnum,fname,&sbuf); if(fmode == 0) fmode = FILE_ATTRIBUTE_NORMAL; mtime = sbuf.st_mtime; - if (fmode & aDIR) { + if (!fsp->is_directory && (fmode & aDIR)) { close_file(fnum,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -591,10 +626,12 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) } else { SIVAL(p,0,file_len); } + p += 12; + SCVAL(p,0,fsp->is_directory ? 1 : 0); } chain_fnum = fnum; - + return chain_reply(inbuf,outbuf,length,bufsize); } |