From 7284bb5ca049a682097bb25afcf25d40f1ac5479 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 30 Jul 1998 21:18:57 +0000 Subject: Makefile.in: Moved UBIQX stuff into UTILOBJ. loadparm.c: Added "ole locking compatibility" option (default "true"). locking.c: Changes to implement union in files_struct. locking_shm.c: Changes to implement union in files_struct. nttrans.c: Made opening a directory explicit (we have to). Added create directory code for nttrans. reply.c: Changes to implement union in files_struct. server.c: Changes to implement union in files_struct. Added create directory code. trans2.c: Changes to implement union in files_struct. smb.h: Changes to implement union in files_struct. util.c: Changed linked list code to UNIQX linked list. This will make the other lists I need to implement for ChangeNotify and blocking locks easier. Jeremy. (This used to be commit 3a5eea850bb256b39cff8ace1e4fb4e0c1f5472b) --- source3/Makefile.in | 7 +- source3/include/proto.h | 5 +- source3/include/smb.h | 18 +++- source3/lib/util.c | 80 ++++++++------- source3/locking/locking.c | 10 +- source3/locking/locking_shm.c | 12 +-- source3/param/loadparm.c | 4 + source3/smbd/nttrans.c | 220 ++++++++++++++++++++++++++---------------- source3/smbd/reply.c | 140 +++++++++++++++------------ source3/smbd/server.c | 169 ++++++++++++++++++++------------ source3/smbd/trans2.c | 20 ++-- 11 files changed, 415 insertions(+), 270 deletions(-) diff --git a/source3/Makefile.in b/source3/Makefile.in index 730fdddf3d..e5a6bfc36a 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -131,7 +131,8 @@ PASSDB_OBJ = passdb.o ldap.o smbpass.o nisppass.o smbpassfile.o UTILOBJ1 = util.o system.o charset.o kanji.o fault.o smbencrypt.o smbdes.o charcnv.o genrand.o UTILOBJ2 = $(UTILOBJ1) md4.o loadparm.o params.o pcap.o username.o time.o membuffer.o namequery.o nmblib.o UTILOBJ3 = $(UTILOBJ2) signal.o netmask.o dfree.o -UTILOBJ = $(UTILOBJ3) credentials.o interface.o replace.o print_svid.o smberr.o pidfile.o slprintf.o $(SSL_OBJ) +UTILOBJ = $(UTILOBJ3) credentials.o interface.o replace.o print_svid.o smberr.o pidfile.o slprintf.o \ + $(SSL_OBJ) $(UBIOBJ) # Client utility object files. CLIENTUTIL = clientgen.o nterr.o @@ -141,7 +142,7 @@ SMBDOBJ1 = $(UTILOBJ) trans2.o nttrans.o message.o dir.o printing.o SMBDOBJ2 = ipc.o reply.o mangle.o chgpasswd.o password.o quotas.o uid.o SMBDOBJ3 = predict.o pipes.o server.o access.o SMBDOBJ4 = ufc.o connection.o groupname.o -SMBDOBJ = $(SMBDOBJ1) $(SMBDOBJ2) $(SMBDOBJ3) $(SMBDOBJ4) $(UBIOBJ) $(RPC_OBJ) $(RPC_SERV_OBJ) \ +SMBDOBJ = $(SMBDOBJ1) $(SMBDOBJ2) $(SMBDOBJ3) $(SMBDOBJ4) $(RPC_OBJ) $(RPC_SERV_OBJ) \ $(RPC_CLIENT_SERVER_SUBSET_OBJ) $(VTP_OBJ) $(LOCKOBJ) $(CLIENTUTIL) $(PASSDB_OBJ) # object code needed for programs that handle the the locking files @@ -155,7 +156,7 @@ NMBDOBJ4 = nmbd_sendannounce.o nmbd_processlogon.o nmbd_incomingdgrams.o NMBDOBJ5 = asyncdns.o nmbd_winsserver.o nmbd_incomingrequests.o nmbd_nameregister.o NMBDOBJ6 = nmbd_namerelease.o nmbd_namequery.o nmbd_become_lmb.o nmbd_elections.o nmbd_namelistdb.o -NMBDOBJ = $(UTILOBJ) $(NMBDOBJ1) $(NMBDOBJ2) $(NMBDOBJ3) $(NMBDOBJ4) $(NMBDOBJ5) $(NMBDOBJ6) $(CLIENTUTIL) $(UBIOBJ) +NMBDOBJ = $(UTILOBJ) $(NMBDOBJ1) $(NMBDOBJ2) $(NMBDOBJ3) $(NMBDOBJ4) $(NMBDOBJ5) $(NMBDOBJ6) $(CLIENTUTIL) # object files for smbclient CLIENT_OBJ = client.o clientutil.o clitar.o getsmbpass.o $(UTILOBJ) diff --git a/source3/include/proto.h b/source3/include/proto.h index 955d746125..56d72bd339 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -1023,6 +1023,7 @@ BOOL lp_bind_interfaces_only(void); BOOL lp_net_wksta_user_logon(void); BOOL lp_unix_password_sync(void); BOOL lp_passwd_chat_debug(void); +BOOL lp_ole_locking_compat(void); int lp_os_level(void); int lp_max_ttl(void); int lp_max_wins_ttl(void); @@ -1804,7 +1805,7 @@ BOOL check_name(char *name,int cnum); void sync_file(int cnum, int fnum); void close_file(int fnum, BOOL normal_close); void close_directory(int fnum); -void open_directory(int fnum,int cnum,char *fname, int *action); +int open_directory(int fnum,int cnum,char *fname, int smb_ofun, int unixmode, int *action); BOOL check_file_sharing(int cnum,char *fname, BOOL rename_op); int check_share_mode( share_mode_entry *share, int deny_mode, char *fname, BOOL fcbopen, int *flags); @@ -2043,7 +2044,7 @@ int read_smb_length(int fd,char *inbuf,int timeout); BOOL receive_smb(int fd,char *buffer, int timeout); BOOL client_receive_smb(int fd,char *buffer, int timeout); BOOL receive_local_message(int fd, char *buffer, int buffer_len, int timeout); -BOOL push_smb_message(char *buf, int msg_len); +BOOL push_oplock_pending_smb_message(char *buf, int msg_len); BOOL receive_message_or_smb(int smbfd, int oplock_fd, char *buffer, int buffer_len, int timeout, BOOL *got_smb); diff --git a/source3/include/smb.h b/source3/include/smb.h index 8d846d4531..115d8ce31b 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -169,6 +169,7 @@ implemented */ #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 supported */ +#define ERROR_NOTIFY_ENUM_DIR 1022 /* Buffer too small to return change notify. */ #define ERRunknownipc 2142 @@ -437,10 +438,24 @@ typedef struct int real_open_flags; } file_fd_struct; +/* + * Structure used to keep directory state information around. + * Used in NT change-notify code. + */ + +typedef struct +{ + time_t modify_time; + time_t status_time; +} dir_status_struct; + typedef struct { int cnum; - file_fd_struct *fd_ptr; + union { + file_fd_struct *fd_ptr; + dir_status_struct *dir_ptr; + } f_u; int pos; uint32 size; int mode; @@ -463,7 +478,6 @@ typedef struct char *name; } files_struct; - struct uid_cache { int entries; int list[UID_CACHE_SIZE]; diff --git a/source3/lib/util.c b/source3/lib/util.c index 35fb80be09..e14211ebd7 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -2611,27 +2611,27 @@ BOOL receive_local_message(int fd, char *buffer, int buffer_len, int timeout) for processing. ****************************************************************************/ -typedef struct _message_list { - struct _message_list *msg_next; +typedef struct smb_message_list { + ubi_slNode msg_next; char *msg_buf; int msg_len; } pending_message_list; -static pending_message_list *smb_msg_head = NULL; +static ubi_slList smb_oplock_queue = { NULL, (ubi_slNodePtr)&smb_oplock_queue, 0}; /**************************************************************************** - Function to push a linked list of local messages ready + Function to push a message onto the tail of a linked list of smb messages ready for processing. ****************************************************************************/ -static BOOL push_local_message(pending_message_list **pml, char *buf, int msg_len) +static BOOL push_local_message(ubi_slList *list_head, char *buf, int msg_len) { pending_message_list *msg = (pending_message_list *) malloc(sizeof(pending_message_list)); if(msg == NULL) { - DEBUG(0,("push_message: malloc fail (1)\n")); + DEBUG(0,("push_local_message: malloc fail (1)\n")); return False; } @@ -2646,20 +2646,19 @@ static BOOL push_local_message(pending_message_list **pml, char *buf, int msg_le memcpy(msg->msg_buf, buf, msg_len); msg->msg_len = msg_len; - msg->msg_next = *pml; - *pml = msg; + ubi_slAddTail( list_head, msg); return True; } /**************************************************************************** - Function to push a linked list of local smb messages ready + Function to push a smb message onto a linked list of local smb messages ready for processing. ****************************************************************************/ -BOOL push_smb_message(char *buf, int msg_len) +BOOL push_oplock_pending_smb_message(char *buf, int msg_len) { - return push_local_message(&smb_msg_head, buf, msg_len); + return push_local_message(&smb_oplock_queue, buf, msg_len); } /**************************************************************************** @@ -2699,11 +2698,10 @@ BOOL receive_message_or_smb(int smbfd, int oplock_fd, * If so - copy and return it. */ - if(smb_msg_head) + if(ubi_slCount(&smb_oplock_queue) != 0) { - pending_message_list *msg = smb_msg_head; + pending_message_list *msg = (pending_message_list *)ubi_slRemHead(&smb_oplock_queue); memcpy(buffer, msg->msg_buf, MIN(buffer_len, msg->msg_len)); - smb_msg_head = msg->msg_next; /* Free the message we just copied. */ free((char *)msg->msg_buf); @@ -4629,35 +4627,47 @@ BOOL fcntl_lock(int fd,int op,uint32 offset,uint32 count,int type) struct flock lock; int ret; -#if 1 - uint32 mask = 0xC0000000; + /* + * FIXME. + * NB - this code will need re-writing to cope with large (64bit) + * lock requests. JRA. + */ - /* make sure the count is reasonable, we might kill the lockd otherwise */ - count &= ~mask; + if(lp_ole_locking_compat()) { + uint32 mask = 0xC0000000; - /* the offset is often strange - remove 2 of its bits if either of - the top two bits are set. Shift the top ones by two bits. This - still allows OLE2 apps to operate, but should stop lockd from - dieing */ - if ((offset & mask) != 0) - offset = (offset & ~mask) | ((offset & mask) >> 2); -#else - uint32 mask = ((unsigned)1<<31); - - /* interpret negative counts as large numbers */ - if (count < 0) + /* make sure the count is reasonable, we might kill the lockd otherwise */ count &= ~mask; - /* no negative offsets */ - offset &= ~mask; + /* the offset is often strange - remove 2 of its bits if either of + the top two bits are set. Shift the top ones by two bits. This + still allows OLE2 apps to operate, but should stop lockd from + dieing */ + if ((offset & mask) != 0) + offset = (offset & ~mask) | ((offset & mask) >> 2); + } else { + uint32 mask = ((unsigned)1<<31); + int32 s_count = (int32) count; /* Signed count. */ + int32 s_offset = (int32)offset; /* Signed offset. */ + + /* interpret negative counts as large numbers */ + if (s_count < 0) + s_count &= ~mask; + + /* no negative offsets */ + if(s_offset < 0) + s_offset &= ~mask; - /* count + offset must be in range */ - while ((offset < 0 || (offset + count < 0)) && mask) + /* count + offset must be in range */ + while ((s_offset < 0 || (s_offset + s_count < 0)) && mask) { - offset &= ~mask; + s_offset &= ~mask; mask = mask >> 1; } -#endif + + offset = (uint32)s_offset; + count = (uint32)s_count; + } DEBUG(8,("fcntl_lock %d %d %d %d %d\n",fd,op,(int)offset,(int)count,type)); diff --git a/source3/locking/locking.c b/source3/locking/locking.c index e303fb5482..1b01efd7ef 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -45,7 +45,7 @@ static struct share_ops *share_ops; static int map_lock_type( files_struct *fsp, int lock_type) { - if((lock_type == F_WRLCK) && (fsp->fd_ptr->real_open_flags == O_RDONLY)) { + if((lock_type == F_WRLCK) && (fsp->f_u.fd_ptr->real_open_flags == O_RDONLY)) { /* * Many UNIX's cannot get a write lock on a file opened read-only. * Win32 locking semantics allow this. @@ -53,7 +53,7 @@ static int map_lock_type( files_struct *fsp, int lock_type) */ DEBUG(10,("map_lock_type: Downgrading write lock to read due to read-only file.\n")); return F_RDLCK; - } else if( (lock_type == F_RDLCK) && (fsp->fd_ptr->real_open_flags == O_WRONLY)) { + } else if( (lock_type == F_RDLCK) && (fsp->f_u.fd_ptr->real_open_flags == O_WRONLY)) { /* * Ditto for read locks on write only files. */ @@ -90,7 +90,7 @@ BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset, int lock_type) * fd. So we don't need to use map_lock_type here. */ - return(fcntl_lock(fsp->fd_ptr->fd,F_GETLK,offset,count,lock_type)); + return(fcntl_lock(fsp->f_u.fd_ptr->fd,F_GETLK,offset,count,lock_type)); } @@ -114,7 +114,7 @@ BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int lock_type, } if (OPEN_FNUM(fnum) && fsp->can_lock && (fsp->cnum == cnum)) - ok = fcntl_lock(fsp->fd_ptr->fd,F_SETLK,offset,count, + ok = fcntl_lock(fsp->f_u.fd_ptr->fd,F_SETLK,offset,count, map_lock_type(fsp,lock_type)); if (!ok) { @@ -139,7 +139,7 @@ BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 * return(True); if (OPEN_FNUM(fnum) && fsp->can_lock && (fsp->cnum == cnum)) - ok = fcntl_lock(fsp->fd_ptr->fd,F_SETLK,offset,count,F_UNLCK); + ok = fcntl_lock(fsp->f_u.fd_ptr->fd,F_SETLK,offset,count,F_UNLCK); if (!ok) { *eclass = ERRDOS; diff --git a/source3/locking/locking_shm.c b/source3/locking/locking_shm.c index 43a927e14c..95d59a8465 100644 --- a/source3/locking/locking_shm.c +++ b/source3/locking/locking_shm.c @@ -268,8 +268,8 @@ static void shm_del_share_mode(int token, int fnum) BOOL found = False; int pid = getpid(); - dev = Files[fnum].fd_ptr->dev; - inode = Files[fnum].fd_ptr->inode; + dev = Files[fnum].f_u.fd_ptr->dev; + inode = Files[fnum].f_u.fd_ptr->inode; hash_entry = HASH_ENTRY(dev, inode); @@ -396,8 +396,8 @@ static BOOL shm_set_share_mode(int token, int fnum, uint16 port, uint16 op_type) int new_entry_offset; BOOL found = False; - dev = fs_p->fd_ptr->dev; - inode = fs_p->fd_ptr->inode; + dev = fs_p->f_u.fd_ptr->dev; + inode = fs_p->f_u.fd_ptr->inode; hash_entry = HASH_ENTRY(dev, inode); @@ -505,8 +505,8 @@ static BOOL shm_remove_share_oplock(int fnum, int token) BOOL found = False; int pid = getpid(); - dev = Files[fnum].fd_ptr->dev; - inode = Files[fnum].fd_ptr->inode; + dev = Files[fnum].f_u.fd_ptr->dev; + inode = Files[fnum].f_u.fd_ptr->inode; hash_entry = HASH_ENTRY(dev, inode); diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 3e76dca731..4d5ef3d657 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -222,6 +222,7 @@ typedef struct BOOL bNetWkstaUserLogon; BOOL bUnixPasswdSync; BOOL bPasswdChatDebug; + BOOL bOleLockingCompat; } global; static global Globals; @@ -675,6 +676,7 @@ static struct parm_struct parm_table[] = {"share modes", P_BOOL, P_LOCAL, &sDefault.bShareModes, NULL, NULL, FLAG_GLOBAL}, {"oplocks", P_BOOL, P_LOCAL, &sDefault.bOpLocks, NULL, NULL, FLAG_GLOBAL}, {"fake oplocks", P_BOOL, P_LOCAL, &sDefault.bFakeOplocks, NULL, NULL, 0}, + {"ole locking compatibility", P_BOOL, P_GLOBAL, &Globals.bOleLockingCompat, NULL, NULL, FLAG_GLOBAL}, #ifdef WITH_LDAP {"Ldap Options", P_SEP, P_SEPARATOR}, @@ -832,6 +834,7 @@ static void init_globals(void) the code in password.c protects us from this bug. */ Globals.bUnixPasswdSync = False; Globals.bPasswdChatDebug = False; + Globals.bOleLockingCompat = True; #ifdef WITH_LDAP /* default values for ldap */ @@ -1120,6 +1123,7 @@ FN_GLOBAL_BOOL(lp_bind_interfaces_only,&Globals.bBindInterfacesOnly) FN_GLOBAL_BOOL(lp_net_wksta_user_logon,&Globals.bNetWkstaUserLogon) FN_GLOBAL_BOOL(lp_unix_password_sync,&Globals.bUnixPasswdSync) FN_GLOBAL_BOOL(lp_passwd_chat_debug,&Globals.bPasswdChatDebug) +FN_GLOBAL_BOOL(lp_ole_locking_compat,&Globals.bOleLockingCompat) FN_GLOBAL_INTEGER(lp_os_level,&Globals.os_level) FN_GLOBAL_INTEGER(lp_max_ttl,&Globals.max_ttl) diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 9b6cfe1621..4e857c183c 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -424,10 +424,6 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) files_struct *fsp; char *p = NULL; - /* If it's a request for a directory open, fail it. */ - if(flags & OPEN_DIRECTORY) - return(ERROR(ERRDOS,ERRnoaccess)); - /* * We need to construct the open_and_X ofun value from the * NT values, as that's what our code is structured to accept. @@ -459,7 +455,7 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize) } else { /* - * Ordinary file. + * Ordinary file or directory. */ /* @@ -495,66 +491,95 @@ 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. + /* + * If it's a request for a directory open, deal with it separately. */ - open_file_shared(fnum,cnum,fname,smb_open_mode,smb_ofun,unixmode, - oplock_request,&rmode,&smb_action); + if(flags & OPEN_DIRECTORY) { + oplock_request = 0; - restore_case_semantics(file_attributes); + open_directory(fnum, cnum, fname, smb_ofun, unixmode, &smb_action); + + restore_case_semantics(file_attributes); + + if(!fsp->open) { + fsp->reserved = False; + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + } else { + + /* + * Ordinary file case. + */ - 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. + * 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. */ - if(errno == EISDIR) { - oplock_request = 0; - open_directory(fnum, cnum, fname, &smb_action); + open_file_shared(fnum,cnum,fname,smb_open_mode,smb_ofun,unixmode, + oplock_request,&rmode,&smb_action); + + 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. + */ + + if(errno == EISDIR) { + oplock_request = 0; + + open_directory(fnum, cnum, fname, smb_ofun, unixmode, &smb_action); + + if(!fsp->open) { + fsp->reserved = False; + restore_case_semantics(file_attributes); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + } else { + if((errno == ENOENT) && bad_path) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } - if(!fsp->open) { fsp->reserved = False; + + restore_case_semantics(file_attributes); + 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(fsp->is_directory) { - if(stat(fsp->name, &sbuf) != 0) { + if(sys_stat(fsp->name, &sbuf) != 0) { close_directory(fnum); + restore_case_semantics(file_attributes); return(ERROR(ERRDOS,ERRnoaccess)); } } else { - if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (fstat(fsp->f_u.fd_ptr->fd,&sbuf) != 0) { close_file(fnum,False); + restore_case_semantics(file_attributes); return(ERROR(ERRDOS,ERRnoaccess)); } } + restore_case_semantics(file_attributes); + file_len = sbuf.st_size; fmode = dos_mode(cnum,fname,&sbuf); if(fmode == 0) @@ -668,10 +693,6 @@ static int call_nt_transact_create(char *inbuf, char *outbuf, int length, files_struct *fsp; char *p = NULL; - /* If it's a request for a directory open, fail it. */ - if(flags & OPEN_DIRECTORY) - return(ERROR(ERRDOS,ERRnoaccess)); - /* * We need to construct the open_and_X ofun value from the * NT values, as that's what our code is structured to accept. @@ -733,56 +754,85 @@ static int call_nt_transact_create(char *inbuf, char *outbuf, int length, oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; - open_file_shared(fnum,cnum,fname,smb_open_mode,smb_ofun,unixmode, - oplock_request,&rmode,&smb_action); + /* + * If it's a request for a directory open, deal with it separately. + */ - fsp = &Files[fnum]; - - if (!fsp->open) { - if((errno == ENOENT) && bad_path) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; + if(flags & OPEN_DIRECTORY) { + + oplock_request = 0; + + /* + * We will get a create directory here if the Win32 + * app specified a security descriptor in the + * CreateDirectory() call. + */ + + open_directory(fnum, cnum, fname, smb_ofun, unixmode, &smb_action); + + if(!fsp->open) { + fsp->reserved = False; + return(UNIXERROR(ERRDOS,ERRnoaccess)); } - Files[fnum].reserved = False; + } else { - restore_case_semantics(file_attributes); + /* + * Ordinary file case. + */ - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { - close_file(fnum,False); + open_file_shared(fnum,cnum,fname,smb_open_mode,smb_ofun,unixmode, + oplock_request,&rmode,&smb_action); - restore_case_semantics(file_attributes); + fsp = &Files[fnum]; + + if (!fsp->open) { + if((errno == ENOENT) && bad_path) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadpath; + } + Files[fnum].reserved = False; - return(ERROR(ERRDOS,ERRnoaccess)); - } + restore_case_semantics(file_attributes); + + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } - restore_case_semantics(file_attributes); + if (fstat(fsp->f_u.fd_ptr->fd,&sbuf) != 0) { + close_file(fnum,False); - 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) { - close_file(fnum,False); - return(ERROR(ERRDOS,ERRnoaccess)); - } + restore_case_semantics(file_attributes); + + return(ERROR(ERRDOS,ERRnoaccess)); + } - /* - * If the caller set the extended oplock request bit - * and we granted one (by whatever means) - set the - * correct bit for extended oplock reply. - */ + 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) { + close_file(fnum,False); + restore_case_semantics(file_attributes); + return(ERROR(ERRDOS,ERRnoaccess)); + } + + /* + * If the caller set the extended oplock request bit + * and we granted one (by whatever means) - set the + * correct bit for extended oplock reply. + */ - if (oplock_request && lp_fake_oplocks(SNUM(cnum))) - smb_action |= EXTENDED_OPLOCK_GRANTED; + if (oplock_request && lp_fake_oplocks(SNUM(cnum))) + smb_action |= EXTENDED_OPLOCK_GRANTED; - if(oplock_request && fsp->granted_oplock) - smb_action |= EXTENDED_OPLOCK_GRANTED; + if(oplock_request && fsp->granted_oplock) + smb_action |= EXTENDED_OPLOCK_GRANTED; + } } + restore_case_semantics(file_attributes); + /* Realloc the size of parameters and data we will return */ params = *ppparams = Realloc(*ppparams, 69); if(params == NULL) @@ -972,7 +1022,7 @@ int reply_nttrans(char *inbuf,char *outbuf,int length,int bufsize) DEBUG(2,("%s: reply_nttrans: queueing message NT_TRANSACT_CREATE \ due to being in oplock break state.\n", timestring() )); - push_smb_message( inbuf, length); + push_oplock_pending_smb_message( inbuf, length); return -1; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f05ba2eee6..2845d5650a 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1287,6 +1287,8 @@ int reply_open(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if (fnum < 0) return(ERROR(ERRSRV,ERRnofids)); + fsp = &Files[fnum]; + if (!check_name(fname,cnum)) { if((errno == ENOENT) && bad_path) @@ -1294,7 +1296,7 @@ int reply_open(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - Files[fnum].reserved = False; + fsp->reserved = False; return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1303,8 +1305,6 @@ int reply_open(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) open_file_shared(fnum,cnum,fname,share_mode,3,unixmode, oplock_request,&rmode,NULL); - fsp = &Files[fnum]; - if (!fsp->open) { if((errno == ENOENT) && bad_path) @@ -1312,11 +1312,11 @@ int reply_open(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - Files[fnum].reserved = False; + fsp->reserved = False; return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (fstat(fsp->f_u.fd_ptr->fd,&sbuf) != 0) { close_file(fnum,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1392,6 +1392,8 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (fnum < 0) return(ERROR(ERRSRV,ERRnofids)); + fsp = &Files[fnum]; + if (!check_name(fname,cnum)) { if((errno == ENOENT) && bad_path) @@ -1399,7 +1401,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - Files[fnum].reserved = False; + fsp->reserved = False; return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1408,8 +1410,6 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode, oplock_request, &rmode,&smb_action); - fsp = &Files[fnum]; - if (!fsp->open) { if((errno == ENOENT) && bad_path) @@ -1417,11 +1417,11 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - Files[fnum].reserved = False; + fsp->reserved = False; return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { + if (fstat(fsp->f_u.fd_ptr->fd,&sbuf) != 0) { close_file(fnum,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1548,6 +1548,8 @@ int reply_mknew(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if (fnum < 0) return(ERROR(ERRSRV,ERRnofids)); + fsp = &Files[fnum]; + if (!check_name(fname,cnum)) { if((errno == ENOENT) && bad_path) @@ -1555,7 +1557,7 @@ int reply_mknew(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - Files[fnum].reserved = False; + fsp->reserved = False; return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1574,8 +1576,6 @@ int reply_mknew(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode, oplock_request, NULL, NULL); - fsp = &Files[fnum]; - if (!fsp->open) { if((errno == ENOENT) && bad_path) @@ -1583,7 +1583,7 @@ int reply_mknew(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - Files[fnum].reserved = False; + fsp->reserved = False; return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1598,7 +1598,8 @@ int reply_mknew(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; DEBUG(2,("new file %s\n",fname)); - DEBUG(3,("%s mknew %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname,Files[fnum].fd_ptr->fd,fnum,cnum,createmode,unixmode)); + DEBUG(3,("%s mknew %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n", + timestring(),fname,fsp->f_u.fd_ptr->fd,fnum,cnum,createmode,unixmode)); return(outsize); } @@ -1632,6 +1633,8 @@ int reply_ctemp(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if (fnum < 0) return(ERROR(ERRSRV,ERRnofids)); + fsp = &Files[fnum]; + if (!check_name(fname,cnum)) { if((errno == ENOENT) && bad_path) @@ -1639,7 +1642,7 @@ int reply_ctemp(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - Files[fnum].reserved = False; + fsp->reserved = False; return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1650,8 +1653,6 @@ int reply_ctemp(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode, oplock_request, NULL, NULL); - fsp = &Files[fnum]; - if (!fsp->open) { if((errno == ENOENT) && bad_path) @@ -1659,7 +1660,7 @@ int reply_ctemp(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - Files[fnum].reserved = False; + fsp->reserved = False; return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1676,7 +1677,8 @@ int reply_ctemp(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; DEBUG(2,("created temp file %s\n",fname2)); - DEBUG(3,("%s ctemp %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum,createmode,unixmode)); + DEBUG(3,("%s ctemp %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n", + timestring(),fname2,fsp->f_u.fd_ptr->fd,fnum,cnum,createmode,unixmode)); return(outsize); } @@ -1821,6 +1823,7 @@ int reply_readbraw(char *inbuf, char *outbuf, int dum_size, int dum_buffsize) int ret=0; int fd; char *fname; + files_struct *fsp; /* * Special check if an oplock break has been issued @@ -1848,35 +1851,37 @@ int reply_readbraw(char *inbuf, char *outbuf, int dum_size, int dum_buffsize) maxcount = MAX(mincount,maxcount); if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read) - { - DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum)); - _smb_setlen(header,0); - transfer_file(0,Client,0,header,4,0); - return(-1); - } + { + DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum)); + _smb_setlen(header,0); + transfer_file(0,Client,0,header,4,0); + return(-1); + } else - { - fd = Files[fnum].fd_ptr->fd; - fname = Files[fnum].name; - } + { + fsp = &Files[fnum]; + + fd = fsp->f_u.fd_ptr->fd; + fname = fsp->name; + } if (!is_locked(fnum,cnum,maxcount,startpos, F_RDLCK)) - { - int size = Files[fnum].size; - int sizeneeded = startpos + maxcount; + { + int size = fsp->size; + int sizeneeded = startpos + maxcount; - if (size < sizeneeded) { - struct stat st; - if (fstat(Files[fnum].fd_ptr->fd,&st) == 0) - size = st.st_size; - if (!Files[fnum].can_write) - Files[fnum].size = size; - } - - nread = MIN(maxcount,(int)(size - startpos)); + if (size < sizeneeded) { + struct stat st; + if (fstat(fsp->f_u.fd_ptr->fd,&st) == 0) + size = st.st_size; + if (!fsp->can_write) + fsp->size = size; } + nread = MIN(maxcount,(int)(size - startpos)); + } + if (nread < mincount) nread = 0; @@ -1891,7 +1896,7 @@ int reply_readbraw(char *inbuf, char *outbuf, int dum_size, int dum_buffsize) _smb_setlen(header,nread); #if USE_READ_PREDICTION - if (!Files[fnum].can_write) + if (!fsp->can_write) predict = read_predict(fd,startpos,header+4,NULL,nread); #endif @@ -2138,7 +2143,7 @@ int reply_writebraw(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) tcount,nwritten,numtowrite)); } - nwritten = transfer_file(Client,Files[fnum].fd_ptr->fd,numtowrite,NULL,0, + nwritten = transfer_file(Client,Files[fnum].f_u.fd_ptr->fd,numtowrite,NULL,0, startpos+nwritten); total_written += nwritten; @@ -2255,7 +2260,7 @@ int reply_write(char *inbuf,char *outbuf,int dum_size,int dum_buffsize) zero then the file size should be extended or truncated to the size given in smb_vwv[2-3] */ if(numtowrite == 0) - nwritten = set_filelen(Files[fnum].fd_ptr->fd, startpos); + nwritten = set_filelen(Files[fnum].f_u.fd_ptr->fd, startpos); else nwritten = write_file(fnum,data,numtowrite); @@ -2349,7 +2354,8 @@ int reply_lseek(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) int32 res= -1; int mode,umode; int outsize = 0; - + files_struct *fsp; + cnum = SVAL(inbuf,smb_tid); fnum = GETFNUM(inbuf,smb_vwv0); @@ -2367,9 +2373,11 @@ int reply_lseek(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) default: umode = SEEK_SET; break; } + + fsp = &Files[fnum]; - res = lseek(Files[fnum].fd_ptr->fd,startpos,umode); - Files[fnum].pos = res; + res = lseek(fsp->f_u.fd_ptr->fd,startpos,umode); + fsp->pos = res; outsize = set_message(outbuf,2,0,True); SIVALS(outbuf,smb_vwv0,res); @@ -2477,7 +2485,7 @@ int reply_close(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) set_filetime(cnum, fsp->name,mtime); DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n", - timestring(),fsp->fd_ptr->fd,fnum,cnum, + timestring(),fsp->f_u.fd_ptr->fd,fnum,cnum, Connections[cnum].num_files_open)); close_file(fnum,True); @@ -2560,7 +2568,8 @@ int reply_lock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) count = IVAL(inbuf,smb_vwv1); offset = IVAL(inbuf,smb_vwv3); - DEBUG(3,("%s lock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,offset,count)); + DEBUG(3,("%s lock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n", + timestring(),Files[fnum].f_u.fd_ptr->fd,fnum,cnum,offset,count)); if(!do_lock( fnum, cnum, count, offset, F_WRLCK, &eclass, &ecode)) return (ERROR(eclass,ecode)); @@ -2592,7 +2601,8 @@ int reply_unlock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode)) return (ERROR(eclass,ecode)); - DEBUG(3,("%s unlock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,offset,count)); + DEBUG(3,("%s unlock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n", + timestring(),Files[fnum].f_u.fd_ptr->fd,fnum,cnum,offset,count)); return(outsize); } @@ -2686,6 +2696,7 @@ int reply_printopen(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) int cnum; int fnum = -1; int outsize = 0; + files_struct *fsp; *fname = *fname2 = 0; @@ -2715,10 +2726,12 @@ int reply_printopen(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if (fnum < 0) return(ERROR(ERRSRV,ERRnofids)); + fsp = &Files[fnum]; + pstrcpy(fname2,(char *)mktemp(fname)); if (!check_name(fname2,cnum)) { - Files[fnum].reserved = False; + fsp->reserved = False; return(ERROR(ERRDOS,ERRnoaccess)); } @@ -2726,18 +2739,19 @@ int reply_printopen(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0), 0, NULL, NULL); - if (!Files[fnum].open) { - Files[fnum].reserved = False; + if (!fsp->open) { + fsp->reserved = False; return(UNIXERROR(ERRDOS,ERRnoaccess)); } /* force it to be a print file */ - Files[fnum].print_file = True; + fsp->print_file = True; outsize = set_message(outbuf,1,0,True); SSVAL(outbuf,smb_vwv0,fnum); - DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum)); + DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n", + timestring(),fname2,fsp->f_u.fd_ptr->fd,fnum,cnum)); return(outsize); } @@ -2760,7 +2774,8 @@ int reply_printclose(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) if (!CAN_PRINT(cnum)) return(ERROR(ERRDOS,ERRnoaccess)); - DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum)); + DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n", + timestring(),Files[fnum].f_u.fd_ptr->fd,fnum,cnum)); close_file(fnum,True); @@ -3453,11 +3468,12 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun, } if ((ofun&3) == 1) { - lseek(Files[fnum2].fd_ptr->fd,0,SEEK_END); + lseek(Files[fnum2].f_u.fd_ptr->fd,0,SEEK_END); } if (st.st_size) - ret = transfer_file(Files[fnum1].fd_ptr->fd,Files[fnum2].fd_ptr->fd,st.st_size,NULL,0,0); + ret = transfer_file(Files[fnum1].f_u.fd_ptr->fd, + Files[fnum2].f_u.fd_ptr->fd,st.st_size,NULL,0,0); close_file(fnum1,False); close_file(fnum2,False); @@ -3675,8 +3691,8 @@ int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize) { int token; files_struct *fsp = &Files[fnum]; - uint32 dev = fsp->fd_ptr->dev; - uint32 inode = fsp->fd_ptr->inode; + uint32 dev = fsp->f_u.fd_ptr->dev; + uint32 inode = fsp->f_u.fd_ptr->inode; DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n", fnum)); @@ -4077,7 +4093,7 @@ int reply_getattrE(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) CHECK_ERROR(fnum); /* Do an fstat on this file */ - if(fstat(Files[fnum].fd_ptr->fd, &sbuf)) + if(fstat(Files[fnum].f_u.fd_ptr->fd, &sbuf)) return(UNIXERROR(ERRDOS,ERRnoaccess)); mode = dos_mode(cnum,Files[fnum].name,&sbuf); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 8eee0209b6..056611a886 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1047,7 +1047,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct int accmode = (flags & (O_RDONLY | O_WRONLY | O_RDWR)); fsp->open = False; - fsp->fd_ptr = 0; + fsp->f_u.fd_ptr = 0; fsp->granted_oplock = False; errno = EPERM; @@ -1222,7 +1222,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct if (sys_disk_free(dname,&dum1,&dum2,&dum3) < lp_minprintspace(SNUM(cnum))) { fd_attempt_close(fd_ptr); - fsp->fd_ptr = 0; + fsp->f_u.fd_ptr = 0; if(fd_ptr->ref_count == 0) sys_unlink(fname); errno = ENOSPC; @@ -1259,7 +1259,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct fd_ptr->dev = (uint32)sbuf->st_dev; fd_ptr->inode = (uint32)sbuf->st_ino; - fsp->fd_ptr = fd_ptr; + fsp->f_u.fd_ptr = fd_ptr; Connections[cnum].num_files_open++; fsp->mode = sbuf->st_mode; GetTimeOfDay(&fsp->open_time); @@ -1316,7 +1316,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct { fsp->mmap_size = file_size(fname); fsp->mmap_ptr = (char *)mmap(NULL,fsp->mmap_size, - PROT_READ,MAP_SHARED,fsp->fd_ptr->fd,0); + PROT_READ,MAP_SHARED,fsp->f_u.fd_ptr->fd,0); if (fsp->mmap_ptr == (char *)-1 || !fsp->mmap_ptr) { @@ -1334,7 +1334,7 @@ void sync_file(int cnum, int fnum) { #ifdef HAVE_FSYNC if(lp_strict_sync(SNUM(cnum))) - fsync(Files[fnum].fd_ptr->fd); + fsync(Files[fnum].f_u.fd_ptr->fd); #endif } @@ -1381,26 +1381,26 @@ static void check_magic(int fnum,int cnum) Common code to close a file or a directory. ****************************************************************************/ -static void close_filestruct(files_struct *fs_p) +static void close_filestruct(files_struct *fsp) { - int cnum = fs_p->cnum; + int cnum = fsp->cnum; - fs_p->reserved = False; - fs_p->open = False; - fs_p->is_directory = False; + fsp->reserved = False; + fsp->open = False; + fsp->is_directory = False; Connections[cnum].num_files_open--; - if(fs_p->wbmpx_ptr) + if(fsp->wbmpx_ptr) { - free((char *)fs_p->wbmpx_ptr); - fs_p->wbmpx_ptr = NULL; + free((char *)fsp->wbmpx_ptr); + fsp->wbmpx_ptr = NULL; } #if WITH_MMAP - if(fs_p->mmap_ptr) + if(fsp->mmap_ptr) { - munmap(fs_p->mmap_ptr,fs_p->mmap_size); - fs_p->mmap_ptr = NULL; + munmap(fsp->mmap_ptr,fsp->mmap_size); + fsp->mmap_ptr = NULL; } #endif } @@ -1418,14 +1418,14 @@ void close_file(int fnum, BOOL normal_close) { files_struct *fs_p = &Files[fnum]; int cnum = fs_p->cnum; - uint32 dev = fs_p->fd_ptr->dev; - uint32 inode = fs_p->fd_ptr->inode; + uint32 dev = fs_p->f_u.fd_ptr->dev; + uint32 inode = fs_p->f_u.fd_ptr->inode; int token; close_filestruct(fs_p); #if USE_READ_PREDICTION - invalidate_read_prediction(fs_p->fd_ptr->fd); + invalidate_read_prediction(fs_p->f_u.fd_ptr->fd); #endif if (lp_share_modes(SNUM(cnum))) @@ -1434,7 +1434,7 @@ void close_file(int fnum, BOOL normal_close) del_share_mode(token, fnum); } - fd_attempt_close(fs_p->fd_ptr); + fd_attempt_close(fs_p->f_u.fd_ptr); if (lp_share_modes(SNUM(cnum))) unlock_share_entry( cnum, dev, inode, token); @@ -1470,31 +1470,74 @@ void close_file(int fnum, BOOL normal_close) void close_directory(int fnum) { - files_struct *fs_p = &Files[fnum]; + files_struct *fsp = &Files[fnum]; + + /* TODO - walk the list of pending + change notify requests and free + any pertaining to this fnum. */ /* * Do the code common to files and directories. */ - close_filestruct(fs_p); + close_filestruct(fsp); - if (fs_p->name) { - string_free(&fs_p->name); - } + if (fsp->name) + string_free(&fsp->name); + + if (fsp->f_u.dir_ptr) + free((char *)fsp->f_u.dir_ptr); /* we will catch bugs faster by zeroing this structure */ - memset(fs_p, 0, sizeof(*fs_p)); + memset(fsp, 0, sizeof(*fsp)); } /**************************************************************************** Open a directory from an NT SMB call. ****************************************************************************/ -void open_directory(int fnum,int cnum,char *fname, int *action) +int open_directory(int fnum,int cnum,char *fname, int smb_ofun, int unixmode, int *action) { extern struct current_user current_user; files_struct *fsp = &Files[fnum]; + struct stat st; + + if (smb_ofun & 0x10) { + /* + * Create the directory. + */ + + if(sys_mkdir(fname, unixmode) < 0) { + DEBUG(0,("open_directory: unable to create %s. Error was %s\n", + fname, strerror(errno) )); + return -1; + } + + *action = FILE_WAS_CREATED; + + } else { + + /* + * Check that it *was* a directory. + */ + + if(sys_stat(fname, &st) < 0) { + DEBUG(0,("open_directory: unable to stat name = %s. Error was %s\n", + fname, strerror(errno) )); + return -1; + } + + if(!S_ISDIR(st.st_mode)) { + DEBUG(0,("open_directory: %s is not a directory !\n", fname )); + return -1; + } + *action = FILE_WAS_OPENED; + } - fsp->fd_ptr = NULL; + /* + * Setup the files_struct for it. + */ + + fsp->f_u.dir_ptr = NULL; Connections[cnum].num_files_open++; fsp->mode = 0; GetTimeOfDay(&fsp->open_time); @@ -1524,7 +1567,7 @@ void open_directory(int fnum,int cnum,char *fname, int *action) string_set(&fsp->name,fname); fsp->wbmpx_ptr = NULL; - *action = FILE_WAS_OPENED; + return 0; } enum {AFAIL,AREAD,AWRITE,AALL}; @@ -1719,8 +1762,8 @@ static void truncate_unless_locked(int fnum, int cnum, int token, /* If share modes are in force for this connection we have the share entry locked. Unlock it before closing. */ if (*share_locked && lp_share_modes(SNUM(cnum))) - unlock_share_entry( cnum, Files[fnum].fd_ptr->dev, - Files[fnum].fd_ptr->inode, token); + unlock_share_entry( cnum, Files[fnum].f_u.fd_ptr->dev, + Files[fnum].f_u.fd_ptr->inode, token); close_file(fnum,False); /* Share mode no longer locked. */ *share_locked = False; @@ -1729,7 +1772,7 @@ static void truncate_unless_locked(int fnum, int cnum, int token, unix_ERR_code = ERRlock; } else - ftruncate(Files[fnum].fd_ptr->fd,0); + ftruncate(Files[fnum].f_u.fd_ptr->fd,0); } } @@ -1794,7 +1837,7 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, int num_share_modes = 0; fs_p->open = False; - fs_p->fd_ptr = 0; + fs_p->f_u.fd_ptr = 0; /* this is for OS/2 EAs - try and say we don't support them */ if (strstr(fname,".+,;=[].")) @@ -1970,8 +2013,8 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); if((share_locked == False) && lp_share_modes(SNUM(cnum))) { /* We created the file - thus we must now lock the share entry before creating it. */ - dev = fs_p->fd_ptr->dev; - inode = fs_p->fd_ptr->inode; + dev = fs_p->f_u.fd_ptr->dev; + inode = fs_p->f_u.fd_ptr->inode; lock_share_entry(cnum, dev, inode, &token); share_locked = True; } @@ -2046,12 +2089,13 @@ seek a file. Try to avoid the seek if possible int seek_file(int fnum,uint32 pos) { uint32 offset = 0; - if (Files[fnum].print_file && POSTSCRIPT(Files[fnum].cnum)) + files_struct *fsp = &Files[fnum]; + + if (fsp->print_file && POSTSCRIPT(fsp->cnum)) offset = 3; - Files[fnum].pos = (int)(lseek(Files[fnum].fd_ptr->fd,pos+offset,SEEK_SET) - - offset); - return(Files[fnum].pos); + fsp->pos = (int)(lseek(fsp->f_u.fd_ptr->fd,pos+offset,SEEK_SET) - offset); + return(fsp->pos); } /**************************************************************************** @@ -2060,11 +2104,12 @@ read from a file int read_file(int fnum,char *data,uint32 pos,int n) { int ret=0,readret; + files_struct *fsp = &Files[fnum]; #if USE_READ_PREDICTION - if (!Files[fnum].can_write) + if (!fsp->can_write) { - ret = read_predict(Files[fnum].fd_ptr->fd,pos,data,NULL,n); + ret = read_predict(fsp->f_u.fd_ptr->fd,pos,data,NULL,n); data += ret; n -= ret; @@ -2073,13 +2118,13 @@ int read_file(int fnum,char *data,uint32 pos,int n) #endif #if WITH_MMAP - if (Files[fnum].mmap_ptr) + if (fsp->mmap_ptr) { - int num = (Files[fnum].mmap_size > pos) ? (Files[fnum].mmap_size - pos) : -1; + int num = (fsp->mmap_size > pos) ? (fsp->mmap_size - pos) : -1; num = MIN(n,num); if (num > 0) { - memcpy(data,Files[fnum].mmap_ptr+pos,num); + memcpy(data,fsp->mmap_ptr+pos,num); data += num; pos += num; n -= num; @@ -2098,7 +2143,7 @@ int read_file(int fnum,char *data,uint32 pos,int n) } if (n > 0) { - readret = read(Files[fnum].fd_ptr->fd,data,n); + readret = read(fsp->f_u.fd_ptr->fd,data,n); if (readret > 0) ret += readret; } @@ -2111,23 +2156,25 @@ write to a file ****************************************************************************/ int write_file(int fnum,char *data,int n) { - if (!Files[fnum].can_write) { + files_struct *fsp = &Files[fnum]; + + if (!fsp->can_write) { errno = EPERM; return(0); } - if (!Files[fnum].modified) { + if (!fsp->modified) { struct stat st; - Files[fnum].modified = True; - if (fstat(Files[fnum].fd_ptr->fd,&st) == 0) { - int dosmode = dos_mode(Files[fnum].cnum,Files[fnum].name,&st); - if (MAP_ARCHIVE(Files[fnum].cnum) && !IS_DOS_ARCHIVE(dosmode)) { - dos_chmod(Files[fnum].cnum,Files[fnum].name,dosmode | aARCH,&st); + fsp->modified = True; + if (fstat(fsp->f_u.fd_ptr->fd,&st) == 0) { + int dosmode = dos_mode(fsp->cnum,fsp->name,&st); + if (MAP_ARCHIVE(fsp->cnum) && !IS_DOS_ARCHIVE(dosmode)) { + dos_chmod(fsp->cnum,fsp->name,dosmode | aARCH,&st); } } } - return(write_data(Files[fnum].fd_ptr->fd,data,n)); + return(write_data(fsp->f_u.fd_ptr->fd,data,n)); } @@ -2871,7 +2918,7 @@ global_oplocks_open = %d\n", timestring(), dev, inode, global_oplocks_open)); { if(OPEN_FNUM(fnum)) { - if((Files[fnum].fd_ptr->dev == dev) && (Files[fnum].fd_ptr->inode == inode) && + if((Files[fnum].f_u.fd_ptr->dev == dev) && (Files[fnum].f_u.fd_ptr->inode == inode) && (Files[fnum].open_time.tv_sec == tval->tv_sec) && (Files[fnum].open_time.tv_usec == tval->tv_usec)) { fsp = &Files[fnum]; @@ -3687,17 +3734,17 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de file table when we have run out. ****************************************************************************/ -static BOOL attempt_close_oplocked_file(files_struct *fp) +static BOOL attempt_close_oplocked_file(files_struct *fsp) { - DEBUG(5,("attempt_close_oplocked_file: checking file %s.\n", fp->name)); + DEBUG(5,("attempt_close_oplocked_file: checking file %s.\n", fsp->name)); - if (fp->open && fp->granted_oplock && !fp->sent_oplock_break) { + if (fsp->open && fsp->granted_oplock && !fsp->sent_oplock_break) { /* Try and break the oplock. */ - file_fd_struct *fsp = fp->fd_ptr; - if(oplock_break( fsp->dev, fsp->inode, &fp->open_time)) { - if(!fp->open) /* Did the oplock break close the file ? */ + file_fd_struct *fd_ptr = fsp->f_u.fd_ptr; + if(oplock_break( fd_ptr->dev, fd_ptr->inode, &fsp->open_time)) { + if(!fsp->open) /* Did the oplock break close the file ? */ return True; } } @@ -4601,7 +4648,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize DEBUG(2,("%s: switch_message: queueing message due to being in oplock break state.\n", timestring() )); - push_smb_message( inbuf, size); + push_oplock_pending_smb_message( inbuf, size); return -1; } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 2fcab32afb..08f6803005 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -207,6 +207,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, struct stat sbuf; int smb_action = 0; BOOL bad_path = False; + files_struct *fsp; StrnCpy(fname,pname,namelen); @@ -221,6 +222,8 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, if (fnum < 0) return(ERROR(ERRSRV,ERRnofids)); + fsp = &Files[fnum]; + if (!check_name(fname,cnum)) { if((errno == ENOENT) && bad_path) @@ -228,28 +231,27 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - Files[fnum].reserved = False; + fsp->reserved = False; return(UNIXERROR(ERRDOS,ERRnoaccess)); } unixmode = unix_mode(cnum,open_attr | aARCH); - open_file_shared(fnum,cnum,fname,open_mode,open_ofun,unixmode, oplock_request, &rmode,&smb_action); - if (!Files[fnum].open) + if (!fsp->open) { if((errno == ENOENT) && bad_path) { unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - Files[fnum].reserved = False; + fsp->reserved = False; return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { + if (fstat(fsp->f_u.fd_ptr->fd,&sbuf) != 0) { close_file(fnum,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1187,11 +1189,11 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, CHECK_ERROR(fnum); fname = Files[fnum].name; - if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { + if (fstat(Files[fnum].f_u.fd_ptr->fd,&sbuf) != 0) { DEBUG(3,("fstat of fnum %d failed (%s)\n",fnum, strerror(errno))); return(UNIXERROR(ERRDOS,ERRbadfid)); } - pos = lseek(Files[fnum].fd_ptr->fd,0,SEEK_CUR); + pos = lseek(Files[fnum].f_u.fd_ptr->fd,0,SEEK_CUR); } else { /* qpathinfo */ info_level = SVAL(params,0); @@ -1411,7 +1413,7 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length, CHECK_ERROR(fnum); fname = Files[fnum].name; - fd = Files[fnum].fd_ptr->fd; + fd = Files[fnum].f_u.fd_ptr->fd; if(fstat(fd,&st)!=0) { DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno))); @@ -1788,7 +1790,7 @@ int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize) DEBUG(2,("%s: reply_trans2: queueing message trans2open due to being in oplock break state.\n", timestring() )); - push_smb_message( inbuf, length); + push_oplock_pending_smb_message( inbuf, length); return -1; } -- cgit