summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
Diffstat (limited to 'source3')
-rw-r--r--source3/include/proto.h2
-rw-r--r--source3/include/smb.h47
-rw-r--r--source3/lib/util.c2
-rw-r--r--source3/smbd/close.c3
-rw-r--r--source3/smbd/ipc.c2
-rw-r--r--source3/smbd/nttrans.c42
-rw-r--r--source3/smbd/open.c71
-rw-r--r--source3/smbd/reply.c38
-rw-r--r--source3/smbd/trans2.c11
9 files changed, 146 insertions, 72 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 6ec6f7e617..9b707adeef 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -231,7 +231,7 @@ BOOL user_in_list(char *user,char *list);
char *tmpdir(void);
BOOL is_a_socket(int fd);
-BOOL set_first_token(char *ptr);
+void set_first_token(char *ptr);
BOOL next_token(char **ptr,char *buff,char *sep, int bufsize);
char **toktocliplist(int *ctok, char *sep);
void set_socket_options(int fd, char *options);
diff --git a/source3/include/smb.h b/source3/include/smb.h
index f755b81b92..d71d1cd1eb 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -186,6 +186,47 @@ implemented */
#define DENY_NONE 4
#define DENY_FCB 7
+/* open modes */
+#define DOS_OPEN_RDONLY 0
+#define DOS_OPEN_WRONLY 1
+#define DOS_OPEN_RDWR 2
+#define DOS_OPEN_FCB 0xF
+
+/* define shifts and masks for share and open modes. */
+#define OPEN_MODE_MASK 0xF
+#define SHARE_MODE_SHIFT 4
+#define SHARE_MODE_MASK 0x7
+#define GET_OPEN_MODE(x) ((x) & OPEN_MODE_MASK)
+#define SET_OPEN_MODE(x) ((x) & OPEN_MODE_MASK)
+#define GET_DENY_MODE(x) (((x)>>SHARE_MODE_SHIFT) & SHARE_MODE_MASK)
+#define SET_DENY_MODE(x) ((x)<<SHARE_MODE_SHIFT)
+
+/* allow delete on open file mode (used by NT SMB's). */
+#define ALLOW_SHARE_DELETE (1<<15)
+#define GET_ALLOW_SHARE_DELETE(x) (((x) & ALLOW_SHARE_DELETE) ? 1 : 0)
+#define SET_ALLOW_SHARE_DELETE(x) ((x) ? ALLOW_SHARE_DELETE : 0)
+
+/* Sync on open file (not sure if used anymore... ?) */
+#define FILE_SYNC_OPENMODE (1<<14)
+#define GET_FILE_SYNC_OPENMODE(x) (((x) & FILE_SYNC_OPENMODE) ? 1 : 0)
+
+/* open disposition values */
+#define FILE_EXISTS_FAIL 0
+#define FILE_EXISTS_OPEN 1
+#define FILE_EXISTS_TRUNCATE 2
+
+/* mask for open disposition. */
+#define FILE_OPEN_MASK 0x3
+
+#define GET_FILE_OPEN_DISPOSITION(x) ((x) & FILE_OPEN_MASK)
+#define SET_FILE_OPEN_DISPOSITION(x) ((x) & FILE_OPEN_MASK)
+
+/* The above can be OR'ed with... */
+#define FILE_CREATE_IF_NOT_EXIST 0x10
+#define FILE_FAIL_IF_NOT_EXIST 0
+
+#define GET_FILE_CREATE_DISPOSITION(x) ((x) & (FILE_CREATE_IF_NOT_EXIST|FILE_FAIL_IF_NOT_EXIST))
+
/* share types */
#define STYPE_DISKTREE 0 /* Disk drive */
#define STYPE_PRINTQ 1 /* Spooler queue */
@@ -433,6 +474,7 @@ typedef struct file_fd_struct
int fd_readonly;
int fd_writeonly;
int real_open_flags;
+ BOOL delete_on_close;
} file_fd_struct;
/*
@@ -517,17 +559,16 @@ typedef struct files_struct
SMB_OFF_T mmap_size;
write_bmpx_struct *wbmpx_ptr;
struct timeval open_time;
+ int share_mode;
BOOL open;
BOOL can_lock;
BOOL can_read;
BOOL can_write;
- BOOL share_mode;
BOOL print_file;
BOOL modified;
BOOL granted_oplock;
BOOL sent_oplock_break;
BOOL is_directory;
- BOOL delete_on_close;
char *fsp_name;
} files_struct;
@@ -788,7 +829,7 @@ struct bitmap {
#define FLAG_HIDE 2 /* options that should be hidden in SWAT */
#define FLAG_PRINT 4 /* printing options */
#define FLAG_GLOBAL 8 /* local options that should be globally settable in SWAT */
-#define FLAG_DEPRECATED 16 /* options that should no longer be used */
+#define FLAG_DEPRECATED 0x10 /* options that should no longer be used */
#ifndef LOCKING_VERSION
#define LOCKING_VERSION 4
diff --git a/source3/lib/util.c b/source3/lib/util.c
index d4f939e081..ced6786194 100644
--- a/source3/lib/util.c
+++ b/source3/lib/util.c
@@ -125,7 +125,7 @@ BOOL is_a_socket(int fd)
static char *last_ptr=NULL;
-BOOL set_first_token(char *ptr)
+void set_first_token(char *ptr)
{
last_ptr = ptr;
}
diff --git a/source3/smbd/close.c b/source3/smbd/close.c
index 981c0d77bb..2dba691a1c 100644
--- a/source3/smbd/close.c
+++ b/source3/smbd/close.c
@@ -103,6 +103,7 @@ void close_file(files_struct *fsp, BOOL normal_close)
SMB_INO_T inode = fsp->fd_ptr->inode;
int token;
BOOL last_reference = False;
+ BOOL delete_on_close = fsp->fd_ptr->delete_on_close;
connection_struct *conn = fsp->conn;
remove_pending_lock_requests_by_fid(fsp);
@@ -140,7 +141,7 @@ void close_file(files_struct *fsp, BOOL normal_close)
* reference to a file.
*/
- if (normal_close && last_reference && fsp->delete_on_close) {
+ if (normal_close && last_reference && delete_on_close) {
if(dos_unlink(fsp->fsp_name) != 0)
DEBUG(0,("close_file: file %s. Delete on close was set and unlink failed \
with error %s\n", fsp->fsp_name, strerror(errno) ));
diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c
index d9ef53e70f..112a79b5ca 100644
--- a/source3/smbd/ipc.c
+++ b/source3/smbd/ipc.c
@@ -37,7 +37,7 @@
extern int DEBUGLEVEL;
extern int max_send;
-extern pstring local_machine;
+extern fstring local_machine;
extern fstring global_myworkgroup;
#define NERR_Success 0
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index 62ca9fe1c8..8b4049cd96 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -317,24 +317,24 @@ static int map_create_disposition( uint32 create_disposition)
switch( create_disposition ) {
case FILE_CREATE:
/* create if not exist, fail if exist */
- ret = 0x10;
+ ret = (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL);
break;
case FILE_SUPERSEDE:
case FILE_OVERWRITE_IF:
/* create if not exist, trunc if exist */
- ret = 0x12;
+ ret = (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE);
break;
case FILE_OPEN:
/* fail if not exist, open if exists */
- ret = 0x1;
+ ret = (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN);
break;
case FILE_OPEN_IF:
/* create if not exist, open if exists */
- ret = 0x11;
+ ret = (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_OPEN);
break;
case FILE_OVERWRITE:
/* fail if not exist, truncate if exists */
- ret = 0x2;
+ ret = (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE);
break;
default:
DEBUG(0,("map_create_disposition: Incorrect value for create_disposition = %d\n",
@@ -358,13 +358,13 @@ static int map_share_mode( char *fname, uint32 desired_access, uint32 share_acce
switch( desired_access & (FILE_READ_DATA|FILE_WRITE_DATA) ) {
case FILE_READ_DATA:
- smb_open_mode = 0;
+ smb_open_mode = DOS_OPEN_RDONLY;
break;
case FILE_WRITE_DATA:
- smb_open_mode = 1;
+ smb_open_mode = DOS_OPEN_WRONLY;
break;
case FILE_READ_DATA|FILE_WRITE_DATA:
- smb_open_mode = 2;
+ smb_open_mode = DOS_OPEN_RDWR;
break;
}
@@ -386,7 +386,7 @@ static int map_share_mode( char *fname, uint32 desired_access, uint32 share_acce
if(desired_access & (DELETE_ACCESS|WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS|
FILE_EXECUTE|FILE_READ_ATTRIBUTES|
FILE_WRITE_ATTRIBUTES|READ_CONTROL_ACCESS))
- smb_open_mode = 0;
+ smb_open_mode = DOS_OPEN_RDONLY;
else {
DEBUG(0,("map_share_mode: Incorrect value %lx for desired_access to file %s\n",
(unsigned long)desired_access, fname));
@@ -394,27 +394,37 @@ static int map_share_mode( char *fname, uint32 desired_access, uint32 share_acce
}
}
- /* Add in the requested share mode - ignore FILE_SHARE_DELETE for now. */
+ /*
+ * Set the special bit that means allow share delete.
+ * This is held outside the normal share mode bits at 1<<15.
+ * JRA.
+ */
+
+ if(share_access & FILE_SHARE_DELETE)
+ smb_open_mode |= ALLOW_SHARE_DELETE;
+
+ /* Add in the requested share mode. */
switch( share_access & (FILE_SHARE_READ|FILE_SHARE_WRITE)) {
case FILE_SHARE_READ:
- smb_open_mode |= (DENY_WRITE<<4);
+ smb_open_mode |= SET_DENY_MODE(DENY_WRITE);
break;
case FILE_SHARE_WRITE:
- smb_open_mode |= (DENY_READ<<4);
+ smb_open_mode |= SET_DENY_MODE(DENY_READ);
break;
case (FILE_SHARE_READ|FILE_SHARE_WRITE):
- smb_open_mode |= (DENY_NONE<<4);
+ smb_open_mode |= SET_DENY_MODE(DENY_NONE);
break;
case FILE_SHARE_NONE:
- smb_open_mode |= (DENY_ALL<<4);
+ smb_open_mode |= SET_DENY_MODE(DENY_ALL);
break;
}
/*
- * Handle a O_SYNC request.
+ * Handle an O_SYNC request.
*/
+
if(file_attributes & FILE_FLAG_WRITE_THROUGH)
- smb_open_mode |= (1<<14);
+ smb_open_mode |= FILE_SYNC_OPENMODE;
DEBUG(10,("map_share_mode: Mapped desired access %lx, share access %lx, file attributes %lx \
to open_mode %x\n", (unsigned long)desired_access, (unsigned long)share_access,
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index a6e2953263..b6b2ef5bb8 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -505,7 +505,6 @@ static void open_file(files_struct *fsp,connection_struct *conn,
fsp->granted_oplock = False;
fsp->sent_oplock_break = False;
fsp->is_directory = False;
- fsp->delete_on_close = False;
fsp->conn = conn;
/*
* Note that the file name here is the *untranslated* name
@@ -657,8 +656,8 @@ static 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;
+ int old_open_mode = GET_OPEN_MODE(share->share_mode);
+ int old_deny_mode = GET_DENY_MODE(share->share_mode);
if (old_deny_mode > 4 || old_open_mode > 2)
{
@@ -702,7 +701,8 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int
{
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 share_locked = False;
@@ -733,7 +733,7 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int
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 ));
@@ -741,24 +741,25 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int
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;
/* 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:
@@ -767,7 +768,7 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int
}
#if defined(O_SYNC)
- if (share_mode&(1<<14)) {
+ if (GET_FILE_SYNC_OPENMODE(share_mode)) {
flags2 |= O_SYNC;
}
#endif /* O_SYNC */
@@ -792,7 +793,8 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int
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)))
{
@@ -908,17 +910,19 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou
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;
@@ -971,11 +975,10 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou
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, mode_t unixmode, int *action)
{
@@ -1057,6 +1060,7 @@ int open_directory(files_struct *fsp,connection_struct *conn,
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;
@@ -1156,9 +1160,20 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou
}
}
- /* 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 */
@@ -1173,8 +1188,14 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou
/* 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:
@@ -1184,5 +1205,3 @@ free_and_exit:
free((char *)old_shares);
return(ret);
}
-
-
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 8b96ff17fd..bc19f1a931 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -1239,6 +1239,7 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
/****************************************************************************
reply to an open
****************************************************************************/
+
int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
pstring fname;
@@ -1276,8 +1277,8 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
unixmode = unix_mode(conn,aARCH);
- open_file_shared(fsp,conn,fname,share_mode,3,unixmode,
- oplock_request,&rmode,NULL);
+ open_file_shared(fsp,conn,fname,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
+ unixmode, oplock_request,&rmode,NULL);
if (!fsp->open)
{
@@ -1529,8 +1530,8 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
}
/* Open file in dos compatibility share mode. */
- open_file_shared(fsp,conn,fname,(DENY_FCB<<4)|0xF, ofun, unixmode,
- oplock_request, NULL, NULL);
+ open_file_shared(fsp,conn,fname,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
+ ofun, unixmode, oplock_request, NULL, NULL);
if (!fsp->open)
{
@@ -1601,8 +1602,8 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
/* Open file in dos compatibility share mode. */
/* We should fail if file exists. */
- open_file_shared(fsp,conn,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode,
- oplock_request, NULL, NULL);
+ open_file_shared(fsp,conn,fname2,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
+ (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unixmode, oplock_request, NULL, NULL);
if (!fsp->open)
{
@@ -1702,8 +1703,10 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
if (!has_wild) {
pstrcat(directory,"/");
pstrcat(directory,mask);
- if (can_delete(directory,conn,dirtype) && !dos_unlink(directory)) count++;
- if (!count) exists = file_exist(directory,NULL);
+ if (can_delete(directory,conn,dirtype) && !dos_unlink(directory))
+ count++;
+ if (!count)
+ exists = file_exist(directory,NULL);
} else {
void *dirptr = NULL;
char *dname;
@@ -2675,9 +2678,8 @@ int reply_printopen(connection_struct *conn,
}
/* Open for exclusive use, write only. */
- open_file_shared(fsp,conn,fname2,
- (DENY_ALL<<4)|1, 0x12, unix_mode(conn,0),
- 0, NULL, NULL);
+ open_file_shared(fsp,conn,fname2, SET_DENY_MODE(DENY_ALL)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
+ (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE), unix_mode(conn,0), 0, NULL, NULL);
if (!fsp->open) {
file_free(fsp);
@@ -3323,6 +3325,7 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, in
/*******************************************************************
copy a file as part of a reply_copy
******************************************************************/
+
static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
int count,BOOL target_is_directory)
{
@@ -3343,12 +3346,15 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
pstrcat(dest,p);
}
- if (!file_exist(src,&st)) return(False);
+ if (!file_exist(src,&st))
+ return(False);
fsp1 = file_new();
- if (!fsp1) return(False);
- open_file_shared(fsp1,conn,src,(DENY_NONE<<4),
- 1,0,0,&Access,&action);
+ if (!fsp1)
+ return(False);
+
+ open_file_shared(fsp1,conn,src,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
+ (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
if (!fsp1->open) {
file_free(fsp1);
@@ -3363,7 +3369,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
close_file(fsp1,False);
return(False);
}
- open_file_shared(fsp2,conn,dest,(DENY_NONE<<4)|1,
+ open_file_shared(fsp2,conn,dest,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
ofun,st.st_mode,0,&Access,&action);
if (!fsp2->open) {
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 5b057410ca..f8d90cd871 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -1658,14 +1658,11 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
if(fsp->is_directory)
return(ERROR(ERRDOS,ERRnoaccess));
/*
- * TODO - check here is this means set
- * this flag bit on all open files that
- * reference this particular dev/inode pair.
- * If so we'll need to search the open
- * file entries here and set this flag on
- * all of them that match. JRA.
+ * Set the delete on close flag in the reference
+ * counted struct. Delete when the last reference
+ * goes away.
*/
- fsp->delete_on_close = CVAL(pdata,0);
+ fsp->fd_ptr->delete_on_close = CVAL(pdata,0);
} else
return(ERROR(ERRDOS,ERRunknownlevel));
break;