diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/include/proto.h | 3 | ||||
-rw-r--r-- | source3/locking/locking.c | 44 | ||||
-rw-r--r-- | source3/param/loadparm.c | 4 | ||||
-rw-r--r-- | source3/smbd/reply.c | 16 | ||||
-rw-r--r-- | source3/smbd/server.c | 14 |
5 files changed, 54 insertions, 27 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h index 2a7e5ed080..92008b46e1 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -1107,6 +1107,7 @@ BOOL lp_manglednames(int ); BOOL lp_widelinks(int ); BOOL lp_symlinks(int ); BOOL lp_syncalways(int ); +BOOL lp_strict_sync(int ); BOOL lp_map_system(int ); BOOL lp_delete_readonly(int ); BOOL lp_fake_oplocks(int ); @@ -1813,7 +1814,7 @@ BOOL unix_convert(char *name,int cnum,pstring saved_last_component, BOOL *bad_pa int disk_free(char *path,int *bsize,int *dfree,int *dsize); int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize); BOOL check_name(char *name,int cnum); -void sync_file(int fnum); +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); diff --git a/source3/locking/locking.c b/source3/locking/locking.c index d5d767d2cc..6aecfed6a5 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -39,6 +39,35 @@ extern files_struct Files[]; static struct share_ops *share_ops; /**************************************************************************** + Utility function to map a lock type correctly depending on the real open + mode of a file. +****************************************************************************/ + +static int map_lock_type( files_struct *fsp, int lock_type) +{ + if((lock_type == F_WRLCK) && (fsp->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. + * Do the best we can and attempt a read-only lock. + */ + return F_RDLCK; + } else if( (lock_type == F_RDLCK) && (fsp->fd_ptr->real_open_flags == O_WRONLY)) { + /* + * Ditto for read locks on write only files. + */ + return F_WRLCK; + } + + /* + * This return should be the most normal, as we attempt + * to always open files read/write. + */ + + return lock_type; +} + +/**************************************************************************** Utility function called to see if a file region is locked. ****************************************************************************/ @@ -53,10 +82,8 @@ BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset, int lock_type) if (!lp_locking(snum) || !lp_strict_locking(snum)) return(False); - if((lock_type == F_WRLCK) && !fsp->can_write) - lock_type = F_RDLCK; - - return(fcntl_lock(fsp->fd_ptr->fd,F_GETLK,offset,count,lock_type)); + return(fcntl_lock(fsp->fd_ptr->fd,F_GETLK,offset,count, + map_lock_type(fsp,lock_type))); } @@ -79,12 +106,9 @@ BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int lock_type, return False; } - if (OPEN_FNUM(fnum) && fsp->can_lock && (fsp->cnum == cnum)) { - if(lock_type == F_WRLCK && !fsp->can_write) - lock_type = F_RDLCK; - - ok = fcntl_lock(fsp->fd_ptr->fd,F_SETLK,offset,count,lock_type); - } + if (OPEN_FNUM(fnum) && fsp->can_lock && (fsp->cnum == cnum)) + ok = fcntl_lock(fsp->fd_ptr->fd,F_SETLK,offset,count, + map_lock_type(fsp,lock_type)); if (!ok) { *eclass = ERRDOS; diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 10b261ed02..da0210eee7 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -308,6 +308,7 @@ typedef struct BOOL bWidelinks; BOOL bSymlinks; BOOL bSyncAlways; + BOOL bStrictSync; char magic_char; BOOL *copymap; BOOL bDeleteReadonly; @@ -398,6 +399,7 @@ static service sDefault = True, /* bWidelinks */ True, /* bSymlinks */ False, /* bSyncAlways */ + False, /* bStrictSync */ '~', /* magic char */ NULL, /* copymap */ False, /* bDeleteReadonly */ @@ -582,6 +584,7 @@ static struct parm_struct parm_table[] = {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL, NULL, 0}, {"min print space", P_INTEGER, P_LOCAL, &sDefault.iMinPrintSpace, NULL, NULL, 0}, {"sync always", P_BOOL, P_LOCAL, &sDefault.bSyncAlways, NULL, NULL, 0}, + {"strict sync", P_BOOL, P_LOCAL, &sDefault.bStrictSync, NULL, NULL, 0}, {"Printing Options", P_SEP, P_SEPARATOR}, {"load printers", P_BOOL, P_GLOBAL, &Globals.bLoadPrinters, NULL, NULL, 0}, @@ -1211,6 +1214,7 @@ FN_LOCAL_BOOL(lp_manglednames,bMangledNames) FN_LOCAL_BOOL(lp_widelinks,bWidelinks) FN_LOCAL_BOOL(lp_symlinks,bSymlinks) FN_LOCAL_BOOL(lp_syncalways,bSyncAlways) +FN_LOCAL_BOOL(lp_strict_sync,bStrictSync) FN_LOCAL_BOOL(lp_map_system,bMap_system) FN_LOCAL_BOOL(lp_delete_readonly,bDeleteReadonly) FN_LOCAL_BOOL(lp_fake_oplocks,bFakeOplocks) diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 35189883e2..c9daf14b4b 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2150,7 +2150,7 @@ int reply_writebraw(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) } if (lp_syncalways(SNUM(cnum)) || write_through) - sync_file(fnum); + sync_file(cnum,fnum); DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n", timestring(),fnum,cnum,startpos,numtowrite,total_written)); @@ -2202,7 +2202,7 @@ int reply_writeunlock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) nwritten = write_file(fnum,data,numtowrite); if (lp_syncalways(SNUM(cnum))) - sync_file(fnum); + sync_file(cnum,fnum); if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2257,7 +2257,7 @@ int reply_write(char *inbuf,char *outbuf,int dum_size,int dum_buffsize) nwritten = write_file(fnum,data,numtowrite); if (lp_syncalways(SNUM(cnum))) - sync_file(fnum); + sync_file(cnum,fnum); if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2330,7 +2330,7 @@ int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) chain_fnum = fnum; if (lp_syncalways(SNUM(cnum)) || write_through) - sync_file(fnum); + sync_file(cnum,fnum); return chain_reply(inbuf,outbuf,length,bufsize); } @@ -2398,10 +2398,10 @@ int reply_flush(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) int i; for (i=0;i<MAX_FNUMS;i++) if (OPEN_FNUM(i)) - sync_file(i); + sync_file(cnum,i); } else - sync_file(fnum); + sync_file(cnum,fnum); DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum)); return(outsize); @@ -3866,7 +3866,7 @@ int reply_writebmpx(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) nwritten = write_file(fnum,data,numtowrite); if(lp_syncalways(SNUM(cnum)) || write_through) - sync_file(fnum); + sync_file(cnum,fnum); if(nwritten < numtowrite) return(UNIXERROR(ERRHRD,ERRdiskfull)); @@ -3967,7 +3967,7 @@ int reply_writebs(char *inbuf,char *outbuf, int dum_size, int dum_buffsize) nwritten = write_file(fnum,data,numtowrite); if(lp_syncalways(SNUM(cnum)) || write_through) - sync_file(fnum); + sync_file(cnum,fnum); if (nwritten < numtowrite) { diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 49ce759945..151a6d7ded 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1435,12 +1435,9 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct #else /* No EROFS */ if((fd_ptr->fd == -1) && (errno == EACCES)) { #endif /* EROFS */ - if(flags & O_WRONLY) { - fd_ptr->fd = fd_attempt_open(fname, open_flags|O_WRONLY, mode); - fd_ptr->real_open_flags = O_WRONLY; - } else { - fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDONLY, mode); - fd_ptr->real_open_flags = O_RDONLY; + if(accmode != O_RDWR) { + fd_ptr->fd = fd_attempt_open(fname, open_flags|accmode, mode); + fd_ptr->real_open_flags = accmode; } } } @@ -1564,10 +1561,11 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct /******************************************************************* sync a file ********************************************************************/ -void sync_file(int fnum) +void sync_file(int cnum, int fnum) { #ifndef NO_FSYNC - fsync(Files[fnum].fd_ptr->fd); + if(lp_strict_sync(SNUM(cnum))) + fsync(Files[fnum].fd_ptr->fd); #endif } |