diff options
-rw-r--r-- | source3/include/proto.h | 1 | ||||
-rw-r--r-- | source3/include/version.h | 2 | ||||
-rw-r--r-- | source3/lib/util.c | 4 | ||||
-rw-r--r-- | source3/locking/locking.c | 18 | ||||
-rw-r--r-- | source3/param/loadparm.c | 4 | ||||
-rw-r--r-- | source3/smbd/reply.c | 30 | ||||
-rw-r--r-- | source3/smbd/server.c | 31 |
7 files changed, 55 insertions, 35 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h index 1fa8c1d95e..04202dd88c 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -683,7 +683,6 @@ BOOL check_name(char *name,int cnum); int fd_attempt_open(char *fname, int flags, int mode); void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr); int fd_attempt_close(file_fd_struct *fd_ptr); -void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct stat *sbuf); void sync_file(int fnum); void close_file(int fnum); BOOL check_file_sharing(int cnum,char *fname); diff --git a/source3/include/version.h b/source3/include/version.h index cc69bef521..2f7596f41d 100644 --- a/source3/include/version.h +++ b/source3/include/version.h @@ -1 +1 @@ -#define VERSION "1.9.17alpha1" +#define VERSION "1.9.17alpha2" diff --git a/source3/lib/util.c b/source3/lib/util.c index 0ed08405ba..831d7d64e0 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -2905,7 +2905,9 @@ int open_socket_out(int type, struct in_addr *addr, int port ,int timeout) connect_again: ret = connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out)); - if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY) && loops--) { + /* Some systems return EAGAIN when they mean EINPROGRESS */ + if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY || + errno == EAGAIN) && loops--) { msleep(connect_loop); goto connect_again; } diff --git a/source3/locking/locking.c b/source3/locking/locking.c index e63e347a26..2c392e924d 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -167,7 +167,7 @@ int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode, ("PANIC ERROR : get_share_modes (FAST_SHARE_MODES): hash_entry %d too large \ (max = %d)\n", hash_entry, lp_shmem_hash_size() )); - abort(); + return 0; } mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off()); @@ -265,7 +265,7 @@ bucket %d",file_scanner_p->locking_version, dev, inode, hash_entry)); DEBUG(0,("PANIC ERROR:get_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \ for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries, dev, inode, hash_entry)); - abort(); + return 0; } DEBUG(0,("get_share_modes (FAST_SHARE_MODES): process %d no longer exists and \ @@ -344,7 +344,7 @@ void del_share_mode(share_lock_token token, int fnum) ("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): hash_entry %d too large \ (max = %d)\n", hash_entry, lp_shmem_hash_size() )); - abort(); + return; } mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off()); @@ -353,7 +353,7 @@ void del_share_mode(share_lock_token token, int fnum) { DEBUG(0,("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): hash bucket %d empty\n", hash_entry)); - abort(); + return; } file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]); @@ -436,7 +436,7 @@ Deleting share mode entry dev = %d, inode = %d in hash bucket %d (num entries no DEBUG(0,("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \ for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries, dev, inode, hash_entry)); - abort(); + return; } /* If we deleted the last share mode entry then remove the share mode record. */ @@ -483,7 +483,7 @@ BOOL set_share_mode(share_lock_token token, int fnum) ("PANIC ERROR:set_share_mode (FAST_SHARE_MODES): hash_entry %d too large \ (max = %d)\n", hash_entry, lp_shmem_hash_size() )); - abort(); + return False; } mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off()); @@ -564,7 +564,7 @@ inode %d in hash bucket %d\n", fs_p->name, dev, inode, hash_entry)); DEBUG(0,("PANIC ERROR:set_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \ for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries, dev, inode, hash_entry)); - abort(); + return False; } /* Increment the share_mode_entries counter */ @@ -838,7 +838,7 @@ int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode, { DEBUG(0,("PANIC ERROR:get_share_mode: num_share_mode_entries < 0 (%d) \ for share file %d\n", num_entries, fname)); - abort(); + return 0; } if(num_entries) @@ -1005,7 +1005,7 @@ void del_share_mode(share_lock_token token, int fnum) { DEBUG(0,("PANIC ERROR:del_share_mode: num_share_mode_entries < 0 (%d) \ for share file %d\n", num_entries, fname)); - abort(); + return; } if(num_entries == 0) diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index af0b05bb5d..ddd8cc90ba 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -1079,6 +1079,10 @@ BOOL lp_add_printer(char *pszPrintername, int iDefaultService) string_set(&iSERVICE(i).szPrintername,pszPrintername); string_set(&iSERVICE(i).comment,comment); iSERVICE(i).bBrowseable = sDefault.bBrowseable; + /* Printers cannot be read_only. */ + iSERVICE(i).bRead_only = False; + /* No share modes on printer services. */ + iSERVICE(i).bShareModes = False; DEBUG(3,("adding printer service %s\n",pszPrintername)); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 639c386c2f..530ce84895 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1135,7 +1135,7 @@ int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize) /**************************************************************************** - reply to a mknew + reply to a mknew or a create ****************************************************************************/ int reply_mknew(char *inbuf,char *outbuf) { @@ -1145,7 +1145,8 @@ int reply_mknew(char *inbuf,char *outbuf) int outsize = 0; int createmode; mode_t unixmode; - + int ofun = 0; + com = SVAL(inbuf,smb_com); cnum = SVAL(inbuf,smb_tid); @@ -1160,9 +1161,6 @@ int reply_mknew(char *inbuf,char *outbuf) unixmode = unix_mode(cnum,createmode); - if (com == SMBmknew && file_exist(fname,NULL)) - return(ERROR(ERRDOS,ERRfilexists)); - fnum = find_free_file(); if (fnum < 0) return(ERROR(ERRSRV,ERRnofids)); @@ -1170,7 +1168,19 @@ int reply_mknew(char *inbuf,char *outbuf) if (!check_name(fname,cnum)) return(UNIXERROR(ERRDOS,ERRnoaccess)); - open_file(fnum,cnum,fname,O_RDWR | O_CREAT | O_TRUNC,unixmode, 0); + if(com == SMBmknew) + { + /* We should fail if file exists. */ + ofun = 0x10; + } + else + { + /* SMBcreate - Create if file doesn't exist, truncate if it does. */ + ofun = 0x12; + } + + /* Open file in dos compatibility share mode. */ + open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode, NULL, NULL); if (!Files[fnum].open) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -1218,7 +1228,9 @@ int reply_ctemp(char *inbuf,char *outbuf) strcpy(fname2,(char *)mktemp(fname)); - open_file(fnum,cnum,fname2,O_RDWR | O_CREAT | O_TRUNC,unixmode, 0); + /* Open file in dos compatibility share mode. */ + /* We should fail if file exists. */ + open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode, NULL, NULL); if (!Files[fnum].open) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2219,8 +2231,8 @@ int reply_printopen(char *inbuf,char *outbuf) if (!check_name(fname2,cnum)) return(ERROR(ERRDOS,ERRnoaccess)); - open_file(fnum,cnum,fname2,O_WRONLY | O_CREAT | O_TRUNC, - unix_mode(cnum,0), 0); + /* Open for exclusive use, write only. */ + open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0), NULL, NULL); if (!Files[fnum].open) return(UNIXERROR(ERRDOS,ERRnoaccess)); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 65e620c7f0..4ae139fc58 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -937,7 +937,7 @@ int fd_attempt_close(file_fd_struct *fd_ptr) /**************************************************************************** open a file ****************************************************************************/ -void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct stat *sbuf) +static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct stat *sbuf) { extern struct current_user current_user; pstring fname; @@ -1033,14 +1033,6 @@ void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct stat *s return; } - /* - * If O_TRUNC was set, ensure we truncate the file. - * open_file_shared explicitly clears this flag before - * calling open_file, so we can safely do this here. - */ - if(flags & O_TRUNC) - ftruncate(fd_ptr->fd, 0); - } else { int open_flags; /* We need to allocate a new file_fd_struct (this increments the @@ -1389,11 +1381,19 @@ free_and_exit: Helper for open_file_shared. Truncate a file after checking locking; close file if locked. **************************************************************************/ -static void truncate_unless_locked(int fnum, int cnum) +static void truncate_unless_locked(int fnum, int cnum, share_lock_token token, + BOOL *share_locked) { if (Files[fnum].can_write){ if (is_locked(fnum,cnum,0x3FFFFFFF,0)){ + /* 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); close_file(fnum); + /* Share mode no longer locked. */ + *share_locked = False; errno = EACCES; unix_ERR_class = ERRDOS; unix_ERR_code = ERRlock; @@ -1600,12 +1600,15 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, if (!file_existed) *action = 2; if (file_existed && (flags2 & O_TRUNC)) *action = 3; } - - if ((flags2&O_TRUNC) && file_existed) - truncate_unless_locked(fnum,cnum); - + /* We must create the share mode entry before truncate as + truncate can fail due to locking and have to close the + file (which expects the share_mode_entry to be there). + */ if (lp_share_modes(SNUM(cnum))) set_share_mode(token, fnum); + + if ((flags2&O_TRUNC) && file_existed) + truncate_unless_locked(fnum,cnum,token,&share_locked); } if (share_locked && lp_share_modes(SNUM(cnum))) |