summaryrefslogtreecommitdiffstats
path: root/source/smbd/open.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/smbd/open.c')
-rw-r--r--source/smbd/open.c229
1 files changed, 99 insertions, 130 deletions
diff --git a/source/smbd/open.c b/source/smbd/open.c
index a95793a0505..79330175bbd 100644
--- a/source/smbd/open.c
+++ b/source/smbd/open.c
@@ -1,5 +1,6 @@
/*
- Unix SMB/CIFS implementation.
+ Unix SMB/Netbios implementation.
+ Version 1.9.
file opening and share modes
Copyright (C) Andrew Tridgell 1992-1998
Copyright (C) Jeremy Allison 2001
@@ -33,18 +34,19 @@ static int fd_open(struct connection_struct *conn, char *fname,
int flags, mode_t mode)
{
int fd;
+
#ifdef O_NOFOLLOW
if (!lp_symlinks(SNUM(conn)))
flags |= O_NOFOLLOW;
#endif
- fd = conn->vfs_ops.open(conn,fname,flags,mode);
+ fd = conn->vfs_ops.open(conn,dos_to_unix_static(fname),flags,mode);
/* Fix for files ending in '.' */
if((fd == -1) && (errno == ENOENT) &&
- (strchr_m(fname,'.')==NULL)) {
+ (strchr(fname,'.')==NULL)) {
pstrcat(fname,".");
- fd = conn->vfs_ops.open(conn,fname,flags,mode);
+ fd = conn->vfs_ops.open(conn,dos_to_unix_static(fname),flags,mode);
}
DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n", fname,
@@ -139,33 +141,21 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn,
* as we always opened files read-write in that release. JRA.
*/
- if ((accmode == O_RDONLY) && ((flags & O_TRUNC) == O_TRUNC)) {
- DEBUG(10,("open_file: truncate requested on read-only open for file %s\n",fname ));
+ if ((accmode == O_RDONLY) && ((flags & O_TRUNC) == O_TRUNC))
local_flags = (flags & ~O_ACCMODE)|O_RDWR;
- }
-
- if ((desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ||
- (local_flags & O_CREAT) || ((local_flags & O_TRUNC) == O_TRUNC) ) {
- /*
- * We can't actually truncate here as the file may be locked.
- * open_file_shared will take care of the truncate later. JRA.
- */
+ /*
+ * We can't actually truncate here as the file may be locked.
+ * open_file_shared will take care of the truncate later. JRA.
+ */
- local_flags &= ~O_TRUNC;
+ local_flags &= ~O_TRUNC;
-#if defined(O_NONBLOCK) && defined(S_ISFIFO)
- /*
- * We would block on opening a FIFO with no one else on the
- * other end. Do what we used to do and add O_NONBLOCK to the
- * open flags. JRA.
- */
+ /* actually do the open */
- if (VALID_STAT(*psbuf) && S_ISFIFO(psbuf->st_mode))
- local_flags |= O_NONBLOCK;
-#endif
+ if ((desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ||
+ (local_flags & O_CREAT)) {
- /* actually do the open */
fsp->fd = fd_open(conn, fname, local_flags, mode);
if (fsp->fd == -1) {
@@ -226,7 +216,15 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn,
fsp->is_directory = False;
fsp->directory_delete_on_close = False;
fsp->conn = conn;
+ /*
+ * Note that the file name here is the *untranslated* name
+ * ie. it is still in the DOS codepage sent from the client.
+ * All use of this filename will pass though the sys_xxxx
+ * functions which will do the dos_to_unix translation before
+ * mapping into a UNIX filename. JRA.
+ */
string_set(&fsp->fsp_name,fname);
+ fsp->wbmpx_ptr = NULL;
fsp->wcp = NULL; /* Write cache pointer. */
DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n",
@@ -262,7 +260,7 @@ return True if the filename is one of the special executable types
********************************************************************/
static BOOL is_executable(const char *fname)
{
- if ((fname = strrchr_m(fname,'.'))) {
+ if ((fname = strrchr(fname,'.'))) {
if (strequal(fname,".com") ||
strequal(fname,".dll") ||
strequal(fname,".exe") ||
@@ -527,10 +525,10 @@ existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsign
****************************************************************************/
static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T dev,
- SMB_INO_T inode,
- uint32 desired_access,
- int share_mode, int *p_flags, int *p_oplock_request,
- BOOL *p_all_current_opens_are_level_II)
+ SMB_INO_T inode,
+ uint32 desired_access,
+ int share_mode, int *p_flags, int *p_oplock_request,
+ BOOL *p_all_current_opens_are_level_II)
{
int i;
int num_share_modes;
@@ -538,28 +536,28 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T
share_mode_entry *old_shares = 0;
BOOL fcbopen = False;
BOOL broke_oplock;
-
+
if(GET_OPEN_MODE(share_mode) == DOS_OPEN_FCB)
fcbopen = True;
-
+
num_share_modes = get_share_modes(conn, dev, inode, &old_shares);
-
+
if(num_share_modes == 0)
return 0;
-
+
/*
* Check if the share modes will give us access.
*/
-
+
do {
share_mode_entry broken_entry;
-
+
broke_oplock = False;
*p_all_current_opens_are_level_II = True;
-
+
for(i = 0; i < num_share_modes; i++) {
share_mode_entry *share_entry = &old_shares[i];
-
+
/*
* By observation of NetBench, oplocks are broken *before* share
* modes are checked. This allows a file to be closed by the client
@@ -567,23 +565,23 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T
* Check if someone has an oplock on this file. If so we must break
* it before continuing.
*/
-
+
if((*p_oplock_request && EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type)) ||
- (!*p_oplock_request && (share_entry->op_type != NO_OPLOCK))) {
-
+ (!*p_oplock_request && (share_entry->op_type != NO_OPLOCK))) {
+
BOOL opb_ret;
DEBUG(5,("open_mode_check: oplock_request = %d, breaking oplock (%x) on file %s, \
dev = %x, inode = %.0f\n", *p_oplock_request, share_entry->op_type, fname, (unsigned int)dev, (double)inode));
-
+
/* Oplock break - unlock to request it. */
unlock_share_entry(conn, dev, inode);
-
+
opb_ret = request_oplock_break(share_entry);
-
+
/* Now relock. */
lock_share_entry(conn, dev, inode);
-
+
if(opb_ret == False) {
DEBUG(0,("open_mode_check: FAILED when breaking oplock (%x) on file %s, \
dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (double)inode));
@@ -593,85 +591,84 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou
unix_ERR_code = ERRbadshare;
return -1;
}
-
+
broke_oplock = True;
broken_entry = *share_entry;
break;
-
+
} else if (!LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) {
*p_all_current_opens_are_level_II = False;
}
-
+
/* someone else has a share lock on it, check to see if we can too */
- if (!check_share_mode(conn, share_entry, share_mode, desired_access,
+ if (!check_share_mode(conn, share_entry, share_mode, desired_access,
fname, fcbopen, p_flags)) {
SAFE_FREE(old_shares);
errno = EACCES;
return -1;
- }
-
+ }
+
} /* end for */
-
+
if(broke_oplock) {
SAFE_FREE(old_shares);
num_share_modes = get_share_modes(conn, dev, inode, &old_shares);
oplock_contention_count++;
-
+
/* Paranoia check that this is no longer an exlusive entry. */
for(i = 0; i < num_share_modes; i++) {
share_mode_entry *share_entry = &old_shares[i];
-
+
if (share_modes_identical(&broken_entry, share_entry) &&
- EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type) ) {
-
+ EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type) ) {
+
/*
* This should not happen. The target left this oplock
* as exlusive.... The process *must* be dead....
*/
-
+
DEBUG(0,("open_mode_check: exlusive oplock left by process %d after break ! For file %s, \
dev = %x, inode = %.0f. Deleting it to continue...\n", (int)broken_entry.pid, fname, (unsigned int)dev, (double)inode));
-
+
if (process_exists(broken_entry.pid)) {
- DEBUG(0,("open_mode_check: Existent process %d left active oplock.\n",
- broken_entry.pid ));
+ DEBUG(0,("open_mode_check: Existent process %u left active oplock.\n",
+ (unsigned int)broken_entry.pid ));
}
-
+
if (del_share_entry(dev, inode, &broken_entry, NULL) == -1) {
errno = EACCES;
unix_ERR_class = ERRDOS;
unix_ERR_code = ERRbadshare;
return -1;
}
-
+
/*
* We must reload the share modes after deleting the
* other process's entry.
*/
-
+
SAFE_FREE(old_shares);
num_share_modes = get_share_modes(conn, dev, inode, &old_shares);
break;
}
} /* end for paranoia... */
} /* end if broke_oplock */
-
+
} while(broke_oplock);
-
- if(old_shares != 0)
- SAFE_FREE(old_shares);
-
+
+ SAFE_FREE(old_shares);
+
/*
* Refuse to grant an oplock in case the contention limit is
* reached when going through the lock list multiple times.
*/
-
+
if(oplock_contention_count >= lp_oplock_contention_limit(SNUM(conn))) {
*p_oplock_request = 0;
DEBUG(4,("open_mode_check: oplock contention = %d. Not granting oplock.\n",
- oplock_contention_count ));
+ oplock_contention_count ));
}
-
+
return num_share_modes;
}
@@ -692,50 +689,24 @@ static void kernel_flock(files_struct *fsp, int deny_mode)
}
-static BOOL open_match_attributes(connection_struct *conn, char *path, mode_t existing_mode, mode_t new_mode)
-{
- uint32 old_dos_mode, new_dos_mode;
- SMB_STRUCT_STAT sbuf;
-
- ZERO_STRUCT(sbuf);
-
- sbuf.st_mode = existing_mode;
- old_dos_mode = dos_mode(conn, path, &sbuf);
-
- sbuf.st_mode = new_mode;
- new_dos_mode = dos_mode(conn, path, &sbuf);
-
- /* If we're mapping SYSTEM and HIDDEN ensure they match. */
- if (lp_map_system(SNUM(conn))) {
- if ((old_dos_mode & FILE_ATTRIBUTE_SYSTEM) != (new_dos_mode & FILE_ATTRIBUTE_SYSTEM))
- return False;
- }
- if (lp_map_hidden(SNUM(conn))) {
- if ((old_dos_mode & FILE_ATTRIBUTE_HIDDEN) != (new_dos_mode & FILE_ATTRIBUTE_HIDDEN))
- return False;
- }
- return True;
-}
-
/****************************************************************************
- Open a file with a share mode. On output from this open we are guarenteeing
- that
+ Open a file with a share mode - old method.
****************************************************************************/
+
files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_STAT *psbuf,
- int share_mode,int ofun, mode_t mode,int oplock_request,
- int *Access,int *action)
+ int share_mode,int ofun, mode_t mode,int oplock_request, int *Access,int *action)
{
- return open_file_shared1(conn, fname, psbuf, 0, share_mode, ofun, mode,
- oplock_request, Access, action);
+ return open_file_shared1(conn, fname, psbuf, 0, share_mode, ofun, mode,
+ oplock_request, Access, action);
}
/****************************************************************************
- Open a file with a share mode. On output from this open we are guarenteeing
- that
+ Open a file with a share mode - called from NTCreateAndX.
****************************************************************************/
+
files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_STAT *psbuf,
- uint32 desired_access,
- int share_mode,int ofun, mode_t mode,int oplock_request,
+ uint32 desired_access,
+ int share_mode,int ofun, mode_t mode,int oplock_request,
int *Access,int *action)
{
int flags=0;
@@ -756,8 +727,8 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_
uint16 port = 0;
if (conn->printer) {
- /* printers are handled completely differently. Most of the passed parameters are
- ignored */
+ /* printers are handled completely differently. Most
+ of the passed parameters are ignored */
if (Access)
*Access = DOS_OPEN_WRONLY;
if (action)
@@ -811,17 +782,6 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_
if (CAN_WRITE(conn) && (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_TRUNCATE))
flags2 |= O_TRUNC;
- /* We only care about matching attributes on file exists and truncate. */
- if (file_existed && (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_TRUNCATE)) {
- if (!open_match_attributes(conn, fname, psbuf->st_mode, mode)) {
- DEBUG(5,("open_file_shared: attributes missmatch for file %s (0%o, 0%o)\n",
- fname, psbuf->st_mode, mode ));
- file_free(fsp);
- errno = EACCES;
- return NULL;
- }
- }
-
if (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_FAIL)
flags2 |= O_EXCL;
@@ -884,10 +844,10 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_
lock_share_entry(conn, dev, inode);
- num_share_modes = open_mode_check(conn, fname, dev, inode,
- desired_access,
- share_mode,
- &flags, &oplock_request, &all_current_opens_are_level_II);
+ num_share_modes = open_mode_check(conn, fname, dev, inode,
+ desired_access, share_mode,
+ &flags, &oplock_request, &all_current_opens_are_level_II);
+
if(num_share_modes == -1) {
/*
@@ -925,7 +885,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n",
*/
if ((flags2 & O_CREAT) && lp_inherit_acls(SNUM(conn)) &&
- (def_acl = directory_has_default_acl(conn, parent_dirname(fname))))
+ (def_acl = directory_has_default_acl(conn, dos_to_unix_static(parent_dirname(fname)))))
mode = 0777;
DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
@@ -960,10 +920,9 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n",
lock_share_entry_fsp(fsp);
- num_share_modes = open_mode_check(conn, fname, dev, inode,
- desired_access,
- share_mode,
- &flags, &oplock_request, &all_current_opens_are_level_II);
+ num_share_modes = open_mode_check(conn, fname, dev, inode,
+ desired_access, share_mode,
+ &flags, &oplock_request, &all_current_opens_are_level_II);
if(num_share_modes == -1) {
unlock_share_entry_fsp(fsp);
@@ -1213,7 +1172,7 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST
*/
if(!got_stat) {
- DEBUG(3,("open_directory: unable to stat name = %s. Error was %s\n",
+ DEBUG(0,("open_directory: unable to stat name = %s. Error was %s\n",
fname, strerror(errno) ));
file_free(fsp);
return NULL;
@@ -1252,7 +1211,6 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST
fsp->is_directory = True;
fsp->directory_delete_on_close = False;
fsp->conn = conn;
- string_set(&fsp->fsp_name,fname);
if (delete_on_close) {
NTSTATUS result = set_delete_on_close_internal(fsp, delete_on_close);
@@ -1262,6 +1220,17 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST
return NULL;
}
}
+
+ /*
+ * Note that the file name here is the *untranslated* name
+ * ie. it is still in the DOS codepage sent from the client.
+ * All use of this filename will pass though the sys_xxxx
+ * functions which will do the dos_to_unix translation before
+ * mapping into a UNIX filename. JRA.
+ */
+ string_set(&fsp->fsp_name,fname);
+ fsp->wbmpx_ptr = NULL;
+
conn->num_files_open++;
return fsp;