extern int DEBUGLEVEL;
extern pstring sesssetup_user;
-extern int global_oplocks_open;
-extern uint16 oplock_port;
+extern uint16 global_oplock_port;
/****************************************************************************
fd support routines - attempt to do a dos_open
****************************************************************************/
-static int fd_attempt_open(char *fname, int flags, int mode)
+static int fd_attempt_open(struct connection_struct *conn, char *fname,
+ int flags, mode_t mode)
{
- int fd = dos_open(fname,flags,mode);
+ int fd = conn->vfs_ops.open(fname,flags,mode);
/* Fix for files ending in '.' */
if((fd == -1) && (errno == ENOENT) &&
(strchr(fname,'.')==NULL))
{
pstrcat(fname,".");
- fd = dos_open(fname,flags,mode);
+ fd = conn->vfs_ops.open(fname,flags,mode);
}
#if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF))
char tmp = p[max_len];
p[max_len] = '\0';
- if ((fd = dos_open(fname,flags,mode)) == -1)
+ if ((fd = conn->vfs_ops.open(fname,flags,mode)) == -1)
p[max_len] = tmp;
}
}
fd support routines - attempt to re-open an already open fd as O_RDWR.
Save the already open fd (we cannot close due to POSIX file locking braindamage.
****************************************************************************/
-static void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr)
+static void fd_attempt_reopen(char *fname, mode_t mode, file_fd_struct *fd_ptr)
{
int fd = dos_open( fname, O_RDWR, mode);
fd support routines - attempt to close the file referenced by this fd.
Decrements the ref_count and returns it.
****************************************************************************/
-int fd_attempt_close(file_fd_struct *fd_ptr)
+uint16 fd_attempt_close(files_struct *fsp)
{
extern struct current_user current_user;
+ file_fd_struct *fd_ptr = fsp->fd_ptr;
+ uint16 ret_ref;
+
+ if (fd_ptr != NULL) {
+ ret_ref = fd_ptr->ref_count;
+ } else {
+ return 0;
+ }
-#ifdef LARGE_SMB_INO_T
DEBUG(3,("fd_attempt_close fd = %d, dev = %x, inode = %.0f, open_flags = %d, ref_count = %d.\n",
fd_ptr->fd, (unsigned int)fd_ptr->dev, (double)fd_ptr->inode,
fd_ptr->real_open_flags,
fd_ptr->ref_count));
-#else /* LARGE_SMB_INO_T */
- DEBUG(3,("fd_attempt_close fd = %d, dev = %x, inode = %lx, open_flags = %d, ref_count = %d.\n",
- fd_ptr->fd, (unsigned int)fd_ptr->dev, (unsigned long)fd_ptr->inode,
- fd_ptr->real_open_flags,
- fd_ptr->ref_count));
-#endif /* LARGE_SMB_INO_T */
-
- if(fd_ptr->ref_count > 0) {
- fd_ptr->ref_count--;
- if(fd_ptr->ref_count == 0) {
- if(fd_ptr->fd != -1)
- close(fd_ptr->fd);
- if(fd_ptr->fd_readonly != -1)
- close(fd_ptr->fd_readonly);
- if(fd_ptr->fd_writeonly != -1)
- close(fd_ptr->fd_writeonly);
- fd_ptr->fd = -1;
- fd_ptr->fd_readonly = -1;
- fd_ptr->fd_writeonly = -1;
- fd_ptr->real_open_flags = -1;
- fd_ptr->dev = (SMB_DEV_T)-1;
- fd_ptr->inode = (SMB_INO_T)-1;
- fd_ptr->uid_cache_count = 0;
- } else {
- fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid);
- }
- }
- return fd_ptr->ref_count;
+
+ SMB_ASSERT(fd_ptr->ref_count != 0);
+
+ fd_ptr->ref_count--;
+ ret_ref = fd_ptr->ref_count;
+
+ if(fd_ptr->ref_count == 0) {
+ if(fd_ptr->fd != -1)
+ fsp->conn->vfs_ops.close(fd_ptr->fd);
+ if(fd_ptr->fd_readonly != -1)
+ fsp->conn->vfs_ops.close(fd_ptr->fd_readonly);
+ if(fd_ptr->fd_writeonly != -1)
+ fsp->conn->vfs_ops.close(fd_ptr->fd_writeonly);
+ /*
+ * Delete this fd_ptr.
+ */
+ fd_ptr_free(fd_ptr);
+ } else {
+ fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid);
+ }
+
+ return ret_ref;
}
/****************************************************************************
fork and then attempt to open the file, and return success or failure
via an exit code.
****************************************************************************/
-static BOOL check_access_allowed_for_current_user( char *fname, int accmode )
+static BOOL check_access_allowed_for_current_user(struct connection_struct
+ *conn, char *fname,
+ int accmode )
{
pid_t child_pid;
*/
int fd;
DEBUG(9,("check_access_allowed_for_current_user: Child - attempting to open %s with mode %d.\n", fname, accmode ));
- if((fd = fd_attempt_open( fname, accmode, 0)) < 0) {
+ if((fd = fd_attempt_open(conn, fname, accmode, 0)) < 0) {
/* Access denied. */
_exit(EACCES);
}
open a file
****************************************************************************/
static void open_file(files_struct *fsp,connection_struct *conn,
- char *fname1,int flags,int mode, SMB_STRUCT_STAT *sbuf)
+ char *fname1,int flags,mode_t mode, SMB_STRUCT_STAT *sbuf)
{
extern struct current_user current_user;
pstring fname;
SMB_STRUCT_STAT statbuf;
file_fd_struct *fd_ptr;
- int accmode = (flags & (O_RDONLY | O_WRONLY | O_RDWR));
+ int accmode = (flags & O_ACCMODE);
fsp->open = False;
fsp->fd_ptr = 0;
/* this handles a bug in Win95 - it doesn't say to create the file when it
should */
if (conn->printer) {
- flags |= O_CREAT;
+ flags |= (O_CREAT|O_EXCL);
}
/*
* open fd table.
*/
if(sbuf == 0) {
- if(dos_stat(fname, &statbuf) < 0) {
+ if(conn->vfs_ops.stat(dos_to_unix(fname,False), &statbuf) < 0) {
if(errno != ENOENT) {
DEBUG(3,("Error doing stat on file %s (%s)\n",
fname,strerror(errno)));
*/
if(!fd_is_in_uid_cache(fd_ptr, (uid_t)current_user.uid)) {
- if(!check_access_allowed_for_current_user( fname, accmode )) {
+ if(!check_access_allowed_for_current_user(conn, fname, accmode )) {
/* Error - permission denied. */
DEBUG(3,("Permission denied opening file %s (flags=%d, accmode = %d)\n",
fname, flags, accmode));
fd_ptr->real_open_flags = O_RDWR;
/* Set the flags as needed without the read/write modes. */
open_flags = flags & ~(O_RDWR|O_WRONLY|O_RDONLY);
- fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDWR, mode);
+ fd_ptr->fd = fd_attempt_open(conn, fname, open_flags|O_RDWR, mode);
/*
* On some systems opening a file for R/W access on a read only
* filesystems sets errno to EROFS.
if((fd_ptr->fd == -1) && (errno == EACCES)) {
#endif /* EROFS */
if(accmode != O_RDWR) {
- fd_ptr->fd = fd_attempt_open(fname, open_flags|accmode, mode);
+ fd_ptr->fd = fd_attempt_open(conn, fname, open_flags|accmode, mode);
fd_ptr->real_open_flags = accmode;
}
}
if ((fd_ptr->fd >=0) &&
conn->printer && lp_minprintspace(SNUM(conn))) {
pstring dname;
- int dum1,dum2,dum3;
+ SMB_BIG_UINT dum1,dum2,dum3;
char *p;
pstrcpy(dname,fname);
p = strrchr(dname,'/');
if (p) *p = 0;
- if (sys_disk_free(dname,&dum1,&dum2,&dum3) <
- lp_minprintspace(SNUM(conn))) {
- fd_attempt_close(fd_ptr);
+ if (conn->vfs_ops.disk_free(dname,&dum1,&dum2,&dum3) <
+ (SMB_BIG_UINT)lp_minprintspace(SNUM(conn))) {
+ if(fd_attempt_close(fsp) == 0)
+ conn->vfs_ops.unlink(fname);
fsp->fd_ptr = 0;
- if(fd_ptr->ref_count == 0)
- dos_unlink(fname);
errno = ENOSPC;
return;
}
DEBUG(3,("Error opening file %s (%s) (flags=%d)\n",
fname,strerror(errno),flags));
/* Ensure the ref_count is decremented. */
- fd_attempt_close(fd_ptr);
+ fd_attempt_close(fsp);
check_for_pipe(fname);
return;
}
{
if(sbuf == 0) {
/* Do the fstat */
- if(sys_fstat(fd_ptr->fd, &statbuf) == -1) {
+ if(conn->vfs_ops.fstat(fd_ptr->fd, &statbuf) == -1) {
/* Error - backout !! */
DEBUG(3,("Error doing fstat on fd %d, file %s (%s)\n",
fd_ptr->fd, fname,strerror(errno)));
/* Ensure the ref_count is decremented. */
- fd_attempt_close(fd_ptr);
+ fd_attempt_close(fsp);
return;
}
sbuf = &statbuf;
*/
if (fsp->print_file && lp_postscript(SNUM(conn)) && fsp->can_write) {
DEBUG(3,("Writing postscript line\n"));
- write_file(fsp,"%!\n",3);
+ conn->vfs_ops.write(fsp->fd_ptr->fd,"%!\n",3);
}
DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n",
conn->num_files_open));
}
+}
+
+/****************************************************************************
+ If it's a read-only file, and we were compiled with mmap enabled,
+ try and mmap the file. This is split out from open_file() above
+ as mmap'ing the file can cause the kernel reference count to
+ be incremented, which can cause kernel oplocks to be refused.
+ Splitting this call off allows the kernel oplock to be granted, then
+ the file mmap'ed.
+****************************************************************************/
+static void mmap_open_file(files_struct *fsp)
+{
#if WITH_MMAP
/* mmap it if read-only */
if (!fsp->can_write) {
- fsp->mmap_size = file_size(fname);
- fsp->mmap_ptr = (char *)mmap(NULL,fsp->mmap_size,
- PROT_READ,MAP_SHARED,fsp->fd_ptr->fd,0);
-
- if (fsp->mmap_ptr == (char *)-1 || !fsp->mmap_ptr) {
- DEBUG(3,("Failed to mmap() %s - %s\n",
- fname,strerror(errno)));
- fsp->mmap_ptr = NULL;
+ fsp->mmap_size = dos_file_size(fsp->fsp_name);
+ if (fsp->mmap_size < MAX_MMAP_SIZE) {
+ fsp->mmap_ptr = (char *)sys_mmap(NULL,fsp->mmap_size,
+ PROT_READ,MAP_SHARED,fsp->fd_ptr->fd,(SMB_OFF_T)0);
+
+ if (fsp->mmap_ptr == (char *)-1 || !fsp->mmap_ptr) {
+ DEBUG(3,("Failed to mmap() %s - %s\n",
+ fsp->fsp_name,strerror(errno)));
+ fsp->mmap_ptr = NULL;
+ }
}
}
#endif
}
-
/****************************************************************************
C. Hoch 11/22/95
Helper for open_file_shared.
static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, int token,
BOOL *share_locked)
{
- if (fsp->can_write){
-#ifdef LARGE_SMB_OFF_T
- if (is_locked(fsp,conn,0x3FFFFFFFFFFFFFFFLL,0,F_WRLCK)){
-#else
- if (is_locked(fsp,conn,0x3FFFFFFF,0,F_WRLCK)){
-#endif
- /* 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(conn)))
- unlock_share_entry( conn, fsp->fd_ptr->dev,
- fsp->fd_ptr->inode, token);
- close_file(fsp,False);
- /* Share mode no longer locked. */
- *share_locked = False;
- errno = EACCES;
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRlock;
+ if (fsp->can_write){
+ SMB_OFF_T mask2 = ((SMB_OFF_T)0x3) << (SMB_OFF_T_BITS-4);
+ SMB_OFF_T mask = (mask2<<2);
+
+ if (is_locked(fsp,conn,~mask,0,F_WRLCK)){
+ /* 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(conn)))
+ unlock_share_entry( conn, fsp->fd_ptr->dev,
+ fsp->fd_ptr->inode, token);
+ close_file(fsp,False);
+ /* Share mode no longer locked. */
+ *share_locked = False;
+ errno = EACCES;
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRlock;
+ } else {
+ sys_ftruncate(fsp->fd_ptr->fd,0);
+ }
+ }
+}
+
+
+enum {AFAIL,AREAD,AWRITE,AALL};
+
+/*******************************************************************
+reproduce the share mode access table
+********************************************************************/
+static int access_table(int new_deny,int old_deny,int old_mode,
+ int share_pid,char *fname)
+{
+ if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);
+
+ if (new_deny == DENY_DOS || old_deny == DENY_DOS) {
+ int pid = getpid();
+ if (old_deny == new_deny && share_pid == pid)
+ return(AALL);
+
+ if (old_mode == 0) return(AREAD);
+
+ /* the new smbpub.zip spec says that if the file extension is
+ .com, .dll, .exe or .sym then allow the open. I will force
+ it to read-only as this seems sensible although the spec is
+ a little unclear on this. */
+ if ((fname = strrchr(fname,'.'))) {
+ if (strequal(fname,".com") ||
+ strequal(fname,".dll") ||
+ strequal(fname,".exe") ||
+ strequal(fname,".sym"))
+ return(AREAD);
}
- else
- sys_ftruncate(fsp->fd_ptr->fd,0);
+
+ return(AFAIL);
}
+
+ switch (new_deny)
+ {
+ case DENY_WRITE:
+ if (old_deny==DENY_WRITE && old_mode==0) return(AREAD);
+ if (old_deny==DENY_READ && old_mode==0) return(AWRITE);
+ if (old_deny==DENY_NONE && old_mode==0) return(AALL);
+ return(AFAIL);
+ case DENY_READ:
+ if (old_deny==DENY_WRITE && old_mode==1) return(AREAD);
+ if (old_deny==DENY_READ && old_mode==1) return(AWRITE);
+ if (old_deny==DENY_NONE && old_mode==1) return(AALL);
+ return(AFAIL);
+ case DENY_NONE:
+ if (old_deny==DENY_WRITE) return(AREAD);
+ if (old_deny==DENY_READ) return(AWRITE);
+ if (old_deny==DENY_NONE) return(AALL);
+ return(AFAIL);
+ }
+ return(AFAIL);
}
+/****************************************************************************
+check if we can open a file with a share mode
+****************************************************************************/
+static int check_share_mode( share_mode_entry *share, int deny_mode,
+ char *fname,
+ BOOL fcbopen, int *flags)
+{
+ int old_open_mode = GET_OPEN_MODE(share->share_mode);
+ int old_deny_mode = GET_DENY_MODE(share->share_mode);
+
+ /*
+ * Don't allow any open once the delete on close flag has been
+ * set.
+ */
+
+ if(GET_DELETE_ON_CLOSE_FLAG(share->share_mode))
+ {
+ DEBUG(5,("check_share_mode: Failing open on file %s as delete on close flag is set.\n",
+ fname ));
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRnoaccess;
+ return False;
+ }
+
+ if (old_deny_mode > 4 || old_open_mode > 2)
+ {
+ DEBUG(0,("Invalid share mode found (%d,%d,%d) on file %s\n",
+ deny_mode,old_deny_mode,old_open_mode,fname));
+
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadshare;
+
+ return False;
+ }
+
+ {
+ int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
+ share->pid,fname);
+
+ if ((access_allowed == AFAIL) ||
+ (!fcbopen && (access_allowed == AREAD && *flags == O_RDWR)) ||
+ (access_allowed == AREAD && *flags == O_WRONLY) ||
+ (access_allowed == AWRITE && *flags == O_RDONLY))
+ {
+ DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s,fcbopen = %d, flags = %d) = %d\n",
+ deny_mode,old_deny_mode,old_open_mode,
+ share->pid,fname, fcbopen, *flags, access_allowed));
+
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadshare;
+
+ return False;
+ }
+
+ if (access_allowed == AREAD)
+ *flags = O_RDONLY;
+
+ if (access_allowed == AWRITE)
+ *flags = O_WRONLY;
+
+ }
+
+ return True;
+}
+
/****************************************************************************
open a file with a share mode
****************************************************************************/
-void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int share_mode,int ofun,
- int mode,int oplock_request, int *Access,int *action)
+void open_file_shared(files_struct *fsp, connection_struct *conn,
+ char *fname, int share_mode, int ofun,
+ mode_t mode, int oplock_request, int *Access,
+ int *action)
{
int flags=0;
int flags2=0;
- int deny_mode = (share_mode>>4)&7;
+ int deny_mode = GET_DENY_MODE(share_mode);
+ BOOL allow_share_delete = GET_ALLOW_SHARE_DELETE(share_mode);
SMB_STRUCT_STAT sbuf;
- BOOL file_existed = file_exist(fname,&sbuf);
+ BOOL file_existed = vfs_file_exist(conn, dos_to_unix(fname,False), &sbuf);
BOOL share_locked = False;
BOOL fcbopen = False;
int token;
fsp->open = False;
fsp->fd_ptr = 0;
+ DEBUG(10,("open_file_shared: fname = %s, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n",
+ fname, share_mode, ofun, (int)mode, oplock_request ));
+
/* this is for OS/2 EAs - try and say we don't support them */
if (strstr(fname,".+,;=[]."))
{
unix_ERR_code = ERROR_EAS_NOT_SUPPORTED;
#endif /* OS2_WPS_FIX */
+ DEBUG(5,("open_file_shared: OS/2 EA's are not supported.\n"));
return;
}
- if ((ofun & 0x3) == 0 && file_existed)
+ if ((GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_FAIL) && file_existed)
{
+ DEBUG(5,("open_file_shared: create new requested for file %s and file already exists.\n",
+ fname ));
errno = EEXIST;
return;
}
- if (ofun & 0x10)
+ if (GET_FILE_CREATE_DISPOSITION(ofun) == FILE_CREATE_IF_NOT_EXIST)
flags2 |= O_CREAT;
- if ((ofun & 0x3) == 2)
+
+ if (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_TRUNCATE)
flags2 |= O_TRUNC;
+ if (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_FAIL)
+ flags2 |= O_EXCL;
+
/* note that we ignore the append flag as
append does not mean the same thing under dos and unix */
- switch (share_mode&0xF)
+ switch (GET_OPEN_MODE(share_mode))
{
- case 1:
+ case DOS_OPEN_WRONLY:
flags = O_WRONLY;
break;
- case 0xF:
+ case DOS_OPEN_FCB:
fcbopen = True;
flags = O_RDWR;
break;
- case 2:
+ case DOS_OPEN_RDWR:
flags = O_RDWR;
break;
default:
}
#if defined(O_SYNC)
- if (share_mode&(1<<14)) {
+ if (GET_FILE_SYNC_OPENMODE(share_mode)) {
flags2 |= O_SYNC;
}
#endif /* O_SYNC */
{
if (!fcbopen)
{
+ DEBUG(5,("open_file_shared: read/write access requested for file %s on read only %s\n",
+ fname, !CAN_WRITE(conn) ? "share" : "file" ));
errno = EACCES;
return;
}
return;
}
- if (deny_mode == DENY_FCB) deny_mode = DENY_DOS;
+ if (deny_mode == DENY_FCB)
+ deny_mode = DENY_DOS;
if (lp_share_modes(SNUM(conn)))
{
if(share_entry->op_type & (EXCLUSIVE_OPLOCK|BATCH_OPLOCK))
{
-#ifdef LARGE_SMB_INO_T
DEBUG(5,("open_file_shared: breaking oplock (%x) on file %s, \
dev = %x, inode = %.0f\n", share_entry->op_type, fname, (unsigned int)dev, (double)inode));
-#else /* LARGE_SMB_INO_T */
- DEBUG(5,("open_file_shared: breaking oplock (%x) on file %s, \
-dev = %x, inode = %lx\n", share_entry->op_type, fname, (unsigned int)dev, (unsigned long)inode));
-#endif /* LARGE_SMB_INO_T */
/* Oplock break.... */
unlock_share_entry(conn, dev, inode, token);
{
free((char *)old_shares);
-#ifdef LARGE_SMB_INO_T
DEBUG(0,("open_file_shared: FAILED when breaking oplock (%x) on file %s, \
dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (double)inode));
-#else /* LARGE_SMB_INO_T */
- DEBUG(0,("open_file_shared: FAILED when breaking oplock (%x) on file %s, \
-dev = %x, inode = %lx\n", old_shares[i].op_type, fname, (unsigned int)dev, (unsigned long)inode));
-#endif /* LARGE_SMB_INO_T */
errno = EACCES;
unix_ERR_class = ERRDOS;
free((char *)old_shares);
unlock_share_entry(conn, dev, inode, token);
errno = EACCES;
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadshare;
return;
}
}
DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
- flags,flags2,mode));
+ flags,flags2,(int)mode));
open_file(fsp,conn,fname,flags|(flags2&~(O_TRUNC)),mode,file_existed ? &sbuf : 0);
if (!fsp->open && flags==O_RDWR && errno!=ENOENT && fcbopen)
switch (flags)
{
case O_RDONLY:
- open_mode = 0;
+ open_mode = DOS_OPEN_RDONLY;
break;
case O_RDWR:
- open_mode = 2;
+ open_mode = DOS_OPEN_RDWR;
break;
case O_WRONLY:
- open_mode = 1;
+ open_mode = DOS_OPEN_WRONLY;
break;
}
- fsp->share_mode = (deny_mode<<4) | open_mode;
+ fsp->share_mode = SET_DENY_MODE(deny_mode) |
+ SET_OPEN_MODE(open_mode) |
+ SET_ALLOW_SHARE_DELETE(allow_share_delete);
if (Access)
(*Access) = open_mode;
if (lp_share_modes(SNUM(conn)))
{
uint16 port = 0;
+
/* JRA. Currently this only services Exlcusive and batch
oplocks (no other opens on this file). This needs to
be extended to level II oplocks (multiple reader
oplocks). */
- if(oplock_request && (num_share_modes == 0) && lp_oplocks(SNUM(conn)) &&
- !IS_VETO_OPLOCK_PATH(conn,fname))
+ if((oplock_request) && (num_share_modes == 0) && lp_oplocks(SNUM(conn)) &&
+ !IS_VETO_OPLOCK_PATH(conn,fname) && set_file_oplock(fsp) )
{
- fsp->granted_oplock = True;
- fsp->sent_oplock_break = False;
- global_oplocks_open++;
- port = oplock_port;
-
-#ifdef LARGE_SMB_INO_T
- DEBUG(5,("open_file_shared: granted oplock (%x) on file %s, \
-dev = %x, inode = %.0f\n", oplock_request, fname, (unsigned int)dev, (double)inode));
-#else /* LARGE_SMB_INO_T */
- DEBUG(5,("open_file_shared: granted oplock (%x) on file %s, \
-dev = %x, inode = %lx\n", oplock_request, fname, (unsigned int)dev, (double)inode));
-#endif /* LARGE_SMB_INO_T */
-
+ port = global_oplock_port;
}
else
{
port = 0;
oplock_request = 0;
}
+
set_share_mode(token, fsp, port, oplock_request);
}
if ((flags2&O_TRUNC) && file_existed)
truncate_unless_locked(fsp,conn,token,&share_locked);
+
+ /*
+ * Attempt to mmap a read only file.
+ * Moved until after a kernel oplock may
+ * be granted due to reference count issues. JRA.
+ */
+ mmap_open_file(fsp);
}
if (share_locked && lp_share_modes(SNUM(conn)))
unlock_share_entry( conn, dev, inode, token);
}
-
-
/****************************************************************************
Open a directory from an NT SMB call.
****************************************************************************/
+
int open_directory(files_struct *fsp,connection_struct *conn,
- char *fname, int smb_ofun, int unixmode, int *action)
+ char *fname, int smb_ofun, mode_t unixmode, int *action)
{
extern struct current_user current_user;
SMB_STRUCT_STAT st;
* Create the directory.
*/
- if(dos_mkdir(fname, unixmode) < 0) {
+ if(conn->vfs_ops.mkdir(dos_to_unix(fname,False),
+ unix_mode(conn,aDIR)) < 0) {
DEBUG(0,("open_directory: unable to create %s. Error was %s\n",
fname, strerror(errno) ));
return -1;
* Check that it *was* a directory.
*/
- if(dos_stat(fname, &st) < 0) {
+ if(conn->vfs_ops.stat(dos_to_unix(fname,False), &st) < 0) {
DEBUG(0,("open_directory: unable to stat name = %s. Error was %s\n",
fname, strerror(errno) ));
return -1;
return 0;
}
-enum {AFAIL,AREAD,AWRITE,AALL};
-
-/*******************************************************************
-reproduce the share mode access table
-********************************************************************/
-static int access_table(int new_deny,int old_deny,int old_mode,
- int share_pid,char *fname)
-{
- if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);
-
- if (new_deny == DENY_DOS || old_deny == DENY_DOS) {
- int pid = getpid();
- if (old_deny == new_deny && share_pid == pid)
- return(AALL);
-
- if (old_mode == 0) return(AREAD);
-
- /* the new smbpub.zip spec says that if the file extension is
- .com, .dll, .exe or .sym then allow the open. I will force
- it to read-only as this seems sensible although the spec is
- a little unclear on this. */
- if ((fname = strrchr(fname,'.'))) {
- if (strequal(fname,".com") ||
- strequal(fname,".dll") ||
- strequal(fname,".exe") ||
- strequal(fname,".sym"))
- return(AREAD);
- }
-
- return(AFAIL);
- }
-
- switch (new_deny)
- {
- case DENY_WRITE:
- if (old_deny==DENY_WRITE && old_mode==0) return(AREAD);
- if (old_deny==DENY_READ && old_mode==0) return(AWRITE);
- if (old_deny==DENY_NONE && old_mode==0) return(AALL);
- return(AFAIL);
- case DENY_READ:
- if (old_deny==DENY_WRITE && old_mode==1) return(AREAD);
- if (old_deny==DENY_READ && old_mode==1) return(AWRITE);
- if (old_deny==DENY_NONE && old_mode==1) return(AALL);
- return(AFAIL);
- case DENY_NONE:
- if (old_deny==DENY_WRITE) return(AREAD);
- if (old_deny==DENY_READ) return(AWRITE);
- if (old_deny==DENY_NONE) return(AALL);
- return(AFAIL);
- }
- return(AFAIL);
-}
/*******************************************************************
check if the share mode on a file allows it to be deleted or unlinked
return True if sharing doesn't prevent the operation
********************************************************************/
+
BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op)
{
int i;
if(!lp_share_modes(SNUM(conn)))
return True;
- if (dos_stat(fname,&sbuf) == -1) return(True);
+ if (conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf) == -1) return(True);
dev = sbuf.st_dev;
inode = sbuf.st_ino;
if(rename_op && (share_entry->pid == pid))
{
-#ifdef LARGE_SMB_INO_T
DEBUG(0,("check_file_sharing: NT redirector workaround - rename attempted on \
batch oplocked file %s, dev = %x, inode = %.0f\n", fname, (unsigned int)dev, (double)inode));
-#else /* LARGE_SMB_INO_T */
- DEBUG(0,("check_file_sharing: NT redirector workaround - rename attempted on \
-batch oplocked file %s, dev = %x, inode = %lx\n", fname, (unsigned int)dev, (unsigned long)inode));
-#endif /* LARGE_SMB_INO_T */
/*
* This next line is a test that allows the deny-mode
else
{
-#ifdef LARGE_SMB_INO_T
DEBUG(5,("check_file_sharing: breaking oplock (%x) on file %s, \
dev = %x, inode = %.0f\n", share_entry->op_type, fname, (unsigned int)dev, (double)inode));
-#else /* LARGE_SMB_INO_T */
- DEBUG(5,("check_file_sharing: breaking oplock (%x) on file %s, \
-dev = %x, inode = %lx\n", share_entry->op_type, fname, (unsigned int)dev, (unsigned long)inode));
-#endif /* LARGE_SMB_INO_T */
/* Oplock break.... */
unlock_share_entry(conn, dev, inode, token);
{
free((char *)old_shares);
-#ifdef LARGE_SMB_INO_T
DEBUG(0,("check_file_sharing: FAILED when breaking oplock (%x) on file %s, \
dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (double)inode));
-#else /* LARGE_SMB_INO_T */
- DEBUG(0,("check_file_sharing: FAILED when breaking oplock (%x) on file %s, \
-dev = %x, inode = %lx\n", old_shares[i].op_type, fname, (unsigned int)dev, (unsigned long)inode));
-#endif /* LARGE_SMB_INO_T */
return False;
}
}
}
- /* someone else has a share lock on it, check to see
- if we can too */
- if ((share_entry->share_mode != DENY_DOS) || (share_entry->pid != pid))
+ /*
+ * If this is a delete request and ALLOW_SHARE_DELETE is set then allow
+ * this to proceed. This takes precedence over share modes.
+ */
+
+ if(!rename_op && GET_ALLOW_SHARE_DELETE(share_entry->share_mode))
+ continue;
+
+ /*
+ * Someone else has a share lock on it, check to see
+ * if we can too.
+ */
+
+ if ((GET_DENY_MODE(share_entry->share_mode) != DENY_DOS) || (share_entry->pid != pid))
goto free_and_exit;
} /* end for */
/* XXXX exactly what share mode combinations should be allowed for
deleting/renaming? */
- /* If we got here then either there were no share modes or
- all share modes were DENY_DOS and the pid == getpid() */
+ /*
+ * If we got here then either there were no share modes or
+ * all share modes were DENY_DOS and the pid == getpid() or
+ * delete access was requested and all share modes had the
+ * ALLOW_SHARE_DELETE bit set (takes precedence over other
+ * share modes).
+ */
+
ret = True;
free_and_exit:
free((char *)old_shares);
return(ret);
}
-
-/****************************************************************************
-check if we can open a file with a share mode
-****************************************************************************/
-int check_share_mode( share_mode_entry *share, int deny_mode, char *fname,
- BOOL fcbopen, int *flags)
-{
- int old_open_mode = share->share_mode &0xF;
- int old_deny_mode = (share->share_mode >>4)&7;
-
- if (old_deny_mode > 4 || old_open_mode > 2)
- {
- DEBUG(0,("Invalid share mode found (%d,%d,%d) on file %s\n",
- deny_mode,old_deny_mode,old_open_mode,fname));
- return False;
- }
-
- {
- int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
- share->pid,fname);
-
- if ((access_allowed == AFAIL) ||
- (!fcbopen && (access_allowed == AREAD && *flags == O_RDWR)) ||
- (access_allowed == AREAD && *flags == O_WRONLY) ||
- (access_allowed == AWRITE && *flags == O_RDONLY))
- {
- DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s,fcbopen = %d, flags = %d) = %d\n",
- deny_mode,old_deny_mode,old_open_mode,
- share->pid,fname, fcbopen, *flags, access_allowed));
- return False;
- }
-
- if (access_allowed == AREAD)
- *flags = O_RDONLY;
-
- if (access_allowed == AWRITE)
- *flags = O_WRONLY;
-
- }
- return True;
-}
-