summaryrefslogtreecommitdiff
path: root/source3/smbd/nttrans.c
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>1998-07-17 22:21:24 +0000
committerJeremy Allison <jra@samba.org>1998-07-17 22:21:24 +0000
commit471087c9d28a4058efc16f98784cb179ffc1e4c4 (patch)
treeaccca93b43b77c8a46b2b78891d64a822ec3a403 /source3/smbd/nttrans.c
parent18067a7f0c7153d5298ab1e6530ace4f25f926e7 (diff)
downloadsamba-471087c9d28a4058efc16f98784cb179ffc1e4c4.tar.gz
samba-471087c9d28a4058efc16f98784cb179ffc1e4c4.tar.bz2
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.c81
1 files changed, 59 insertions, 22 deletions
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index 8f7f40b4f9..672e2c0802 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);
}