-#define OLD_NTDOMAIN 1
-
/*
Unix SMB/Netbios implementation.
Version 1.9.
extern int DEBUGLEVEL;
-extern pstring sesssetup_user;
+extern userdom_struct current_user_info;
extern uint16 global_oplock_port;
extern BOOL global_client_failed_oplock_break;
static int fd_open(struct connection_struct *conn, char *fname,
int flags, mode_t mode)
{
- int fd = conn->vfs_ops.open(dos_to_unix(fname,False),flags,mode);
+ int fd;
+#ifdef O_NONBLOCK
+ flags |= O_NONBLOCK;
+#endif
+
+ fd = conn->vfs_ops.open(conn,dos_to_unix(fname,False),flags,mode);
/* 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);
+ fd = conn->vfs_ops.open(conn,dos_to_unix(fname,False),flags,mode);
}
DEBUG(10,("fd_open: name %s, mode = %d, fd = %d. %s\n", fname, (int)mode, fd,
****************************************************************************/
static BOOL open_file(files_struct *fsp,connection_struct *conn,
- char *fname1,int flags,mode_t mode)
+ char *fname1,SMB_STRUCT_STAT *psbuf,int flags,mode_t mode)
{
extern struct current_user current_user;
pstring fname;
int accmode = (flags & O_ACCMODE);
- SMB_STRUCT_STAT sbuf;
fsp->fd = -1;
fsp->oplock_type = NO_OPLOCK;
return False;
}
- if (conn->vfs_ops.fstat(fsp->fd, &sbuf) == -1) {
- DEBUG(0,("Error doing fstat on open file %s (%s)\n", fname,strerror(errno) ));
- fd_close(conn, fsp);
- return False;
+ if (!VALID_STAT(*psbuf)) {
+ if (vfs_fstat(fsp,fsp->fd,psbuf) == -1) {
+ DEBUG(0,("Error doing fstat on open file %s (%s)\n", fname,strerror(errno) ));
+ fd_close(conn, fsp);
+ return False;
+ }
}
/*
* so catch a directory open and return an EISDIR. JRA.
*/
- if(S_ISDIR(sbuf.st_mode)) {
+ if(S_ISDIR(psbuf->st_mode)) {
fd_close(conn, fsp);
errno = EISDIR;
return False;
}
- fsp->mode = sbuf.st_mode;
- fsp->inode = sbuf.st_ino;
- fsp->dev = sbuf.st_dev;
+ fsp->mode = psbuf->st_mode;
+ fsp->inode = psbuf->st_ino;
+ fsp->dev = psbuf->st_dev;
GetTimeOfDay(&fsp->open_time);
fsp->vuid = current_user.vuid;
- fsp->size = 0;
+ fsp->size = psbuf->st_size;
fsp->pos = -1;
fsp->can_lock = True;
fsp->can_read = ((flags & O_WRONLY)==0);
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,
+ *current_user_info.smb_name ? current_user_info.smb_name : conn->user,fsp->fsp_name,
BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write),
conn->num_files_open + 1));
+ /*
+ * Take care of inherited ACLs on created files. JRA.
+ */
+
+ if ((flags & O_CREAT) && (conn->vfs_ops.fchmod_acl != NULL))
+ conn->vfs_ops.fchmod_acl(fsp, fsp->fd, mode);
+
return True;
}
unix_ERR_code = ERRlock;
return -1;
} else {
- return conn->vfs_ops.ftruncate(fsp->fd,0);
+ return conn->vfs_ops.ftruncate(fsp,fsp->fd,0);
}
}
/****************************************************************************
- Open a file with a share mode.
+ Open a file with a share mode. On output from this open we are guarenteeing
+ that
****************************************************************************/
-files_struct *open_file_shared(connection_struct *conn,char *fname,int share_mode,int ofun,
- mode_t mode,int oplock_request, int *Access,int *action)
+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 flags=0;
int flags2=0;
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 = vfs_file_exist(conn, fname, &sbuf);
+ BOOL file_existed = VALID_STAT(*psbuf);
BOOL fcbopen = False;
SMB_DEV_T dev = 0;
SMB_INO_T inode = 0;
return NULL;
fsp->fd = -1;
+ fsp->conn = conn; /* The vfs_fXXX() macros need this. */
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 ));
#endif /* O_SYNC */
if (flags != O_RDONLY && file_existed &&
- (!CAN_WRITE(conn) || IS_DOS_READONLY(dos_mode(conn,fname,&sbuf)))) {
+ (!CAN_WRITE(conn) || IS_DOS_READONLY(dos_mode(conn,fname,psbuf)))) {
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" ));
}
if (file_existed) {
- dev = sbuf.st_dev;
- inode = sbuf.st_ino;
+
+ dev = psbuf->st_dev;
+ inode = psbuf->st_ino;
lock_share_entry(conn, dev, inode);
num_share_modes = open_mode_check(conn, fname, dev, inode, share_mode,
&flags, &oplock_request, &all_current_opens_are_level_II);
if(num_share_modes == -1) {
+
+ /*
+ * This next line is a subtlety we need for MS-Access. If a file open will
+ * fail due to share permissions and also for security (access)
+ * reasons, we need to return the access failed error, not the
+ * share error. This means we must attempt to open the file anyway
+ * in order to get the UNIX access error - even if we're going to
+ * fail the open for share reasons. This is bad, as we're burning
+ * another fd if there are existing locks but there's nothing else
+ * we can do. We also ensure we're not going to create or tuncate
+ * the file as we only want an access decision at this stage. JRA.
+ */
+ open_file(fsp,conn,fname,psbuf,flags|(flags2&~(O_TRUNC|O_CREAT)),mode);
+
unlock_share_entry(conn, dev, inode);
file_free(fsp);
return NULL;
DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
flags,flags2,(int)mode));
- fsp_open = open_file(fsp,conn,fname,flags|(flags2&~(O_TRUNC)),mode);
+ fsp_open = open_file(fsp,conn,fname,psbuf,flags|(flags2&~(O_TRUNC)),mode);
if (!fsp_open && (flags == O_RDWR) && (errno != ENOENT) && fcbopen) {
- if((fsp_open = open_file(fsp,conn,fname,O_RDONLY,mode)) == True)
+ if((fsp_open = open_file(fsp,conn,fname,psbuf,O_RDONLY,mode)) == True)
flags = O_RDONLY;
}
return NULL;
}
- /* not that we ignore failure for the following. It is
- basically a hack for NFS, and NFS will never set one of
- these only read them. Nobody but Samba can ever set a deny
- mode and we have already checked our more authoritative
- locking database for permission to set this deny mode. If
- the kernel refuses the operations then the kernel is wrong */
- kernel_flock(fsp, deny_mode);
-
/*
* Deal with the race condition where two smbd's detect the file doesn't
* exist and do the create at the same time. One of them will win and
*/
}
+ /* note that we ignore failure for the following. It is
+ basically a hack for NFS, and NFS will never set one of
+ these only read them. Nobody but Samba can ever set a deny
+ mode and we have already checked our more authoritative
+ locking database for permission to set this deny mode. If
+ the kernel refuses the operations then the kernel is wrong */
+ kernel_flock(fsp, deny_mode);
+
/*
* At this point onwards, we can guarentee that the share entry
* is locked, whether we created the file or not, and that the
* If requested, truncate the file.
*/
- if ((flags2&O_TRUNC) && (truncate_unless_locked(conn,fsp) == -1)) {
- unlock_share_entry_fsp(fsp);
- fd_close(conn,fsp);
- file_free(fsp);
- return NULL;
+ if (flags2&O_TRUNC) {
+ /*
+ * We are modifing the file after open - update the stat struct..
+ */
+ if ((truncate_unless_locked(conn,fsp) == -1) || (vfs_fstat(fsp,fsp->fd,psbuf)==-1)) {
+ unlock_share_entry_fsp(fsp);
+ fd_close(conn,fsp);
+ file_free(fsp);
+ return NULL;
+ }
}
switch (flags) {
with the 'stat_open' flag set
****************************************************************************/
-files_struct *open_file_stat(connection_struct *conn,
- char *fname, int smb_ofun, SMB_STRUCT_STAT *pst, int *action)
+files_struct *open_file_stat(connection_struct *conn, char *fname,
+ SMB_STRUCT_STAT *psbuf, int smb_ofun, int *action)
{
extern struct current_user current_user;
- files_struct *fsp = file_new();
+ files_struct *fsp = NULL;
- if(!fsp)
- return NULL;
-
- if(conn->vfs_ops.stat(dos_to_unix(fname, False), pst) < 0) {
- DEBUG(0,("open_file_stat: unable to stat name = %s. Error was %s\n",
- fname, strerror(errno) ));
- file_free(fsp);
+ if (!VALID_STAT(*psbuf)) {
+ DEBUG(0,("open_file_stat: unable to stat name = %s. Error was %s\n", fname, strerror(errno) ));
return NULL;
}
- if(S_ISDIR(pst->st_mode)) {
+ if(S_ISDIR(psbuf->st_mode)) {
DEBUG(0,("open_file_stat: %s is a directory !\n", fname ));
- file_free(fsp);
return NULL;
}
+ fsp = file_new();
+ if(!fsp)
+ return NULL;
+
*action = FILE_WAS_OPENED;
DEBUG(5,("open_file_stat: opening file %s as a stat entry\n", fname));
*/
fsp->fd = -1;
- fsp->mode = 0;
+ fsp->mode = psbuf->st_mode;
+ fsp->inode = psbuf->st_ino;
+ fsp->dev = psbuf->st_dev;
GetTimeOfDay(&fsp->open_time);
+ fsp->size = psbuf->st_size;
fsp->vuid = current_user.vuid;
- fsp->size = 0;
fsp->pos = -1;
fsp->can_lock = False;
fsp->can_read = False;
Open a directory from an NT SMB call.
****************************************************************************/
-files_struct *open_directory(connection_struct *conn,
- char *fname, int smb_ofun, mode_t unixmode, int *action)
+files_struct *open_directory(connection_struct *conn, char *fname,
+ SMB_STRUCT_STAT *psbuf, int smb_ofun, mode_t unixmode, int *action)
{
extern struct current_user current_user;
- SMB_STRUCT_STAT st;
BOOL got_stat = False;
files_struct *fsp = file_new();
if(!fsp)
return NULL;
- if(conn->vfs_ops.stat(dos_to_unix(fname, False), &st) == 0) {
+ fsp->conn = conn; /* THe vfs_fXXX() macros need this. */
+
+ if (VALID_STAT(*psbuf))
got_stat = True;
- }
if (got_stat && (GET_FILE_OPEN_DISPOSITION(smb_ofun) == FILE_EXISTS_FAIL)) {
file_free(fsp);
if (got_stat) {
- if(!S_ISDIR(st.st_mode)) {
+ if(!S_ISDIR(psbuf->st_mode)) {
DEBUG(0,("open_directory: %s is not a directory !\n", fname ));
file_free(fsp);
errno = EACCES;
return NULL;
}
- if(conn->vfs_ops.mkdir(dos_to_unix(fname, False),
- unix_mode(conn,aDIR, fname)) < 0) {
+ if(vfs_mkdir(conn,fname, unix_mode(conn,aDIR, fname)) < 0) {
DEBUG(0,("open_directory: unable to create %s. Error was %s\n",
fname, strerror(errno) ));
file_free(fsp);
return NULL;
}
+
+ if(vfs_stat(conn,fname, psbuf) != 0) {
+ file_free(fsp);
+ return NULL;
+ }
+
*action = FILE_WAS_CREATED;
}
return NULL;
}
- if(!S_ISDIR(st.st_mode)) {
+ if(!S_ISDIR(psbuf->st_mode)) {
DEBUG(0,("open_directory: %s is not a directory !\n", fname ));
file_free(fsp);
return NULL;
*action = FILE_WAS_OPENED;
}
- DEBUG(5,("open_directory: opening directory %s\n",
- fname));
+ DEBUG(5,("open_directory: opening directory %s\n", fname));
/*
* Setup the files_struct for it.
*/
fsp->fd = -1;
- fsp->mode = 0;
+ fsp->mode = psbuf->st_mode;
+ fsp->inode = psbuf->st_ino;
+ fsp->dev = psbuf->st_dev;
GetTimeOfDay(&fsp->open_time);
+ fsp->size = psbuf->st_size;
fsp->vuid = current_user.vuid;
- fsp->size = 0;
fsp->pos = -1;
fsp->can_lock = True;
fsp->can_read = False;
SMB_DEV_T dev;
SMB_INO_T inode;
- if (conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf) == -1)
+ if (vfs_stat(conn,fname,&sbuf) == -1)
return(True);
dev = sbuf.st_dev;
free((char *)old_shares);
return(ret);
}
-
-#undef OLD_NTDOMAIN