locking.c: Changed aborts to returns so not so drastic on PANIC errors.
proto.h: Removed definition of open_file as this is now never externally called.
reply.c: Changed reply_mknew, reply_ctemp, reply_printopen to go through open_file_shared.
server.c: Modified open_file_shared to be more robust and be useful for printer & temp files.
Removed truncate option from open_file (now all truncates are done in open_file_shared).
util.c: Added EAGAIN to errors checked in open_socket_out().
version.h: Updated to 1.9.17alpha2.
jallison@whistle.com
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);
-#define VERSION "1.9.17alpha1"
+#define VERSION "1.9.17alpha2"
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;
}
("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());
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 \
("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());
{
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]);
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. */
("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());
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 */
{
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)
{
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)
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));
/****************************************************************************
- reply to a mknew
+ reply to a mknew or a create
****************************************************************************/
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);
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));
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));
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));
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));
/****************************************************************************
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;
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
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;
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)))