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.c186
1 files changed, 102 insertions, 84 deletions
diff --git a/source/smbd/open.c b/source/smbd/open.c
index f4c0733b20d..cc02abe4f6a 100644
--- a/source/smbd/open.c
+++ b/source/smbd/open.c
@@ -28,35 +28,41 @@ extern uint16 global_oplock_port;
extern BOOL global_client_failed_oplock_break;
/****************************************************************************
-fd support routines - attempt to do a dos_open
+ fd support routines - attempt to do a dos_open.
****************************************************************************/
+
static int fd_open(struct connection_struct *conn, char *fname,
- int flags, mode_t mode)
+ int flags, mode_t mode)
{
- int fd = conn->vfs_ops.open(dos_to_unix(fname,False),flags,mode);
+ int fd = conn->vfs_ops.open(dos_to_unix(fname,False),flags,mode);
- /* Fix for files ending in '.' */
- if((fd == -1) && (errno == ENOENT) &&
+ /* Fix for files ending in '.' */
+ if((fd == -1) && (errno == ENOENT) &&
(strchr(fname,'.')==NULL)) {
- pstrcat(fname,".");
- fd = conn->vfs_ops.open(dos_to_unix(fname,False),flags,mode);
- }
+ pstrcat(fname,".");
+ fd = conn->vfs_ops.open(dos_to_unix(fname,False),flags,mode);
+ }
+
+ DEBUG(10,("fd_open: name %s, mode = %d, fd = %d. %s\n", fname, (int)mode, fd,
+ (fd == -1) ? strerror(errno) : "" ));
- return fd;
+ return fd;
}
/****************************************************************************
-close the file associated with a fsp
+ Close the file associated with a fsp.
****************************************************************************/
-void fd_close(files_struct *fsp, int *err_ret)
+
+int fd_close(struct connection_struct *conn, files_struct *fsp)
{
- fsp->conn->vfs_ops.close(fsp->fd);
+ int ret = conn->vfs_ops.close(fsp->fd);
fsp->fd = -1;
- }
+ return ret;
+}
/****************************************************************************
-check a filename for the pipe string
+ Check a filename for the pipe string.
****************************************************************************/
static void check_for_pipe(char *fname)
@@ -73,99 +79,111 @@ static void check_for_pipe(char *fname)
}
/****************************************************************************
-open a file
+ Open a file.
****************************************************************************/
static void open_file(files_struct *fsp,connection_struct *conn,
char *fname1,int flags,mode_t mode)
{
- extern struct current_user current_user;
- pstring fname;
- int accmode = (flags & O_ACCMODE);
+ extern struct current_user current_user;
+ pstring fname;
+ int accmode = (flags & O_ACCMODE);
SMB_STRUCT_STAT sbuf;
- fsp->open = False;
+ fsp->open = False;
fsp->fd = 0;
- fsp->oplock_type = NO_OPLOCK;
- errno = EPERM;
+ fsp->oplock_type = NO_OPLOCK;
+ errno = EPERM;
- pstrcpy(fname,fname1);
+ pstrcpy(fname,fname1);
- /* check permissions */
+ /* Check permissions */
- /*
- * This code was changed after seeing a client open request
- * containing the open mode of (DENY_WRITE/read-only) with
- * the 'create if not exist' bit set. The previous code
- * would fail to open the file read only on a read-only share
- * as it was checking the flags parameter directly against O_RDONLY,
- * this was failing as the flags parameter was set to O_RDONLY|O_CREAT.
- * JRA.
- */
+ /*
+ * This code was changed after seeing a client open request
+ * containing the open mode of (DENY_WRITE/read-only) with
+ * the 'create if not exist' bit set. The previous code
+ * would fail to open the file read only on a read-only share
+ * as it was checking the flags parameter directly against O_RDONLY,
+ * this was failing as the flags parameter was set to O_RDONLY|O_CREAT.
+ * JRA.
+ */
if (!CAN_WRITE(conn)) {
- /* It's a read-only share - fail if we wanted to write. */
- if(accmode != O_RDONLY) {
- DEBUG(3,("Permission denied opening %s\n",fname));
- check_for_pipe(fname);
- return;
- } else if(flags & O_CREAT) {
- /* We don't want to write - but we must make sure that O_CREAT
- doesn't create the file if we have write access into the
- directory.
- */
- flags &= ~O_CREAT;
- }
- }
+ /* It's a read-only share - fail if we wanted to write. */
+ if(accmode != O_RDONLY) {
+ DEBUG(3,("Permission denied opening %s\n",fname));
+ check_for_pipe(fname);
+ return;
+ } else if(flags & O_CREAT) {
+ /* We don't want to write - but we must make sure that O_CREAT
+ doesn't create the file if we have write access into the
+ directory.
+ */
+ flags &= ~O_CREAT;
+ }
+ }
/* actually do the open */
fsp->fd = fd_open(conn, fname, flags, mode);
-
- if (fsp->fd == -1) {
- DEBUG(3,("Error opening file %s (%s) (flags=%d)\n",
- fname,strerror(errno),flags));
- check_for_pipe(fname);
- return;
- }
+
+ if (fsp->fd == -1) {
+ DEBUG(3,("Error opening file %s (%s) (flags=%d)\n",
+ fname,strerror(errno),flags));
+ check_for_pipe(fname);
+ return;
+ }
conn->vfs_ops.fstat(fsp->fd, &sbuf);
- conn->num_files_open++;
+ /*
+ * POSIX allows read-only opens of directories. We don't
+ * want to do this (we use a different code path for this)
+ * so catch a directory open and return an EISDIR. JRA.
+ */
+
+ if(S_ISDIR(sbuf.st_mode)) {
+ fd_close(conn, fsp);
+ errno = EISDIR;
+ return;
+ }
+
+ conn->num_files_open++;
fsp->mode = sbuf.st_mode;
fsp->inode = sbuf.st_ino;
fsp->dev = sbuf.st_dev;
- GetTimeOfDay(&fsp->open_time);
- fsp->vuid = current_user.key.vuid;
- fsp->size = 0;
- fsp->pos = -1;
- fsp->open = True;
- fsp->can_lock = True;
- fsp->can_read = ((flags & O_WRONLY)==0);
- fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
- fsp->share_mode = 0;
+ GetTimeOfDay(&fsp->open_time);
+ fsp->vuid = current_user.key.vuid;
+ fsp->size = 0;
+ fsp->pos = -1;
+ fsp->open = True;
+ fsp->can_lock = True;
+ fsp->can_read = ((flags & O_WRONLY)==0);
+ fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
+ fsp->share_mode = 0;
fsp->print_file = False;
- fsp->modified = False;
- fsp->oplock_type = NO_OPLOCK;
- fsp->sent_oplock_break = NO_BREAK_SENT;
- fsp->is_directory = False;
- fsp->stat_open = 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. */
+ fsp->modified = False;
+ fsp->oplock_type = NO_OPLOCK;
+ fsp->sent_oplock_break = NO_BREAK_SENT;
+ fsp->is_directory = False;
+ fsp->stat_open = 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",
- *sesssetup_user ? sesssetup_user : conn->user,fsp->fsp_name,
- BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write),
- conn->num_files_open));
+ DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n",
+ *sesssetup_user ? sesssetup_user : conn->user,fsp->fsp_name,
+ BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write),
+ conn->num_files_open));
}
/****************************************************************************
@@ -598,7 +616,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou
open_file(fsp,conn,fname,flags|(flags2&~(O_TRUNC)),mode);
if (!fsp->open && flags==O_RDWR && errno != ENOENT && fcbopen) {
- flags = O_RDONLY;
+ flags = O_RDONLY;
open_file(fsp,conn,fname,flags,mode);
}