From c3effa8b599a6a0a2fe05487edc3a0d13e83d427 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 17 Aug 1998 13:11:34 +0000 Subject: this completes the splitup of server.c. the splitup was done with an axe, not a scalpel, so there are some rough edges. I mostly wanted to get the general form right with fine tuning of what goes where to come later. Still, this is better than what we had before where server.c was a general repository for anything that didn't fit elsewhere. (This used to be commit a6d194886a4a5f7507fa37289ff96c1be56f14a6) --- source3/smbd/open.c | 1150 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1150 insertions(+) create mode 100644 source3/smbd/open.c (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c new file mode 100644 index 0000000000..311eac07e5 --- /dev/null +++ b/source3/smbd/open.c @@ -0,0 +1,1150 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + file opening and share modes + Copyright (C) Andrew Tridgell 1992-1998 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +extern int DEBUGLEVEL; + +extern pstring sesssetup_user; +extern int global_oplocks_open; +extern uint16 oplock_port; + + +/**************************************************************************** +fd support routines - attempt to do a sys_open +****************************************************************************/ +static int fd_attempt_open(char *fname, int flags, int mode) +{ + int fd = sys_open(fname,flags,mode); + + /* Fix for files ending in '.' */ + if((fd == -1) && (errno == ENOENT) && + (strchr(fname,'.')==NULL)) + { + pstrcat(fname,"."); + fd = sys_open(fname,flags,mode); + } + +#if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF)) + if ((fd == -1) && (errno == ENAMETOOLONG)) + { + int max_len; + char *p = strrchr(fname, '/'); + + if (p == fname) /* name is "/xxx" */ + { + max_len = pathconf("/", _PC_NAME_MAX); + p++; + } + else if ((p == NULL) || (p == fname)) + { + p = fname; + max_len = pathconf(".", _PC_NAME_MAX); + } + else + { + *p = '\0'; + max_len = pathconf(fname, _PC_NAME_MAX); + *p = '/'; + p++; + } + if (strlen(p) > max_len) + { + char tmp = p[max_len]; + + p[max_len] = '\0'; + if ((fd = sys_open(fname,flags,mode)) == -1) + p[max_len] = tmp; + } + } +#endif + return fd; +} + +/**************************************************************************** +Cache a uid_t currently with this file open. This is an optimization only +used when multiple sessionsetup's have been done to one smbd. +****************************************************************************/ +void fd_add_to_uid_cache(file_fd_struct *fd_ptr, uid_t u) +{ + if(fd_ptr->uid_cache_count >= sizeof(fd_ptr->uid_users_cache)/sizeof(uid_t)) + return; + fd_ptr->uid_users_cache[fd_ptr->uid_cache_count++] = u; +} + +/**************************************************************************** +Remove a uid_t that currently has this file open. This is an optimization only +used when multiple sessionsetup's have been done to one smbd. +****************************************************************************/ +static void fd_remove_from_uid_cache(file_fd_struct *fd_ptr, uid_t u) +{ + int i; + for(i = 0; i < fd_ptr->uid_cache_count; i++) + if(fd_ptr->uid_users_cache[i] == u) { + if(i < (fd_ptr->uid_cache_count-1)) + memmove((char *)&fd_ptr->uid_users_cache[i], (char *)&fd_ptr->uid_users_cache[i+1], + sizeof(uid_t)*(fd_ptr->uid_cache_count-1-i) ); + fd_ptr->uid_cache_count--; + } + return; +} + +/**************************************************************************** +Check if a uid_t that currently has this file open is present. This is an +optimization only used when multiple sessionsetup's have been done to one smbd. +****************************************************************************/ +static BOOL fd_is_in_uid_cache(file_fd_struct *fd_ptr, uid_t u) +{ + int i; + for(i = 0; i < fd_ptr->uid_cache_count; i++) + if(fd_ptr->uid_users_cache[i] == u) + return True; + return False; +} + + +/**************************************************************************** +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) +{ + int fd = sys_open( fname, O_RDWR, mode); + + if(fd == -1) + return; + + if(fd_ptr->real_open_flags == O_RDONLY) + fd_ptr->fd_readonly = fd_ptr->fd; + if(fd_ptr->real_open_flags == O_WRONLY) + fd_ptr->fd_writeonly = fd_ptr->fd; + + fd_ptr->fd = fd; + fd_ptr->real_open_flags = O_RDWR; +} + +/**************************************************************************** +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) +{ + extern struct current_user current_user; + + DEBUG(3,("fd_attempt_close fd = %d, dev = %x, inode = %x, open_flags = %d, ref_count = %d.\n", + fd_ptr->fd, fd_ptr->dev, fd_ptr->inode, + fd_ptr->real_open_flags, + fd_ptr->ref_count)); + 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 = (uint32)-1; + fd_ptr->inode = (uint32)-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; +} + +/**************************************************************************** +fd support routines - check that current user has permissions +to open this file. Used when uid not found in optimization cache. +This is really ugly code, as due to POSIX locking braindamage we must +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 ) +{ + pid_t child_pid; + + if((child_pid = fork()) < 0) { + DEBUG(0,("check_access_allowed_for_current_user: fork failed.\n")); + return False; + } + + if(child_pid) { + /* + * Parent. + */ + pid_t wpid; + int status_code; + if ((wpid = sys_waitpid(child_pid, &status_code, 0)) < 0) { + DEBUG(0,("check_access_allowed_for_current_user: The process is no longer waiting!\n")); + return(False); + } + + if (child_pid != wpid) { + DEBUG(0,("check_access_allowed_for_current_user: We were waiting for the wrong process ID\n")); + return(False); + } +#if defined(WIFEXITED) && defined(WEXITSTATUS) + if (WIFEXITED(status_code) == 0) { + DEBUG(0,("check_access_allowed_for_current_user: The process exited while we were waiting\n")); + return(False); + } + if (WEXITSTATUS(status_code) != 0) { + DEBUG(9,("check_access_allowed_for_current_user: The status of the process exiting was %d. Returning access denied.\n", status_code)); + return(False); + } +#else /* defined(WIFEXITED) && defined(WEXITSTATUS) */ + if(status_code != 0) { + DEBUG(9,("check_access_allowed_for_current_user: The status of the process exiting was %d. Returning access denied.\n", status_code)); + return(False); + } +#endif /* defined(WIFEXITED) && defined(WEXITSTATUS) */ + + /* + * Success - the child could open the file. + */ + DEBUG(9,("check_access_allowed_for_current_user: The status of the process exiting was %d. Returning access allowed.\n", status_code)); + return True; + } else { + /* + * Child. + */ + 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) { + /* Access denied. */ + _exit(EACCES); + } + close(fd); + DEBUG(9,("check_access_allowed_for_current_user: Child - returning ok.\n")); + _exit(0); + } + + return False; +} + +/**************************************************************************** +check a filename for the pipe string +****************************************************************************/ +static void check_for_pipe(char *fname) +{ + /* special case of pipe opens */ + char s[10]; + StrnCpy(s,fname,9); + strlower(s); + if (strstr(s,"pipe/")) { + DEBUG(3,("Rejecting named pipe open for %s\n",fname)); + unix_ERR_class = ERRSRV; + unix_ERR_code = ERRaccess; + } +} + +/**************************************************************************** +open a file +****************************************************************************/ +static void open_file(files_struct *fsp,connection_struct *conn, + char *fname1,int flags,int mode, struct stat *sbuf) +{ + extern struct current_user current_user; + pstring fname; + struct stat statbuf; + file_fd_struct *fd_ptr; + int accmode = (flags & (O_RDONLY | O_WRONLY | O_RDWR)); + + fsp->open = False; + fsp->fd_ptr = 0; + fsp->granted_oplock = False; + errno = EPERM; + + pstrcpy(fname,fname1); + + /* 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. + */ + + if (conn->read_only && !conn->printer) { + /* 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; + } + } + + /* this handles a bug in Win95 - it doesn't say to create the file when it + should */ + if (conn->printer) { + flags |= O_CREAT; + } + +/* + if (flags == O_WRONLY) + DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n")); +*/ + + /* + * Ensure we have a valid struct stat so we can search the + * open fd table. + */ + if(sbuf == 0) { + if(sys_stat(fname, &statbuf) < 0) { + if(errno != ENOENT) { + DEBUG(3,("Error doing stat on file %s (%s)\n", + fname,strerror(errno))); + + check_for_pipe(fname); + return; + } + sbuf = 0; + } else { + sbuf = &statbuf; + } + } + + /* + * Check to see if we have this file already + * open. If we do, just use the already open fd and increment the + * reference count (fd_get_already_open increments the ref_count). + */ + if((fd_ptr = fd_get_already_open(sbuf))!= 0) { + /* + * File was already open. + */ + + /* + * Check it wasn't open for exclusive use. + */ + if((flags & O_CREAT) && (flags & O_EXCL)) { + fd_ptr->ref_count--; + errno = EEXIST; + return; + } + + /* + * Ensure that the user attempting to open + * this file has permissions to do so, if + * the user who originally opened the file wasn't + * the same as the current user. + */ + + if(!fd_is_in_uid_cache(fd_ptr, (uid_t)current_user.uid)) { + if(!check_access_allowed_for_current_user( fname, accmode )) { + /* Error - permission denied. */ + DEBUG(3,("Permission denied opening file %s (flags=%d, accmode = %d)\n", + fname, flags, accmode)); + /* Ensure the ref_count is decremented. */ + fd_ptr->ref_count--; + fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid); + errno = EACCES; + return; + } + } + + fd_add_to_uid_cache(fd_ptr, (uid_t)current_user.uid); + + /* + * If not opened O_RDWR try + * and do that here - a chmod may have been done + * between the last open and now. + */ + if(fd_ptr->real_open_flags != O_RDWR) + fd_attempt_reopen(fname, mode, fd_ptr); + + /* + * Ensure that if we wanted write access + * it has been opened for write, and if we wanted read it + * was open for read. + */ + if(((accmode == O_WRONLY) && (fd_ptr->real_open_flags == O_RDONLY)) || + ((accmode == O_RDONLY) && (fd_ptr->real_open_flags == O_WRONLY)) || + ((accmode == O_RDWR) && (fd_ptr->real_open_flags != O_RDWR))) { + DEBUG(3,("Error opening (already open for flags=%d) file %s (%s) (flags=%d)\n", + fd_ptr->real_open_flags, fname,strerror(EACCES),flags)); + check_for_pipe(fname); + fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid); + fd_ptr->ref_count--; + return; + } + + } else { + int open_flags; + /* We need to allocate a new file_fd_struct (this increments the + ref_count). */ + if((fd_ptr = fd_get_new()) == 0) + return; + /* + * Whatever the requested flags, attempt read/write access, + * as we don't know what flags future file opens may require. + * If this fails, try again with the required flags. + * Even if we open read/write when only read access was + * requested the setting of the can_write flag in + * the file_struct will protect us from errant + * write requests. We never need to worry about O_APPEND + * as this is not set anywhere in Samba. + */ + 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); + /* + * On some systems opening a file for R/W access on a read only + * filesystems sets errno to EROFS. + */ +#ifdef EROFS + if((fd_ptr->fd == -1) && ((errno == EACCES) || (errno == EROFS))) { +#else /* No 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->real_open_flags = accmode; + } + } + } + + if ((fd_ptr->fd >=0) && + conn->printer && lp_minprintspace(SNUM(conn))) { + pstring dname; + int 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); + fsp->fd_ptr = 0; + if(fd_ptr->ref_count == 0) + sys_unlink(fname); + errno = ENOSPC; + return; + } + } + + if (fd_ptr->fd < 0) + { + 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); + check_for_pipe(fname); + return; + } + + if (fd_ptr->fd >= 0) + { + if(sbuf == 0) { + /* Do the fstat */ + if(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); + return; + } + sbuf = &statbuf; + } + + /* Set the correct entries in fd_ptr. */ + fd_ptr->dev = (uint32)sbuf->st_dev; + fd_ptr->inode = (uint32)sbuf->st_ino; + + fsp->fd_ptr = fd_ptr; + conn->num_files_open++; + fsp->mode = sbuf->st_mode; + GetTimeOfDay(&fsp->open_time); + fsp->vuid = current_user.vuid; + fsp->size = 0; + fsp->pos = -1; + fsp->open = True; + fsp->mmap_ptr = NULL; + fsp->mmap_size = 0; + 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 = conn->printer; + fsp->modified = False; + fsp->granted_oplock = False; + fsp->sent_oplock_break = False; + fsp->is_directory = 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; + + /* + * If the printer is marked as postscript output a leading + * file identifier to ensure the file is treated as a raw + * postscript file. + * This has a similar effect as CtrlD=0 in WIN.INI file. + * tim@fsg.com 09/06/94 + */ + if (fsp->print_file && lp_postscript(SNUM(conn)) && fsp->can_write) { + DEBUG(3,("Writing postscript line\n")); + write_file(fsp,"%!\n",3); + } + + DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n", + *sesssetup_user ? sesssetup_user : conn->user,fname, + BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write), + conn->num_files_open)); + + } + +#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; + } + } +#endif +} + + +/**************************************************************************** + C. Hoch 11/22/95 + Helper for open_file_shared. + Truncate a file after checking locking; close file if locked. + **************************************************************************/ +static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, int token, + BOOL *share_locked) +{ + if (fsp->can_write){ + if (is_locked(fsp,conn,0x3FFFFFFF,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 + ftruncate(fsp->fd_ptr->fd,0); + } +} + + + +/**************************************************************************** +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) +{ + int flags=0; + int flags2=0; + int deny_mode = (share_mode>>4)&7; + struct stat sbuf; + BOOL file_existed = file_exist(fname,&sbuf); + BOOL share_locked = False; + BOOL fcbopen = False; + int token; + uint32 dev = 0; + uint32 inode = 0; + int num_share_modes = 0; + + fsp->open = False; + fsp->fd_ptr = 0; + + /* this is for OS/2 EAs - try and say we don't support them */ + if (strstr(fname,".+,;=[].")) + { + unix_ERR_class = ERRDOS; + /* OS/2 Workplace shell fix may be main code stream in a later release. */ +#if 1 /* OS2_WPS_FIX - Recent versions of OS/2 need this. */ + unix_ERR_code = ERRcannotopen; +#else /* OS2_WPS_FIX */ + unix_ERR_code = ERROR_EAS_NOT_SUPPORTED; +#endif /* OS2_WPS_FIX */ + + return; + } + + if ((ofun & 0x3) == 0 && file_existed) + { + errno = EEXIST; + return; + } + + if (ofun & 0x10) + flags2 |= O_CREAT; + if ((ofun & 0x3) == 2) + 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) + { + case 1: + flags = O_WRONLY; + break; + case 0xF: + fcbopen = True; + flags = O_RDWR; + break; + case 2: + flags = O_RDWR; + break; + default: + flags = O_RDONLY; + break; + } + +#if defined(O_SYNC) + if (share_mode&(1<<14)) { + flags2 |= O_SYNC; + } +#endif /* O_SYNC */ + + if (flags != O_RDONLY && file_existed && + (!CAN_WRITE(conn) || IS_DOS_READONLY(dos_mode(conn,fname,&sbuf)))) + { + if (!fcbopen) + { + errno = EACCES; + return; + } + flags = O_RDONLY; + } + + if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) + { + DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname)); + errno = EINVAL; + return; + } + + if (deny_mode == DENY_FCB) deny_mode = DENY_DOS; + + if (lp_share_modes(SNUM(conn))) + { + int i; + share_mode_entry *old_shares = 0; + + if (file_existed) + { + dev = (uint32)sbuf.st_dev; + inode = (uint32)sbuf.st_ino; + lock_share_entry(conn, dev, inode, &token); + share_locked = True; + num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); + } + + /* + * Check if the share modes will give us access. + */ + + if(share_locked && (num_share_modes != 0)) + { + BOOL broke_oplock; + + do + { + + broke_oplock = False; + 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 + * if the share mode would deny access and the client has an oplock. + * Check if someone has an oplock on this file. If so we must break + * it before continuing. + */ + if(share_entry->op_type & (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) + { + + DEBUG(5,("open_file_shared: breaking oplock (%x) on file %s, \ +dev = %x, inode = %x\n", share_entry->op_type, fname, dev, inode)); + + /* Oplock break.... */ + unlock_share_entry(conn, dev, inode, token); + if(request_oplock_break(share_entry, dev, inode) == False) + { + free((char *)old_shares); + DEBUG(0,("open_file_shared: FAILED when breaking oplock (%x) on file %s, \ +dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); + errno = EACCES; + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + return; + } + lock_share_entry(conn, dev, inode, &token); + broke_oplock = True; + break; + } + + /* someone else has a share lock on it, check to see + if we can too */ + if(check_share_mode(share_entry, deny_mode, fname, fcbopen, &flags) == False) + { + free((char *)old_shares); + unlock_share_entry(conn, dev, inode, token); + errno = EACCES; + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + return; + } + + } /* end for */ + + if(broke_oplock) + { + free((char *)old_shares); + num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); + } + } while(broke_oplock); + } + + if(old_shares != 0) + free((char *)old_shares); + } + + DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", + flags,flags2,mode)); + + open_file(fsp,conn,fname,flags|(flags2&~(O_TRUNC)),mode,file_existed ? &sbuf : 0); + if (!fsp->open && flags==O_RDWR && errno!=ENOENT && fcbopen) + { + flags = O_RDONLY; + open_file(fsp,conn,fname,flags,mode,file_existed ? &sbuf : 0 ); + } + + if (fsp->open) + { + int open_mode=0; + + if((share_locked == False) && lp_share_modes(SNUM(conn))) + { + /* We created the file - thus we must now lock the share entry before creating it. */ + dev = fsp->fd_ptr->dev; + inode = fsp->fd_ptr->inode; + lock_share_entry(conn, dev, inode, &token); + share_locked = True; + } + + switch (flags) + { + case O_RDONLY: + open_mode = 0; + break; + case O_RDWR: + open_mode = 2; + break; + case O_WRONLY: + open_mode = 1; + break; + } + + fsp->share_mode = (deny_mode<<4) | open_mode; + + if (Access) + (*Access) = open_mode; + + if (action) + { + if (file_existed && !(flags2 & O_TRUNC)) *action = FILE_WAS_OPENED; + if (!file_existed) *action = FILE_WAS_CREATED; + if (file_existed && (flags2 & O_TRUNC)) *action = FILE_WAS_OVERWRITTEN; + } + /* We must create the share mode entry before truncate as + truncate can fail due to locking and have to close the + file (which expects the share_mode_entry to be there). + */ + 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)) + { + fsp->granted_oplock = True; + fsp->sent_oplock_break = False; + global_oplocks_open++; + port = oplock_port; + + DEBUG(5,("open_file_shared: granted oplock (%x) on file %s, \ +dev = %x, inode = %x\n", oplock_request, fname, dev, inode)); + + } + 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); + } + + 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) +{ + extern struct current_user current_user; + struct stat st; + + if (smb_ofun & 0x10) { + /* + * Create the directory. + */ + + if(sys_mkdir(fname, unixmode) < 0) { + DEBUG(0,("open_directory: unable to create %s. Error was %s\n", + fname, strerror(errno) )); + return -1; + } + + *action = FILE_WAS_CREATED; + } else { + /* + * Check that it *was* a directory. + */ + + if(sys_stat(fname, &st) < 0) { + DEBUG(0,("open_directory: unable to stat name = %s. Error was %s\n", + fname, strerror(errno) )); + return -1; + } + + if(!S_ISDIR(st.st_mode)) { + DEBUG(0,("open_directory: %s is not a directory !\n", fname )); + return -1; + } + *action = FILE_WAS_OPENED; + } + + DEBUG(5,("open_directory: opening directory %s\n", + fname)); + + /* + * Setup the files_struct for it. + */ + + fsp->fd_ptr = NULL; + conn->num_files_open++; + fsp->mode = 0; + GetTimeOfDay(&fsp->open_time); + fsp->vuid = current_user.vuid; + fsp->size = 0; + fsp->pos = -1; + fsp->open = True; + fsp->mmap_ptr = NULL; + fsp->mmap_size = 0; + fsp->can_lock = True; + fsp->can_read = False; + fsp->can_write = False; + fsp->share_mode = 0; + fsp->print_file = False; + fsp->modified = False; + fsp->granted_oplock = False; + fsp->sent_oplock_break = False; + fsp->is_directory = True; + 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; + + 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; + int ret = False; + share_mode_entry *old_shares = 0; + int num_share_modes; + struct stat sbuf; + int token; + int pid = getpid(); + uint32 dev, inode; + + if(!lp_share_modes(SNUM(conn))) + return True; + + if (sys_stat(fname,&sbuf) == -1) return(True); + + dev = (uint32)sbuf.st_dev; + inode = (uint32)sbuf.st_ino; + + lock_share_entry(conn, dev, inode, &token); + num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); + + /* + * Check if the share modes will give us access. + */ + + if(num_share_modes != 0) + { + BOOL broke_oplock; + + do + { + + broke_oplock = False; + for(i = 0; i < num_share_modes; i++) + { + share_mode_entry *share_entry = &old_shares[i]; + + /* + * Break oplocks before checking share modes. See comment in + * open_file_shared for details. + * Check if someone has an oplock on this file. If so we must + * break it before continuing. + */ + if(share_entry->op_type & BATCH_OPLOCK) + { + + /* + * It appears that the NT redirector may have a bug, in that + * it tries to do an SMBmv on a file that it has open with a + * batch oplock, and then fails to respond to the oplock break + * request. This only seems to occur when the client is doing an + * SMBmv to the smbd it is using - thus we try and detect this + * condition by checking if the file being moved is open and oplocked by + * this smbd process, and then not sending the oplock break in this + * special case. If the file was open with a deny mode that + * prevents the move the SMBmv will fail anyway with a share + * violation error. JRA. + */ + if(rename_op && (share_entry->pid == pid)) + { + DEBUG(0,("check_file_sharing: NT redirector workaround - rename attempted on \ +batch oplocked file %s, dev = %x, inode = %x\n", fname, dev, inode)); + /* + * This next line is a test that allows the deny-mode + * processing to be skipped. This seems to be needed as + * NT insists on the rename succeeding (in Office 9x no less !). + * This should be removed as soon as (a) MS fix the redirector + * bug or (b) NT SMB support in Samba makes NT not issue the + * call (as is my fervent hope). JRA. + */ + continue; + } + else + { + DEBUG(5,("check_file_sharing: breaking oplock (%x) on file %s, \ +dev = %x, inode = %x\n", share_entry->op_type, fname, dev, inode)); + + /* Oplock break.... */ + unlock_share_entry(conn, dev, inode, token); + if(request_oplock_break(share_entry, dev, inode) == False) + { + free((char *)old_shares); + DEBUG(0,("check_file_sharing: FAILED when breaking oplock (%x) on file %s, \ +dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); + return False; + } + lock_share_entry(conn, dev, inode, &token); + broke_oplock = True; + break; + } + } + + /* 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)) + goto free_and_exit; + + } /* end for */ + + if(broke_oplock) + { + free((char *)old_shares); + num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); + } + } while(broke_oplock); + } + + /* 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() */ + ret = True; + +free_and_exit: + + unlock_share_entry(conn, dev, inode, token); + if(old_shares != NULL) + 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; +} + -- cgit From 5ae06b99c06313d1465b03d5120e7fbf6a87b9e5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 25 Aug 1998 02:29:17 +0000 Subject: Added code to (correctly) ignore TRANSACT2_SETFILEINFO with SMB_SET_FILE_ALLOCATION_INFO. Office 97 expects this call to succeed when you tell it you do NT SMB calls. Jeremy. (This used to be commit 260e7e27401d863e9f580d4748c577334d9fc9d0) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 311eac07e5..e54a456092 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -530,7 +530,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, } DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n", - *sesssetup_user ? sesssetup_user : conn->user,fname, + *sesssetup_user ? sesssetup_user : conn->user,fsp->fsp_name, BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write), conn->num_files_open)); -- cgit From 693480af8bb2d3e83566af9463ca427f47a879da Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 31 Aug 1998 20:20:54 +0000 Subject: configure.in, configure: include/config.h.in: Added stropts and poll. include/smb.h: Moved old typedefs of uint8 etc. into include/includes.h where all the other defines live (changed them from typedefs to defines). Other changes : changed from using uint32 to SMB_DEV_T and SMB_INO_T in preparation for moving to size independed (ie. 64 bit clean) device and inode access. Stat call wrapper comes next :-). Jeremy. (This used to be commit 3d9ec96de5e04e83abafe9c5d980bd39eee856ea) --- source3/smbd/open.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index e54a456092..1a16a25c0a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -166,8 +166,8 @@ int fd_attempt_close(file_fd_struct *fd_ptr) fd_ptr->fd_readonly = -1; fd_ptr->fd_writeonly = -1; fd_ptr->real_open_flags = -1; - fd_ptr->dev = (uint32)-1; - fd_ptr->inode = (uint32)-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); @@ -484,8 +484,8 @@ static void open_file(files_struct *fsp,connection_struct *conn, } /* Set the correct entries in fd_ptr. */ - fd_ptr->dev = (uint32)sbuf->st_dev; - fd_ptr->inode = (uint32)sbuf->st_ino; + fd_ptr->dev = sbuf->st_dev; + fd_ptr->inode = sbuf->st_ino; fsp->fd_ptr = fd_ptr; conn->num_files_open++; @@ -596,8 +596,8 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int BOOL share_locked = False; BOOL fcbopen = False; int token; - uint32 dev = 0; - uint32 inode = 0; + SMB_DEV_T dev = 0; + SMB_INO_T inode = 0; int num_share_modes = 0; fsp->open = False; @@ -681,8 +681,8 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int if (file_existed) { - dev = (uint32)sbuf.st_dev; - inode = (uint32)sbuf.st_ino; + dev = sbuf.st_dev; + inode = sbuf.st_ino; lock_share_entry(conn, dev, inode, &token); share_locked = True; num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); @@ -994,15 +994,16 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) struct stat sbuf; int token; int pid = getpid(); - uint32 dev, inode; + SMB_DEV_T dev; + SMB_INO_T inode; if(!lp_share_modes(SNUM(conn))) return True; if (sys_stat(fname,&sbuf) == -1) return(True); - dev = (uint32)sbuf.st_dev; - inode = (uint32)sbuf.st_ino; + dev = sbuf.st_dev; + inode = sbuf.st_ino; lock_share_entry(conn, dev, inode, &token); num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); -- cgit From 18556274139cc5a00593471bd745354d98a35303 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 1 Sep 1998 20:11:54 +0000 Subject: More abstraction of file system data types, to move to a 64 bit file interface for the NT SMB's. Created a new define, SMB_STRUCT_STAT that currently is defined to be struct stat - this wil change to a user defined type containing 64 bit info when the correct wrappers are written for 64 bit stat(), fstat() and lstat() calls. Also changed all sys_xxxx() calls that were previously just wrappers to the same call prefixed by a dos_to_unix() call into dos_xxxx() calls. This makes it explicit when a pathname translation is being done, and when it is not. Now, all sys_xxx() calls are meant to be wrappers to mask OS differences, and not silently converting filenames on the fly. Jeremy. (This used to be commit 28aa182dbffaa4ffd86047e608400de4b26e80eb) --- source3/smbd/open.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 1a16a25c0a..76e88c2e85 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -29,18 +29,18 @@ extern uint16 oplock_port; /**************************************************************************** -fd support routines - attempt to do a sys_open +fd support routines - attempt to do a dos_open ****************************************************************************/ static int fd_attempt_open(char *fname, int flags, int mode) { - int fd = sys_open(fname,flags,mode); + int fd = dos_open(fname,flags,mode); /* Fix for files ending in '.' */ if((fd == -1) && (errno == ENOENT) && (strchr(fname,'.')==NULL)) { pstrcat(fname,"."); - fd = sys_open(fname,flags,mode); + fd = dos_open(fname,flags,mode); } #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF)) @@ -71,7 +71,7 @@ static int fd_attempt_open(char *fname, int flags, int mode) char tmp = p[max_len]; p[max_len] = '\0'; - if ((fd = sys_open(fname,flags,mode)) == -1) + if ((fd = dos_open(fname,flags,mode)) == -1) p[max_len] = tmp; } } @@ -127,7 +127,7 @@ 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) { - int fd = sys_open( fname, O_RDWR, mode); + int fd = dos_open( fname, O_RDWR, mode); if(fd == -1) return; @@ -266,11 +266,11 @@ static void check_for_pipe(char *fname) open a file ****************************************************************************/ static void open_file(files_struct *fsp,connection_struct *conn, - char *fname1,int flags,int mode, struct stat *sbuf) + char *fname1,int flags,int mode, SMB_STRUCT_STAT *sbuf) { extern struct current_user current_user; pstring fname; - struct stat statbuf; + SMB_STRUCT_STAT statbuf; file_fd_struct *fd_ptr; int accmode = (flags & (O_RDONLY | O_WRONLY | O_RDWR)); @@ -324,7 +324,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, * open fd table. */ if(sbuf == 0) { - if(sys_stat(fname, &statbuf) < 0) { + if(dos_stat(fname, &statbuf) < 0) { if(errno != ENOENT) { DEBUG(3,("Error doing stat on file %s (%s)\n", fname,strerror(errno))); @@ -452,7 +452,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, fd_attempt_close(fd_ptr); fsp->fd_ptr = 0; if(fd_ptr->ref_count == 0) - sys_unlink(fname); + dos_unlink(fname); errno = ENOSPC; return; } @@ -591,7 +591,7 @@ 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; - struct stat sbuf; + SMB_STRUCT_STAT sbuf; BOOL file_existed = file_exist(fname,&sbuf); BOOL share_locked = False; BOOL fcbopen = False; @@ -856,14 +856,14 @@ int open_directory(files_struct *fsp,connection_struct *conn, char *fname, int smb_ofun, int unixmode, int *action) { extern struct current_user current_user; - struct stat st; + SMB_STRUCT_STAT st; if (smb_ofun & 0x10) { /* * Create the directory. */ - if(sys_mkdir(fname, unixmode) < 0) { + if(dos_mkdir(fname, unixmode) < 0) { DEBUG(0,("open_directory: unable to create %s. Error was %s\n", fname, strerror(errno) )); return -1; @@ -875,7 +875,7 @@ int open_directory(files_struct *fsp,connection_struct *conn, * Check that it *was* a directory. */ - if(sys_stat(fname, &st) < 0) { + if(dos_stat(fname, &st) < 0) { DEBUG(0,("open_directory: unable to stat name = %s. Error was %s\n", fname, strerror(errno) )); return -1; @@ -991,7 +991,7 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) int ret = False; share_mode_entry *old_shares = 0; int num_share_modes; - struct stat sbuf; + SMB_STRUCT_STAT sbuf; int token; int pid = getpid(); SMB_DEV_T dev; @@ -1000,7 +1000,7 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) if(!lp_share_modes(SNUM(conn))) return True; - if (sys_stat(fname,&sbuf) == -1) return(True); + if (dos_stat(fname,&sbuf) == -1) return(True); dev = sbuf.st_dev; inode = sbuf.st_ino; -- cgit From 7bb86c1b132bce31a006ea9768a54db7a45fe1a5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 3 Sep 1998 18:40:31 +0000 Subject: Ok - this is the 64 bit widening check in. It changes the configure to check for stat64 and friends, and then changes much of Samba to use the data type SMB_OFF_T for file size information. stat/fstat/lstat/lseek/ftruncate have now become sys_stat etc. to hide the 64 bit calls if needed. Note that this still does not expose 64 bit functionality to the client, as the changes to the reply_xxx smb's are not yet done. This code change should make these changes possible. Still to do before full 64 bit-ness to the client: fcntl lock code. statfs code widening of dev_t and ino_t (now possible due to SMB_DEV_T and SMB_OFF_T types being in place). Let me know if wierd things happen after this check-in and I'll fix them :-). Jeremy. (This used to be commit 14500936c321d15995c963766aac67bf1f4e3824) --- source3/smbd/open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 76e88c2e85..395de66a88 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -472,7 +472,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, { if(sbuf == 0) { /* Do the fstat */ - if(fstat(fd_ptr->fd, &statbuf) == -1) { + if(sys_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))); @@ -576,7 +576,7 @@ static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, i unix_ERR_code = ERRlock; } else - ftruncate(fsp->fd_ptr->fd,0); + sys_ftruncate(fsp->fd_ptr->fd,0); } } -- cgit From 623a18db4b0f46c80c29e93a0ad0a2fcbfec71dc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 4 Sep 1998 00:23:28 +0000 Subject: More 64 bit stuff - now the fcntl locks are 64 bit clean. Nearly at the stage where I can expose the 64-bit-ness to the NT clients.... Jeremy. (This used to be commit 422f1dd45074c0e28203aca5952e57bbe56676b6) --- source3/smbd/open.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 395de66a88..f24d4ac962 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -562,7 +562,11 @@ static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, i 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))) -- cgit From 83900f2b682c62f2b5620b29ecb710274990ac51 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 4 Sep 1998 20:53:58 +0000 Subject: Modified dev_t and ino_t code to be 64 bit clean (including changes to oplock break message passing). I think that smbd/nmbd are now inode and offset size independent (at least for 32 bit and 64 bit systems). Now to expose all this new functionality to NT clients..... Jeremy. (This used to be commit 5910d07bbf45a34d3c901461f74704c029a79474) --- source3/smbd/open.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 53 insertions(+), 8 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index f24d4ac962..45d919187f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -149,10 +149,18 @@ int fd_attempt_close(file_fd_struct *fd_ptr) { extern struct current_user current_user; - DEBUG(3,("fd_attempt_close fd = %d, dev = %x, inode = %x, open_flags = %d, ref_count = %d.\n", - fd_ptr->fd, fd_ptr->dev, fd_ptr->inode, +#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) { @@ -718,16 +726,28 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int 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 = %x\n", share_entry->op_type, fname, dev, inode)); +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); if(request_oplock_break(share_entry, dev, inode) == False) { 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 = %x\n", old_shares[i].op_type, fname, dev, inode)); +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; unix_ERR_code = ERRbadshare; @@ -831,8 +851,13 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); 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 = %x\n", oplock_request, fname, dev, inode)); +dev = %x, inode = %lx\n", oplock_request, fname, (unsigned int)dev, (double)inode)); +#endif /* LARGE_SMB_INO_T */ } else @@ -1051,8 +1076,15 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) */ 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 = %x\n", fname, dev, inode)); +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 * processing to be skipped. This seems to be needed as @@ -1065,16 +1097,29 @@ batch oplocked file %s, dev = %x, inode = %x\n", fname, dev, inode)); } else { + +#ifdef LARGE_SMB_INO_T DEBUG(5,("check_file_sharing: breaking oplock (%x) on file %s, \ -dev = %x, inode = %x\n", share_entry->op_type, fname, dev, inode)); +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); if(request_oplock_break(share_entry, dev, inode) == False) { 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 = %x\n", old_shares[i].op_type, fname, dev, inode)); +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; } lock_share_entry(conn, dev, inode, &token); -- cgit From 98f524bde4801bd0b013a6bc79c5552ef62b59f8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 5 Sep 1998 03:14:40 +0000 Subject: Bugfix for leak in reference counted file struct. Added "nt smb support" parameter to allow NT SMB's to be turned off. Jeremy. (This used to be commit 63f65f5027d5022153fa2757b49c56829db1725b) --- source3/smbd/open.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 45d919187f..a72469f2b2 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -170,13 +170,10 @@ int fd_attempt_close(file_fd_struct *fd_ptr) 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; + /* + * Delete this fd_ptr. + */ + fd_ptr_free(fd_ptr); } else { fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid); } @@ -457,10 +454,9 @@ static void open_file(files_struct *fsp,connection_struct *conn, if (p) *p = 0; if (sys_disk_free(dname,&dum1,&dum2,&dum3) < lp_minprintspace(SNUM(conn))) { - fd_attempt_close(fd_ptr); - fsp->fd_ptr = 0; - if(fd_ptr->ref_count == 0) + if(fd_attempt_close(fd_ptr) == 0) dos_unlink(fname); + fsp->fd_ptr = 0; errno = ENOSPC; return; } -- cgit From e9ea36e4d2270bd7d32da12ef6d6e2299641582d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 5 Sep 1998 05:07:05 +0000 Subject: tridge the destroyer returns! prompted by the interpret_security() dead code that Jean-Francois pointed out I added a make target "finddead" that finds potentially dead (ie. unused) code. It spat out 304 function names ... I went through these are deleted many of them, making others static (finddead also reports functions that are used only in the local file). in doing this I have almost certainly deleted some useful code. I may have even prevented compilation with some compile options. I apologise. I decided it was better to get rid of this code now and add back the one or two functions that are needed than to keep all this baggage. So, if I have done a bit too much "destroying" then let me know. Keep the swearing to a minimum :) One bit I didn't do is the ubibt code. Chris, can you look at that? Heaps of unused functions there. Can they be made static? (This used to be commit 2204475c87f3024ea8fd1fbd7385b2def617a46f) --- source3/smbd/open.c | 190 +++++++++++++++++++++++++++------------------------- 1 file changed, 97 insertions(+), 93 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index a72469f2b2..e6289b1cdb 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -589,6 +589,102 @@ static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, i } +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 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 = 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; +} + /**************************************************************************** open a file with a share mode @@ -852,7 +948,7 @@ dev = %x, inode = %lx\n", old_shares[i].op_type, fname, (unsigned int)dev, (unsi 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)); +dev = %x, inode = %lx\n", oplock_request, fname, (unsigned int)dev, (unsigned long)inode)); #endif /* LARGE_SMB_INO_T */ } @@ -953,58 +1049,6 @@ int open_directory(files_struct *fsp,connection_struct *conn, 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 @@ -1153,44 +1197,4 @@ free_and_exit: 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; -} -- cgit From 6e0c276ec8b918165a19b3dfc86bc7bef6d1f706 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 8 Sep 1998 19:21:04 +0000 Subject: Added back groupname map stuff removed by Andrew's "slash 'n' burn" tactics :-). Protected by #ifdef until used. Fixed bug in fd_attempt_close() where a pointer to potentially free'd memory was returned. I hate that. Added "blocking locks" as a per-share option for performance testing. Changed is_mangled() so it will return true if called with a pathname and any component of the pathname was mangled (it was already attempting to do this, but not checking for a '/' as end-of-mangle). This should be a better fix for the wierd stat cache bug Andrew identified. Jeremy. (This used to be commit 0de01f45980c7bc261248a9cead972a8d8cbd594) --- source3/smbd/open.c | 49 +++++++++++++++++++++++-------------------------- 1 file changed, 23 insertions(+), 26 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index e6289b1cdb..bd1ead6921 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -145,40 +145,37 @@ static void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr) 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(file_fd_struct *fd_ptr) { extern struct current_user current_user; + uint16 ret_ref = fd_ptr->ref_count; -#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); - /* - * Delete this fd_ptr. - */ - fd_ptr_free(fd_ptr); - } 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) + 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); + /* + * 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; } /**************************************************************************** -- cgit From 06cc91f9a631a23dcd4902d710b89e4b7584c459 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 11 Sep 1998 01:24:30 +0000 Subject: Added ssize_t to configure code. Got 'religion' about using size_t and ssize_t for read/write stuff as part of the code to expose 64 bits to the client. This checkin does all the 'easy' stuff - such as all the read/write/lock calls - but now comes the harder parts (open & friends) and all the file enquiry functions..... Jeremy. (This used to be commit 36544fe5476f7770bd5748574fc54be7b3ee4d4a) --- source3/smbd/open.c | 30 ------------------------------ 1 file changed, 30 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index bd1ead6921..bdd4816aa7 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -815,13 +815,8 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int 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); @@ -829,13 +824,8 @@ dev = %x, inode = %lx\n", share_entry->op_type, fname, (unsigned int)dev, (unsig { 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; @@ -940,13 +930,8 @@ dev = %x, inode = %lx\n", old_shares[i].op_type, fname, (unsigned int)dev, (unsi 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, (unsigned long)inode)); -#endif /* LARGE_SMB_INO_T */ } else @@ -1114,13 +1099,8 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) 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 @@ -1135,13 +1115,8 @@ batch oplocked file %s, dev = %x, inode = %lx\n", fname, (unsigned int)dev, (uns 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); @@ -1149,13 +1124,8 @@ dev = %x, inode = %lx\n", share_entry->op_type, fname, (unsigned int)dev, (unsig { 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; } -- cgit From 27d0bef143fbc4d7547c022046c094bbdbd0bfc1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 11 Sep 1998 19:14:27 +0000 Subject: Ok - this is the 'expose 64 bit to the clients' checkin. I have tested it by creating a 'holey' 20GB file - checking that it shows up correctl in the NT file view (it does) and am busily copying it to NULL: on the NT box. All good so far.... :-). Also implemented NT 'delete on close' semantics. Jeremy. (This used to be commit 1654faee80648583e6a47ab7eda990fefdf85124) --- source3/smbd/open.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index bdd4816aa7..42b0fba425 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -507,6 +507,7 @@ 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 -- cgit From ac9b687cc2496409e1c8d86393812faf94ec7550 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 17 Sep 1998 19:16:12 +0000 Subject: configure configure.in: Added tests for fseek64 and ftell64. config.h.in: Added fseek64 and ftell64. includes.h: Added definition of SMB_BIG_INTEGER. smb.h: Changed (*getsmbpwpos) and (*setsmbpwpos) to use SMB_BIG_INTEGER. access.c: Tidyup of dbug statement. system.c: Added sys_fseek and sys_ftell. Changed mode calls to use mode_t. asyncdns.c: Tidyup of comment. loadparm.c: Tidyup of set_default_server_announce_type() function definition. ldap.c: Changed (*getsmbpwpos) and (*setsmbpwpos) to use SMB_BIG_INTEGER. nispass.c: Changed (*getsmbpwpos) and (*setsmbpwpos) to use SMB_BIG_INTEGER. smbpass.c: Changed (*getsmbpwpos) and (*setsmbpwpos) to use SMB_BIG_INTEGER. smbpassfile.c: Use sys_fseek(). chgpasswd.c: Tidyup of debug statement. dosmode.c: Changed mode calls to use mode_t. ipc.c: Removal of dead code. nttrans.c: Changed mode calls to use mode_t. open.c: Changed mode calls to use mode_t. pipes.c: Removal of dead code. reply.c: Removal of dead code. trans2.c: Removal of dead code. Changed mode calls to use mode_t. Jeremy. (This used to be commit c381d32e3dc23fe887408016cae821aceb30da2c) --- source3/smbd/open.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 42b0fba425..ad4dd9f52f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -31,7 +31,7 @@ extern uint16 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(char *fname, int flags, mode_t mode) { int fd = dos_open(fname,flags,mode); @@ -125,7 +125,7 @@ static BOOL fd_is_in_uid_cache(file_fd_struct *fd_ptr, uid_t u) 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); @@ -268,7 +268,7 @@ static void check_for_pipe(char *fname) 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; @@ -688,7 +688,7 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, 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) + mode_t mode,int oplock_request, int *Access,int *action) { int flags=0; int flags2=0; @@ -865,7 +865,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou } 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) -- cgit From b8b67f4fab4a6fd686c5796c2701882197a7bd9d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 17 Sep 1998 23:06:57 +0000 Subject: configure configure.in: Added checks for statvfs64. Last bit of 64 bit widening (I hope :-). include/config.h.in: Added #undef STAT_STATVFS64. include/includes.h: Added SMB_STRUCT_STATVFS type, Changed SMB_BIG_INTEGER to SMB_BIG_UINT and SMB_BIG_INT types. include/smb.h: Added flag defines from CIFS spec. lib/debug.c: Fixed one more mode_t issue. lib/system.c: Added sys_statvfs wrapper. lib/util.c: Changed trim_string to use size_t. param/loadparm.c: Moved "blocking locks" into locking section. Alphabetised locking options. Question - shuld we do this for all options ? passdb/ldap.c: Changed SMB_BIG_INTEGER to SMB_BIG_UINT. passdb/nispass.c: Changed SMB_BIG_INTEGER to SMB_BIG_UINT. passdb/smbpass.c: Changed SMB_BIG_INTEGER to SMB_BIG_UINT. smbd/dfree.c: Changed to use 64 bit types if available. Moved to use unsigned types. smbd/dosmode.c: Fixed one more mode_t issue. smbd/negprot.c: Changed literals to be FLAG_ #defines. smbd/nttrans.c: Removed dead code. smbd/open.c: Changed disk_free call. smbd/process.c: Changed literals to be FLAG_ #defines. smbd/reply.c: Changed disk_free call. smbd/trans2.c: Fixed but in SMB_QUERY_FS_VOLUME_INFO call. Was using UNICODE - should use ascii. tests/summary.c: Added STAT_STATVFS64 check. Jeremy. (This used to be commit c512b1b91fb7f2a7a93b9033a33e06d966daadb4) --- source3/smbd/open.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index ad4dd9f52f..108ef814ee 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -444,13 +444,12 @@ static void open_file(files_struct *fsp,connection_struct *conn, 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))) { + if (sys_disk_free(dname,&dum1,&dum2,&dum3) < (SMB_BIG_UINT)lp_minprintspace(SNUM(conn))) { if(fd_attempt_close(fd_ptr) == 0) dos_unlink(fname); fsp->fd_ptr = 0; @@ -957,7 +956,7 @@ dev = %x, inode = %.0f\n", oplock_request, fname, (unsigned int)dev, (double)ino 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; -- cgit From b3b44e02f3c0c2f6c4b66bc112e546a08ef45316 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 18 Sep 1998 02:27:24 +0000 Subject: removed another use of the LL suffix. Hopefully this is the last one (a grep doesn't show any more) (This used to be commit c1bd188744b0df950f2e00550c25f7d3e148094b) --- source3/smbd/open.c | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 108ef814ee..a02fe91e68 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -562,27 +562,25 @@ static void open_file(files_struct *fsp,connection_struct *conn, 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; - } - else - sys_ftruncate(fsp->fd_ptr->fd,0); - } + if (fsp->can_write){ + SMB_OFF_T mask = ((SMB_OFF_T)0xC) << (SMB_OFF_T_BITS-4); + + 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); + } + } } -- cgit From c7da9992cb39fc84a6a915dd2158beaf5e616617 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 18 Sep 1998 03:00:20 +0000 Subject: gto ri of a bunch more #ifdef LARGE_SMB_OFF_T checks by introducing a SOFF_T() macro for setting an SMB_OFF_T variable also limited mmap based reads to MAX_MMAP_SIZE. We really can't mmap 2^50 bytes due to virtual address space problems. (This used to be commit 4e784b18899eddd2399a51fa7d8c219560432922) --- source3/smbd/open.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index a02fe91e68..394c7be3f8 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -541,13 +541,15 @@ static void open_file(files_struct *fsp,connection_struct *conn, /* 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; + if (fsp->mmap_size < MAX_MMAP_SIZE) { + 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; + } } } #endif -- cgit From 184db9266efcbcea13169f99002b32208dc2ec9b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 18 Sep 1998 17:50:18 +0000 Subject: configure configure.in include/config.h.in include/includes.h Fixed bugs in readline autoconf. param/loadparm.c smbd/open.c smbd/oplock.c: Started on kernel oplock code - checking forced by above issue. Should not be used currently. Jeremy. (This used to be commit f939efac9e6c45331b17e3d3aa6bc2235e886c1a) --- source3/smbd/open.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 394c7be3f8..abbc0d6741 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -687,7 +687,7 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, open a file with a share mode ****************************************************************************/ 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) + mode_t mode,int *oplock_request, int *Access,int *action) { int flags=0; int flags2=0; @@ -922,24 +922,34 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou be extended to level II oplocks (multiple reader oplocks). */ - if(oplock_request && (num_share_modes == 0) && lp_oplocks(SNUM(conn)) && + if((*oplock_request) && (num_share_modes == 0) && lp_oplocks(SNUM(conn)) && !IS_VETO_OPLOCK_PATH(conn,fname)) { +#if defined(HAVE_KERNEL_OPLOCKS) + /* + * Try and get a *real* oplock on this file. + * If we fail, set the port and oplock request to + * zero so that we don't tell other SMB's that we + * got an oplock. + */ + if(lp_kernel_oplocks()) +#endif /* HAVE_KERNEL_OPLOCKS */ + fsp->granted_oplock = True; fsp->sent_oplock_break = False; global_oplocks_open++; port = oplock_port; DEBUG(5,("open_file_shared: granted oplock (%x) on file %s, \ -dev = %x, inode = %.0f\n", oplock_request, fname, (unsigned int)dev, (double)inode)); +dev = %x, inode = %.0f\n", *oplock_request, fname, (unsigned int)dev, (double)inode)); } else { port = 0; - oplock_request = 0; + *oplock_request = 0; } - set_share_mode(token, fsp, port, oplock_request); + set_share_mode(token, fsp, port, *oplock_request); } if ((flags2&O_TRUNC) && file_existed) -- cgit From 31ebc956e5f17fef8411b5fef1a6529df072df2a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 18 Sep 1998 18:09:17 +0000 Subject: Fixed problems with premature kernel oplock checkin code. The ./configure & build now seem to work ok. Jeremy. (This used to be commit 7c1a5ed1c2a55543d3f3c8bbd38e6c9c35b80390) --- source3/smbd/open.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index abbc0d6741..0d8fcddbe5 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -687,7 +687,7 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, open a file with a share mode ****************************************************************************/ 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) + mode_t mode,int oplock_request, int *Access,int *action) { int flags=0; int flags2=0; @@ -922,7 +922,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou be extended to level II oplocks (multiple reader oplocks). */ - if((*oplock_request) && (num_share_modes == 0) && lp_oplocks(SNUM(conn)) && + if((oplock_request) && (num_share_modes == 0) && lp_oplocks(SNUM(conn)) && !IS_VETO_OPLOCK_PATH(conn,fname)) { #if defined(HAVE_KERNEL_OPLOCKS) @@ -941,15 +941,15 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou port = oplock_port; DEBUG(5,("open_file_shared: granted oplock (%x) on file %s, \ -dev = %x, inode = %.0f\n", *oplock_request, fname, (unsigned int)dev, (double)inode)); +dev = %x, inode = %.0f\n", oplock_request, fname, (unsigned int)dev, (double)inode)); } else { port = 0; - *oplock_request = 0; + oplock_request = 0; } - set_share_mode(token, fsp, port, *oplock_request); + set_share_mode(token, fsp, port, oplock_request); } if ((flags2&O_TRUNC) && file_existed) -- cgit From aab2fe021643417854451c65e564932f4ac25f10 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 23 Sep 1998 01:48:45 +0000 Subject: First cut at kernel oplocks. This should have no effect unless runnin on a machine that supports them in autoconf. Move various functions out of lib/util.c into smbd/process.c and smbd/oplock.c where they belong. Jeremy. (This used to be commit c3c5e13f85c97939746070132dad941e79c546fb) --- source3/smbd/open.c | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 0d8fcddbe5..64f28ddfe2 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -24,8 +24,7 @@ extern int DEBUGLEVEL; extern pstring sesssetup_user; -extern int global_oplocks_open; -extern uint16 oplock_port; +extern uint16 global_oplock_port; /**************************************************************************** @@ -917,38 +916,23 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou 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)) + !IS_VETO_OPLOCK_PATH(conn,fname) && set_file_oplock(fsp) ) { -#if defined(HAVE_KERNEL_OPLOCKS) - /* - * Try and get a *real* oplock on this file. - * If we fail, set the port and oplock request to - * zero so that we don't tell other SMB's that we - * got an oplock. - */ - if(lp_kernel_oplocks()) -#endif /* HAVE_KERNEL_OPLOCKS */ - - fsp->granted_oplock = True; - fsp->sent_oplock_break = False; - global_oplocks_open++; - port = oplock_port; - - DEBUG(5,("open_file_shared: granted oplock (%x) on file %s, \ -dev = %x, inode = %.0f\n", oplock_request, fname, (unsigned int)dev, (double)inode)); - + port = global_oplock_port; } else { port = 0; oplock_request = 0; } + set_share_mode(token, fsp, port, oplock_request); } -- cgit From 5f7ee360567a6b4e1a6f43ff01da057d2998fef8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 25 Sep 1998 23:40:49 +0000 Subject: Makefile.in: Fixed bug with continuation line causing proto to fail. Added $(PROGS) $(SPROGS) as targets for make clean. acconfig.h: Added HAVE_IRIX_SPECIFIC_CAPABILITIES. configure.in: Added sys/capability.h header check. Added function checks for srandom random srand rand. Added HAVE_IRIX_SPECIFIC_CAPABILITIES test. includes.h: Added #include . ntdomain.h: Moved struct acct_info into here from smb.h smb.h: Added KERNEL_OPLOCK_CAPABILITY define. Moved enum action_type into rpcclient.h Moved struct cli_state into client.h Moved struct nt_client_info, struct tar_client_info, struct client_info into rpcclient.h lib/genrand.c: Changed to use sys_random() & friends. lib/smbrun.c: Lose capabilities after fork. lib/system.c: Added set_process_capability(), set_inherited_process_capability() sys_random(), sys_srandom(). lib/util.c: Added Ander's EFBIG lock check to fcntl_lock for 64 bit access to an 32 bit mounted NFS filesystem. nmbd/nmbd.c: Changed to use sys_random() & friends. nmbd/nmbd_browsesync.c: Changed to use sys_random() & friends. passdb/ldap.c: Missed one pdb_encode_acct_ctrl call. passdb/passdb.c: Changed to Ander's code for ' ' characters. passdb/smbpass.c: Added Ander's code to reset ACB_PWNOTREQ. script/mkproto.awk: Added 'long' to prototypes. smbd/chgpasswd.c: Lose capabilities after fork. smbd/open.c: Do the mmap *after* the kernel oplock. smbd/oplock.c: Removed stub code from kernel oplock path. Added set_process_capability(), set_inherited_process_capability() calls. smbd/reply.c: Initialize count = 0, offset = 0. smbd/server.c: Added set_process_capability(), set_inherited_process_capability() calls. tests/summary.c: Ensure we have RANDOM or RAND. utils/smbpasswd.c: Added Ander's code to reset ACB_PWNOTREQ. utils/torture.c: Changed to use sys_random() & friends. Jeremy. (This used to be commit e8be306f23963ac00b1a383ebe0cc1421529fb02) --- source3/smbd/open.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 64f28ddfe2..2b2f0f0524 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -535,18 +535,30 @@ static void open_file(files_struct *fsp,connection_struct *conn, 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_size = file_size(fsp->fsp_name); if (fsp->mmap_size < MAX_MMAP_SIZE) { 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->fsp_name,strerror(errno))); fsp->mmap_ptr = NULL; } } @@ -554,7 +566,6 @@ static void open_file(files_struct *fsp,connection_struct *conn, #endif } - /**************************************************************************** C. Hoch 11/22/95 Helper for open_file_shared. @@ -938,6 +949,13 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou 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))) -- cgit From d0fb78b85efa70f4a62618873e6a03318b1f7b38 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 3 Oct 1998 11:54:00 +0000 Subject: use O_ACCMODE (This used to be commit cc6270f327fdc998e5e3a2d8c3b50f33a29ec3c1) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 2b2f0f0524..311c494a97 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -273,7 +273,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, 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; -- cgit From 1ee499385c1ea0b4add82d3d4513ea997d048af1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 22 Oct 1998 16:55:03 +0000 Subject: libsmb/smbdes.c: #ifdef'ed out code prior to removal. rpc_client/cli_pipe.c: Inlined code removed from smbdes.c rpc_server/srv_samr.c: Fixed unused variable warning. rpc_server/srv_util.c: Inlined code removed from smbdes.c Luke - the above changes are the first part of the changes you and I discussed as being neccessary at the CIFS conference. *PLEASE REVIEW THESE CHANGES* - make sure I haven't broken any of the authenticated DCE/RPC code. smbd/nttrans.c: Fixed to allow NT5.0beta2 to use Samba shares with NT SMB support. smbd/open.c: Fixed mkdir when called from nttrans calls. smbd/server.c: Set correct size for strcpy of global_myworkgroup. Jeremy. (This used to be commit d891421d16ff80998dee429227bd391455f9d1a1) --- source3/smbd/open.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 311c494a97..a6e2953263 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -696,6 +696,7 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, /**************************************************************************** open a file with a share mode ****************************************************************************/ + 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) { @@ -714,6 +715,9 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int 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, mode, oplock_request )); + /* this is for OS/2 EAs - try and say we don't support them */ if (strstr(fname,".+,;=[].")) { @@ -725,11 +729,14 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int 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) { + DEBUG(5,("open_file_shared: create new requested for file %s and file already exists.\n", + fname )); errno = EEXIST; return; } @@ -770,6 +777,8 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int { 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; } @@ -978,7 +987,7 @@ int open_directory(files_struct *fsp,connection_struct *conn, * Create the directory. */ - if(dos_mkdir(fname, unixmode) < 0) { + if(dos_mkdir(fname, unix_mode(conn,aDIR)) < 0) { DEBUG(0,("open_directory: unable to create %s. Error was %s\n", fname, strerror(errno) )); return -1; -- cgit From 5d6ed11ef3c860c95ae7b3a855b0ddb123bd9737 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 23 Oct 1998 00:58:28 +0000 Subject: include/smb.h: Added #defines for lots of things - makes our code a *lot* easier to read. lib/util.c: Fixed Luke's set_first_token() function - should return void. smbd/close.c: Move delete_on_close into file_fd_struct structure. smbd/ipc.c: Changed local_machine back to fstring. smbd/nttrans.c: Use defines for mapping share modes. smbd/open.c: Move delete_on_close into file_fd_struct structure, added code for ALLOW_SHARE_DELETE. smbd/reply.c: Use defines for mapping share modes. smbd/trans2.c: Move delete_on_close into file_fd_struct structure. Jeremy. (This used to be commit 8e1ce307bd6a9056b4a95fe6f52ff42dc6e03a08) --- source3/smbd/open.c | 71 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 45 insertions(+), 26 deletions(-) (limited to 'source3/smbd/open.c') 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); } - - -- cgit From 9bb7ac81b6e4d33e1be49447dbdbbb8d24259f53 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 23 Oct 1998 03:34:50 +0000 Subject: Reasonably large change to give us *exactly* correct NT delete on close semantics. This was trickier than it looks :-). Check out the new DELETE_ON_CLOSE flag in the share modes and the new code that iterates through all open files on the same device and inode in files.c and trans2.c Also changed the code that modifies share mode entries to take generic function pointers rather than doing a specific thing so this sort of change should be easier in the future. Jeremy. (This used to be commit 5e6a7cd99d29d1cf068fc517272559c1cf47ea3a) --- source3/smbd/open.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index b6b2ef5bb8..aac4b02fba 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -659,6 +659,26 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, int old_open_mode = GET_OPEN_MODE(share->share_mode); int old_deny_mode = GET_DENY_MODE(share->share_mode); + /* + * Setup the potential error to return. + */ + + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + + /* + * 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_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", @@ -688,6 +708,7 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, *flags = O_WRONLY; } + return True; } @@ -865,8 +886,6 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou free((char *)old_shares); unlock_share_entry(conn, dev, inode, token); errno = EACCES; - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; return; } -- cgit From ce2a92d86434c1b04d9b09b710ad362407d9bdc6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 29 Oct 1998 20:17:02 +0000 Subject: Fixed bug (that I introduced when doing the "delete on close" work that caused NetBench to fail as the wrong error code was being returned from a getatr call. Change was not to set the unix_ERR_class global when you are not returning an error. This is a big of Samba internal folklore that is *important*. Jeremy. (This used to be commit a1923d465be4c63a40d55abb800cc9b16a4b87d0) --- source3/smbd/open.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index aac4b02fba..670161f2d0 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -659,13 +659,6 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, int old_open_mode = GET_OPEN_MODE(share->share_mode); int old_deny_mode = GET_DENY_MODE(share->share_mode); - /* - * Setup the potential error to return. - */ - - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - /* * Don't allow any open once the delete on close flag has been * set. @@ -675,6 +668,7 @@ static int check_share_mode( share_mode_entry *share, int deny_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; } @@ -683,6 +677,10 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, { 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; } @@ -698,6 +696,10 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, 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; } -- cgit From 8fc1504ff8204dd1ca735f31c769f6dadf0f88cb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 13 Nov 1998 21:41:01 +0000 Subject: Makefile.in configure configure.in include/config.h.in: Changes for DGUX and UNIXWARE. groupdb/aliasdb.c groupdb/aliasfile.c groupdb/groupfile.c: Don't use snprinf, use slprintf. include/includes.h: Fix YP problem. include/smb.h: Fix ZERO_STRUCTP. lib/util_sock.c: Added strerror() in debugs. passdb/ldap.c: Don't use snprinf, use slprintf. rpc_client/cli_lsarpc.c rpc_client/cli_pipe.c rpc_parse/parse_sec.c rpc_server/srv_pipe.c: Don't use snprinf, use slprintf. script/installman.sh: DGUX changes. smbd/open.c smbd/oplock.c: Fixed gcc warnings. web/swat.c: Changes USER to SWAT_USER. (This used to be commit 4c2b5a00983501e5d4aad1456ba8b5ab0dfd9b4c) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 670161f2d0..f9ddc969a8 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -739,7 +739,7 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int 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, mode, oplock_request )); + 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,".+,;=[].")) -- cgit From 31739a0e1e32abfa7da166afbc5075aeab4124e6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 16 Nov 1998 21:38:13 +0000 Subject: O_EXCL fixes for printing files & oplocks. Jeremy. (This used to be commit 4ca71c90985b1c88d92bdd0f9079a4afc263dc46) --- source3/smbd/open.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index f9ddc969a8..c81334c8ae 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -312,7 +312,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, /* 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); } /* @@ -770,6 +770,9 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int 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 */ -- cgit From 768761820e8d7481c586c4e0ab4ac7cb36d18c4b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 17 Nov 1998 20:50:07 +0000 Subject: Added the same open()/fopen()/creat()/mmap() -> sys_XXX calls. Tidied up some of the mess (no other word for it). Still doesn't compile cleanly. There are calls with incorrect parameters that don't seem to be doing the right thing. This code still needs surgery :-(. Jeremy. (This used to be commit 18ff93a9abbf68ee8c59c0af3e57c63e4a015dac) --- source3/smbd/open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index c81334c8ae..d7cef6d63b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -552,8 +552,8 @@ static void mmap_open_file(files_struct *fsp) if (!fsp->can_write) { fsp->mmap_size = file_size(fsp->fsp_name); if (fsp->mmap_size < MAX_MMAP_SIZE) { - fsp->mmap_ptr = (char *)mmap(NULL,fsp->mmap_size, - PROT_READ,MAP_SHARED,fsp->fd_ptr->fd,0); + 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", -- cgit From bfc38ff872446e0ad365c22327c779e72a81bef9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 25 Nov 1998 21:17:20 +0000 Subject: Makefile.in: Added maintainer mode fixes. aclocal.m4: Added AC_LIBTESTFUNC. configure.in: Fixed -lsecurity -lsec problems. client.c: dos_ fixes. groupdb/aliasunix.c: Dead code removal. include/includes.h: Added default PRINTCAP_NAME. lib/genrand.c: dos_ fixes. lib/replace.c: Added strtoul. lib/system.c: dos_ fixes. lib/util.c: dos_ fixes. lib/util_sid.c: Signed/unsigned fixes. lib/util_str.c: removed bad const. locking/locking_slow.c: dos_ fixes. printing/printing.c: dos_ fixes. rpc_server/srv_samr.c: Dead code removal. rpc_server/srv_sid.c: global_myworkgroup defined with wrong size AGAIN ! smbd/dir.c: dos_ fixes. smbd/open.c: dos_ fixes. smbd/oplock.c: dos_ fixes. smbd/reply.c smbd/server.c smbd/service.c smbd/uid.c: dos_ fixes. Jeremy. (This used to be commit 6acb4b68f68d516e2ac3c47e500f5600d653435e) --- source3/smbd/open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index d7cef6d63b..dd1ece7fe1 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -550,7 +550,7 @@ 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(fsp->fsp_name); + 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); @@ -727,7 +727,7 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int 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 = dos_file_exist(fname,&sbuf); BOOL share_locked = False; BOOL fcbopen = False; int token; -- cgit From e50ab2b528a3dd176d98f95cb644fc6695c55318 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 7 Dec 1998 22:43:43 +0000 Subject: fixed warnings (and potential errors) due to integer overflow when creating locking masks (This used to be commit 5e2844d5edb15de29b976d2ff077ffbe012b860c) --- source3/smbd/open.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index dd1ece7fe1..6658b8926f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -574,7 +574,8 @@ static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, i BOOL *share_locked) { if (fsp->can_write){ - SMB_OFF_T mask = ((SMB_OFF_T)0xC) << (SMB_OFF_T_BITS-4); + 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 -- cgit From 10858bba8e790eeff1d8bfb60733cff65fca70c9 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sun, 4 Apr 1999 05:57:16 +0000 Subject: Use VFS operations for file I/O. Changed arg to fd_attempt_close() from fd to fsp_struct. (This used to be commit c40124bc9a2ebccf0bb56b1fafa81a551d934aa5) --- source3/smbd/open.c | 54 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 22 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 6658b8926f..da5303fc5a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -144,10 +144,17 @@ static void fd_attempt_reopen(char *fname, mode_t mode, file_fd_struct *fd_ptr) fd support routines - attempt to close the file referenced by this fd. Decrements the ref_count and returns it. ****************************************************************************/ -uint16 fd_attempt_close(file_fd_struct *fd_ptr) +uint16 fd_attempt_close(files_struct *fsp) { extern struct current_user current_user; - uint16 ret_ref = fd_ptr->ref_count; + file_fd_struct *fd_ptr = fsp->fd_ptr; + uint16 ret_ref; + + if (fd_ptr != NULL) { + ret_ref = fd_ptr->ref_count; + } else { + return 0; + } 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, @@ -161,11 +168,11 @@ uint16 fd_attempt_close(file_fd_struct *fd_ptr) if(fd_ptr->ref_count == 0) { if(fd_ptr->fd != -1) - close(fd_ptr->fd); + fsp->conn->vfs_ops.close(fd_ptr->fd); if(fd_ptr->fd_readonly != -1) - close(fd_ptr->fd_readonly); + fsp->conn->vfs_ops.close(fd_ptr->fd_readonly); if(fd_ptr->fd_writeonly != -1) - close(fd_ptr->fd_writeonly); + fsp->conn->vfs_ops.close(fd_ptr->fd_writeonly); /* * Delete this fd_ptr. */ @@ -325,7 +332,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, * 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))); @@ -423,7 +430,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, 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 = conn->vfs_ops.open(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. @@ -434,7 +441,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, 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 = conn->vfs_ops.open(fname, open_flags|accmode, mode); fd_ptr->real_open_flags = accmode; } } @@ -448,9 +455,10 @@ static void open_file(files_struct *fsp,connection_struct *conn, pstrcpy(dname,fname); p = strrchr(dname,'/'); if (p) *p = 0; - if (sys_disk_free(dname,&dum1,&dum2,&dum3) < (SMB_BIG_UINT)lp_minprintspace(SNUM(conn))) { - if(fd_attempt_close(fd_ptr) == 0) - dos_unlink(fname); + 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; errno = ENOSPC; return; @@ -462,7 +470,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, 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; } @@ -471,12 +479,12 @@ static void open_file(files_struct *fsp,connection_struct *conn, { 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; @@ -525,7 +533,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, */ 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", @@ -719,16 +727,17 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, /**************************************************************************** open a file with a share mode ****************************************************************************/ - -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) +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 = GET_DENY_MODE(share_mode); BOOL allow_share_delete = GET_ALLOW_SHARE_DELETE(share_mode); SMB_STRUCT_STAT sbuf; - BOOL file_existed = dos_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; @@ -1015,7 +1024,8 @@ int open_directory(files_struct *fsp,connection_struct *conn, * Create the directory. */ - if(dos_mkdir(fname, unix_mode(conn,aDIR)) < 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; @@ -1027,7 +1037,7 @@ int open_directory(files_struct *fsp,connection_struct *conn, * 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; @@ -1101,7 +1111,7 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) 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; -- cgit From 4085fb08fdd936212d9f3bbc9ded660dd3332786 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 5 Apr 1999 05:19:34 +0000 Subject: Fix incorrect conversion of fd_attempt_open() calls to vfs_ops.open(). Use VFS I/O for fd_attempt_open() and check_access_allowed_for_current_user(). (This used to be commit abf31ca66f3dab1b8bd7772f83e736e41afb4b1e) --- source3/smbd/open.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index da5303fc5a..2c12d425b9 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -30,16 +30,17 @@ extern uint16 global_oplock_port; /**************************************************************************** fd support routines - attempt to do a dos_open ****************************************************************************/ -static int fd_attempt_open(char *fname, int flags, mode_t 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)) @@ -70,7 +71,7 @@ static int fd_attempt_open(char *fname, int flags, mode_t mode) 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; } } @@ -191,7 +192,9 @@ This is really ugly code, as due to POSIX locking braindamage we must 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; @@ -242,7 +245,7 @@ static BOOL check_access_allowed_for_current_user( char *fname, int accmode ) */ 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); } @@ -373,7 +376,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, */ 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)); @@ -430,7 +433,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, 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 = conn->vfs_ops.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. @@ -441,7 +444,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, if((fd_ptr->fd == -1) && (errno == EACCES)) { #endif /* EROFS */ if(accmode != O_RDWR) { - fd_ptr->fd = conn->vfs_ops.open(fname, open_flags|accmode, mode); + fd_ptr->fd = fd_attempt_open(conn, fname, open_flags|accmode, mode); fd_ptr->real_open_flags = accmode; } } -- cgit From 3db52feb1f3b2c07ce0b06ad4a7099fa6efe3fc7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 13 Dec 1999 13:27:58 +0000 Subject: first pass at updating head branch to be to be the same as the SAMBA_2_0 branch (This used to be commit 453a822a76780063dff23526c35408866d0c0154) --- source3/smbd/open.c | 386 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 256 insertions(+), 130 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 2c12d425b9..4491082b2c 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -25,22 +25,22 @@ extern int DEBUGLEVEL; extern pstring sesssetup_user; extern uint16 global_oplock_port; - +extern BOOL global_client_failed_oplock_break; /**************************************************************************** fd support routines - attempt to do a dos_open ****************************************************************************/ -static int fd_attempt_open(struct connection_struct *conn, char *fname, - int flags, mode_t mode) + +static int fd_attempt_open(char *fname, int flags, mode_t mode) { - int fd = conn->vfs_ops.open(fname,flags,mode); + int fd = dos_open(fname,flags,mode); /* Fix for files ending in '.' */ if((fd == -1) && (errno == ENOENT) && (strchr(fname,'.')==NULL)) { pstrcat(fname,"."); - fd = conn->vfs_ops.open(fname,flags,mode); + fd = dos_open(fname,flags,mode); } #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF)) @@ -71,7 +71,7 @@ static int fd_attempt_open(struct connection_struct *conn, char *fname, char tmp = p[max_len]; p[max_len] = '\0'; - if ((fd = conn->vfs_ops.open(fname,flags,mode)) == -1) + if ((fd = dos_open(fname,flags,mode)) == -1) p[max_len] = tmp; } } @@ -83,6 +83,7 @@ static int fd_attempt_open(struct connection_struct *conn, char *fname, Cache a uid_t currently with this file open. This is an optimization only used when multiple sessionsetup's have been done to one smbd. ****************************************************************************/ + void fd_add_to_uid_cache(file_fd_struct *fd_ptr, uid_t u) { if(fd_ptr->uid_cache_count >= sizeof(fd_ptr->uid_users_cache)/sizeof(uid_t)) @@ -94,6 +95,7 @@ void fd_add_to_uid_cache(file_fd_struct *fd_ptr, uid_t u) Remove a uid_t that currently has this file open. This is an optimization only used when multiple sessionsetup's have been done to one smbd. ****************************************************************************/ + static void fd_remove_from_uid_cache(file_fd_struct *fd_ptr, uid_t u) { int i; @@ -111,6 +113,7 @@ static void fd_remove_from_uid_cache(file_fd_struct *fd_ptr, uid_t u) Check if a uid_t that currently has this file open is present. This is an optimization only used when multiple sessionsetup's have been done to one smbd. ****************************************************************************/ + static BOOL fd_is_in_uid_cache(file_fd_struct *fd_ptr, uid_t u) { int i; @@ -120,11 +123,11 @@ static BOOL fd_is_in_uid_cache(file_fd_struct *fd_ptr, uid_t u) return False; } - /**************************************************************************** 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, mode_t mode, file_fd_struct *fd_ptr) { int fd = dos_open( fname, O_RDWR, mode); @@ -145,17 +148,13 @@ static void fd_attempt_reopen(char *fname, mode_t mode, file_fd_struct *fd_ptr) fd support routines - attempt to close the file referenced by this fd. Decrements the ref_count and returns it. ****************************************************************************/ -uint16 fd_attempt_close(files_struct *fsp) + +uint16 fd_attempt_close(file_fd_struct *fd_ptr, int *err_ret) { extern struct current_user current_user; - file_fd_struct *fd_ptr = fsp->fd_ptr; - uint16 ret_ref; + uint16 ret_ref = fd_ptr->ref_count; - if (fd_ptr != NULL) { - ret_ref = fd_ptr->ref_count; - } else { - return 0; - } + *err_ret = 0; 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, @@ -168,12 +167,26 @@ uint16 fd_attempt_close(files_struct *fsp) 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); + + if(fd_ptr->fd != -1) { + if(close(fd_ptr->fd) < 0) + *err_ret = errno; + } + + if(fd_ptr->fd_readonly != -1) { + if(close(fd_ptr->fd_readonly) < 0) { + if(*err_ret == 0) + *err_ret = errno; + } + } + + if(fd_ptr->fd_writeonly != -1) { + if( close(fd_ptr->fd_writeonly) < 0) { + if(*err_ret == 0) + *err_ret = errno; + } + } + /* * Delete this fd_ptr. */ @@ -182,7 +195,7 @@ uint16 fd_attempt_close(files_struct *fsp) fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid); } - return ret_ref; + return ret_ref; } /**************************************************************************** @@ -192,14 +205,21 @@ This is really ugly code, as due to POSIX locking braindamage we must 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(struct connection_struct - *conn, char *fname, - int accmode ) + +static BOOL check_access_allowed_for_current_user( char *fname, int accmode ) { pid_t child_pid; + /* + * We need to temporarily stop CatchChild from eating + * SIGCLD signals as it also eats the exit status code. JRA. + */ + + CatchChildLeaveStatus(); + if((child_pid = fork()) < 0) { DEBUG(0,("check_access_allowed_for_current_user: fork failed.\n")); + CatchChild(); return False; } @@ -209,11 +229,23 @@ static BOOL check_access_allowed_for_current_user(struct connection_struct */ pid_t wpid; int status_code; - if ((wpid = sys_waitpid(child_pid, &status_code, 0)) < 0) { - DEBUG(0,("check_access_allowed_for_current_user: The process is no longer waiting!\n")); + + while ((wpid = sys_waitpid(child_pid, &status_code, 0)) < 0) { + if(errno == EINTR) { + errno = 0; + continue; + } + DEBUG(0,("check_access_allowed_for_current_user: The process \ +is no longer waiting ! Error = %s\n", strerror(errno) )); + CatchChild(); return(False); } + /* + * Go back to ignoring children. + */ + CatchChild(); + if (child_pid != wpid) { DEBUG(0,("check_access_allowed_for_current_user: We were waiting for the wrong process ID\n")); return(False); @@ -245,7 +277,7 @@ static BOOL check_access_allowed_for_current_user(struct connection_struct */ 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(conn, fname, accmode, 0)) < 0) { + if((fd = fd_attempt_open( fname, accmode, 0)) < 0) { /* Access denied. */ _exit(EACCES); } @@ -260,11 +292,12 @@ static BOOL check_access_allowed_for_current_user(struct connection_struct /**************************************************************************** check a filename for the pipe string ****************************************************************************/ + static void check_for_pipe(char *fname) { /* special case of pipe opens */ char s[10]; - StrnCpy(s,fname,9); + StrnCpy(s,fname,sizeof(s)-1); strlower(s); if (strstr(s,"pipe/")) { DEBUG(3,("Rejecting named pipe open for %s\n",fname)); @@ -276,6 +309,7 @@ static void check_for_pipe(char *fname) /**************************************************************************** open a file ****************************************************************************/ + static void open_file(files_struct *fsp,connection_struct *conn, char *fname1,int flags,mode_t mode, SMB_STRUCT_STAT *sbuf) { @@ -287,7 +321,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, fsp->open = False; fsp->fd_ptr = 0; - fsp->granted_oplock = False; + fsp->oplock_type = NO_OPLOCK; errno = EPERM; pstrcpy(fname,fname1); @@ -304,7 +338,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, * JRA. */ - if (conn->read_only && !conn->printer) { + if (!CAN_WRITE(conn) && !conn->printer) { /* It's a read-only share - fail if we wanted to write. */ if(accmode != O_RDONLY) { DEBUG(3,("Permission denied opening %s\n",fname)); @@ -335,7 +369,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, * open fd table. */ if(sbuf == 0) { - if(conn->vfs_ops.stat(dos_to_unix(fname,False), &statbuf) < 0) { + if(dos_stat(fname, &statbuf) < 0) { if(errno != ENOENT) { DEBUG(3,("Error doing stat on file %s (%s)\n", fname,strerror(errno))); @@ -376,7 +410,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, */ if(!fd_is_in_uid_cache(fd_ptr, (uid_t)current_user.uid)) { - if(!check_access_allowed_for_current_user(conn, fname, accmode )) { + if(!check_access_allowed_for_current_user( fname, accmode )) { /* Error - permission denied. */ DEBUG(3,("Permission denied opening file %s (flags=%d, accmode = %d)\n", fname, flags, accmode)); @@ -433,7 +467,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, 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(conn, fname, open_flags|O_RDWR, mode); + fd_ptr->fd = fd_attempt_open(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. @@ -444,7 +478,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, if((fd_ptr->fd == -1) && (errno == EACCES)) { #endif /* EROFS */ if(accmode != O_RDWR) { - fd_ptr->fd = fd_attempt_open(conn, fname, open_flags|accmode, mode); + fd_ptr->fd = fd_attempt_open(fname, open_flags|accmode, mode); fd_ptr->real_open_flags = accmode; } } @@ -458,10 +492,10 @@ static void open_file(files_struct *fsp,connection_struct *conn, pstrcpy(dname,fname); p = strrchr(dname,'/'); if (p) *p = 0; - 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); + if (sys_disk_free(dname,False,&dum1,&dum2,&dum3) < (SMB_BIG_UINT)lp_minprintspace(SNUM(conn))) { + int err; + if(fd_attempt_close(fd_ptr, &err) == 0) + dos_unlink(fname); fsp->fd_ptr = 0; errno = ENOSPC; return; @@ -470,10 +504,11 @@ static void open_file(files_struct *fsp,connection_struct *conn, if (fd_ptr->fd < 0) { + int err; DEBUG(3,("Error opening file %s (%s) (flags=%d)\n", fname,strerror(errno),flags)); /* Ensure the ref_count is decremented. */ - fd_attempt_close(fsp); + fd_attempt_close(fd_ptr,&err); check_for_pipe(fname); return; } @@ -482,12 +517,13 @@ static void open_file(files_struct *fsp,connection_struct *conn, { if(sbuf == 0) { /* Do the fstat */ - if(conn->vfs_ops.fstat(fd_ptr->fd, &statbuf) == -1) { + if(sys_fstat(fd_ptr->fd, &statbuf) == -1) { + int err; /* 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(fsp); + fd_attempt_close(fd_ptr,&err); return; } sbuf = &statbuf; @@ -505,17 +541,17 @@ static void open_file(files_struct *fsp,connection_struct *conn, fsp->size = 0; fsp->pos = -1; fsp->open = True; - fsp->mmap_ptr = NULL; - fsp->mmap_size = 0; 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 = conn->printer; fsp->modified = False; - fsp->granted_oplock = False; - fsp->sent_oplock_break = 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 @@ -526,6 +562,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, */ string_set(&fsp->fsp_name,fname); fsp->wbmpx_ptr = NULL; + fsp->wcp = NULL; /* Write cache pointer. */ /* * If the printer is marked as postscript output a leading @@ -536,7 +573,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, */ if (fsp->print_file && lp_postscript(SNUM(conn)) && fsp->can_write) { DEBUG(3,("Writing postscript line\n")); - conn->vfs_ops.write(fsp->fd_ptr->fd,"%!\n",3); + write_file(fsp,"%!\n",-1,3); } DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n", @@ -547,40 +584,12 @@ static void open_file(files_struct *fsp,connection_struct *conn, } } -/**************************************************************************** - 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 = 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. Truncate a file after checking locking; close file if locked. **************************************************************************/ + static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, int token, BOOL *share_locked) { @@ -606,19 +615,19 @@ static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, i } } - 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) + pid_t 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(); + pid_t pid = getpid(); if (old_deny == new_deny && share_pid == pid) return(AALL); @@ -660,10 +669,10 @@ static int access_table(int new_deny,int old_deny,int old_mode, 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) @@ -707,7 +716,7 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, { 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)); + (int)share->pid,fname, fcbopen, *flags, access_allowed)); unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadshare; @@ -726,34 +735,39 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, 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, - mode_t 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 = 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, dos_to_unix(fname,False), &sbuf); + BOOL file_existed = dos_file_exist(fname,&sbuf); BOOL share_locked = False; BOOL fcbopen = False; - int token; + int token = 0; SMB_DEV_T dev = 0; SMB_INO_T inode = 0; int num_share_modes = 0; - + int oplock_contention_count = 0; + BOOL all_current_opens_are_level_II = False; 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 )); + + /* ignore any oplock requests if oplocks are disabled */ + if (!lp_oplocks(SNUM(conn)) || global_client_failed_oplock_break) { + oplock_request = 0; + } + /* this is for OS/2 EAs - try and say we don't support them */ if (strstr(fname,".+,;=[].")) { @@ -861,6 +875,8 @@ void open_file_shared(files_struct *fsp, connection_struct *conn, { broke_oplock = False; + all_current_opens_are_level_II = True; + for(i = 0; i < num_share_modes; i++) { share_mode_entry *share_entry = &old_shares[i]; @@ -872,7 +888,8 @@ void open_file_shared(files_struct *fsp, connection_struct *conn, * Check if someone has an oplock on this file. If so we must break * it before continuing. */ - if(share_entry->op_type & (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) + if((oplock_request && EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type)) || + (!oplock_request && (share_entry->op_type != NO_OPLOCK))) { DEBUG(5,("open_file_shared: breaking oplock (%x) on file %s, \ @@ -894,7 +911,10 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou } lock_share_entry(conn, dev, inode, &token); broke_oplock = True; + all_current_opens_are_level_II = False; break; + } else if (!LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) { + all_current_opens_are_level_II = False; } /* someone else has a share lock on it, check to see @@ -913,6 +933,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou { free((char *)old_shares); num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); + oplock_contention_count++; } } while(broke_oplock); } @@ -921,6 +942,18 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou free((char *)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))) + { + oplock_request = 0; + DEBUG(4,("open_file_shared: oplock contention = %d. Not granting oplock.\n", + oplock_contention_count )); + } + DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", flags,flags2,(int)mode)); @@ -978,18 +1011,19 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou { 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). */ + /* + * Setup the oplock info in both the shared memory and + * file structs. + */ - if((oplock_request) && (num_share_modes == 0) && lp_oplocks(SNUM(conn)) && - !IS_VETO_OPLOCK_PATH(conn,fname) && set_file_oplock(fsp) ) - { + if(oplock_request && (num_share_modes == 0) && + !IS_VETO_OPLOCK_PATH(conn,fname) && set_file_oplock(fsp, oplock_request) ) { port = global_oplock_port; - } - else - { + } else if (oplock_request && all_current_opens_are_level_II) { + port = global_oplock_port; + oplock_request = LEVEL_II_OPLOCK; + set_file_oplock(fsp, oplock_request); + } else { port = 0; oplock_request = 0; } @@ -999,19 +1033,75 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou 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 file for permissions read only. Return a pseudo file entry + with the 'stat_open' flag set and a fd_ptr of NULL. +****************************************************************************/ + +int open_file_stat(files_struct *fsp,connection_struct *conn, + char *fname, int smb_ofun, SMB_STRUCT_STAT *pst, int *action) +{ + extern struct current_user current_user; + + if(dos_stat(fname, pst) < 0) { + DEBUG(0,("open_file_stat: unable to stat name = %s. Error was %s\n", + fname, strerror(errno) )); + return -1; + } + + if(S_ISDIR(pst->st_mode)) { + DEBUG(0,("open_file_stat: %s is a directory !\n", fname )); + return -1; + } + + *action = FILE_WAS_OPENED; + + DEBUG(5,("open_file_stat: opening file %s as a stat entry\n", fname)); + + /* + * Setup the files_struct for it. + */ + + fsp->fd_ptr = NULL; + conn->num_files_open++; + fsp->mode = 0; + GetTimeOfDay(&fsp->open_time); + fsp->vuid = current_user.vuid; + fsp->size = 0; + fsp->pos = -1; + fsp->open = True; + fsp->can_lock = False; + fsp->can_read = False; + fsp->can_write = False; + 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 = True; + 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. */ + + return 0; +} + /**************************************************************************** Open a directory from an NT SMB call. ****************************************************************************/ @@ -1021,26 +1111,55 @@ int open_directory(files_struct *fsp,connection_struct *conn, { extern struct current_user current_user; SMB_STRUCT_STAT st; + BOOL got_stat = False; - if (smb_ofun & 0x10) { - /* - * Create the directory. - */ + if(dos_stat(fname, &st) == 0) { + got_stat = True; + } - 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; - } + if (got_stat && (GET_FILE_OPEN_DISPOSITION(smb_ofun) == FILE_EXISTS_FAIL)) { + errno = EEXIST; /* Setup so correct error is returned to client. */ + return -1; + } + + if (GET_FILE_CREATE_DISPOSITION(smb_ofun) == FILE_CREATE_IF_NOT_EXIST) { + + if (got_stat) { + + if(!S_ISDIR(st.st_mode)) { + DEBUG(0,("open_directory: %s is not a directory !\n", fname )); + errno = EACCES; + return -1; + } + *action = FILE_WAS_OPENED; + + } else { + + /* + * Try and create the directory. + */ + + if(!CAN_WRITE(conn)) { + DEBUG(2,("open_directory: failing create on read-only share\n")); + errno = EACCES; + return -1; + } - *action = FILE_WAS_CREATED; + if(dos_mkdir(fname, unix_mode(conn,aDIR)) < 0) { + DEBUG(0,("open_directory: unable to create %s. Error was %s\n", + fname, strerror(errno) )); + return -1; + } + *action = FILE_WAS_CREATED; + + } } else { + /* - * Check that it *was* a directory. + * Don't create - just check that it *was* a directory. */ - if(conn->vfs_ops.stat(dos_to_unix(fname,False), &st) < 0) { + if(!got_stat) { DEBUG(0,("open_directory: unable to stat name = %s. Error was %s\n", fname, strerror(errno) )); return -1; @@ -1050,6 +1169,7 @@ int open_directory(files_struct *fsp,connection_struct *conn, DEBUG(0,("open_directory: %s is not a directory !\n", fname )); return -1; } + *action = FILE_WAS_OPENED; } @@ -1068,17 +1188,16 @@ int open_directory(files_struct *fsp,connection_struct *conn, fsp->size = 0; fsp->pos = -1; fsp->open = True; - fsp->mmap_ptr = NULL; - fsp->mmap_size = 0; fsp->can_lock = True; fsp->can_read = False; fsp->can_write = False; fsp->share_mode = 0; fsp->print_file = False; fsp->modified = False; - fsp->granted_oplock = False; - fsp->sent_oplock_break = False; + fsp->oplock_type = NO_OPLOCK; + fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = True; + fsp->directory_delete_on_close = False; fsp->conn = conn; /* * Note that the file name here is the *untranslated* name @@ -1093,10 +1212,9 @@ int open_directory(files_struct *fsp,connection_struct *conn, return 0; } - /******************************************************************* -check if the share mode on a file allows it to be deleted or unlinked -return True if sharing doesn't prevent the operation + 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) @@ -1107,14 +1225,14 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) int num_share_modes; SMB_STRUCT_STAT sbuf; int token; - int pid = getpid(); + pid_t pid = getpid(); SMB_DEV_T dev; SMB_INO_T inode; if(!lp_share_modes(SNUM(conn))) return True; - if (conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf) == -1) return(True); + if (dos_stat(fname,&sbuf) == -1) return(True); dev = sbuf.st_dev; inode = sbuf.st_ino; @@ -1144,9 +1262,16 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) * Check if someone has an oplock on this file. If so we must * break it before continuing. */ - if(share_entry->op_type & BATCH_OPLOCK) + if(BATCH_OPLOCK_TYPE(share_entry->op_type)) { +#if 0 + +/* JRA. Try removing this code to see if the new oplock changes + fix the problem. I'm dubious, but Andrew is recommending we + try this.... +*/ + /* * It appears that the NT redirector may have a bug, in that * it tries to do an SMBmv on a file that it has open with a @@ -1176,6 +1301,7 @@ batch oplocked file %s, dev = %x, inode = %.0f\n", fname, (unsigned int)dev, (do continue; } else +#endif /* 0 */ { DEBUG(5,("check_file_sharing: breaking oplock (%x) on file %s, \ -- cgit From 4e1291a83f61a72989045879763d9ef05fd38f71 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 21 Dec 1999 09:25:59 +0000 Subject: converted all our existing shared memory code to use a tdb database instead of either sysv or mmap shared memory or lock files. this means we can now completely remove locking_shm.c locking_slow.c shmem.c shmem_sysv.c and lots of other things also got simpler locking.c got a bit larger, but is much better compartmentalised now (This used to be commit e48c2d9937eea0667b8cd3332e49c06314ef31e7) --- source3/smbd/open.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 4491082b2c..a940eda85d 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -602,7 +602,7 @@ static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, i 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); + fsp->fd_ptr->inode); close_file(fsp,False); /* Share mode no longer locked. */ *share_locked = False; @@ -858,9 +858,9 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int { dev = sbuf.st_dev; inode = sbuf.st_ino; - lock_share_entry(conn, dev, inode, &token); + lock_share_entry(conn, dev, inode); share_locked = True; - num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); + num_share_modes = get_share_modes(conn, dev, inode, &old_shares); } /* @@ -896,7 +896,7 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int dev = %x, inode = %.0f\n", share_entry->op_type, fname, (unsigned int)dev, (double)inode)); /* Oplock break.... */ - unlock_share_entry(conn, dev, inode, token); + unlock_share_entry(conn, dev, inode); if(request_oplock_break(share_entry, dev, inode) == False) { free((char *)old_shares); @@ -909,7 +909,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou unix_ERR_code = ERRbadshare; return; } - lock_share_entry(conn, dev, inode, &token); + lock_share_entry(conn, dev, inode); broke_oplock = True; all_current_opens_are_level_II = False; break; @@ -922,7 +922,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou if(check_share_mode(share_entry, deny_mode, fname, fcbopen, &flags) == False) { free((char *)old_shares); - unlock_share_entry(conn, dev, inode, token); + unlock_share_entry(conn, dev, inode); errno = EACCES; return; } @@ -932,7 +932,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou if(broke_oplock) { free((char *)old_shares); - num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); + num_share_modes = get_share_modes(conn, dev, inode, &old_shares); oplock_contention_count++; } } while(broke_oplock); @@ -973,7 +973,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou /* We created the file - thus we must now lock the share entry before creating it. */ dev = fsp->fd_ptr->dev; inode = fsp->fd_ptr->inode; - lock_share_entry(conn, dev, inode, &token); + lock_share_entry(conn, dev, inode); share_locked = True; } @@ -1028,7 +1028,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou oplock_request = 0; } - set_share_mode(token, fsp, port, oplock_request); + set_share_mode(fsp, port, oplock_request); } if ((flags2&O_TRUNC) && file_existed) @@ -1036,7 +1036,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou } if (share_locked && lp_share_modes(SNUM(conn))) - unlock_share_entry( conn, dev, inode, token); + unlock_share_entry( conn, dev, inode); } /**************************************************************************** @@ -1224,7 +1224,6 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) share_mode_entry *old_shares = 0; int num_share_modes; SMB_STRUCT_STAT sbuf; - int token; pid_t pid = getpid(); SMB_DEV_T dev; SMB_INO_T inode; @@ -1237,8 +1236,8 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) dev = sbuf.st_dev; inode = sbuf.st_ino; - lock_share_entry(conn, dev, inode, &token); - num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); + lock_share_entry(conn, dev, inode); + num_share_modes = get_share_modes(conn, dev, inode, &old_shares); /* * Check if the share modes will give us access. @@ -1308,7 +1307,7 @@ batch oplocked file %s, dev = %x, inode = %.0f\n", fname, (unsigned int)dev, (do dev = %x, inode = %.0f\n", share_entry->op_type, fname, (unsigned int)dev, (double)inode)); /* Oplock break.... */ - unlock_share_entry(conn, dev, inode, token); + unlock_share_entry(conn, dev, inode); if(request_oplock_break(share_entry, dev, inode) == False) { free((char *)old_shares); @@ -1318,7 +1317,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou return False; } - lock_share_entry(conn, dev, inode, &token); + lock_share_entry(conn, dev, inode); broke_oplock = True; break; } @@ -1345,7 +1344,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou if(broke_oplock) { free((char *)old_shares); - num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); + num_share_modes = get_share_modes(conn, dev, inode, &old_shares); } } while(broke_oplock); } @@ -1364,7 +1363,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou free_and_exit: - unlock_share_entry(conn, dev, inode, token); + unlock_share_entry(conn, dev, inode); if(old_shares != NULL) free((char *)old_shares); return(ret); -- cgit From faa302c7688eeb03f543d6dac817b5a80753a9f5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 8 Jan 2000 01:23:13 +0000 Subject: Fixed deny mode bug : : If a file is resident on NT and the first user opens it read/write with DENY_READ then a subsequent : attempt by a second user (running under Windows 95) to open it read/write DENY_NONE fails. : Under samba 2.0.5a the second open succeeds but the file is write only. Jeremy. (This used to be commit 974af581fe428fd0233c2516b16a5132b0e1b583) --- source3/smbd/open.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index a940eda85d..2e4f54e40f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -631,7 +631,7 @@ static int access_table(int new_deny,int old_deny,int old_mode, if (old_deny == new_deny && share_pid == pid) return(AALL); - if (old_mode == 0) return(AREAD); + if (old_mode == DOS_OPEN_RDONLY) 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 @@ -651,14 +651,14 @@ static int access_table(int new_deny,int old_deny,int old_mode, 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); + if (old_deny==DENY_WRITE && old_mode==DOS_OPEN_RDONLY) return(AREAD); + if (old_deny==DENY_READ && old_mode==DOS_OPEN_RDONLY) return(AWRITE); + if (old_deny==DENY_NONE && old_mode==DOS_OPEN_RDONLY) 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); + if (old_deny==DENY_WRITE && old_mode==DOS_OPEN_WRONLY) return(AREAD); + if (old_deny==DENY_READ && old_mode==DOS_OPEN_WRONLY) return(AWRITE); + if (old_deny==DENY_NONE && old_mode==DOS_OPEN_WRONLY) return(AALL); return(AFAIL); case DENY_NONE: if (old_deny==DENY_WRITE) return(AREAD); @@ -711,8 +711,8 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, if ((access_allowed == AFAIL) || (!fcbopen && (access_allowed == AREAD && *flags == O_RDWR)) || - (access_allowed == AREAD && *flags == O_WRONLY) || - (access_allowed == AWRITE && *flags == O_RDONLY)) + (access_allowed == AREAD && *flags != O_RDONLY) || + (access_allowed == AWRITE && *flags != O_WRONLY)) { 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, -- cgit From f2fc3a2dca56fcca71e0b677625d3cdb7946d5c1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 8 Jan 2000 11:32:00 +0000 Subject: fix a error in access_table revealed by the new deny test in smbtorture. We now exactly match NT for normal files. We still don't match for *.exe files though (This used to be commit 3f7fea58e8da6d98acadaabf0498ea2e88ea5678) --- source3/smbd/open.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 2e4f54e40f..57f90b78b4 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -631,8 +631,6 @@ static int access_table(int new_deny,int old_deny,int old_mode, if (old_deny == new_deny && share_pid == pid) return(AALL); - if (old_mode == DOS_OPEN_RDONLY) 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 @@ -645,6 +643,10 @@ static int access_table(int new_deny,int old_deny,int old_mode, return(AREAD); } + if (old_deny == DENY_READ || new_deny == DENY_READ) return AFAIL; + if (old_mode == DOS_OPEN_RDONLY) return(AREAD); + + return(AFAIL); } @@ -707,7 +709,7 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, { int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode, - share->pid,fname); + share->pid,fname); if ((access_allowed == AFAIL) || (!fcbopen && (access_allowed == AREAD && *flags == O_RDWR)) || -- cgit From 826446ddef1ef0f462c02932d11e3713f00497c7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 13 Jan 2000 12:10:48 +0000 Subject: changes to reflect the new syntax of the locking calls. (This used to be commit 44117df2c908d473b3e1a1020b22af6d584809ef) --- source3/smbd/open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 57f90b78b4..88de1db151 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -597,7 +597,7 @@ static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, i 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 (is_locked(fsp,conn,~mask,0,WRITE_LOCK)){ /* 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))) @@ -640,7 +640,7 @@ static int access_table(int new_deny,int old_deny,int old_mode, strequal(fname,".dll") || strequal(fname,".exe") || strequal(fname,".sym")) - return(AREAD); + return(AALL); } if (old_deny == DENY_READ || new_deny == DENY_READ) return AFAIL; -- cgit From 3a6c2069d77176bfa2b379ef711034396c477791 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 14 Jan 2000 01:41:04 +0000 Subject: Added "inherit permissions" patch. Fixed locking bug found by Andrew. Jeremy. (This used to be commit 38dffd360dc2e44bfc9e751f017e24f81ff0f2fa) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 88de1db151..ad208005a0 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1147,7 +1147,7 @@ int open_directory(files_struct *fsp,connection_struct *conn, return -1; } - if(dos_mkdir(fname, unix_mode(conn,aDIR)) < 0) { + if(dos_mkdir(fname, unix_mode(conn,aDIR, fname)) < 0) { DEBUG(0,("open_directory: unable to create %s. Error was %s\n", fname, strerror(errno) )); return -1; -- cgit From 2d96e58287a89d6f2cf584ada6154eca83cf1e6b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 16 Jan 2000 11:21:33 +0000 Subject: rewrote the access_table() code to get it right for *.exe, *.dll, *.sym and *.com files. I still find it incredible that SMB treats file locking differently depending on the file name - that is so ugly it stinks. anyway, we now behave the same way as NT, except for the same-connection case which I'm still working on. (This used to be commit 5b9be3feca26f1f20fe3f32ba90769cc78f9bb6b) --- source3/smbd/open.c | 68 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 27 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index ad208005a0..7558954ec6 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -620,34 +620,50 @@ enum {AFAIL,AREAD,AWRITE,AALL}; /******************************************************************* reproduce the share mode access table ********************************************************************/ - static int access_table(int new_deny,int old_deny,int old_mode, pid_t share_pid,char *fname) { if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL); - if (new_deny == DENY_DOS || old_deny == DENY_DOS) { - pid_t pid = getpid(); - if (old_deny == new_deny && share_pid == pid) - return(AALL); - - /* 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(AALL); - } - - if (old_deny == DENY_READ || new_deny == DENY_READ) return AFAIL; - if (old_mode == DOS_OPEN_RDONLY) return(AREAD); - - - return(AFAIL); + if (old_deny == DENY_DOS || new_deny == DENY_DOS || + old_deny == DENY_FCB || new_deny == DENY_FCB) { + if ((fname = strrchr(fname,'.'))) { + if (strequal(fname,".com") || + strequal(fname,".dll") || + strequal(fname,".exe") || + strequal(fname,".sym")) { + if (old_deny == DENY_FCB || new_deny == DENY_FCB) { + return AFAIL; + } + if (old_deny == DENY_DOS) { + if (new_deny == DENY_READ && + (old_mode == DOS_OPEN_RDONLY || + old_mode == DOS_OPEN_RDWR)) { + return AFAIL; + } + if (new_deny == DENY_WRITE && + (old_mode == DOS_OPEN_WRONLY || + old_mode == DOS_OPEN_RDWR)) { + return AFAIL; + } + return AALL; + } + if (old_deny == DENY_NONE) return AALL; + if (old_deny == DENY_READ) return AWRITE; + if (old_deny == DENY_WRITE) return AREAD; + } + } + /* it isn't a exe, dll, sym or com file */ + { + pid_t pid = getpid(); + if (old_deny == new_deny && share_pid == pid) + return(AALL); + + if (old_deny == DENY_READ || new_deny == DENY_READ) return AFAIL; + if (old_mode == DOS_OPEN_RDONLY) return(AREAD); + + return(AFAIL); + } } switch (new_deny) @@ -848,9 +864,6 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int return; } - if (deny_mode == DENY_FCB) - deny_mode = DENY_DOS; - if (lp_share_modes(SNUM(conn))) { int i; @@ -1338,7 +1351,8 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou * if we can too. */ - if ((GET_DENY_MODE(share_entry->share_mode) != DENY_DOS) || (share_entry->pid != pid)) + if ((GET_DENY_MODE(share_entry->share_mode) != DENY_DOS) || + (share_entry->pid != pid)) goto free_and_exit; } /* end for */ -- cgit From 446f2aef8326f41a0f56c9f2d8229413a61f1d81 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 16 Jan 2000 12:26:42 +0000 Subject: as obelix would say "these romans are crazy" I've finally got the access table code right for the case where the two opens are on the same connection. It is _incredibly_ complex, but now all 1296 test cases pass. I'll be very surprised if anyone by MS and us gets this right at CIFS2000 (This used to be commit 31a5857ce4f03eb53ff8ea96c5f1ce335941336d) --- source3/smbd/open.c | 99 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 59 insertions(+), 40 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 7558954ec6..d0a48ced4b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -623,15 +623,49 @@ reproduce the share mode access table static int access_table(int new_deny,int old_deny,int old_mode, pid_t share_pid,char *fname) { - if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL); - - if (old_deny == DENY_DOS || new_deny == DENY_DOS || - old_deny == DENY_FCB || new_deny == DENY_FCB) { + pid_t pid = getpid(); + BOOL isexe = False; + if ((fname = strrchr(fname,'.'))) { if (strequal(fname,".com") || strequal(fname,".dll") || strequal(fname,".exe") || strequal(fname,".sym")) { + isexe = True; + } + } + + if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL); + + if (share_pid == pid) { + if (isexe && old_mode == O_RDONLY && + old_deny == DENY_DOS && new_deny == DENY_READ) { + return AFAIL; + } + if (!isexe && old_mode == O_RDONLY && + old_deny == DENY_DOS && new_deny == DENY_DOS) { + return AREAD; + } + if (new_deny == DENY_FCB && old_deny == DENY_DOS) { + if (isexe) return AFAIL; + if (old_mode == DOS_OPEN_RDONLY) return AFAIL; + return AALL; + } + if (old_mode == O_RDONLY && old_deny == DENY_DOS) { + if (new_deny == DENY_FCB || new_deny == DENY_READ) { + if (isexe) return AREAD; + return AFAIL; + } + } + if (old_deny == DENY_FCB) { + if (new_deny == DENY_DOS || new_deny == DENY_FCB) return AALL; + return AFAIL; + } + } + + if (old_deny == DENY_DOS || new_deny == DENY_DOS || + old_deny == DENY_FCB || new_deny == DENY_FCB) { + if (isexe) { if (old_deny == DENY_FCB || new_deny == DENY_FCB) { return AFAIL; } @@ -652,10 +686,7 @@ static int access_table(int new_deny,int old_deny,int old_mode, if (old_deny == DENY_READ) return AWRITE; if (old_deny == DENY_WRITE) return AREAD; } - } - /* it isn't a exe, dll, sym or com file */ - { - pid_t pid = getpid(); + /* it isn't a exe, dll, sym or com file */ if (old_deny == new_deny && share_pid == pid) return(AALL); @@ -664,27 +695,26 @@ static int access_table(int new_deny,int old_deny,int old_mode, return(AFAIL); } - } - - switch (new_deny) - { - case DENY_WRITE: - if (old_deny==DENY_WRITE && old_mode==DOS_OPEN_RDONLY) return(AREAD); - if (old_deny==DENY_READ && old_mode==DOS_OPEN_RDONLY) return(AWRITE); - if (old_deny==DENY_NONE && old_mode==DOS_OPEN_RDONLY) return(AALL); - return(AFAIL); - case DENY_READ: - if (old_deny==DENY_WRITE && old_mode==DOS_OPEN_WRONLY) return(AREAD); - if (old_deny==DENY_READ && old_mode==DOS_OPEN_WRONLY) return(AWRITE); - if (old_deny==DENY_NONE && old_mode==DOS_OPEN_WRONLY) 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); + + switch (new_deny) + { + case DENY_WRITE: + if (old_deny==DENY_WRITE && old_mode==DOS_OPEN_RDONLY) return(AREAD); + if (old_deny==DENY_READ && old_mode==DOS_OPEN_RDONLY) return(AWRITE); + if (old_deny==DENY_NONE && old_mode==DOS_OPEN_RDONLY) return(AALL); + return(AFAIL); + case DENY_READ: + if (old_deny==DENY_WRITE && old_mode==DOS_OPEN_WRONLY) return(AREAD); + if (old_deny==DENY_READ && old_mode==DOS_OPEN_WRONLY) return(AWRITE); + if (old_deny==DENY_NONE && old_mode==DOS_OPEN_WRONLY) 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); } /**************************************************************************** @@ -712,17 +742,6 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, 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); -- cgit From 62b02ca2e277e45a5b0377710dfa5f13ae58f0b6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 16 Jan 2000 12:53:12 +0000 Subject: made access_table() a pure logic function - makes it simpler to apply maths to (This used to be commit 0ad62f128d1c26b8f7e71bc045c6f4a584f8d374) --- source3/smbd/open.c | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index d0a48ced4b..8a30f5e5c3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -615,29 +615,38 @@ static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, i } } + +/******************************************************************* +return True if the filename is one of the special executable types +********************************************************************/ +static BOOL is_executable(char *fname) +{ + if ((fname = strrchr(fname,'.'))) { + if (strequal(fname,".com") || + strequal(fname,".dll") || + strequal(fname,".exe") || + strequal(fname,".sym")) { + return True; + } + } + return False; +} + enum {AFAIL,AREAD,AWRITE,AALL}; /******************************************************************* reproduce the share mode access table +this is horrendoously complex, and really can't be justified on any +rational grounds except that this is _exactly_ what NT does. See +the DENY1 and DENY2 tests in smbtorture for a comprehensive set of +test routines. ********************************************************************/ static int access_table(int new_deny,int old_deny,int old_mode, - pid_t share_pid,char *fname) + BOOL same_pid, BOOL isexe) { - pid_t pid = getpid(); - BOOL isexe = False; - - if ((fname = strrchr(fname,'.'))) { - if (strequal(fname,".com") || - strequal(fname,".dll") || - strequal(fname,".exe") || - strequal(fname,".sym")) { - isexe = True; - } - } - if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL); - if (share_pid == pid) { + if (same_pid) { if (isexe && old_mode == O_RDONLY && old_deny == DENY_DOS && new_deny == DENY_READ) { return AFAIL; @@ -687,7 +696,7 @@ static int access_table(int new_deny,int old_deny,int old_mode, if (old_deny == DENY_WRITE) return AREAD; } /* it isn't a exe, dll, sym or com file */ - if (old_deny == new_deny && share_pid == pid) + if (old_deny == new_deny && same_pid) return(AALL); if (old_deny == DENY_READ || new_deny == DENY_READ) return AFAIL; @@ -717,6 +726,7 @@ static int access_table(int new_deny,int old_deny,int old_mode, return(AFAIL); } + /**************************************************************************** check if we can open a file with a share mode ****************************************************************************/ @@ -744,7 +754,7 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, { int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode, - share->pid,fname); + (share->pid == getpid()),is_executable(fname)); if ((access_allowed == AFAIL) || (!fcbopen && (access_allowed == AREAD && *flags == O_RDWR)) || -- cgit From 4e15be9cf1378149688f7a2744c1fe36a7f54f7e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 16 Jan 2000 13:17:05 +0000 Subject: fixed some typos in access_table() which, amaziingly enough, make no difference to the result. (This used to be commit 9e28b7220bc293e386fec30c2d2e7e401b61b1f7) --- source3/smbd/open.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 8a30f5e5c3..57fbdb24c4 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -647,11 +647,11 @@ static int access_table(int new_deny,int old_deny,int old_mode, if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL); if (same_pid) { - if (isexe && old_mode == O_RDONLY && + if (isexe && old_mode == DOS_OPEN_RDONLY && old_deny == DENY_DOS && new_deny == DENY_READ) { return AFAIL; } - if (!isexe && old_mode == O_RDONLY && + if (!isexe && old_mode == DOS_OPEN_RDONLY && old_deny == DENY_DOS && new_deny == DENY_DOS) { return AREAD; } @@ -660,7 +660,7 @@ static int access_table(int new_deny,int old_deny,int old_mode, if (old_mode == DOS_OPEN_RDONLY) return AFAIL; return AALL; } - if (old_mode == O_RDONLY && old_deny == DENY_DOS) { + if (old_mode == DOS_OPEN_RDONLY && old_deny == DENY_DOS) { if (new_deny == DENY_FCB || new_deny == DENY_READ) { if (isexe) return AREAD; return AFAIL; -- cgit From 16bb009dbbe6302febf3848cee61e9927eeb0fb5 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 3 Feb 2000 05:17:25 +0000 Subject: Mega-VFS merge. Yeah baby! Synopsis: change every disk access function to work through a vfs_ops structure contained in the connection_struct. (This used to be commit 3aad500c0fb61232ed3431ff4b743b5d18ec852f) --- source3/smbd/open.c | 71 ++++++++++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 34 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 57fbdb24c4..1b4179da33 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -30,17 +30,17 @@ extern BOOL global_client_failed_oplock_break; /**************************************************************************** fd support routines - attempt to do a dos_open ****************************************************************************/ - -static int fd_attempt_open(char *fname, int flags, mode_t 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)) @@ -71,7 +71,7 @@ static int fd_attempt_open(char *fname, int flags, mode_t mode) 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; } } @@ -128,9 +128,10 @@ 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, mode_t mode, file_fd_struct *fd_ptr) +static void fd_attempt_reopen(char *fname, mode_t mode, files_struct *fsp) { - int fd = dos_open( fname, O_RDWR, mode); + int fd = fsp->conn->vfs_ops.open(dos_to_unix(fname, False), O_RDWR, mode); + file_fd_struct *fd_ptr = fsp->fd_ptr; if(fd == -1) return; @@ -148,10 +149,10 @@ static void fd_attempt_reopen(char *fname, mode_t mode, file_fd_struct *fd_ptr) fd support routines - attempt to close the file referenced by this fd. Decrements the ref_count and returns it. ****************************************************************************/ - -uint16 fd_attempt_close(file_fd_struct *fd_ptr, int *err_ret) +uint16 fd_attempt_close(files_struct *fsp, int *err_ret) { extern struct current_user current_user; + file_fd_struct *fd_ptr = fsp->fd_ptr; uint16 ret_ref = fd_ptr->ref_count; *err_ret = 0; @@ -169,19 +170,19 @@ uint16 fd_attempt_close(file_fd_struct *fd_ptr, int *err_ret) if(fd_ptr->ref_count == 0) { if(fd_ptr->fd != -1) { - if(close(fd_ptr->fd) < 0) + if(fsp->conn->vfs_ops.close(fd_ptr->fd) < 0) *err_ret = errno; } if(fd_ptr->fd_readonly != -1) { - if(close(fd_ptr->fd_readonly) < 0) { + if(fsp->conn->vfs_ops.close(fd_ptr->fd_readonly) < 0) { if(*err_ret == 0) *err_ret = errno; } } if(fd_ptr->fd_writeonly != -1) { - if( close(fd_ptr->fd_writeonly) < 0) { + if(fsp->conn->vfs_ops.close(fd_ptr->fd_writeonly) < 0) { if(*err_ret == 0) *err_ret = errno; } @@ -205,8 +206,9 @@ This is really ugly code, as due to POSIX locking braindamage we must 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; @@ -277,11 +279,11 @@ is no longer waiting ! Error = %s\n", strerror(errno) )); */ 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); } - close(fd); + conn->vfs_ops.close(fd); DEBUG(9,("check_access_allowed_for_current_user: Child - returning ok.\n")); _exit(0); } @@ -369,7 +371,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, * 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))); @@ -410,7 +412,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, */ 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)); @@ -430,7 +432,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, * between the last open and now. */ if(fd_ptr->real_open_flags != O_RDWR) - fd_attempt_reopen(fname, mode, fd_ptr); + fd_attempt_reopen(fname, mode, fsp); /* * Ensure that if we wanted write access @@ -467,7 +469,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, 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. @@ -478,7 +480,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, 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; } } @@ -492,10 +494,11 @@ static void open_file(files_struct *fsp,connection_struct *conn, pstrcpy(dname,fname); p = strrchr(dname,'/'); if (p) *p = 0; - if (sys_disk_free(dname,False,&dum1,&dum2,&dum3) < (SMB_BIG_UINT)lp_minprintspace(SNUM(conn))) { + if (conn->vfs_ops.disk_free(dname,False,&dum1,&dum2,&dum3) < + (SMB_BIG_UINT)lp_minprintspace(SNUM(conn))) { int err; - if(fd_attempt_close(fd_ptr, &err) == 0) - dos_unlink(fname); + if(fd_attempt_close(fsp, &err) == 0) + conn->vfs_ops.unlink(dos_to_unix(fname, False)); fsp->fd_ptr = 0; errno = ENOSPC; return; @@ -508,7 +511,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, 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,&err); + fd_attempt_close(fsp,&err); check_for_pipe(fname); return; } @@ -517,13 +520,13 @@ static void open_file(files_struct *fsp,connection_struct *conn, { if(sbuf == 0) { /* Do the fstat */ - if(sys_fstat(fd_ptr->fd, &statbuf) == -1) { - int err; + if(conn->vfs_ops.fstat(fd_ptr->fd, &statbuf) == -1) { + int err; /* 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,&err); + fd_attempt_close(fsp,&err); return; } sbuf = &statbuf; @@ -573,7 +576,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, */ if (fsp->print_file && lp_postscript(SNUM(conn)) && fsp->can_write) { DEBUG(3,("Writing postscript line\n")); - write_file(fsp,"%!\n",-1,3); + conn->vfs_ops.write(fsp->fd_ptr->fd,"%!\n",3); } DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n", @@ -794,7 +797,7 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int 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 = dos_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 = 0; @@ -1093,7 +1096,7 @@ int open_file_stat(files_struct *fsp,connection_struct *conn, { extern struct current_user current_user; - if(dos_stat(fname, pst) < 0) { + 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) )); return -1; @@ -1157,7 +1160,7 @@ int open_directory(files_struct *fsp,connection_struct *conn, SMB_STRUCT_STAT st; BOOL got_stat = False; - if(dos_stat(fname, &st) == 0) { + if(conn->vfs_ops.stat(dos_to_unix(fname, False), &st) == 0) { got_stat = True; } @@ -1189,7 +1192,7 @@ int open_directory(files_struct *fsp,connection_struct *conn, return -1; } - if(dos_mkdir(fname, unix_mode(conn,aDIR, fname)) < 0) { + if(conn->vfs_ops.mkdir(dos_to_unix(fname, False), unix_mode(conn,aDIR, fname)) < 0) { DEBUG(0,("open_directory: unable to create %s. Error was %s\n", fname, strerror(errno) )); return -1; @@ -1275,7 +1278,7 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) 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; -- cgit From ae7696117e81bb469fa71f9bc880f6b5aac0724e Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 3 Feb 2000 23:08:24 +0000 Subject: Put back lots of missing calls to dos_to_unix(). Thanks to aono@cc.osaka-kyoiku.ac.jp (Tomoki AONO) (This used to be commit 176c405d2702a4245561ff56c8eac3c754a0dea3) --- source3/smbd/open.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 1b4179da33..30409707d3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -33,14 +33,14 @@ fd support routines - attempt to do a dos_open static int fd_attempt_open(struct connection_struct *conn, char *fname, int flags, mode_t mode) { - int fd = conn->vfs_ops.open(fname,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) && (strchr(fname,'.')==NULL)) { pstrcat(fname,"."); - fd = conn->vfs_ops.open(fname,flags,mode); + fd = conn->vfs_ops.open(dos_to_unix(fname,False),flags,mode); } #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF)) @@ -71,7 +71,7 @@ static int fd_attempt_open(struct connection_struct *conn, char *fname, char tmp = p[max_len]; p[max_len] = '\0'; - if ((fd = conn->vfs_ops.open(fname,flags,mode)) == -1) + if ((fd = conn->vfs_ops.open(dos_to_unix(fname,False),flags,mode)) == -1) p[max_len] = tmp; } } @@ -494,7 +494,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, pstrcpy(dname,fname); p = strrchr(dname,'/'); if (p) *p = 0; - if (conn->vfs_ops.disk_free(dname,False,&dum1,&dum2,&dum3) < + if (conn->vfs_ops.disk_free(dos_to_unix(dname,False),False,&dum1,&dum2,&dum3) < (SMB_BIG_UINT)lp_minprintspace(SNUM(conn))) { int err; if(fd_attempt_close(fsp, &err) == 0) @@ -797,7 +797,7 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int 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, dos_to_unix(fname,False), &sbuf); + BOOL file_existed = vfs_file_exist(conn, fname, &sbuf); BOOL share_locked = False; BOOL fcbopen = False; int token = 0; @@ -1192,7 +1192,8 @@ int open_directory(files_struct *fsp,connection_struct *conn, return -1; } - if(conn->vfs_ops.mkdir(dos_to_unix(fname, False), unix_mode(conn,aDIR, fname)) < 0) { + if(conn->vfs_ops.mkdir(dos_to_unix(fname, False), + unix_mode(conn,aDIR, fname)) < 0) { DEBUG(0,("open_directory: unable to create %s. Error was %s\n", fname, strerror(errno) )); return -1; -- cgit From 92bf37e21d63c0c9edede1617c85510a16011e7a Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 17 Feb 2000 23:22:26 +0000 Subject: Don't assume that the (files_struct *) passed to fd_attempt_close() will be non-NULL. (This used to be commit 02f845e54351ec57ee873a8ed887285552c6ecab) --- source3/smbd/open.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 30409707d3..6352233dbc 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -152,11 +152,18 @@ Decrements the ref_count and returns it. uint16 fd_attempt_close(files_struct *fsp, int *err_ret) { extern struct current_user current_user; - file_fd_struct *fd_ptr = fsp->fd_ptr; - uint16 ret_ref = fd_ptr->ref_count; + file_fd_struct *fd_ptr; + uint16 ret_ref; *err_ret = 0; + if ((fsp == NULL) || (fsp->fd_ptr == NULL)) { + return 0; + } + + fd_ptr = fsp->fd_ptr; + ret_ref = fd_ptr->ref_count; + 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, -- cgit From 689ec46450a3f373b583ebe98d124ab4a99ce3ef Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 10 Apr 2000 13:05:23 +0000 Subject: the bulk of the changes to get rid of fd_ptr and move print open handling to printing/printing.c most of this was just replacing things like fsp->fd_ptr->fd with fsp->fd the changes in open.c are quite dramatic. Most of it is removing all the functions that handled the fd multiplexing (This used to be commit d1827a3648009fd0a0d165055015d9aeda7a1037) --- source3/smbd/open.c | 650 ++++++++++------------------------------------------ 1 file changed, 116 insertions(+), 534 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 6352233dbc..4c5605fb3b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -30,274 +30,31 @@ extern BOOL global_client_failed_oplock_break; /**************************************************************************** fd support routines - attempt to do a dos_open ****************************************************************************/ -static int fd_attempt_open(struct connection_struct *conn, char *fname, - int flags, mode_t mode) +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 = conn->vfs_ops.open(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); - } - -#if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF)) - if ((fd == -1) && (errno == ENAMETOOLONG)) - { - int max_len; - char *p = strrchr(fname, '/'); - - if (p == fname) /* name is "/xxx" */ - { - max_len = pathconf("/", _PC_NAME_MAX); - p++; - } - else if ((p == NULL) || (p == fname)) - { - p = fname; - max_len = pathconf(".", _PC_NAME_MAX); - } - else - { - *p = '\0'; - max_len = pathconf(fname, _PC_NAME_MAX); - *p = '/'; - p++; - } - if (strlen(p) > max_len) - { - char tmp = p[max_len]; - - p[max_len] = '\0'; - if ((fd = conn->vfs_ops.open(dos_to_unix(fname,False),flags,mode)) == -1) - p[max_len] = tmp; - } - } -#endif - return fd; -} - -/**************************************************************************** -Cache a uid_t currently with this file open. This is an optimization only -used when multiple sessionsetup's have been done to one smbd. -****************************************************************************/ - -void fd_add_to_uid_cache(file_fd_struct *fd_ptr, uid_t u) -{ - if(fd_ptr->uid_cache_count >= sizeof(fd_ptr->uid_users_cache)/sizeof(uid_t)) - return; - fd_ptr->uid_users_cache[fd_ptr->uid_cache_count++] = u; -} - -/**************************************************************************** -Remove a uid_t that currently has this file open. This is an optimization only -used when multiple sessionsetup's have been done to one smbd. -****************************************************************************/ - -static void fd_remove_from_uid_cache(file_fd_struct *fd_ptr, uid_t u) -{ - int i; - for(i = 0; i < fd_ptr->uid_cache_count; i++) - if(fd_ptr->uid_users_cache[i] == u) { - if(i < (fd_ptr->uid_cache_count-1)) - memmove((char *)&fd_ptr->uid_users_cache[i], (char *)&fd_ptr->uid_users_cache[i+1], - sizeof(uid_t)*(fd_ptr->uid_cache_count-1-i) ); - fd_ptr->uid_cache_count--; - } - return; -} - -/**************************************************************************** -Check if a uid_t that currently has this file open is present. This is an -optimization only used when multiple sessionsetup's have been done to one smbd. -****************************************************************************/ - -static BOOL fd_is_in_uid_cache(file_fd_struct *fd_ptr, uid_t u) -{ - int i; - for(i = 0; i < fd_ptr->uid_cache_count; i++) - if(fd_ptr->uid_users_cache[i] == u) - return True; - return False; -} - -/**************************************************************************** -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, mode_t mode, files_struct *fsp) -{ - int fd = fsp->conn->vfs_ops.open(dos_to_unix(fname, False), O_RDWR, mode); - file_fd_struct *fd_ptr = fsp->fd_ptr; - - if(fd == -1) - return; - - if(fd_ptr->real_open_flags == O_RDONLY) - fd_ptr->fd_readonly = fd_ptr->fd; - if(fd_ptr->real_open_flags == O_WRONLY) - fd_ptr->fd_writeonly = fd_ptr->fd; - - fd_ptr->fd = fd; - fd_ptr->real_open_flags = O_RDWR; -} - -/**************************************************************************** -fd support routines - attempt to close the file referenced by this fd. -Decrements the ref_count and returns it. -****************************************************************************/ -uint16 fd_attempt_close(files_struct *fsp, int *err_ret) -{ - extern struct current_user current_user; - file_fd_struct *fd_ptr; - uint16 ret_ref; - - *err_ret = 0; - - if ((fsp == NULL) || (fsp->fd_ptr == NULL)) { - return 0; - } - - fd_ptr = fsp->fd_ptr; - ret_ref = fd_ptr->ref_count; - - 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)); - - 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) { - if(fsp->conn->vfs_ops.close(fd_ptr->fd) < 0) - *err_ret = errno; - } - - if(fd_ptr->fd_readonly != -1) { - if(fsp->conn->vfs_ops.close(fd_ptr->fd_readonly) < 0) { - if(*err_ret == 0) - *err_ret = errno; - } - } - - if(fd_ptr->fd_writeonly != -1) { - if(fsp->conn->vfs_ops.close(fd_ptr->fd_writeonly) < 0) { - if(*err_ret == 0) - *err_ret = errno; - } + /* 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); } - /* - * 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; + return fd; } /**************************************************************************** -fd support routines - check that current user has permissions -to open this file. Used when uid not found in optimization cache. -This is really ugly code, as due to POSIX locking braindamage we must -fork and then attempt to open the file, and return success or failure -via an exit code. +close the file associated with a fsp ****************************************************************************/ -static BOOL check_access_allowed_for_current_user(struct connection_struct - *conn, char *fname, - int accmode ) +void fd_close(files_struct *fsp, int *err_ret) { - pid_t child_pid; - - /* - * We need to temporarily stop CatchChild from eating - * SIGCLD signals as it also eats the exit status code. JRA. - */ - - CatchChildLeaveStatus(); - - if((child_pid = fork()) < 0) { - DEBUG(0,("check_access_allowed_for_current_user: fork failed.\n")); - CatchChild(); - return False; - } - - if(child_pid) { - /* - * Parent. - */ - pid_t wpid; - int status_code; - - while ((wpid = sys_waitpid(child_pid, &status_code, 0)) < 0) { - if(errno == EINTR) { - errno = 0; - continue; - } - DEBUG(0,("check_access_allowed_for_current_user: The process \ -is no longer waiting ! Error = %s\n", strerror(errno) )); - CatchChild(); - return(False); - } - - /* - * Go back to ignoring children. - */ - CatchChild(); - - if (child_pid != wpid) { - DEBUG(0,("check_access_allowed_for_current_user: We were waiting for the wrong process ID\n")); - return(False); - } -#if defined(WIFEXITED) && defined(WEXITSTATUS) - if (WIFEXITED(status_code) == 0) { - DEBUG(0,("check_access_allowed_for_current_user: The process exited while we were waiting\n")); - return(False); - } - if (WEXITSTATUS(status_code) != 0) { - DEBUG(9,("check_access_allowed_for_current_user: The status of the process exiting was %d. Returning access denied.\n", status_code)); - return(False); - } -#else /* defined(WIFEXITED) && defined(WEXITSTATUS) */ - if(status_code != 0) { - DEBUG(9,("check_access_allowed_for_current_user: The status of the process exiting was %d. Returning access denied.\n", status_code)); - return(False); - } -#endif /* defined(WIFEXITED) && defined(WEXITSTATUS) */ - - /* - * Success - the child could open the file. - */ - DEBUG(9,("check_access_allowed_for_current_user: The status of the process exiting was %d. Returning access allowed.\n", status_code)); - return True; - } else { - /* - * Child. - */ - 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(conn, fname, accmode, 0)) < 0) { - /* Access denied. */ - _exit(EACCES); - } - conn->vfs_ops.close(fd); - DEBUG(9,("check_access_allowed_for_current_user: Child - returning ok.\n")); - _exit(0); - } - - return False; + fsp->conn->vfs_ops.close(fsp->fd); + fsp->fd = -1; } + /**************************************************************************** check a filename for the pipe string ****************************************************************************/ @@ -320,278 +77,95 @@ open a file ****************************************************************************/ static void open_file(files_struct *fsp,connection_struct *conn, - char *fname1,int flags,mode_t mode, SMB_STRUCT_STAT *sbuf) + char *fname1,int flags,mode_t mode) { - extern struct current_user current_user; - pstring fname; - SMB_STRUCT_STAT statbuf; - file_fd_struct *fd_ptr; - int accmode = (flags & O_ACCMODE); - - fsp->open = False; - fsp->fd_ptr = 0; - fsp->oplock_type = NO_OPLOCK; - errno = EPERM; - - pstrcpy(fname,fname1); - - /* 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. - */ - - if (!CAN_WRITE(conn) && !conn->printer) { - /* 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; - } - } - - /* this handles a bug in Win95 - it doesn't say to create the file when it - should */ - if (conn->printer) { - flags |= (O_CREAT|O_EXCL); - } - -/* - if (flags == O_WRONLY) - DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n")); -*/ - - /* - * Ensure we have a valid struct stat so we can search the - * open fd table. - */ - if(sbuf == 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))); - - check_for_pipe(fname); - return; - } - sbuf = 0; - } else { - sbuf = &statbuf; - } - } - - /* - * Check to see if we have this file already - * open. If we do, just use the already open fd and increment the - * reference count (fd_get_already_open increments the ref_count). - */ - if((fd_ptr = fd_get_already_open(sbuf))!= 0) { - /* - * File was already open. - */ - - /* - * Check it wasn't open for exclusive use. - */ - if((flags & O_CREAT) && (flags & O_EXCL)) { - fd_ptr->ref_count--; - errno = EEXIST; - return; - } - - /* - * Ensure that the user attempting to open - * this file has permissions to do so, if - * the user who originally opened the file wasn't - * the same as the current user. - */ + extern struct current_user current_user; + pstring fname; + int accmode = (flags & O_ACCMODE); + SMB_STRUCT_STAT sbuf; - if(!fd_is_in_uid_cache(fd_ptr, (uid_t)current_user.uid)) { - 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)); - /* Ensure the ref_count is decremented. */ - fd_ptr->ref_count--; - fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid); - errno = EACCES; - return; - } - } + fsp->open = False; + fsp->fd = 0; + fsp->oplock_type = NO_OPLOCK; + errno = EPERM; - fd_add_to_uid_cache(fd_ptr, (uid_t)current_user.uid); + pstrcpy(fname,fname1); - /* - * If not opened O_RDWR try - * and do that here - a chmod may have been done - * between the last open and now. - */ - if(fd_ptr->real_open_flags != O_RDWR) - fd_attempt_reopen(fname, mode, fsp); + /* check permissions */ - /* - * Ensure that if we wanted write access - * it has been opened for write, and if we wanted read it - * was open for read. - */ - if(((accmode == O_WRONLY) && (fd_ptr->real_open_flags == O_RDONLY)) || - ((accmode == O_RDONLY) && (fd_ptr->real_open_flags == O_WRONLY)) || - ((accmode == O_RDWR) && (fd_ptr->real_open_flags != O_RDWR))) { - DEBUG(3,("Error opening (already open for flags=%d) file %s (%s) (flags=%d)\n", - fd_ptr->real_open_flags, fname,strerror(EACCES),flags)); - check_for_pipe(fname); - fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid); - fd_ptr->ref_count--; - return; - } + /* + * 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. + */ - } else { - int open_flags; - /* We need to allocate a new file_fd_struct (this increments the - ref_count). */ - if((fd_ptr = fd_get_new()) == 0) - return; - /* - * Whatever the requested flags, attempt read/write access, - * as we don't know what flags future file opens may require. - * If this fails, try again with the required flags. - * Even if we open read/write when only read access was - * requested the setting of the can_write flag in - * the file_struct will protect us from errant - * write requests. We never need to worry about O_APPEND - * as this is not set anywhere in Samba. - */ - 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(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. - */ -#ifdef EROFS - if((fd_ptr->fd == -1) && ((errno == EACCES) || (errno == EROFS))) { -#else /* No EROFS */ - if((fd_ptr->fd == -1) && (errno == EACCES)) { -#endif /* EROFS */ - if(accmode != O_RDWR) { - fd_ptr->fd = fd_attempt_open(conn, fname, open_flags|accmode, mode); - fd_ptr->real_open_flags = accmode; - } - } - } + 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; + } + } - if ((fd_ptr->fd >=0) && - conn->printer && lp_minprintspace(SNUM(conn))) { - pstring dname; - SMB_BIG_UINT dum1,dum2,dum3; - char *p; - pstrcpy(dname,fname); - p = strrchr(dname,'/'); - if (p) *p = 0; - if (conn->vfs_ops.disk_free(dos_to_unix(dname,False),False,&dum1,&dum2,&dum3) < - (SMB_BIG_UINT)lp_minprintspace(SNUM(conn))) { - int err; - if(fd_attempt_close(fsp, &err) == 0) - conn->vfs_ops.unlink(dos_to_unix(fname, False)); - fsp->fd_ptr = 0; - errno = ENOSPC; - return; - } - } - - if (fd_ptr->fd < 0) - { - int err; - DEBUG(3,("Error opening file %s (%s) (flags=%d)\n", - fname,strerror(errno),flags)); - /* Ensure the ref_count is decremented. */ - fd_attempt_close(fsp,&err); - check_for_pipe(fname); - return; - } + /* actually do the open */ + fsp->fd = fd_open(conn, fname, flags, mode); - if (fd_ptr->fd >= 0) - { - if(sbuf == 0) { - /* Do the fstat */ - if(conn->vfs_ops.fstat(fd_ptr->fd, &statbuf) == -1) { - int err; - /* 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(fsp,&err); - return; - } - sbuf = &statbuf; - } + if (fsp->fd == -1) { + DEBUG(3,("Error opening file %s (%s) (flags=%d)\n", + fname,strerror(errno),flags)); + check_for_pipe(fname); + return; + } - /* Set the correct entries in fd_ptr. */ - fd_ptr->dev = sbuf->st_dev; - fd_ptr->inode = sbuf->st_ino; - - fsp->fd_ptr = fd_ptr; - conn->num_files_open++; - fsp->mode = sbuf->st_mode; - GetTimeOfDay(&fsp->open_time); - fsp->vuid = current_user.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 = conn->printer; - 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. */ + conn->vfs_ops.fstat(fsp->fd, &sbuf); - /* - * If the printer is marked as postscript output a leading - * file identifier to ensure the file is treated as a raw - * postscript file. - * This has a similar effect as CtrlD=0 in WIN.INI file. - * tim@fsg.com 09/06/94 - */ - if (fsp->print_file && lp_postscript(SNUM(conn)) && fsp->can_write) { - DEBUG(3,("Writing postscript line\n")); - conn->vfs_ops.write(fsp->fd_ptr->fd,"%!\n",3); - } - - 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)); + 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.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. */ - } + 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)); } /**************************************************************************** @@ -611,8 +185,7 @@ static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, i /* 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); + unlock_share_entry_fsp(fsp); close_file(fsp,False); /* Share mode no longer locked. */ *share_locked = False; @@ -620,7 +193,7 @@ static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, i unix_ERR_class = ERRDOS; unix_ERR_code = ERRlock; } else { - sys_ftruncate(fsp->fd_ptr->fd,0); + sys_ftruncate(fsp->fd,0); } } } @@ -814,11 +387,23 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int int oplock_contention_count = 0; BOOL all_current_opens_are_level_II = False; fsp->open = False; - fsp->fd_ptr = 0; + fsp->fd = -1; + + if (conn->printer) { + /* printers are handled completely differently. Most of the passed parameters are + ignored */ + *Access = DOS_OPEN_WRONLY; + *action = FILE_WAS_CREATED; + print_open_file(fsp, conn, fname); + return; + } 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 )); + if (!check_name(fname,conn)) { + return; + } /* ignore any oplock requests if oplocks are disabled */ if (!lp_oplocks(SNUM(conn)) || global_client_failed_oplock_break) { @@ -1011,11 +596,10 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", 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) - { - flags = O_RDONLY; - open_file(fsp,conn,fname,flags,mode,file_existed ? &sbuf : 0 ); + open_file(fsp,conn,fname,flags|(flags2&~(O_TRUNC)),mode); + if (!fsp->open && flags==O_RDWR && errno != ENOENT && fcbopen) { + flags = O_RDONLY; + open_file(fsp,conn,fname,flags,mode); } if (fsp->open) @@ -1025,9 +609,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou if((share_locked == False) && lp_share_modes(SNUM(conn))) { /* We created the file - thus we must now lock the share entry before creating it. */ - dev = fsp->fd_ptr->dev; - inode = fsp->fd_ptr->inode; - lock_share_entry(conn, dev, inode); + lock_share_entry_fsp(fsp); share_locked = True; } @@ -1090,12 +672,12 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou } if (share_locked && lp_share_modes(SNUM(conn))) - unlock_share_entry( conn, dev, inode); + unlock_share_entry_fsp(fsp); } /**************************************************************************** Open a file for permissions read only. Return a pseudo file entry - with the 'stat_open' flag set and a fd_ptr of NULL. + with the 'stat_open' flag set ****************************************************************************/ int open_file_stat(files_struct *fsp,connection_struct *conn, @@ -1122,7 +704,7 @@ int open_file_stat(files_struct *fsp,connection_struct *conn, * Setup the files_struct for it. */ - fsp->fd_ptr = NULL; + fsp->fd = -1; conn->num_files_open++; fsp->mode = 0; GetTimeOfDay(&fsp->open_time); @@ -1235,7 +817,7 @@ int open_directory(files_struct *fsp,connection_struct *conn, * Setup the files_struct for it. */ - fsp->fd_ptr = NULL; + fsp->fd = -1; conn->num_files_open++; fsp->mode = 0; GetTimeOfDay(&fsp->open_time); -- cgit From 2311ecab4c8aa4026d2ac609f439b90834ff96e2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Apr 2000 21:38:45 +0000 Subject: The latest open() code changes broke the NT directory opens. Detect if a read-only open on a directory was done and return an EISDIR from open_file(). Changed interface to fd_close to return error. Jeremy. (This used to be commit df4302f3911447fcebe9342f6cbf3b89bd3bafba) --- source3/smbd/open.c | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 4c5605fb3b..02832308c6 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -28,8 +28,9 @@ 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) { @@ -42,21 +43,26 @@ static int fd_open(struct connection_struct *conn, char *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; } /**************************************************************************** -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,7 +79,7 @@ static void check_for_pipe(char *fname) } /**************************************************************************** -open a file + Open a file. ****************************************************************************/ static void open_file(files_struct *fsp,connection_struct *conn, @@ -91,7 +97,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, pstrcpy(fname,fname1); - /* check permissions */ + /* Check permissions */ /* * This code was changed after seeing a client open request @@ -121,7 +127,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, /* actually do the open */ fsp->fd = fd_open(conn, fname, flags, mode); - if (fsp->fd == -1) { + if (fsp->fd == -1) { DEBUG(3,("Error opening file %s (%s) (flags=%d)\n", fname,strerror(errno),flags)); check_for_pipe(fname); @@ -130,6 +136,18 @@ static void open_file(files_struct *fsp,connection_struct *conn, conn->vfs_ops.fstat(fsp->fd, &sbuf); + /* + * 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; -- cgit From 8316237e9ca83d1bd0cecdc63d7e47b44cf13181 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Apr 2000 17:59:09 +0000 Subject: Code to map tdb locks onto POSIX. Mainly placeholder code at the moment, but the structure is done enough so that Andrew can look it over and give a yea/nay decision. Jeremy. (This used to be commit db96f83e34a139f47776fcbb5c1624fbf9d9943b) --- source3/smbd/open.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 02832308c6..1c5a7e26e2 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -165,6 +165,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, fsp->modified = False; fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; + fsp->num_posix_locks = 0; fsp->is_directory = False; fsp->stat_open = False; fsp->directory_delete_on_close = False; @@ -738,6 +739,7 @@ int open_file_stat(files_struct *fsp,connection_struct *conn, fsp->modified = False; fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; + fsp->num_posix_locks = 0; fsp->is_directory = False; fsp->stat_open = True; fsp->directory_delete_on_close = False; @@ -851,6 +853,7 @@ int open_directory(files_struct *fsp,connection_struct *conn, fsp->modified = False; fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; + fsp->num_posix_locks = 0; fsp->is_directory = True; fsp->directory_delete_on_close = False; fsp->conn = conn; -- cgit From 54de56a1be8ede7476c741cd1631ad1ac8107fcc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 16 Apr 2000 06:22:31 +0000 Subject: the changes to the main smb code ------------ The following series of commits are for the new tdb based printing backend. This completely replaces our old printing backend. Major changes include: - all print ops are now done in printing/*.c rather than scattered all over the place - system job ids are decoupled from SMB job ids - the lpq parsers don't need to be nearly so smart, they only need to parse the filename, the status and system job id - we can store lots more info about a job, including the full job name - the queue cache control is much better I also added a new utility routine file_lines_load() that loads a text file and parses it into lines. This is used in out lpq parsing and I also want to use it to replace all of our fgets() based code in other places. (This used to be commit d870542c2884510bd45fd5b54ff2157434d53f4c) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 1c5a7e26e2..bd8e860a17 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -413,7 +413,7 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int ignored */ *Access = DOS_OPEN_WRONLY; *action = FILE_WAS_CREATED; - print_open_file(fsp, conn, fname); + print_fsp_open(fsp, conn, fname); return; } -- cgit From 6259f51dd9918eccc9697f3763d918f7c9b82b50 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 22 Apr 2000 00:33:16 +0000 Subject: This is a *big* checkin that may break some things, but implements the new open mechanism Andrew & I discussed. config.sub: configure: Included the QNX patch. include/vfs.h: smbd/vfs-wrap.c: smbd/vfs.c: Added ftruncate vfs call (needed). Note that we will also need locking calls in the vfs (to be added). lib/util_unistr.c: nmbd/nmbd_processlogon.c: Fix for NT domain logons causing nmbd to core dump. Also fix for sidsize DOS bug. locking/locking.c: Check value of ret before using it for memdup. printing/printing.c: Convert print_fsp_open to return an allocated fsp. rpc_server/srv_lsa.c: Fix for NT domain logons. I have removed all use of lp_share_modes() from the code (although I left the parameter in the table for backwards compatibility). It no longer makes sense for this to exist. smbd/close.c: Removed lp_share_modes(). smbd/fileio.c: Fixed parameters to unlock_share_entry call in panic code. smbd/files.c: Correctly set the unix_ERR_code to ERRnofids on fsp allocation fail. smbd/nttrans.c: smbd/reply.c: smbd/trans2.c: Changed all occurrences of open_file_shared/open_directory/ open_file_stat to return an fsp from the call. smbd/open.c: Changed all occurrences of open_file_shared/open_directory/ open_file_stat to return an fsp from the call. In addition I have fixed a long standing race condition in the deny mode processing w.r.t. two smbd's creating a file. Andrew, please note that your original idea of using open with O_EXCL in this case would not work (I went over the races very carefully) and so we must re-check deny modes *after* the open() call returns. This is because there is a race between the open with O_EXCL and the lock of the share mode entry. Imagine the case where the first smbd does the open with O_EXCL and a deny mode of DENY_ALL, but is pre-empted before it locks the share modes and creates the deny mode entry for DENY_ALL. A second smbd could then come in with O_RDONLY and a deny mode of DENY_NONE and the two opens would be allowed. The *only* way to fix this race is to lock the share modes after the open and then do the deny mode checks *after* this lock in the case where the file did not originally exist. This code will need extensive testing but seems to initially work. Jeremy. (This used to be commit ab0ecc39d688f16b9692fe90b991f0b89287070a) --- source3/smbd/open.c | 751 ++++++++++++++++++++++++++++------------------------ 1 file changed, 411 insertions(+), 340 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index bd8e860a17..d2368aa44d 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -82,7 +82,7 @@ static void check_for_pipe(char *fname) Open a file. ****************************************************************************/ -static void open_file(files_struct *fsp,connection_struct *conn, +static BOOL open_file(files_struct *fsp,connection_struct *conn, char *fname1,int flags,mode_t mode) { extern struct current_user current_user; @@ -114,7 +114,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, if(accmode != O_RDONLY) { DEBUG(3,("Permission denied opening %s\n",fname)); check_for_pipe(fname); - return; + return False; } 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 @@ -131,7 +131,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, DEBUG(3,("Error opening file %s (%s) (flags=%d)\n", fname,strerror(errno),flags)); check_for_pipe(fname); - return; + return False; } conn->vfs_ops.fstat(fsp->fd, &sbuf); @@ -145,10 +145,9 @@ static void open_file(files_struct *fsp,connection_struct *conn, if(S_ISDIR(sbuf.st_mode)) { fd_close(conn, fsp); errno = EISDIR; - return; + return False; } - conn->num_files_open++; fsp->mode = sbuf.st_mode; fsp->inode = sbuf.st_ino; fsp->dev = sbuf.st_dev; @@ -184,7 +183,9 @@ static void open_file(files_struct *fsp,connection_struct *conn, 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)); + conn->num_files_open + 1)); + + return True; } /**************************************************************************** @@ -193,35 +194,27 @@ static void open_file(files_struct *fsp,connection_struct *conn, Truncate a file after checking locking; close file if locked. **************************************************************************/ -static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, int token, - BOOL *share_locked) +static int truncate_unless_locked(struct connection_struct *conn, files_struct *fsp) { - 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,WRITE_LOCK)){ - /* 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_fsp(fsp); - 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,0); - } + SMB_BIG_UINT mask = (SMB_BIG_UINT)-1; + + if (!fsp->can_write) + return -1; + + if (is_locked(fsp,fsp->conn,mask,0,WRITE_LOCK)){ + errno = EACCES; + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRlock; + return -1; + } else { + return conn->vfs_ops.ftruncate(fsp->fd,0); } } - /******************************************************************* return True if the filename is one of the special executable types ********************************************************************/ -static BOOL is_executable(char *fname) +static BOOL is_executable(const char *fname) { if ((fname = strrchr(fname,'.'))) { if (strequal(fname,".com") || @@ -334,364 +327,426 @@ 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) + const 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); + 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; + } + + { + int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode, + (share->pid == getpid()),is_executable(fname)); + + if ((access_allowed == AFAIL) || + (!fcbopen && (access_allowed == AREAD && *flags == O_RDWR)) || + (access_allowed == AREAD && *flags != O_RDONLY) || + (access_allowed == AWRITE && *flags != O_WRONLY)) { + + 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, + (int)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; +} + +/**************************************************************************** + Deal with open deny mode and oplock break processing. + Invarient: Share mode must be locked on entry and exit. + Returns -1 on error, or number of share modes on success (may be zero). +****************************************************************************/ + +static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T dev, + SMB_INO_T inode, int share_mode, int *p_flags, int *p_oplock_request, + BOOL *p_all_current_opens_are_level_II) +{ + int i; + int num_share_modes; + int oplock_contention_count = 0; + share_mode_entry *old_shares = 0; + BOOL fcbopen = False; + int deny_mode = GET_DENY_MODE(share_mode); + 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; /* - * Don't allow any open once the delete on close flag has been - * set. + * Check if the share modes will give us access. */ - 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; - } + do { - { - int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode, - (share->pid == getpid()),is_executable(fname)); + broke_oplock = False; + *p_all_current_opens_are_level_II = True; - if ((access_allowed == AFAIL) || - (!fcbopen && (access_allowed == AREAD && *flags == O_RDWR)) || - (access_allowed == AREAD && *flags != O_RDONLY) || - (access_allowed == AWRITE && *flags != O_WRONLY)) - { - 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, - (int)share->pid,fname, fcbopen, *flags, access_allowed)); + 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 + * if the share mode would deny access and the client has an oplock. + * Check if someone has an oplock on this file. If so we must break + * it before continuing. + */ - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; + if((*p_oplock_request && EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type)) || + (!*p_oplock_request && (share_entry->op_type != NO_OPLOCK))) { - return False; + BOOL opb_ret; + + DEBUG(5,("open_mode_check: breaking oplock (%x) on file %s, \ +dev = %x, inode = %.0f\n", 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, dev, inode); + + /* Now relock. */ + lock_share_entry(conn, dev, inode); + + if(opb_ret == False) { + free((char *)old_shares); + 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)); + errno = EACCES; + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + return -1; + } + + broke_oplock = True; + *p_all_current_opens_are_level_II = False; + 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(share_entry, deny_mode, fname, fcbopen, p_flags) == False) { + free((char *)old_shares); + errno = EACCES; + return -1; + } + + } /* end for */ + + if(broke_oplock) { + free((char *)old_shares); + num_share_modes = get_share_modes(conn, dev, inode, &old_shares); + oplock_contention_count++; } + } while(broke_oplock); - if (access_allowed == AREAD) - *flags = O_RDONLY; + if(old_shares != 0) + free((char *)old_shares); - if (access_allowed == AWRITE) - *flags = O_WRONLY; + /* + * 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 )); } - return True; + return num_share_modes; } /**************************************************************************** -open a file with a share mode + Open a file with a share mode. ****************************************************************************/ -void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int share_mode,int ofun, +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) { - 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 share_locked = False; - BOOL fcbopen = False; - int token = 0; - SMB_DEV_T dev = 0; - SMB_INO_T inode = 0; - int num_share_modes = 0; - int oplock_contention_count = 0; - BOOL all_current_opens_are_level_II = False; - fsp->open = False; - fsp->fd = -1; - - if (conn->printer) { - /* printers are handled completely differently. Most of the passed parameters are - ignored */ - *Access = DOS_OPEN_WRONLY; - *action = FILE_WAS_CREATED; - print_fsp_open(fsp, conn, fname); - return; - } + 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 fcbopen = False; + SMB_DEV_T dev = 0; + SMB_INO_T inode = 0; + int num_share_modes = 0; + BOOL all_current_opens_are_level_II = False; + files_struct *fsp = NULL; + int open_mode=0; + uint16 port = 0; + + if (conn->printer) { + /* printers are handled completely differently. Most of the passed parameters are + ignored */ + *Access = DOS_OPEN_WRONLY; + *action = FILE_WAS_CREATED; + return print_fsp_open(conn, fname); + } - 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 )); + fsp = file_new(); + if(!fsp) + return NULL; - if (!check_name(fname,conn)) { - return; - } + fsp->open = False; + fsp->fd = -1; - /* ignore any oplock requests if oplocks are disabled */ - if (!lp_oplocks(SNUM(conn)) || global_client_failed_oplock_break) { - oplock_request = 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_class = ERRDOS; - /* OS/2 Workplace shell fix may be main code stream in a later release. */ + if (!check_name(fname,conn)) { + file_free(fsp); + return NULL; + } + + /* ignore any oplock requests if oplocks are disabled */ + if (!lp_oplocks(SNUM(conn)) || global_client_failed_oplock_break) { + oplock_request = 0; + } + + /* this is for OS/2 EAs - try and say we don't support them */ + if (strstr(fname,".+,;=[].")) { + unix_ERR_class = ERRDOS; + /* OS/2 Workplace shell fix may be main code stream in a later release. */ #if 1 /* OS2_WPS_FIX - Recent versions of OS/2 need this. */ - unix_ERR_code = ERRcannotopen; + unix_ERR_code = ERRcannotopen; #else /* OS2_WPS_FIX */ - unix_ERR_code = ERROR_EAS_NOT_SUPPORTED; + 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; - } + DEBUG(5,("open_file_shared: OS/2 EA's are not supported.\n")); + file_free(fsp); + return NULL; + } - 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 ((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 )); + file_free(fsp); + errno = EEXIST; + return NULL; + } - if (GET_FILE_CREATE_DISPOSITION(ofun) == FILE_CREATE_IF_NOT_EXIST) - flags2 |= O_CREAT; - - 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 (GET_OPEN_MODE(share_mode)) - { - case DOS_OPEN_WRONLY: - flags = O_WRONLY; - break; - case DOS_OPEN_FCB: - fcbopen = True; - flags = O_RDWR; - break; - case DOS_OPEN_RDWR: - flags = O_RDWR; - break; - default: - flags = O_RDONLY; - break; - } + if (GET_FILE_CREATE_DISPOSITION(ofun) == FILE_CREATE_IF_NOT_EXIST) + flags2 |= O_CREAT; + + 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 (GET_OPEN_MODE(share_mode)) { + case DOS_OPEN_WRONLY: + flags = O_WRONLY; + break; + case DOS_OPEN_FCB: + fcbopen = True; + flags = O_RDWR; + break; + case DOS_OPEN_RDWR: + flags = O_RDWR; + break; + default: + flags = O_RDONLY; + break; + } #if defined(O_SYNC) - if (GET_FILE_SYNC_OPENMODE(share_mode)) { - flags2 |= O_SYNC; - } + if (GET_FILE_SYNC_OPENMODE(share_mode)) { + flags2 |= O_SYNC; + } #endif /* O_SYNC */ - if (flags != O_RDONLY && file_existed && - (!CAN_WRITE(conn) || IS_DOS_READONLY(dos_mode(conn,fname,&sbuf)))) - { - 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; - } - flags = O_RDONLY; - } - - if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) - { - DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname)); - errno = EINVAL; - return; - } - - if (lp_share_modes(SNUM(conn))) - { - int i; - share_mode_entry *old_shares = 0; - - if (file_existed) - { - dev = sbuf.st_dev; - inode = sbuf.st_ino; - lock_share_entry(conn, dev, inode); - share_locked = True; - num_share_modes = get_share_modes(conn, dev, inode, &old_shares); - } + if (flags != O_RDONLY && file_existed && + (!CAN_WRITE(conn) || IS_DOS_READONLY(dos_mode(conn,fname,&sbuf)))) { + 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" )); + file_free(fsp); + errno = EACCES; + return NULL; + } + flags = O_RDONLY; + } - /* - * Check if the share modes will give us access. - */ + if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) { + DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname)); + file_free(fsp); + errno = EINVAL; + return NULL; + } - if(share_locked && (num_share_modes != 0)) - { - BOOL broke_oplock; + if (file_existed) { + dev = sbuf.st_dev; + inode = sbuf.st_ino; - do - { + lock_share_entry(conn, dev, inode); - broke_oplock = False; - all_current_opens_are_level_II = True; + 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) { + unlock_share_entry(conn, dev, inode); + file_free(fsp); + return NULL; + } - 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 - * if the share mode would deny access and the client has an oplock. - * Check if someone has an oplock on this file. If so we must break - * it before continuing. - */ - if((oplock_request && EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type)) || - (!oplock_request && (share_entry->op_type != NO_OPLOCK))) - { + /* + * We exit this block with the share entry *locked*..... + */ + } - 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)); + DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", + flags,flags2,(int)mode)); - /* Oplock break.... */ - unlock_share_entry(conn, dev, inode); - if(request_oplock_break(share_entry, dev, inode) == False) - { - free((char *)old_shares); + fsp->open = open_file(fsp,conn,fname,flags|(flags2&~(O_TRUNC)),mode); - 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)); + if (!fsp->open && (flags == O_RDWR) && (errno != ENOENT) && fcbopen) { + if((fsp->open = open_file(fsp,conn,fname,O_RDONLY,mode)) == True) + flags = O_RDONLY; + } - errno = EACCES; - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - return; - } - lock_share_entry(conn, dev, inode); - broke_oplock = True; - all_current_opens_are_level_II = False; - break; - } else if (!LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) { - all_current_opens_are_level_II = False; - } + if (!fsp->open) { + if(file_existed) + unlock_share_entry(conn, dev, inode); + file_free(fsp); + return NULL; + } - /* someone else has a share lock on it, check to see - if we can too */ - if(check_share_mode(share_entry, deny_mode, fname, fcbopen, &flags) == False) - { - free((char *)old_shares); - unlock_share_entry(conn, dev, inode); - errno = EACCES; - return; - } + /* + * 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 + * set a share mode, the other (ie. this one) should check if the + * requested share mode for this create is allowed. + */ - } /* end for */ + if (!file_existed) { - if(broke_oplock) - { - free((char *)old_shares); - num_share_modes = get_share_modes(conn, dev, inode, &old_shares); - oplock_contention_count++; - } - } while(broke_oplock); - } + lock_share_entry_fsp(fsp); - if(old_shares != 0) - free((char *)old_shares); - } + num_share_modes = open_mode_check(conn, fname, dev, inode, share_mode, + &flags, &oplock_request, &all_current_opens_are_level_II); - /* - * Refuse to grant an oplock in case the contention limit is - * reached when going through the lock list multiple times. - */ + if(num_share_modes == -1) { + unlock_share_entry_fsp(fsp); + fd_close(conn,fsp); + file_free(fsp); + return NULL; + } - if(oplock_contention_count >= lp_oplock_contention_limit(SNUM(conn))) - { - oplock_request = 0; - DEBUG(4,("open_file_shared: oplock contention = %d. Not granting oplock.\n", - oplock_contention_count )); - } + /* + * We exit this block with the share entry *locked*..... + */ + } - DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", - flags,flags2,(int)mode)); + /* + * At this point onwards, we can guarentee that the share entry + * is locked, whether we created the file or not, and that the + * deny mode is compatible with all current opens. + */ - open_file(fsp,conn,fname,flags|(flags2&~(O_TRUNC)),mode); - if (!fsp->open && flags==O_RDWR && errno != ENOENT && fcbopen) { - flags = O_RDONLY; - open_file(fsp,conn,fname,flags,mode); - } + /* + * If requested, truncate the file. + */ - if (fsp->open) - { - int open_mode=0; + 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((share_locked == False) && lp_share_modes(SNUM(conn))) - { - /* We created the file - thus we must now lock the share entry before creating it. */ - lock_share_entry_fsp(fsp); - share_locked = True; - } + switch (flags) { + case O_RDONLY: + open_mode = DOS_OPEN_RDONLY; + break; + case O_RDWR: + open_mode = DOS_OPEN_RDWR; + break; + case O_WRONLY: + open_mode = DOS_OPEN_WRONLY; + break; + } - switch (flags) - { - case O_RDONLY: - open_mode = DOS_OPEN_RDONLY; - break; - case O_RDWR: - open_mode = DOS_OPEN_RDWR; - break; - case O_WRONLY: - open_mode = DOS_OPEN_WRONLY; - break; - } + fsp->share_mode = SET_DENY_MODE(deny_mode) | + SET_OPEN_MODE(open_mode) | + SET_ALLOW_SHARE_DELETE(allow_share_delete); - 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 (Access) - (*Access) = open_mode; + if (action) { + if (file_existed && !(flags2 & O_TRUNC)) + *action = FILE_WAS_OPENED; + if (!file_existed) + *action = FILE_WAS_CREATED; + if (file_existed && (flags2 & O_TRUNC)) + *action = FILE_WAS_OVERWRITTEN; + } - if (action) - { - if (file_existed && !(flags2 & O_TRUNC)) *action = FILE_WAS_OPENED; - if (!file_existed) *action = FILE_WAS_CREATED; - if (file_existed && (flags2 & O_TRUNC)) *action = FILE_WAS_OVERWRITTEN; - } - /* We must create the share mode entry before truncate as - truncate can fail due to locking and have to close the - file (which expects the share_mode_entry to be there). - */ - if (lp_share_modes(SNUM(conn))) - { - uint16 port = 0; + /* + * Setup the oplock info in both the shared memory and + * file structs. + */ - /* - * Setup the oplock info in both the shared memory and - * file structs. - */ + if(oplock_request && (num_share_modes == 0) && + !IS_VETO_OPLOCK_PATH(conn,fname) && set_file_oplock(fsp, oplock_request) ) { + port = global_oplock_port; + } else if (oplock_request && all_current_opens_are_level_II) { + port = global_oplock_port; + oplock_request = LEVEL_II_OPLOCK; + set_file_oplock(fsp, oplock_request); + } else { + port = 0; + oplock_request = 0; + } - if(oplock_request && (num_share_modes == 0) && - !IS_VETO_OPLOCK_PATH(conn,fname) && set_file_oplock(fsp, oplock_request) ) { - port = global_oplock_port; - } else if (oplock_request && all_current_opens_are_level_II) { - port = global_oplock_port; - oplock_request = LEVEL_II_OPLOCK; - set_file_oplock(fsp, oplock_request); - } else { - port = 0; - oplock_request = 0; - } + set_share_mode(fsp, port, oplock_request); - set_share_mode(fsp, port, oplock_request); - } + unlock_share_entry_fsp(fsp); - if ((flags2&O_TRUNC) && file_existed) - truncate_unless_locked(fsp,conn,token,&share_locked); - } + conn->num_files_open++; - if (share_locked && lp_share_modes(SNUM(conn))) - unlock_share_entry_fsp(fsp); + return fsp; } /**************************************************************************** @@ -699,20 +754,26 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou with the 'stat_open' flag set ****************************************************************************/ -int open_file_stat(files_struct *fsp,connection_struct *conn, +files_struct *open_file_stat(connection_struct *conn, char *fname, int smb_ofun, SMB_STRUCT_STAT *pst, int *action) { extern struct current_user current_user; + files_struct *fsp = file_new(); + + 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) )); - return -1; + file_free(fsp); + return NULL; } if(S_ISDIR(pst->st_mode)) { DEBUG(0,("open_file_stat: %s is a directory !\n", fname )); - return -1; + file_free(fsp); + return NULL; } *action = FILE_WAS_OPENED; @@ -724,7 +785,6 @@ int open_file_stat(files_struct *fsp,connection_struct *conn, */ fsp->fd = -1; - conn->num_files_open++; fsp->mode = 0; GetTimeOfDay(&fsp->open_time); fsp->vuid = current_user.vuid; @@ -755,27 +815,34 @@ int open_file_stat(files_struct *fsp,connection_struct *conn, fsp->wbmpx_ptr = NULL; fsp->wcp = NULL; /* Write cache pointer. */ - return 0; + conn->num_files_open++; + + return fsp; } /**************************************************************************** Open a directory from an NT SMB call. ****************************************************************************/ -int open_directory(files_struct *fsp,connection_struct *conn, +files_struct *open_directory(connection_struct *conn, char *fname, 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) { got_stat = True; } if (got_stat && (GET_FILE_OPEN_DISPOSITION(smb_ofun) == FILE_EXISTS_FAIL)) { + file_free(fsp); errno = EEXIST; /* Setup so correct error is returned to client. */ - return -1; + return NULL; } if (GET_FILE_CREATE_DISPOSITION(smb_ofun) == FILE_CREATE_IF_NOT_EXIST) { @@ -784,8 +851,9 @@ int open_directory(files_struct *fsp,connection_struct *conn, if(!S_ISDIR(st.st_mode)) { DEBUG(0,("open_directory: %s is not a directory !\n", fname )); + file_free(fsp); errno = EACCES; - return -1; + return NULL; } *action = FILE_WAS_OPENED; @@ -797,15 +865,17 @@ int open_directory(files_struct *fsp,connection_struct *conn, if(!CAN_WRITE(conn)) { DEBUG(2,("open_directory: failing create on read-only share\n")); + file_free(fsp); errno = EACCES; - return -1; + return NULL; } if(conn->vfs_ops.mkdir(dos_to_unix(fname, False), unix_mode(conn,aDIR, fname)) < 0) { DEBUG(0,("open_directory: unable to create %s. Error was %s\n", fname, strerror(errno) )); - return -1; + file_free(fsp); + return NULL; } *action = FILE_WAS_CREATED; @@ -819,12 +889,14 @@ int open_directory(files_struct *fsp,connection_struct *conn, if(!got_stat) { DEBUG(0,("open_directory: unable to stat name = %s. Error was %s\n", fname, strerror(errno) )); - return -1; + file_free(fsp); + return NULL; } if(!S_ISDIR(st.st_mode)) { DEBUG(0,("open_directory: %s is not a directory !\n", fname )); - return -1; + file_free(fsp); + return NULL; } *action = FILE_WAS_OPENED; @@ -838,7 +910,6 @@ int open_directory(files_struct *fsp,connection_struct *conn, */ fsp->fd = -1; - conn->num_files_open++; fsp->mode = 0; GetTimeOfDay(&fsp->open_time); fsp->vuid = current_user.vuid; @@ -867,7 +938,9 @@ int open_directory(files_struct *fsp,connection_struct *conn, string_set(&fsp->fsp_name,fname); fsp->wbmpx_ptr = NULL; - return 0; + conn->num_files_open++; + + return fsp; } /******************************************************************* @@ -886,10 +959,8 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) SMB_DEV_T dev; SMB_INO_T inode; - if(!lp_share_modes(SNUM(conn))) - return True; - - if (conn->vfs_ops.stat(dos_to_unix(fname,False),&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; -- cgit From e82dbfcbe97c79b1c81915ae949bb2b1763970ba Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 24 Apr 2000 19:23:51 +0000 Subject: Now that fsp's are created on successful file open, the structure member fsp->open is no longer needed (if an fsp pointer is valid, then it's open :-). NB for Luke, this patch also did not apply to TNG. TNG is not yet identical w.r.t file serving with HEAD. This makes it impossible for me to help maintain TNG. Please fix asap. lib/substitute.c: Removed unused variable (pidstr). Jeremy. (This used to be commit 389b700a26e8a308a0dff6fc038c38068aa0119a) --- source3/smbd/open.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index d2368aa44d..353e20df8a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -90,8 +90,7 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, int accmode = (flags & O_ACCMODE); SMB_STRUCT_STAT sbuf; - fsp->open = False; - fsp->fd = 0; + fsp->fd = -1; fsp->oplock_type = NO_OPLOCK; errno = EPERM; @@ -155,7 +154,6 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->vuid = current_user.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); @@ -508,6 +506,7 @@ files_struct *open_file_shared(connection_struct *conn,char *fname,int share_mod SMB_INO_T inode = 0; int num_share_modes = 0; BOOL all_current_opens_are_level_II = False; + BOOL fsp_open = False; files_struct *fsp = NULL; int open_mode=0; uint16 port = 0; @@ -524,7 +523,6 @@ files_struct *open_file_shared(connection_struct *conn,char *fname,int share_mod if(!fsp) return NULL; - fsp->open = False; fsp->fd = -1; DEBUG(10,("open_file_shared: fname = %s, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n", @@ -638,14 +636,14 @@ files_struct *open_file_shared(connection_struct *conn,char *fname,int share_mod 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,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 && (flags == O_RDWR) && (errno != ENOENT) && fcbopen) { + if((fsp_open = open_file(fsp,conn,fname,O_RDONLY,mode)) == True) flags = O_RDONLY; } - if (!fsp->open) { + if (!fsp_open) { if(file_existed) unlock_share_entry(conn, dev, inode); file_free(fsp); @@ -790,7 +788,6 @@ files_struct *open_file_stat(connection_struct *conn, fsp->vuid = current_user.vuid; fsp->size = 0; fsp->pos = -1; - fsp->open = True; fsp->can_lock = False; fsp->can_read = False; fsp->can_write = False; @@ -915,7 +912,6 @@ files_struct *open_directory(connection_struct *conn, fsp->vuid = current_user.vuid; fsp->size = 0; fsp->pos = -1; - fsp->open = True; fsp->can_lock = True; fsp->can_read = False; fsp->can_write = False; -- cgit From 644f22ac6141f58f2badd3a9761ac156831c16a3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 24 Apr 2000 20:48:40 +0000 Subject: Added the code that keeps fd's open across a close if there are other fsp's open on the same dev/inode pair with existing POSIX locks. This is done at the smbd/open layer, so smbd just calls fd_close() and the transfer of any open fd's is done under the covers of fd_close(). When an fsp is closed and no other fsp's open on the same dev/inode pair have existing POSIX locks then all fd's associated with this fsp are closed. Now only the hard part of doing the POSIX range unlock code when read locks overlap remains for full POSIX/SMB lock integration.... Jeremy. (This used to be commit 1df48ed55ee303b6d84d7277fd79761cfe5f7052) --- source3/smbd/open.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 119 insertions(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 353e20df8a..44bb6ebaf7 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -49,14 +49,126 @@ static int fd_open(struct connection_struct *conn, char *fname, return fd; } +/**************************************************************************** + Take care of moving any POSIX pending close fd's to another fsp. +****************************************************************************/ + +static BOOL fd_close_posix_locks(files_struct *fsp) +{ + files_struct *other_fsp; + + DEBUG(10,("fd_close_posix_locks: file %s: fsp->num_posix_pending_closes = %u.\n", fsp->fsp_name, + (unsigned int)fsp->num_posix_pending_closes )); + + for(other_fsp = file_find_di_first(fsp->dev, fsp->inode); other_fsp; + other_fsp = file_find_di_next(other_fsp)) { + + if ((other_fsp->fd != -1) && other_fsp->num_posix_locks) { + + /* + * POSIX locks pending on another fsp held open, transfer + * the fd in this fsp and all the pending fd's in this fsp pending close array + * to the other_fsp pending close array. + */ + + unsigned int extra_fds = fsp->num_posix_pending_closes + 1; + + DEBUG(10,("fd_close_posix_locks: file %s: Transferring to \ +file %s, other_fsp->num_posix_pending_closes = %u.\n", + fsp->fsp_name, other_fsp->fsp_name, (unsigned int)other_fsp->num_posix_pending_closes )); + + other_fsp->posix_pending_close_fds = (int *)Realloc(other_fsp->posix_pending_close_fds, + (other_fsp->num_posix_pending_closes + + extra_fds)*sizeof(int)); + + if(other_fsp->posix_pending_close_fds == NULL) { + DEBUG(0,("fd_close_posix_locks: Unable to increase posix_pending_close_fds array size !\n")); + return False; + } + + /* + * Copy over any fd's in the existing fsp's pending array. + */ + + if(fsp->posix_pending_close_fds) { + memcpy(&other_fsp->posix_pending_close_fds[other_fsp->num_posix_pending_closes], + &fsp->posix_pending_close_fds[0], fsp->num_posix_pending_closes * sizeof(int) ); + + free((char *)fsp->posix_pending_close_fds); + fsp->posix_pending_close_fds = NULL; + fsp->num_posix_pending_closes = 0; + } + + other_fsp->posix_pending_close_fds[other_fsp->num_posix_pending_closes+extra_fds-1] = fsp->fd; + other_fsp->num_posix_pending_closes += extra_fds; + + fsp->fd = -1; /* We have moved this fd to other_fsp's pending close array.... */ + + break; + } + } + + return True; +} + /**************************************************************************** Close the file associated with a fsp. + + This is where we must deal with POSIX "first close drops all locks" + locking braindamage. We do this by searching for any other fsp open + on the same dev/inode with open POSIX locks, and then transferring this + fd (and all pending fd's attached to this fsp) to the posix_pending_close_fds + array in that fsp. + + If there are no open fsp's on the same dev/inode then we close all the + fd's in the posix_pending_close_fds array and then close the fd. + ****************************************************************************/ int fd_close(struct connection_struct *conn, files_struct *fsp) { - int ret = conn->vfs_ops.close(fsp->fd); + int ret = 0; + int saved_errno = 0; + unsigned int i; + + /* + * Deal with transferring any pending fd's if there + * are POSIX locks outstanding. + */ + + if(!fd_close_posix_locks(fsp)) + return -1; + + /* + * Close and free any pending closes given to use from + * other fsp's. + */ + + if (fsp->posix_pending_close_fds) { + + for(i = 0; i < fsp->num_posix_pending_closes; i++) { + if (fsp->posix_pending_close_fds[i] != -1) { + if (conn->vfs_ops.close(fsp->posix_pending_close_fds[i]) == -1) { + saved_errno = errno; + } + } + } + + free((char *)fsp->posix_pending_close_fds); + fsp->posix_pending_close_fds = NULL; + fsp->num_posix_pending_closes = 0; + } + + if(fsp->fd != -1) + ret = conn->vfs_ops.close(fsp->fd); + fsp->fd = -1; + + if (saved_errno != 0) { + errno = saved_errno; + ret = -1; + } + return ret; } @@ -163,6 +275,8 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; fsp->num_posix_locks = 0; + fsp->num_posix_pending_closes = 0; + fsp->posix_pending_close_fds = NULL; fsp->is_directory = False; fsp->stat_open = False; fsp->directory_delete_on_close = False; @@ -797,6 +911,8 @@ files_struct *open_file_stat(connection_struct *conn, fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; fsp->num_posix_locks = 0; + fsp->num_posix_pending_closes = 0; + fsp->posix_pending_close_fds = NULL; fsp->is_directory = False; fsp->stat_open = True; fsp->directory_delete_on_close = False; @@ -921,6 +1037,8 @@ files_struct *open_directory(connection_struct *conn, fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; fsp->num_posix_locks = 0; + fsp->num_posix_pending_closes = 0; + fsp->posix_pending_close_fds = NULL; fsp->is_directory = True; fsp->directory_delete_on_close = False; fsp->conn = conn; -- cgit From e3987ff7a638f9ea8b6794f1ed0df530d8488033 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Apr 2000 18:46:10 +0000 Subject: Fixed crash bugs Andrew pointed out with LOCK4 smbtorture test. Was miscounting posix locks, plus was not taking into account the case where other_fsp == fsp in the 'move locks' case. DOH ! This code will be re-written anyway :-). Jeremy. (This used to be commit 5278ec016cb24d8263fe6e7c1d389f466270ef24) --- source3/smbd/open.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 44bb6ebaf7..c7ca8256d2 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -57,12 +57,16 @@ static BOOL fd_close_posix_locks(files_struct *fsp) { files_struct *other_fsp; - DEBUG(10,("fd_close_posix_locks: file %s: fsp->num_posix_pending_closes = %u.\n", fsp->fsp_name, - (unsigned int)fsp->num_posix_pending_closes )); + DEBUG(10,("fd_close_posix_locks: file %s: fsp->num_posix_pending_closes = %u \ +fsp->posix_pending_close_fds = %lx.\n", fsp->fsp_name, + (unsigned int)fsp->num_posix_pending_closes, (unsigned long)fsp->posix_pending_close_fds )); for(other_fsp = file_find_di_first(fsp->dev, fsp->inode); other_fsp; other_fsp = file_find_di_next(other_fsp)) { + if(other_fsp == fsp) + continue; + if ((other_fsp->fd != -1) && other_fsp->num_posix_locks) { /* @@ -74,8 +78,8 @@ static BOOL fd_close_posix_locks(files_struct *fsp) unsigned int extra_fds = fsp->num_posix_pending_closes + 1; DEBUG(10,("fd_close_posix_locks: file %s: Transferring to \ -file %s, other_fsp->num_posix_pending_closes = %u.\n", - fsp->fsp_name, other_fsp->fsp_name, (unsigned int)other_fsp->num_posix_pending_closes )); +file %s, extra_fds = %u, other_fsp->num_posix_pending_closes = %u.\n", + fsp->fsp_name, other_fsp->fsp_name, extra_fds, (unsigned int)other_fsp->num_posix_pending_closes )); other_fsp->posix_pending_close_fds = (int *)Realloc(other_fsp->posix_pending_close_fds, (other_fsp->num_posix_pending_closes + -- cgit From 3d3c50326ba7f32ebb2fc683a3410dc0d1f18cdc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Apr 2000 21:12:33 +0000 Subject: Did the rewrite Andrew wanted where all knowledge of POSIX locking is removed from the smbd/open.c code. We now use a dlink list of structures indexed by dev/inode to store all pending fd's for close. This could be rewritten to use lib/hash.c if this is discovered to be too slow in use. Andrew, please take a look and let me know if this is what you had in mind. Jeremy. (This used to be commit 0487841120a7584da9a2b83b9574562c415d7024) --- source3/smbd/open.c | 115 +--------------------------------------------------- 1 file changed, 1 insertion(+), 114 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index c7ca8256d2..737b9b5ef3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -49,130 +49,26 @@ static int fd_open(struct connection_struct *conn, char *fname, return fd; } -/**************************************************************************** - Take care of moving any POSIX pending close fd's to another fsp. -****************************************************************************/ - -static BOOL fd_close_posix_locks(files_struct *fsp) -{ - files_struct *other_fsp; - - DEBUG(10,("fd_close_posix_locks: file %s: fsp->num_posix_pending_closes = %u \ -fsp->posix_pending_close_fds = %lx.\n", fsp->fsp_name, - (unsigned int)fsp->num_posix_pending_closes, (unsigned long)fsp->posix_pending_close_fds )); - - for(other_fsp = file_find_di_first(fsp->dev, fsp->inode); other_fsp; - other_fsp = file_find_di_next(other_fsp)) { - - if(other_fsp == fsp) - continue; - - if ((other_fsp->fd != -1) && other_fsp->num_posix_locks) { - - /* - * POSIX locks pending on another fsp held open, transfer - * the fd in this fsp and all the pending fd's in this fsp pending close array - * to the other_fsp pending close array. - */ - - unsigned int extra_fds = fsp->num_posix_pending_closes + 1; - - DEBUG(10,("fd_close_posix_locks: file %s: Transferring to \ -file %s, extra_fds = %u, other_fsp->num_posix_pending_closes = %u.\n", - fsp->fsp_name, other_fsp->fsp_name, extra_fds, (unsigned int)other_fsp->num_posix_pending_closes )); - - other_fsp->posix_pending_close_fds = (int *)Realloc(other_fsp->posix_pending_close_fds, - (other_fsp->num_posix_pending_closes + - extra_fds)*sizeof(int)); - - if(other_fsp->posix_pending_close_fds == NULL) { - DEBUG(0,("fd_close_posix_locks: Unable to increase posix_pending_close_fds array size !\n")); - return False; - } - - /* - * Copy over any fd's in the existing fsp's pending array. - */ - - if(fsp->posix_pending_close_fds) { - memcpy(&other_fsp->posix_pending_close_fds[other_fsp->num_posix_pending_closes], - &fsp->posix_pending_close_fds[0], fsp->num_posix_pending_closes * sizeof(int) ); - - free((char *)fsp->posix_pending_close_fds); - fsp->posix_pending_close_fds = NULL; - fsp->num_posix_pending_closes = 0; - } - - other_fsp->posix_pending_close_fds[other_fsp->num_posix_pending_closes+extra_fds-1] = fsp->fd; - other_fsp->num_posix_pending_closes += extra_fds; - - fsp->fd = -1; /* We have moved this fd to other_fsp's pending close array.... */ - - break; - } - } - - return True; -} - /**************************************************************************** Close the file associated with a fsp. - - This is where we must deal with POSIX "first close drops all locks" - locking braindamage. We do this by searching for any other fsp open - on the same dev/inode with open POSIX locks, and then transferring this - fd (and all pending fd's attached to this fsp) to the posix_pending_close_fds - array in that fsp. - - If there are no open fsp's on the same dev/inode then we close all the - fd's in the posix_pending_close_fds array and then close the fd. - ****************************************************************************/ int fd_close(struct connection_struct *conn, files_struct *fsp) { int ret = 0; - int saved_errno = 0; - unsigned int i; /* * Deal with transferring any pending fd's if there * are POSIX locks outstanding. */ - if(!fd_close_posix_locks(fsp)) + if(!fd_close_posix_locks(conn,fsp)) return -1; - /* - * Close and free any pending closes given to use from - * other fsp's. - */ - - if (fsp->posix_pending_close_fds) { - - for(i = 0; i < fsp->num_posix_pending_closes; i++) { - if (fsp->posix_pending_close_fds[i] != -1) { - if (conn->vfs_ops.close(fsp->posix_pending_close_fds[i]) == -1) { - saved_errno = errno; - } - } - } - - free((char *)fsp->posix_pending_close_fds); - fsp->posix_pending_close_fds = NULL; - fsp->num_posix_pending_closes = 0; - } - if(fsp->fd != -1) ret = conn->vfs_ops.close(fsp->fd); fsp->fd = -1; - - if (saved_errno != 0) { - errno = saved_errno; - ret = -1; - } - return ret; } @@ -278,9 +174,6 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->modified = False; fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; - fsp->num_posix_locks = 0; - fsp->num_posix_pending_closes = 0; - fsp->posix_pending_close_fds = NULL; fsp->is_directory = False; fsp->stat_open = False; fsp->directory_delete_on_close = False; @@ -914,9 +807,6 @@ files_struct *open_file_stat(connection_struct *conn, fsp->modified = False; fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; - fsp->num_posix_locks = 0; - fsp->num_posix_pending_closes = 0; - fsp->posix_pending_close_fds = NULL; fsp->is_directory = False; fsp->stat_open = True; fsp->directory_delete_on_close = False; @@ -1040,9 +930,6 @@ files_struct *open_directory(connection_struct *conn, fsp->modified = False; fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; - fsp->num_posix_locks = 0; - fsp->num_posix_pending_closes = 0; - fsp->posix_pending_close_fds = NULL; fsp->is_directory = True; fsp->directory_delete_on_close = False; fsp->conn = conn; -- cgit From 36db78fedad935aaa689d52d7f58e075f1f71812 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Apr 2000 22:23:04 +0000 Subject: Fixed subtle unlocking bug when a file is closed. We need to store the smbpid used when a file was opened in the files_struct. Else we use the wrong global_smbpid when we are closing the file and trying to remove the brl locks - this causes the brl locks to be left when the file is closed as the samba_context check fails. Jeremy. (This used to be commit 2746e5602e493e5b022764b4b839eb4d2f14363b) --- source3/smbd/open.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 737b9b5ef3..92bba76619 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -26,6 +26,7 @@ extern int DEBUGLEVEL; extern pstring sesssetup_user; extern uint16 global_oplock_port; extern BOOL global_client_failed_oplock_break; +extern int global_smbpid; /**************************************************************************** fd support routines - attempt to do a dos_open. @@ -164,6 +165,7 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->dev = sbuf.st_dev; GetTimeOfDay(&fsp->open_time); fsp->vuid = current_user.vuid; + fsp->smbpid = global_smbpid; fsp->size = 0; fsp->pos = -1; fsp->can_lock = True; @@ -797,6 +799,7 @@ files_struct *open_file_stat(connection_struct *conn, fsp->mode = 0; GetTimeOfDay(&fsp->open_time); fsp->vuid = current_user.vuid; + fsp->smbpid = global_smbpid; fsp->size = 0; fsp->pos = -1; fsp->can_lock = False; @@ -920,6 +923,7 @@ files_struct *open_directory(connection_struct *conn, fsp->mode = 0; GetTimeOfDay(&fsp->open_time); fsp->vuid = current_user.vuid; + fsp->smbpid = global_smbpid; fsp->size = 0; fsp->pos = -1; fsp->can_lock = True; -- cgit From 4b60a33c6fa733060068e192b87c2e858103d6eb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Apr 2000 23:28:56 +0000 Subject: Ok - this is more subtle than it looks :-). When a file is being closed, once it passes the fnum and tid tests then the locking context should be ignored when removing all locks. This is what is done in the brl close case, but when you have outstanding POSIX locks, then you cannot remove all the brl locks in one go, you have to get the lock list and call do_unlock individually. As this uses global_smbpid as the locking context, you need to make sure that this is set correctly for the specific lock being removed. I now do this by storing the smbpid in each entry in the unlock list returned from the query call. I removed the smbpid from fsp (not needed) and things seem ok (even with the stupid smbpid tricks that smbtorture plays :-). Jeremy. (This used to be commit 6baa96bb466915cc17e8cbad50254d6bd47b967b) --- source3/smbd/open.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 92bba76619..737b9b5ef3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -26,7 +26,6 @@ extern int DEBUGLEVEL; extern pstring sesssetup_user; extern uint16 global_oplock_port; extern BOOL global_client_failed_oplock_break; -extern int global_smbpid; /**************************************************************************** fd support routines - attempt to do a dos_open. @@ -165,7 +164,6 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->dev = sbuf.st_dev; GetTimeOfDay(&fsp->open_time); fsp->vuid = current_user.vuid; - fsp->smbpid = global_smbpid; fsp->size = 0; fsp->pos = -1; fsp->can_lock = True; @@ -799,7 +797,6 @@ files_struct *open_file_stat(connection_struct *conn, fsp->mode = 0; GetTimeOfDay(&fsp->open_time); fsp->vuid = current_user.vuid; - fsp->smbpid = global_smbpid; fsp->size = 0; fsp->pos = -1; fsp->can_lock = False; @@ -923,7 +920,6 @@ files_struct *open_directory(connection_struct *conn, fsp->mode = 0; GetTimeOfDay(&fsp->open_time); fsp->vuid = current_user.vuid; - fsp->smbpid = global_smbpid; fsp->size = 0; fsp->pos = -1; fsp->can_lock = True; -- cgit From be828fcec88a43306ddfb53473fda52df1d9965b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 28 Apr 2000 00:39:23 +0000 Subject: Made changes suggested by Andrew review. fd_close now calls fd_close_posix() directly. set_posix_lock/release_posix_lock() now handle the reference counting. More changes due when this gets moved to the file locking/posix.c Jeremy. (This used to be commit 239abd48f049c6a8d2bbc0636eacf347ab77588c) --- source3/smbd/open.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 737b9b5ef3..9aadb39bc9 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -55,21 +55,7 @@ static int fd_open(struct connection_struct *conn, char *fname, int fd_close(struct connection_struct *conn, files_struct *fsp) { - int ret = 0; - - /* - * Deal with transferring any pending fd's if there - * are POSIX locks outstanding. - */ - - if(!fd_close_posix_locks(conn,fsp)) - return -1; - - if(fsp->fd != -1) - ret = conn->vfs_ops.close(fsp->fd); - - fsp->fd = -1; - return ret; + return fd_close_posix(conn, fsp); } -- cgit From 693ffb8466ada58ecc59fde754ba79fc6f51528d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 2 May 2000 02:23:41 +0000 Subject: Added sys_fork() and sys_getpid() functions to stop the overhead of doing a system call every time we want to just get our pid. Jeremy. (This used to be commit 148628b616b5c29ba6340d65fc3ddbcabba6e67a) --- source3/smbd/open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 9aadb39bc9..0c6927ba2a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -342,7 +342,7 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, { int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode, - (share->pid == getpid()),is_executable(fname)); + (share->pid == sys_getpid()),is_executable(fname)); if ((access_allowed == AFAIL) || (!fcbopen && (access_allowed == AREAD && *flags == O_RDWR)) || @@ -946,7 +946,7 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) share_mode_entry *old_shares = 0; int num_share_modes; SMB_STRUCT_STAT sbuf; - pid_t pid = getpid(); + pid_t pid = sys_getpid(); SMB_DEV_T dev; SMB_INO_T inode; -- cgit From 49a0e6d5989656c1b3c9c063a20308ca4ee5d73b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 10 May 2000 10:41:59 +0000 Subject: more merging voodoo this adds "#define OLD_NTDOMAIN 1" in lots of places. Don't panic - this isn't permanent, it should go after another few merge steps have been done (This used to be commit 92109d7b3c06f240452d39f669ecb8c9c86ab610) --- source3/smbd/open.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 0c6927ba2a..e501d9ded8 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1,3 +1,5 @@ +#define OLD_NTDOMAIN 1 + /* Unix SMB/Netbios implementation. Version 1.9. @@ -1089,3 +1091,5 @@ free_and_exit: free((char *)old_shares); return(ret); } + +#undef OLD_NTDOMAIN -- cgit From 28d8970987265275f53ba1898b0057cf20629c9c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 12 May 2000 00:11:49 +0000 Subject: Check fstat return for error. Jeremy. (This used to be commit c54e77b1f9defce3d6c2e530e0fb460c2b0c54c2) --- source3/smbd/open.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index e501d9ded8..23d95eadfd 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -133,7 +133,11 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, return False; } - conn->vfs_ops.fstat(fsp->fd, &sbuf); + 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; + } /* * POSIX allows read-only opens of directories. We don't -- cgit From f94f053b7618157f6caaa1d65553c1abb3aba917 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 15 Jun 2000 09:35:37 +0000 Subject: added support for kernel level share modes. These are a (small) hack, I suspect we will either get rid of them or do them properly at some stage. (This used to be commit fabe1f350e1fc58db33d22cebd38652950697ced) --- source3/smbd/open.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 23d95eadfd..5a0493e625 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -492,9 +492,24 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou } /**************************************************************************** - Open a file with a share mode. +set a kernel flock on a file for NFS interoperability +this requires a patch to Linux ****************************************************************************/ +static void kernel_flock(files_struct *fsp, int deny_mode) +{ +#if HAVE_KERNEL_SHARE_MODES + int kernel_mode = 0; + if (deny_mode == DENY_READ) kernel_mode = LOCK_MAND|LOCK_WRITE; + else if (deny_mode == DENY_WRITE) kernel_mode = LOCK_MAND|LOCK_READ; + else if (deny_mode == DENY_ALL) kernel_mode = LOCK_MAND; + if (kernel_mode) flock(fsp->fd, kernel_mode); +#endif +} + +/**************************************************************************** + Open a file with a share mode. +****************************************************************************/ 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) { @@ -653,6 +668,14 @@ files_struct *open_file_shared(connection_struct *conn,char *fname,int share_mod 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 -- cgit From c5285699d9cdfea1ce77955c311f08981a5a97ba Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 15 Jun 2000 14:15:48 +0000 Subject: open files with O_NONBLOCK when available. This is necessary to prevent possible deadlocks with kernel leases and harmless when kernel leases are not used. basically we don't ever want smbd to block (This used to be commit 9fd67b94a7e43c9dcbe098940b88879ae8743c00) --- source3/smbd/open.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 5a0493e625..e9d2f01e10 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -36,7 +36,12 @@ 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(dos_to_unix(fname,False),flags,mode); /* Fix for files ending in '.' */ if((fd == -1) && (errno == ENOENT) && -- cgit From 3ad2ee22bb4ecee24d069bb7efadff18c25044d1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 3 Oct 2000 02:12:14 +0000 Subject: utf-8 and EUC3 patch from Hiroshi Miura Samba User Group Japan staff. mkdir high bits patch from Robert Dahlem" . jeremy. (This used to be commit b40191d27180ab1e59935086073c4d312552f717) --- source3/smbd/open.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index e9d2f01e10..4964e15e01 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -897,8 +897,7 @@ files_struct *open_directory(connection_struct *conn, 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); -- cgit From 636f146abf0a75cd3b21a57b50627ee149a635ab Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 6 Oct 2000 03:21:49 +0000 Subject: Restructuring of vfs layer to include a "this" pointer - can be an fsp or a conn struct depending on the call. We need this to have a clean NT ACL call interface. This will break any existing VFS libraries (that's why this is pre-release code). Andrew gets credit for this one :-) :-). In addition - added Herb's WITH_PROFILE changes - Herb - please examine the changes I've made to the smbd/reply.c code you added. The original code was very ugly and I have replaced it with a START_PROFILE(x)/END_PROFILE(x) pair using the preprocessor. Please check this compiles ok with the --with-profile switch. Jeremy. (This used to be commit b07611f8159b0b3f42e7e02611be9f4d56de96f5) --- source3/smbd/open.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 4964e15e01..edd94bd865 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -41,13 +41,13 @@ static int fd_open(struct connection_struct *conn, char *fname, flags |= O_NONBLOCK; #endif - 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); /* 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, @@ -138,7 +138,7 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, return False; } - if (conn->vfs_ops.fstat(fsp->fd, &sbuf) == -1) { + if (conn->vfs_ops.fstat(fsp,fsp->fd, &sbuf) == -1) { DEBUG(0,("Error doing fstat on open file %s (%s)\n", fname,strerror(errno) )); fd_close(conn, fsp); return False; @@ -213,7 +213,7 @@ static int truncate_unless_locked(struct connection_struct *conn, files_struct * unix_ERR_code = ERRlock; return -1; } else { - return conn->vfs_ops.ftruncate(fsp->fd,0); + return conn->vfs_ops.ftruncate(fsp,fsp->fd,0); } } @@ -792,7 +792,7 @@ files_struct *open_file_stat(connection_struct *conn, if(!fsp) return NULL; - if(conn->vfs_ops.stat(dos_to_unix(fname, False), pst) < 0) { + if(conn->vfs_ops.stat(conn,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); @@ -862,7 +862,7 @@ files_struct *open_directory(connection_struct *conn, if(!fsp) return NULL; - if(conn->vfs_ops.stat(dos_to_unix(fname, False), &st) == 0) { + if(conn->vfs_ops.stat(conn,dos_to_unix(fname, False), &st) == 0) { got_stat = True; } @@ -983,7 +983,7 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) SMB_DEV_T dev; SMB_INO_T inode; - if (conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf) == -1) + if (conn->vfs_ops.stat(conn,dos_to_unix(fname,False),&sbuf) == -1) return(True); dev = sbuf.st_dev; -- cgit From abf055046fe70842badc2a1904f2cd6966bafbf4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 19 Oct 2000 02:58:24 +0000 Subject: Ok - this is a big patch - and it may break smbd a bit (although I hope not). If you encounter strange file-serving behavior after this patch then back it out. I analysed our stat() usage and realised we were doing approx. 3 stat calls per open, and 2 per getattr/setattr. This patch should fix all that. It causes the stat struct returned from unix_convert() (which now *must* be passed a valid SMB_STRUCT_STAT pointer) to be passed through into the open code. This should prevent the multiple stats that were being done so as not to violate layer encapsulation in the API's. Herb - if you could run a NetBench test with this code and do a padc/par syscall test and also run with the current 2.2.0 code and test the padc/par syscalls I'd appreciate it - you should find the number of stat calls reduced - not sure by how much. The patch depends on unix_convert() actually finding the file and returning a stat struct, or returning a zero'd out stat struct if the file didn't exist. I believe we can guarentee this to be the case - I just wasn't confident enough to make this an assertion before. Ok ok - I did write this whilst at the Miami conference..... sometimes you get a little free time at these things :-). Jeremy. (This used to be commit 66a5c05ec46b641224fbe01b30bd7e83571a2a1b) --- source3/smbd/open.c | 116 +++++++++++++++++++++++++++++----------------------- 1 file changed, 64 insertions(+), 52 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index edd94bd865..12f6d12948 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -88,12 +88,11 @@ static void check_for_pipe(char *fname) ****************************************************************************/ 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; @@ -138,10 +137,12 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, return False; } - if (conn->vfs_ops.fstat(fsp,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; + } } /* @@ -150,18 +151,18 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, * 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); @@ -513,17 +514,17 @@ static void kernel_flock(files_struct *fsp, int deny_mode) /**************************************************************************** - 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; @@ -619,7 +620,7 @@ files_struct *open_file_shared(connection_struct *conn,char *fname,int share_mod #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" )); @@ -638,8 +639,9 @@ files_struct *open_file_shared(connection_struct *conn,char *fname,int share_mod } 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); @@ -659,10 +661,10 @@ files_struct *open_file_shared(connection_struct *conn,char *fname,int share_mod 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; } @@ -717,11 +719,16 @@ files_struct *open_file_shared(connection_struct *conn,char *fname,int share_mod * 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) { @@ -783,28 +790,26 @@ files_struct *open_file_shared(connection_struct *conn,char *fname,int share_mod 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(); - - if(!fsp) - return NULL; + files_struct *fsp = NULL; - if(conn->vfs_ops.stat(conn,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)); @@ -814,10 +819,12 @@ files_struct *open_file_stat(connection_struct *conn, */ 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; @@ -851,20 +858,18 @@ files_struct *open_file_stat(connection_struct *conn, 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(conn,dos_to_unix(fname, False), &st) == 0) { + if (VALID_STAT(*psbuf)) got_stat = True; - } if (got_stat && (GET_FILE_OPEN_DISPOSITION(smb_ofun) == FILE_EXISTS_FAIL)) { file_free(fsp); @@ -876,7 +881,7 @@ files_struct *open_directory(connection_struct *conn, 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; @@ -903,6 +908,12 @@ files_struct *open_directory(connection_struct *conn, file_free(fsp); return NULL; } + + if(vfs_stat(conn,fname, psbuf) != 0) { + file_free(fsp); + return NULL; + } + *action = FILE_WAS_CREATED; } @@ -919,7 +930,7 @@ files_struct *open_directory(connection_struct *conn, 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; @@ -928,18 +939,19 @@ files_struct *open_directory(connection_struct *conn, *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; @@ -983,7 +995,7 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) SMB_DEV_T dev; SMB_INO_T inode; - if (conn->vfs_ops.stat(conn,dos_to_unix(fname,False),&sbuf) == -1) + if (vfs_stat(conn,fname,&sbuf) == -1) return(True); dev = sbuf.st_dev; -- cgit From bbce6b44eb2247362c353c5f90278bfafe98dc11 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 20 Oct 2000 23:59:47 +0000 Subject: Fix for vfs_fstat() crash with new stat code. Jeremy. (This used to be commit 979aa01e011d433328af0ead7644f47d0cfadf13) --- source3/smbd/open.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 12f6d12948..258e463ecf 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -548,6 +548,7 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S 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 )); @@ -868,6 +869,8 @@ files_struct *open_directory(connection_struct *conn, char *fname, if(!fsp) return NULL; + fsp->conn = conn; /* THe vfs_fXXX() macros need this. */ + if (VALID_STAT(*psbuf)) got_stat = True; -- cgit From ccb5cbf175c43455a956d42b2815a4529ab9383f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 11 Dec 2000 21:09:48 +0000 Subject: Fixed very subtle bug returning correct error on an open, when we have a choice of invalid share mode and access denied. We must return the access denied by preference, but also remember to break the oplocks... This is needed for multi-user MS-Access. Jeremy. (This used to be commit 7eb7241442ea0f1e065b009c3cccd5821b89a8b6) --- source3/smbd/open.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 258e463ecf..b23da55542 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -649,6 +649,20 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S 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; @@ -676,14 +690,6 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S 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 @@ -710,6 +716,14 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S */ } + /* 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 -- cgit From 2f7c1db093504a9798cdfd9c5d08a259cb4abc46 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 23 Jan 2001 01:52:30 +0000 Subject: include/vfs.h: smbd/vfs-wrap.c: smbd/vfs.c: Added fchmod_acl and chmod_acl. lib/substitute.c: smbd/lanman.c: smbd/open.c: smbd/process.c: smbd/reply.c: smbd/service.c: Removed sessetup_user variable. Added current_user_info struct which conatins domain info etc. Added '%D' for client domain parameter. Jeremy. (This used to be commit 2844ec3d511680609d6794b8718001a1bda9e89f) --- source3/smbd/open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index b23da55542..77962562e3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -25,7 +25,7 @@ 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; @@ -188,7 +188,7 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, 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)); -- cgit From b15e9adea1bd09cfe78f32be9a007a9731bcb3e4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 24 Jan 2001 21:54:44 +0000 Subject: Sync up with POSIX ACL code from 2.2. Jeremy. (This used to be commit e0431672cc54ed09d6c5cf083054db12ccd9dcf6) --- source3/smbd/open.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 77962562e3..3665e7d20f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -192,6 +192,13 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, 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; } -- cgit From da3053048c3d224a20d6383ac6682d31059cd46c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 11 Mar 2001 00:32:10 +0000 Subject: Merge of new 2.2 code into HEAD (Gerald I hate you :-) :-). Allows new SAMR RPC code to merge with new passdb code. Currently rpcclient doesn't compile. I'm working on it... Jeremy. (This used to be commit 0be41d5158ea4e645e93e8cd30617c038416e549) --- source3/smbd/open.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 3665e7d20f..afcaeff1ae 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1,5 +1,3 @@ -#define OLD_NTDOMAIN 1 - /* Unix SMB/Netbios implementation. Version 1.9. @@ -1158,5 +1156,3 @@ free_and_exit: free((char *)old_shares); return(ret); } - -#undef OLD_NTDOMAIN -- cgit From e670b3564c3c12baaab0e988f155a86b9437f66e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 26 Mar 2001 19:18:06 +0000 Subject: smbd/posix_acls.c: Saving and restoring errno here is the wrong place. Moved it to the places where [f]chmod_acl is called instead. Jeremy. (This used to be commit 641ada44ae6429761c1fd0dbcafabc69f897fac7) --- source3/smbd/open.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index afcaeff1ae..c601121459 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -194,9 +194,12 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, * 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); - + if ((flags & O_CREAT) && (conn->vfs_ops.fchmod_acl != NULL)) { + int saved_errno = errno; /* We might get ENOSYS in the next call.. */ + if (conn->vfs_ops.fchmod_acl(fsp, fsp->fd, mode) == -1 && errno == ENOSYS) + errno = saved_errno; /* Ignore ENOSYS */ + } + return True; } -- cgit From 6e7f03f9b920d1b81056959cca8c0b27ada4ee2d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 30 Mar 2001 08:57:24 +0000 Subject: This is a big, rather ugly patch. Whilst investigating the files not truncated when copying to a full disk problem, I discovered that we were not allowing the delete on close flag to be set properly, this led to other things, and after investigation of the proper delete on close semantics and their relationship to the file_share_delete flag I discovered there were some cases where we weren't doing the deny modes properly. And this after only 5 years working on them..... :-) :-). So here's the latest attempt. I realised the delete on close flag needs to be set across all smbds with a dev/ino pair open - in addition, the delete on close flag, allow share delete and delete access requested all need to be stored in the share mode tdb. The "delete_on_close" entry in the fsp struct is now redundant and should really be removed. This may also mean we can get rid of the "iterate_fsp" calls that I didn't like adding in the first place. Whilst doing this patch, I also discovered we needed to do the se_map_generic() call for file opens and POSIX ACL mapping, so I added that also. This code, although ugly, now passes the deny mode torture tests plus the delete on close tests I added. I do need to add one more multiple connection delete on close test to make sure I got the semantics exactly right, plus we should also (as Andrew suggested) move to random testing here. The good news is that NT should now correctly delete the file on disk full error when copying to a disk :-). Jeremy. (This used to be commit 51987684bd231c744da2e5f3705fd236d5616173) --- source3/smbd/open.c | 45 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 6 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index c601121459..5f8657262a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -341,18 +341,19 @@ static int access_table(int new_deny,int old_deny,int old_mode, check if we can open a file with a share mode ****************************************************************************/ -static int check_share_mode( share_mode_entry *share, int deny_mode, +static int check_share_mode( share_mode_entry *share, int share_mode, const char *fname, BOOL fcbopen, int *flags) { + int deny_mode = GET_DENY_MODE(share_mode); 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 + * Don't allow any opens once the delete on close flag has been * set. */ - if(GET_DELETE_ON_CLOSE_FLAG(share->share_mode)) { + 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; @@ -360,6 +361,35 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, return False; } + /* + * If delete access was requested and the existing share mode doesn't have + * ALLOW_SHARE_DELETE then deny. + */ + + if (GET_DELETE_ACCESS_REQUESTED(share_mode) && !GET_ALLOW_SHARE_DELETE(share->share_mode)) { + DEBUG(5,("check_share_mode: Failing open on file %s as delete access requested and allow share delete not set.\n", + fname )); + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + + return False; + } + + /* + * The inverse of the above. + * If delete access was granted and the new share mode doesn't have + * ALLOW_SHARE_DELETE then deny. + */ + + if (GET_DELETE_ACCESS_REQUESTED(share->share_mode) && !GET_ALLOW_SHARE_DELETE(share_mode)) { + DEBUG(5,("check_share_mode: Failing open on file %s as delete access granted and allow share delete not requested.\n", + 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 == sys_getpid()),is_executable(fname)); @@ -405,7 +435,6 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T int oplock_contention_count = 0; share_mode_entry *old_shares = 0; BOOL fcbopen = False; - int deny_mode = GET_DENY_MODE(share_mode); BOOL broke_oplock; if(GET_OPEN_MODE(share_mode) == DOS_OPEN_FCB) @@ -473,7 +502,7 @@ 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(check_share_mode(share_entry, deny_mode, fname, fcbopen, p_flags) == False) { + if(check_share_mode(share_entry, share_mode, fname, fcbopen, p_flags) == False) { free((char *)old_shares); errno = EACCES; return -1; @@ -532,6 +561,7 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S int flags2=0; int deny_mode = GET_DENY_MODE(share_mode); BOOL allow_share_delete = GET_ALLOW_SHARE_DELETE(share_mode); + BOOL delete_access_requested = GET_DELETE_ACCESS_REQUESTED(share_mode); BOOL file_existed = VALID_STAT(*psbuf); BOOL fcbopen = False; SMB_DEV_T dev = 0; @@ -768,7 +798,10 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S fsp->share_mode = SET_DENY_MODE(deny_mode) | SET_OPEN_MODE(open_mode) | - SET_ALLOW_SHARE_DELETE(allow_share_delete); + SET_ALLOW_SHARE_DELETE(allow_share_delete) | + SET_DELETE_ACCESS_REQUESTED(delete_access_requested); + + DEBUG(10,("open_file_shared : share_mode = %x\n", fsp->share_mode )); if (Access) (*Access) = open_mode; -- cgit From 819482c07137937ee0c063437d2b2eade2895b99 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 13 Apr 2001 20:49:11 +0000 Subject: Fixed potential file descriptor leak with MS-Access fix. Jeremy. (This used to be commit 192887fe72157a141b8df1977085f479e5204782) --- source3/smbd/open.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 5f8657262a..007a169f9e 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -60,6 +60,8 @@ static int fd_open(struct connection_struct *conn, char *fname, int fd_close(struct connection_struct *conn, files_struct *fsp) { + if (fsp->fd == -1) + return -1; return fd_close_posix(conn, fsp); } @@ -699,9 +701,15 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S * 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); + fsp_open = open_file(fsp,conn,fname,psbuf,flags|(flags2&~(O_TRUNC|O_CREAT)),mode); + + DEBUG(4,("open_file_shared : share_mode deny - calling open_file with \ +flags=0x%X flags2=0x%X mode=0%o returned %d\n", + flags,(flags2&~(O_TRUNC|O_CREAT)),(int)mode,(int)fsp_open )); unlock_share_entry(conn, dev, inode); + if (fsp_open) + fd_close(conn, fsp); file_free(fsp); return NULL; } -- cgit From 53850c51caf1c4d53ff285b2e5505e0615beeeee Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 14 Apr 2001 00:19:12 +0000 Subject: configure: configure.in: include/config.h.in: include/profile.h: smbd/vfs-wrap.c: smbd/vfs.c: Added fchmod and fchown to VFS (sorry Gerald - but we needed them anyway). smbd/dosmode.c: smbd/files.c: printing/printfsp.c: smbd/close.c: smbd/open.c: Fixed "dos filemode" correctly so there are no race conditions. Forces test of open of file O_WRONLY before allowing fchmod as root. Afterwards, calls standard close function that preserves POSIX locks due to POSIX-me-harder braindamage. :-). Andrew please review this code. Also - in removing the tmpdir param in smbrun an extra NULL parameter was missed in each print_run_command() call (which is a varargs fn.). Now fixed. Jeremy. (This used to be commit 32397e5bc6d995ce7ca37c82d6aedc1e5b1b6fbd) --- source3/smbd/open.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 7 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 007a169f9e..f450e74e58 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -583,13 +583,10 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S return print_fsp_open(conn, fname); } - fsp = file_new(); + fsp = file_new(conn); if(!fsp) 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 )); @@ -870,7 +867,7 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, return NULL; } - fsp = file_new(); + fsp = file_new(conn); if(!fsp) return NULL; @@ -918,6 +915,49 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, return fsp; } +/**************************************************************************** + Open a file for for write to ensure that we can fchmod it. +****************************************************************************/ + +files_struct *open_file_fchmod(connection_struct *conn, char *fname, SMB_STRUCT_STAT *psbuf) +{ + files_struct *fsp = NULL; + BOOL fsp_open; + + if (!VALID_STAT(*psbuf)) + return NULL; + + fsp = file_new(conn); + if(!fsp) + return NULL; + + fsp_open = open_file(fsp,conn,fname,psbuf,O_WRONLY,0); + + /* + * This is not a user visible file open. + * Don't set a share mode and don't increment + * the conn->num_files_open. + */ + + if (!fsp_open) { + file_free(fsp); + return NULL; + } + + return fsp; +} + +/**************************************************************************** + Close the fchmod file fd - ensure no locks are lost. +****************************************************************************/ + +int close_file_fchmod(files_struct *fsp) +{ + int ret = fd_close(fsp->conn, fsp); + file_free(fsp); + return ret; +} + /**************************************************************************** Open a directory from an NT SMB call. ****************************************************************************/ @@ -927,12 +967,12 @@ files_struct *open_directory(connection_struct *conn, char *fname, { extern struct current_user current_user; BOOL got_stat = False; - files_struct *fsp = file_new(); + files_struct *fsp = file_new(conn); if(!fsp) return NULL; - fsp->conn = conn; /* THe vfs_fXXX() macros need this. */ + fsp->conn = conn; /* The vfs_fXXX() macros need this. */ if (VALID_STAT(*psbuf)) got_stat = True; -- cgit From 2df39394fe01de6fb19cd919554272f407ecee4a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 14 Apr 2001 20:47:30 +0000 Subject: This little piece of insanity is inspired by the fact that an NT client can open a file for O_RDONLY, but set the create disposition to FILE_EXISTS_TRUNCATE. If the client *can* write to the file, then it expects to truncate the file, even though it is opening for readonly. Quicken uses this stupid trick in backup file creation... Thanks *greatly* to "David W. Chapman Jr." for helping track this one down. It didn't bite us in 2.0.x as we always opened files read-write in that release. Jeremy. (This used to be commit 5baef56831f9bc4fa10a851abd5f9305b974fb3b) --- source3/smbd/open.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index f450e74e58..cebb37ab29 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -48,8 +48,8 @@ static int fd_open(struct connection_struct *conn, char *fname, 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, - (fd == -1) ? strerror(errno) : "" )); + DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n", fname, + flags, (int)mode, fd, (fd == -1) ? strerror(errno) : "" )); return fd; } @@ -647,7 +647,22 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S flags = O_RDWR; break; default: - flags = O_RDONLY; + /* + * This little piece of insanity is inspired by the + * fact that an NT client can open a file for O_RDONLY, + * but set the create disposition to FILE_EXISTS_TRUNCATE. + * If the client *can* write to the file, then it expects to + * truncate the file, even though it is opening for readonly. + * Quicken uses this stupid trick in backup file creation... + * Thanks *greatly* to "David W. Chapman Jr." + * for helping track this one down. It didn't bite us in 2.0.x + * as we always opened files read-write in that release. JRA. + */ + + if (flags2 & O_TRUNC) + flags = O_RDWR; + else + flags = O_RDONLY; break; } -- cgit From d5b74f71300f4366441511620d519b63442773b9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 16 Apr 2001 00:02:29 +0000 Subject: Correct fix for open readonly with truncate. Jeremy. (This used to be commit 6706e258e17c3d69d617b95feb3407124f50852d) --- source3/smbd/open.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index cebb37ab29..7c40b0720e 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -93,6 +93,7 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, extern struct current_user current_user; pstring fname; int accmode = (flags & O_ACCMODE); + int local_flags = flags; fsp->fd = -1; fsp->oplock_type = NO_OPLOCK; @@ -127,8 +128,23 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, } } + /* + * This little piece of insanity is inspired by the + * fact that an NT client can open a file for O_RDONLY, + * but set the create disposition to FILE_EXISTS_TRUNCATE. + * If the client *can* write to the file, then it expects to + * truncate the file, even though it is opening for readonly. + * Quicken uses this stupid trick in backup file creation... + * Thanks *greatly* to "David W. Chapman Jr." + * for helping track this one down. It didn't bite us in 2.0.x + * as we always opened files read-write in that release. JRA. + */ + + if ((accmode == O_RDONLY) && ((flags & O_TRUNC) == O_TRUNC)) + local_flags = (flags & ~O_ACCMODE)|O_RDWR; + /* actually do the open */ - fsp->fd = fd_open(conn, fname, flags, mode); + fsp->fd = fd_open(conn, fname, local_flags, mode); if (fsp->fd == -1) { DEBUG(3,("Error opening file %s (%s) (flags=%d)\n", @@ -647,22 +663,7 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S flags = O_RDWR; break; default: - /* - * This little piece of insanity is inspired by the - * fact that an NT client can open a file for O_RDONLY, - * but set the create disposition to FILE_EXISTS_TRUNCATE. - * If the client *can* write to the file, then it expects to - * truncate the file, even though it is opening for readonly. - * Quicken uses this stupid trick in backup file creation... - * Thanks *greatly* to "David W. Chapman Jr." - * for helping track this one down. It didn't bite us in 2.0.x - * as we always opened files read-write in that release. JRA. - */ - - if (flags2 & O_TRUNC) - flags = O_RDWR; - else - flags = O_RDONLY; + flags = O_RDONLY; break; } -- cgit From 71ae6a09cd2c4792f95459220645c424f7659913 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 16 Apr 2001 00:34:03 +0000 Subject: Finally got the semantics right (hurrah!). Jeremy. (This used to be commit 362574c5a32005d4247c7ac75a5aa9e35e894db0) --- source3/smbd/open.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 7c40b0720e..c6d4a44688 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -143,12 +143,19 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, if ((accmode == O_RDONLY) && ((flags & O_TRUNC) == O_TRUNC)) local_flags = (flags & ~O_ACCMODE)|O_RDWR; + /* + * 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; + /* actually do the open */ fsp->fd = fd_open(conn, fname, local_flags, mode); if (fsp->fd == -1) { - DEBUG(3,("Error opening file %s (%s) (flags=%d)\n", - fname,strerror(errno),flags)); + DEBUG(3,("Error opening file %s (%s) (local_flags=%d) (flags=%d)\n", + fname,strerror(errno),local_flags,flags)); check_for_pipe(fname); return False; } @@ -231,9 +238,6 @@ static int truncate_unless_locked(struct connection_struct *conn, files_struct * { SMB_BIG_UINT mask = (SMB_BIG_UINT)-1; - if (!fsp->can_write) - return -1; - if (is_locked(fsp,fsp->conn,mask,0,WRITE_LOCK)){ errno = EACCES; unix_ERR_class = ERRDOS; @@ -735,7 +739,11 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", 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,psbuf,flags|(flags2&~(O_TRUNC)),mode); + /* + * open_file strips any O_TRUNC flags itself. + */ + + fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,mode); if (!fsp_open && (flags == O_RDWR) && (errno != ENOENT) && fcbopen) { if((fsp_open = open_file(fsp,conn,fname,psbuf,O_RDONLY,mode)) == True) -- cgit From 6f78636a56106c510545dc1c8218b3a90a486c67 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 18 Apr 2001 05:12:46 +0000 Subject: Removed mktemp from HEAD - same as done in 2.2. Jeremy. (This used to be commit 121b59669fbcd1aaedb08011ff36169fc6561c55) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index c6d4a44688..8db4400664 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -600,7 +600,7 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S ignored */ *Access = DOS_OPEN_WRONLY; *action = FILE_WAS_CREATED; - return print_fsp_open(conn, fname); + return print_fsp_open(conn); } fsp = file_new(conn); -- cgit From 850a0e27e19ac21bc66d3d26875d3f9bafd5245c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 19 Jun 2001 07:31:55 +0000 Subject: Extra debug in open.c, fix for bad debug message in reply.c Jeremy. (This used to be commit 2c2fc8513699eb39721ac1d65fa1fdaecde526a8) --- source3/smbd/open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 8db4400664..a88dfd5573 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -492,8 +492,8 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T BOOL opb_ret; - DEBUG(5,("open_mode_check: breaking oplock (%x) on file %s, \ -dev = %x, inode = %.0f\n", share_entry->op_type, fname, (unsigned int)dev, (double)inode)); + 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); -- cgit From d1f38ac53107d818b88cae9ee4d4442381dc4702 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 30 Jun 2001 01:59:48 +0000 Subject: Fixed the first locking error (test #8 found by locktest code from Clarion locktest. Jeremy. (This used to be commit 5c42845b5bb6fafd0ebf93fbdd23d9bf861da865) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index a88dfd5573..8bfddd4c71 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -238,7 +238,7 @@ static int truncate_unless_locked(struct connection_struct *conn, files_struct * { SMB_BIG_UINT mask = (SMB_BIG_UINT)-1; - if (is_locked(fsp,fsp->conn,mask,0,WRITE_LOCK)){ + if (is_locked(fsp,fsp->conn,mask,0,WRITE_LOCK,True)){ errno = EACCES; unix_ERR_class = ERRDOS; unix_ERR_code = ERRlock; -- cgit From 87fbb7092b8f8b2f0db0f361c3d625e19de57cd9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 4 Jul 2001 07:15:53 +0000 Subject: The big character set handling changeover! This commit gets rid of all our old codepage handling and replaces it with iconv. All internal strings in Samba are now in "unix" charset, which may be multi-byte. See internals.doc and my posting to samba-technical for a more complete explanation. (This used to be commit debb471267960e56005a741817ebd227ecfc512a) --- source3/smbd/open.c | 26 ++------------------------ 1 file changed, 2 insertions(+), 24 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 8bfddd4c71..7c48e28138 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -38,14 +38,13 @@ static int fd_open(struct connection_struct *conn, char *fname, #ifdef O_NONBLOCK flags |= O_NONBLOCK; #endif - - fd = conn->vfs_ops.open(conn,dos_to_unix(fname,False),flags,mode); + fd = conn->vfs_ops.open(conn,fname,flags,mode); /* Fix for files ending in '.' */ if((fd == -1) && (errno == ENOENT) && (strchr(fname,'.')==NULL)) { pstrcat(fname,"."); - fd = conn->vfs_ops.open(conn,dos_to_unix(fname,False),flags,mode); + fd = conn->vfs_ops.open(conn,fname,flags,mode); } DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n", fname, @@ -199,13 +198,6 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, 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. */ @@ -923,13 +915,6 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, fsp->stat_open = True; 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. */ @@ -1094,13 +1079,6 @@ files_struct *open_directory(connection_struct *conn, char *fname, fsp->is_directory = True; 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; -- cgit From 527e824293ee934ca5da0ef5424efe5ab7757248 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 4 Jul 2001 07:36:09 +0000 Subject: strchr and strrchr are macros when compiling with optimisation in gcc, so we can't redefine them. damn. (This used to be commit c41fc06376d1a2b83690612304e85010b5e5f3cf) --- source3/smbd/open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 7c48e28138..858a26191f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -42,7 +42,7 @@ static int fd_open(struct connection_struct *conn, char *fname, /* Fix for files ending in '.' */ if((fd == -1) && (errno == ENOENT) && - (strchr(fname,'.')==NULL)) { + (strchr_m(fname,'.')==NULL)) { pstrcat(fname,"."); fd = conn->vfs_ops.open(conn,fname,flags,mode); } @@ -245,7 +245,7 @@ return True if the filename is one of the special executable types ********************************************************************/ static BOOL is_executable(const char *fname) { - if ((fname = strrchr(fname,'.'))) { + if ((fname = strrchr_m(fname,'.'))) { if (strequal(fname,".com") || strequal(fname,".dll") || strequal(fname,".exe") || -- cgit From aa91def29f54a466c7c7efbc8cf442b7a9759afa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 5 Jul 2001 23:37:09 +0000 Subject: Fix race where wrong action (created or opened) could be returned. Jeremy. (This used to be commit af5b649b017f703a14a69f77a9067efb9c6a8269) --- source3/smbd/open.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 858a26191f..f67490b61d 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -770,6 +770,14 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", return NULL; } + /* + * If there are any share modes set then the file *did* + * exist. Ensure we return the correct value for action. + */ + + if (num_share_modes > 0) + file_existed = True; + /* * We exit this block with the share entry *locked*..... */ -- cgit From 76f36b8c360c427fbcc19aa043a3c4b923fd37e7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 24 Jul 2001 01:18:43 +0000 Subject: We were making an assumption in the oplock break code path that was invalid (ie. we were assuming we could infer a non-levelII oplock when such an oplock was detected - this may no longer be valid once we've processed the break process dealing with the break will change the state of it anyway. This prevents the state where we get the following packet trace : client server NTcreate -> <- NTcreate resp NTcreate -> <- break to level II ok - broken -> <- break to none Thanks to Alan Romeril for providing the trace that allowed me to track this down. Jeremy. (This used to be commit c343e4f49070011986fc2ed4acd4ce690d5f1d71) --- source3/smbd/open.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index f67490b61d..a32e032921 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -506,7 +506,6 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou } broke_oplock = True; - *p_all_current_opens_are_level_II = False; break; } else if (!LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) { -- cgit From e6a6dee0272a170848d3b9c177bf3839214d0a20 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 21 Aug 2001 01:25:45 +0000 Subject: This is Jeremy pretending to be Volker, 'cos the link from Seattle is having problems. I've added 3 things here to work on the fcntl spin problem. 1). Check *all* tdb return codes... :-). 2). If we're asking ourselves to break an oplock, and we can't find a fsp pointer that matches the entry, this is a *logic bug* and we should abort and panic so someone with gdb can pick up the pieces. 3). After we've broken an oplock, ensure that the entry itself has been removed, and if not remove it ourselves. This should not be neccessary in a correctly working environmen,t, but will provide an added layer of robustness in error situations. 4). I hate german keyboards :-) :-). Jeremy. (This used to be commit 1c94fa80646f9e31377fbb41332fe4780f550cab) --- source3/smbd/open.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index a32e032921..143aa934a6 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -464,6 +464,7 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T */ do { + share_mode_entry broken_entry; broke_oplock = False; *p_all_current_opens_are_level_II = True; @@ -506,6 +507,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou } broke_oplock = True; + broken_entry = *share_entry; break; } else if (!LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) { @@ -525,6 +527,14 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou if(broke_oplock) { free((char *)old_shares); + if (del_share_entry(dev, inode, &broken_entry, NULL) == -1) { + DEBUG(0,("open_mode_check: cannot delete entry when breaking oplock (%x) on file %s, \ +dev = %x, inode = %.0f\n", broken_entry.op_type, fname, (unsigned int)dev, (double)inode)); + errno = EACCES; + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + return -1; + } num_share_modes = get_share_modes(conn, dev, inode, &old_shares); oplock_contention_count++; } -- cgit From e4275a35a64fde95a3b59307572d44c8d53909ad Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 22 Aug 2001 00:29:40 +0000 Subject: Fixed the (incorrect) paranioa fix I put in for the fcntl lock spin. Don't delete a share mode that failed to remove the oplock (doh!), just set the oplock entry to zero.... Jeremy. (This used to be commit fe4aa720181a43f7a636ca029680fab0c836b968) --- source3/smbd/open.c | 44 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 9 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 143aa934a6..633cf71817 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -527,17 +527,42 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou if(broke_oplock) { free((char *)old_shares); - if (del_share_entry(dev, inode, &broken_entry, NULL) == -1) { - DEBUG(0,("open_mode_check: cannot delete entry when breaking oplock (%x) on file %s, \ -dev = %x, inode = %.0f\n", broken_entry.op_type, fname, (unsigned int)dev, (double)inode)); - errno = EACCES; - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - return -1; - } 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) ) { + + /* + * This should not happen. The target left this oplock + * as exlusive.... The process *must* be dead.... + */ + + DEBUG(0,("open_mode_check: exlusive oplock left after break ! For file %s, +dev = %x, inode = %.0f\n", fname, (unsigned int)dev, (double)inode)); + + if (process_exists(broken_entry.pid)) { + pstring errmsg; + slprintf(errmsg, sizeof(errmsg)-1, + "open_mode_check: Existant process %d left active oplock.\n", + broken_entry.pid ); + smb_panic(errmsg); + } + + if (!clear_share_entry(dev, inode, &broken_entry)) { + errno = EACCES; + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + return -1; + } + } + } /* end for paranoia... */ + } /* end if broke_oplock */ + } while(broke_oplock); if(old_shares != 0) @@ -570,6 +595,7 @@ static void kernel_flock(files_struct *fsp, int deny_mode) else if (deny_mode == DENY_ALL) kernel_mode = LOCK_MAND; if (kernel_mode) flock(fsp->fd, kernel_mode); #endif + ;; } -- cgit From 85e063f5b8b9ac872dc5e30da99b34230434df84 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 22 Aug 2001 01:01:37 +0000 Subject: Tidyup fixes for fcntl spin problem. Jeremy. (This used to be commit 27d3dd0e7cb777ef6b21d6966c07045c2940fd37) --- source3/smbd/open.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 633cf71817..a8cf9aba89 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -3,6 +3,7 @@ Version 1.9. file opening and share modes Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 2001 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -542,8 +543,8 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou * as exlusive.... The process *must* be dead.... */ - DEBUG(0,("open_mode_check: exlusive oplock left after break ! For file %s, -dev = %x, inode = %.0f\n", fname, (unsigned int)dev, (double)inode)); + 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)) { pstring errmsg; @@ -553,12 +554,21 @@ dev = %x, inode = %.0f\n", fname, (unsigned int)dev, (double)inode)); smb_panic(errmsg); } - if (!clear_share_entry(dev, inode, &broken_entry)) { + 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. + */ + + free((char *)old_shares); + num_share_modes = get_share_modes(conn, dev, inode, &old_shares); + break; } } /* end for paranoia... */ } /* end if broke_oplock */ -- cgit From ecea36501ec6d4d2db0c27311d4548e8e404ec1a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 22 Aug 2001 01:06:27 +0000 Subject: Missed '\' at eol... Jeremy. (This used to be commit 0dbd1be704209c1a66280148b40f7b7437d47242) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index a8cf9aba89..2e1ddb07fb 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -543,7 +543,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou * as exlusive.... The process *must* be dead.... */ - DEBUG(0,("open_mode_check: exlusive oplock left by process %d after break ! For file %s, + 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)) { -- cgit From e8e98c9ea0690e3acf1126b50882e59e1056c7b3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 27 Aug 2001 08:19:43 +0000 Subject: converted smbd to use NTSTATUS by default major changes include: - added NSTATUS type - added automatic mapping between dos and nt error codes - changed all ERROR() calls to ERROR_DOS() and many to ERROR_NT() these calls auto-translate to the client error code system - got rid of the cached error code and the writebmpx code We eventually will need to also: - get rid of BOOL, so we don't lose error info - replace all ERROR_DOS() calls with ERROR_NT() calls but that is too much for one night (This used to be commit 83d9896c1ea8be796192b51a4678c2a3b87f7518) --- source3/smbd/open.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 2e1ddb07fb..6a1eac7602 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -200,7 +200,6 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->directory_delete_on_close = False; fsp->conn = conn; 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", @@ -969,8 +968,7 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, fsp->directory_delete_on_close = False; fsp->conn = conn; string_set(&fsp->fsp_name,fname); - fsp->wbmpx_ptr = NULL; - fsp->wcp = NULL; /* Write cache pointer. */ + fsp->wcp = NULL; /* Write cache pointer. */ conn->num_files_open++; @@ -1133,7 +1131,6 @@ files_struct *open_directory(connection_struct *conn, char *fname, fsp->directory_delete_on_close = False; fsp->conn = conn; string_set(&fsp->fsp_name,fname); - fsp->wbmpx_ptr = NULL; conn->num_files_open++; -- cgit From 387f1fd09ca8101f161c729394340f50e882a955 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 5 Sep 2001 21:11:52 +0000 Subject: fixed formatting to make the code vaguely readable. It's still a dogs breakfast, but at least you can follow the indents (This used to be commit 9955ea0aaa299c6c946b4e7b7e98017c39b60bc8) --- source3/smbd/open.c | 285 ++++++++++++++++++++++++++-------------------------- 1 file changed, 143 insertions(+), 142 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 6a1eac7602..145d12e3f3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -444,151 +444,151 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T SMB_INO_T inode, int share_mode, int *p_flags, int *p_oplock_request, BOOL *p_all_current_opens_are_level_II) { - int i; - int num_share_modes; - int oplock_contention_count = 0; - 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 - * if the share mode would deny access and the client has an oplock. - * 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))) { - - BOOL opb_ret; + int i; + int num_share_modes; + int oplock_contention_count = 0; + 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 + * if the share mode would deny access and the client has an oplock. + * 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))) { + + BOOL opb_ret; - DEBUG(5,("open_mode_check: oplock_request = %d, breaking oplock (%x) on file %s, \ + 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, dev, inode); - - /* Now relock. */ - lock_share_entry(conn, dev, inode); - - if(opb_ret == False) { - free((char *)old_shares); - DEBUG(0,("open_mode_check: FAILED when breaking oplock (%x) on file %s, \ + + /* Oplock break - unlock to request it. */ + unlock_share_entry(conn, dev, inode); + + opb_ret = request_oplock_break(share_entry, dev, inode); + + /* Now relock. */ + lock_share_entry(conn, dev, inode); + + if(opb_ret == False) { + free((char *)old_shares); + 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)); - errno = EACCES; - unix_ERR_class = ERRDOS; - 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(share_entry, share_mode, fname, fcbopen, p_flags) == False) { - free((char *)old_shares); - errno = EACCES; - return -1; - } - - } /* end for */ - - if(broke_oplock) { - free((char *)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) ) { - - /* - * 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, \ + errno = EACCES; + unix_ERR_class = ERRDOS; + 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(share_entry, share_mode, fname, fcbopen, p_flags) == False) { + free((char *)old_shares); + errno = EACCES; + return -1; + } + + } /* end for */ + + if(broke_oplock) { + free((char *)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) ) { + + /* + * 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)) { - pstring errmsg; - slprintf(errmsg, sizeof(errmsg)-1, - "open_mode_check: Existant process %d left active oplock.\n", - broken_entry.pid ); - smb_panic(errmsg); - } - - 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. - */ - - free((char *)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) - free((char *)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 )); - } - - return num_share_modes; + + if (process_exists(broken_entry.pid)) { + pstring errmsg; + slprintf(errmsg, sizeof(errmsg)-1, + "open_mode_check: Existant process %d left active oplock.\n", + broken_entry.pid ); + smb_panic(errmsg); + } + + 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. + */ + + free((char *)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) + free((char *)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 )); + } + + return num_share_modes; } /**************************************************************************** @@ -613,7 +613,8 @@ static void kernel_flock(files_struct *fsp, int deny_mode) that ****************************************************************************/ 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) { int flags=0; int flags2=0; -- cgit From 72c35310b2b0d39c077c50a2175c76ced5d4c662 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 15 Sep 2001 13:21:54 +0000 Subject: use variables _before_ freeing them! thanks to Andreas Moroder for spotting these two. (This used to be commit 01f30ca0ad472eaab8f80ec4278b1d391be3a1ae) --- source3/smbd/open.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 145d12e3f3..7974ea0ae0 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -497,9 +497,9 @@ dev = %x, inode = %.0f\n", *p_oplock_request, share_entry->op_type, fname, (unsi lock_share_entry(conn, dev, inode); if(opb_ret == False) { - free((char *)old_shares); 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)); + free((char *)old_shares); errno = EACCES; unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadshare; @@ -1234,11 +1234,10 @@ dev = %x, inode = %.0f\n", share_entry->op_type, fname, (unsigned int)dev, (doub unlock_share_entry(conn, dev, inode); if(request_oplock_break(share_entry, dev, inode) == False) { - free((char *)old_shares); - 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)); + free((char *)old_shares); return False; } lock_share_entry(conn, dev, inode); -- cgit From 61b2794968faa35dc91edce17e9b91e5366c3514 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 17 Sep 2001 11:25:41 +0000 Subject: move to SAFE_FREE() (This used to be commit a95943fde0ad89ae3f2deca2f7ba9cb5ab612b74) --- source3/smbd/open.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 7974ea0ae0..7ac5a18609 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -499,7 +499,7 @@ dev = %x, inode = %.0f\n", *p_oplock_request, share_entry->op_type, fname, (unsi 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)); - free((char *)old_shares); + SAFE_FREE(old_shares); errno = EACCES; unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadshare; @@ -518,7 +518,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou if we can too */ if(check_share_mode(share_entry, share_mode, fname, fcbopen, p_flags) == False) { - free((char *)old_shares); + SAFE_FREE(old_shares); errno = EACCES; return -1; } @@ -526,7 +526,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou } /* end for */ if(broke_oplock) { - free((char *)old_shares); + SAFE_FREE(old_shares); num_share_modes = get_share_modes(conn, dev, inode, &old_shares); oplock_contention_count++; @@ -565,7 +565,7 @@ dev = %x, inode = %.0f. Deleting it to continue...\n", (int)broken_entry.pid, fn * other process's entry. */ - free((char *)old_shares); + SAFE_FREE(old_shares); num_share_modes = get_share_modes(conn, dev, inode, &old_shares); break; } @@ -575,7 +575,7 @@ dev = %x, inode = %.0f. Deleting it to continue...\n", (int)broken_entry.pid, fn } while(broke_oplock); if(old_shares != 0) - free((char *)old_shares); + SAFE_FREE(old_shares); /* * Refuse to grant an oplock in case the contention limit is @@ -1237,7 +1237,7 @@ dev = %x, inode = %.0f\n", share_entry->op_type, fname, (unsigned int)dev, (doub 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)); - free((char *)old_shares); + SAFE_FREE(old_shares); return False; } lock_share_entry(conn, dev, inode); @@ -1267,7 +1267,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou if(broke_oplock) { - free((char *)old_shares); + SAFE_FREE(old_shares); num_share_modes = get_share_modes(conn, dev, inode, &old_shares); } } while(broke_oplock); @@ -1288,7 +1288,6 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou free_and_exit: unlock_share_entry(conn, dev, inode); - if(old_shares != NULL) - free((char *)old_shares); + SAFE_FREE(old_shares); return(ret); } -- cgit From abaa4ab96a192047a7f8ff6fa579f723a7b4912e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 24 Sep 2001 23:50:28 +0000 Subject: Change log message to 2 from zero when failing to create directory. Stops spurious profile creation messages. Jeremy. (This used to be commit fa74d07207fa9024b6ebdb10686b032ef6673d18) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 7ac5a18609..6e6d5e1e83 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1070,7 +1070,7 @@ files_struct *open_directory(connection_struct *conn, char *fname, } if(vfs_mkdir(conn,fname, unix_mode(conn,aDIR, fname)) < 0) { - DEBUG(0,("open_directory: unable to create %s. Error was %s\n", + DEBUG(2,("open_directory: unable to create %s. Error was %s\n", fname, strerror(errno) )); file_free(fsp); return NULL; -- cgit From dc1fc3ee8ec2199bc73bb5d7ec711c6800f61d65 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 2 Oct 2001 04:29:50 +0000 Subject: Removed 'extern int DEBUGLEVEL' as it is now in the smb.h header. (This used to be commit 2d0922b0eabfdc0aaf1d0797482fef47ed7fde8e) --- source3/smbd/open.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 6e6d5e1e83..3578a82f8f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -22,8 +22,6 @@ #include "includes.h" -extern int DEBUGLEVEL; - extern userdom_struct current_user_info; extern uint16 global_oplock_port; extern BOOL global_client_failed_oplock_break; -- cgit From 88b55f47b4914f7d390939e4394ec3edd42be91f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 20 Oct 2001 21:59:34 +0000 Subject: Move from timestamp to gen count file id's for finding oplocked files in a tdb. Jeremy. (This used to be commit 058ae6b58f61ef46013dd076af3a84de5fbaaab1) --- source3/smbd/open.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 3578a82f8f..325913c3d9 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -181,7 +181,6 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, 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 = psbuf->st_size; fsp->pos = -1; @@ -489,7 +488,7 @@ dev = %x, inode = %.0f\n", *p_oplock_request, share_entry->op_type, fname, (unsi /* Oplock break - unlock to request it. */ unlock_share_entry(conn, dev, inode); - opb_ret = request_oplock_break(share_entry, dev, inode); + opb_ret = request_oplock_break(share_entry); /* Now relock. */ lock_share_entry(conn, dev, inode); @@ -946,11 +945,9 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, * Setup the files_struct for it. */ - fsp->fd = -1; 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->pos = -1; @@ -1110,11 +1107,9 @@ files_struct *open_directory(connection_struct *conn, char *fname, * Setup the files_struct for it. */ - fsp->fd = -1; 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->pos = -1; @@ -1230,7 +1225,7 @@ dev = %x, inode = %.0f\n", share_entry->op_type, fname, (unsigned int)dev, (doub /* Oplock break.... */ unlock_share_entry(conn, dev, inode); - if(request_oplock_break(share_entry, dev, inode) == False) + if(request_oplock_break(share_entry) == False) { 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)); -- cgit From d05bbf042209b737e42a5daa8d59236d351ec8d0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 23 Nov 2001 11:18:20 +0000 Subject: Fixed delete on close bug. Added core dump code to winbindd. Jeremy. (This used to be commit a58d0f91f9ee7354c01a9c20cfe178d5dc02142d) --- source3/smbd/open.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 325913c3d9..1eae228f40 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -618,6 +618,7 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S int deny_mode = GET_DENY_MODE(share_mode); BOOL allow_share_delete = GET_ALLOW_SHARE_DELETE(share_mode); BOOL delete_access_requested = GET_DELETE_ACCESS_REQUESTED(share_mode); + BOOL delete_on_close = GET_DELETE_ON_CLOSE_FLAG(share_mode); BOOL file_existed = VALID_STAT(*psbuf); BOOL fcbopen = False; SMB_DEV_T dev = 0; @@ -905,6 +906,17 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", set_share_mode(fsp, port, oplock_request); + if (delete_on_close) { + NTSTATUS result = set_delete_on_close_internal(fsp, delete_on_close); + + if (NT_STATUS_V(result) != NT_STATUS_V(NT_STATUS_OK)) { + unlock_share_entry_fsp(fsp); + fd_close(conn,fsp); + file_free(fsp); + return NULL; + } + } + unlock_share_entry_fsp(fsp); conn->num_files_open++; @@ -1019,11 +1031,12 @@ int close_file_fchmod(files_struct *fsp) ****************************************************************************/ files_struct *open_directory(connection_struct *conn, char *fname, - SMB_STRUCT_STAT *psbuf, int smb_ofun, mode_t unixmode, int *action) + SMB_STRUCT_STAT *psbuf, int share_mode, int smb_ofun, mode_t unixmode, int *action) { extern struct current_user current_user; BOOL got_stat = False; files_struct *fsp = file_new(conn); + BOOL delete_on_close = GET_DELETE_ON_CLOSE_FLAG(share_mode); if(!fsp) return NULL; @@ -1126,6 +1139,14 @@ files_struct *open_directory(connection_struct *conn, char *fname, fsp->conn = conn; string_set(&fsp->fsp_name,fname); + if (delete_on_close) { + NTSTATUS result = set_delete_on_close_internal(fsp, delete_on_close); + + if (NT_STATUS_V(result) != NT_STATUS_V(NT_STATUS_OK)) { + file_free(fsp); + return NULL; + } + } conn->num_files_open++; return fsp; -- cgit From 064b3e7da7adfae06eae459e54ae0853924a4e4b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 27 Nov 2001 06:28:06 +0000 Subject: nsswitch/winbindd_group.c nsswitch/winbindd_user.c: formatting fixups. smbd/open.c: Fix "delete on close" for directories. Jeremy. (This used to be commit 014b0973a3b3b9eb22cce3053171fa55f5c16a63) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 1eae228f40..7c4e69946f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1129,7 +1129,7 @@ files_struct *open_directory(connection_struct *conn, char *fname, fsp->can_lock = True; fsp->can_read = False; fsp->can_write = False; - fsp->share_mode = 0; + fsp->share_mode = share_mode; fsp->print_file = False; fsp->modified = False; fsp->oplock_type = NO_OPLOCK; -- cgit From 01d91a82493bd025901e819d8b2626a07bc64d31 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 27 Nov 2001 23:12:25 +0000 Subject: Fix for the logic bug wrt. existant oplocks. See long message in samba-technical for explaination. Jeremy. (This used to be commit 8150f0f3f72957e77a1e6ca06760c87c516792eb) --- source3/smbd/open.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 7c4e69946f..67be12626b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -543,11 +543,8 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou 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)) { - pstring errmsg; - slprintf(errmsg, sizeof(errmsg)-1, - "open_mode_check: Existant process %d left active oplock.\n", - broken_entry.pid ); - smb_panic(errmsg); + DEBUG(0,("open_mode_check: Existant process %d left active oplock.\n", + broken_entry.pid )); } if (del_share_entry(dev, inode, &broken_entry, NULL) == -1) { -- cgit From 1a50b36d978416e7c08423296db351e434bdea50 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 28 Nov 2001 04:47:46 +0000 Subject: Re-added "Share modes" meaning don't allow deny mode conflict. Due to user demand (don't talk to me about removing parameters.... :-). Jeremy. (This used to be commit b69127391b322d81cc648f73a601ed61e79c8a44) --- source3/smbd/open.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 67be12626b..487a8a71a8 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -352,13 +352,21 @@ static int access_table(int new_deny,int old_deny,int old_mode, check if we can open a file with a share mode ****************************************************************************/ -static int check_share_mode( share_mode_entry *share, int share_mode, +static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, int share_mode, const char *fname, BOOL fcbopen, int *flags) { int deny_mode = GET_DENY_MODE(share_mode); int old_open_mode = GET_OPEN_MODE(share->share_mode); int old_deny_mode = GET_DENY_MODE(share->share_mode); + /* + * share modes = false means don't bother to check for + * DENY mode conflict. This is a *really* bad idea :-). JRA. + */ + + if(!lp_share_modes(SNUM(conn))) + return True; + /* * Don't allow any opens once the delete on close flag has been * set. @@ -514,7 +522,7 @@ 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(check_share_mode(share_entry, share_mode, fname, fcbopen, p_flags) == False) { + if(check_share_mode(conn, share_entry, share_mode, fname, fcbopen, p_flags) == False) { SAFE_FREE(old_shares); errno = EACCES; return -1; -- cgit From a17867af97a258b9d22d6216d8de887174eaa707 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 28 Nov 2001 05:03:37 +0000 Subject: Ensure the CAN_WRITE is checked and prevents O_CREAT and O_TRUNC from being set. Also prevent an open on a file on a readonly share from setting delete on close. Jeremy. (This used to be commit 1f3dcd99bdd36cd3ff492394e80c3e2037a9aa48) --- source3/smbd/open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 487a8a71a8..1e34e0c9fe 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -683,10 +683,10 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S return NULL; } - if (GET_FILE_CREATE_DISPOSITION(ofun) == FILE_CREATE_IF_NOT_EXIST) + if (CAN_WRITE(conn) && (GET_FILE_CREATE_DISPOSITION(ofun) == FILE_CREATE_IF_NOT_EXIST)) flags2 |= O_CREAT; - if (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_TRUNCATE) + if (CAN_WRITE(conn) && (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_TRUNCATE)) flags2 |= O_TRUNC; if (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_FAIL) -- cgit From 59a8827f5d7174dd2d5487dda09ccaedb43a01c3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 28 Nov 2001 18:10:13 +0000 Subject: Spelling pedents strike again :-). Jeremy. (This used to be commit 0187d4ba16c794faa372bf1a50261b8f47482064) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 1e34e0c9fe..03540ec7c3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -551,7 +551,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou 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: Existant process %d left active oplock.\n", + DEBUG(0,("open_mode_check: Existent process %d left active oplock.\n", broken_entry.pid )); } -- cgit From 28df80cf68158c37fa8ddcadd0ce94dd3ef3887e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 16 Dec 2001 23:44:38 +0000 Subject: Moved fchown_acl change to the point where we *really* know if we created the file or not. Jeremy. (This used to be commit 32dffa0ba792a81d89d06b527d82820b89507efd) --- source3/smbd/open.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 03540ec7c3..72f73deb84 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -204,16 +204,6 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, 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)) { - int saved_errno = errno; /* We might get ENOSYS in the next call.. */ - if (conn->vfs_ops.fchmod_acl(fsp, fsp->fd, mode) == -1 && errno == ENOSYS) - errno = saved_errno; /* Ignore ENOSYS */ - } - return True; } @@ -922,6 +912,16 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", } } + /* + * Take care of inherited ACLs on created files. JRA. + */ + + if (!file_existed && (conn->vfs_ops.fchmod_acl != NULL)) { + int saved_errno = errno; /* We might get ENOSYS in the next call.. */ + if (conn->vfs_ops.fchmod_acl(fsp, fsp->fd, mode) == -1 && errno == ENOSYS) + errno = saved_errno; /* Ignore ENOSYS */ + } + unlock_share_entry_fsp(fsp); conn->num_files_open++; -- cgit From 68245b54cd561f362762a057d9b99ca43d0bf958 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 12 Jan 2002 00:50:01 +0000 Subject: Added the O_NOFOLLOW flag if follow symlinks is set off. Jeremy. (This used to be commit 4f1f5f28b514dda86f6f49465bd5887357e37bc6) --- source3/smbd/open.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 72f73deb84..b42c1bacc3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -37,6 +37,12 @@ static int fd_open(struct connection_struct *conn, char *fname, #ifdef O_NONBLOCK flags |= O_NONBLOCK; #endif + +#ifdef O_NOFOLLOW + if (!lp_symlinks(SNUM(conn))) + flags |= O_NOFOLLOW; +#endif + fd = conn->vfs_ops.open(conn,fname,flags,mode); /* Fix for files ending in '.' */ -- cgit From 630e0ae8ef14e8ec75ea4d38f88453084780bf56 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 17 Jan 2002 00:25:13 +0000 Subject: don't use O_NONBLOCK in open(). This was added erroneously for kernel oplocks and really shouldn't be used (This used to be commit c3a83002cfc2e0b5158cae1898eda8bafcb41e48) --- source3/smbd/open.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index b42c1bacc3..589f1a32b4 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -34,10 +34,6 @@ static int fd_open(struct connection_struct *conn, char *fname, int flags, mode_t mode) { int fd; -#ifdef O_NONBLOCK - flags |= O_NONBLOCK; -#endif - #ifdef O_NOFOLLOW if (!lp_symlinks(SNUM(conn))) flags |= O_NOFOLLOW; -- cgit From 9d8ed7220fed8a3b7ff9d45b9c5902c3255956ac Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 25 Jan 2002 20:16:14 +0000 Subject: Fixed display of "remote downlevel document" in old print job submission case. Jeremy. (This used to be commit 248770d73072e36fd9812ec5986dce5380dfab33) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 589f1a32b4..6a6e22353b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -632,7 +632,7 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S ignored */ *Access = DOS_OPEN_WRONLY; *action = FILE_WAS_CREATED; - return print_fsp_open(conn); + return print_fsp_open(conn, fname); } fsp = file_new(conn); -- cgit From cd68afe31256ad60748b34f7318a180cfc2127cc Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 30 Jan 2002 06:08:46 +0000 Subject: Removed version number from file header. Changed "SMB/Netbios" to "SMB/CIFS" in file header. (This used to be commit 6a58c9bd06d0d7502a24bf5ce5a2faf0a146edfa) --- source3/smbd/open.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 6a6e22353b..915063a5df 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. file opening and share modes Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Jeremy Allison 2001 -- cgit From cd38c3a71c74d2c62c0cf25a3b6e9ea460036ef6 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 15 Feb 2002 02:46:13 +0000 Subject: Merge of smbclient print crash bug fix from app head. (This used to be commit a56298d56ae67a764e9b9a43c1c568b7125e1c18) --- source3/smbd/open.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 915063a5df..aab7b5079e 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -629,8 +629,10 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S if (conn->printer) { /* printers are handled completely differently. Most of the passed parameters are ignored */ - *Access = DOS_OPEN_WRONLY; - *action = FILE_WAS_CREATED; + if (Access) + *Access = DOS_OPEN_WRONLY; + if (action) + *action = FILE_WAS_CREATED; return print_fsp_open(conn, fname); } -- cgit From 97d96862ca84f599ee6fed0910389e07d46ee91d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 26 Feb 2002 05:45:33 +0000 Subject: This is a nasty hack to fix "xcopy /o" from win2000 on a Samba share The hack passes the true ntcreate desired_access down to open_file_shared1() from the ntcreatex function. This is used to determine if share modes should be used in denying this open. This hack will become unnecessary when we redo open.c to use the proper NTCreateX semantics rather than trying to jam the ntcreate semantics into openX semantics. (This used to be commit d09ae0c667a94fcf870c0fc7f97119266a650d45) --- source3/smbd/open.c | 59 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 13 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index aab7b5079e..7396233c26 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -437,8 +437,10 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i ****************************************************************************/ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T dev, - SMB_INO_T inode, 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; @@ -510,13 +512,27 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou *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, fname, fcbopen, p_flags) == False) { - SAFE_FREE(old_shares); - errno = EACCES; - return -1; + /* this is a nasty hack, but necessary until we rewrite our open + handling to use a NTCreateX call as the basic call. + NT may open a file with neither read nor write access, and in + this case it expects the open not to conflict with any + existing deny modes. This happens (for example) during a + "xcopy /o" where the second file descriptor is used for + ACL sets + This code should be removed once we have a propoer ntcreateX + open functions + (tridge) + */ + if (desired_access == 0 || + (desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE))) { + /* someone else has a share lock on it, check to see + if we can too */ + if (!check_share_mode(conn, share_entry, share_mode, + fname, fcbopen, p_flags)) { + SAFE_FREE(old_shares); + errno = EACCES; + return -1; + } } } /* end for */ @@ -608,6 +624,19 @@ static void kernel_flock(files_struct *fsp, int deny_mode) 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) +{ + 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 +****************************************************************************/ +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, + int *Access,int *action) { int flags=0; int flags2=0; @@ -736,8 +765,10 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S 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); + 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) { /* @@ -801,8 +832,10 @@ 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, 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); -- cgit From 11c0e88d9ef1728a4cfe518d85bb4cd3678edc43 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 7 Mar 2002 04:21:12 +0000 Subject: Fixed delete on close semantics - preparing for share mode rewrite. Jeremy. (This used to be commit 25dd73be29bbf0a080fe0bcbe5c478545d1e8db7) --- source3/smbd/open.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 7396233c26..03646c5019 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -941,6 +941,8 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", NTSTATUS result = set_delete_on_close_internal(fsp, delete_on_close); if (NT_STATUS_V(result) != NT_STATUS_V(NT_STATUS_OK)) { + /* Remember to delete the mode we just added. */ + del_share_mode(fsp, NULL); unlock_share_entry_fsp(fsp); fd_close(conn,fsp); file_free(fsp); -- cgit From db4c62d7ed2eb5503927edf7e25c5a2fc94f4174 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 11 Mar 2002 21:57:12 +0000 Subject: Implemented default ACL patch (set inherit acls = true on a per share basis). Based on code donated by Olaf Fr±czyk . Further commit will change to sending via vfs interface. Jeremy. (This used to be commit d85133e2697eb22f1573c78447b57791ae63dd6b) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source3/smbd/open.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 03646c5019..b284175302 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -646,6 +646,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ BOOL delete_on_close = GET_DELETE_ON_CLOSE_FLAG(share_mode); BOOL file_existed = VALID_STAT(*psbuf); BOOL fcbopen = False; + BOOL def_acl = False; SMB_DEV_T dev = 0; SMB_INO_T inode = 0; int num_share_modes = 0; @@ -800,6 +801,14 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", */ } + /* + * Ensure we pay attention to default ACLs on directories if required. + */ + + if ((flags2 & O_CREAT) && lp_inherit_acls(SNUM(conn)) && + (def_acl = directory_has_default_acl(parent_dirname(fname)))) + mode = 0777; + DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", flags,flags2,(int)mode)); @@ -951,10 +960,11 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", } /* - * Take care of inherited ACLs on created files. JRA. + * Take care of inherited ACLs on created files - if default ACL not + * selected. */ - if (!file_existed && (conn->vfs_ops.fchmod_acl != NULL)) { + if (!file_existed && !def_acl && (conn->vfs_ops.fchmod_acl != NULL)) { int saved_errno = errno; /* We might get ENOSYS in the next call.. */ if (conn->vfs_ops.fchmod_acl(fsp, fsp->fd, mode) == -1 && errno == ENOSYS) errno = saved_errno; /* Ignore ENOSYS */ -- cgit From 3bb219161a270f12c27c3bc7e1220829c6e9f284 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 12 Mar 2002 00:08:08 +0000 Subject: Added POSIX ACL layer into the vfs. Jeremy. (This used to be commit 7d59445b6962547a8938928a9371651a09e26516) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index b284175302..b86d9763a4 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -806,7 +806,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(parent_dirname(fname)))) + (def_acl = directory_has_default_acl(conn, parent_dirname(fname)))) mode = 0777; DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", -- cgit From b9e91d2a8e41a43d7ebb7d7eed807a7d8de9b329 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 20 Mar 2002 00:46:53 +0000 Subject: Remove the "stat open" code - make it inline. This should fix the bugs with opening and renaming mp3 files, also the word rename problems that people have had for a while. Needs a make clean :-) make. Also added JohnR's printing fix. Jeremy. (This used to be commit 504e5ef0494c54efbd0357e334cb2aa5a9eb9c14) --- source3/smbd/open.c | 101 ++++++++++++++-------------------------------------- 1 file changed, 27 insertions(+), 74 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index b86d9763a4..0aaf5fd1c7 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -60,7 +60,7 @@ static int fd_open(struct connection_struct *conn, char *fname, int fd_close(struct connection_struct *conn, files_struct *fsp) { if (fsp->fd == -1) - return -1; + return 0; /* what we used to call a stat open. */ return fd_close_posix(conn, fsp); } @@ -87,7 +87,7 @@ static void check_for_pipe(char *fname) ****************************************************************************/ static BOOL open_file(files_struct *fsp,connection_struct *conn, - char *fname1,SMB_STRUCT_STAT *psbuf,int flags,mode_t mode) + char *fname1,SMB_STRUCT_STAT *psbuf,int flags,mode_t mode, uint32 desired_access) { extern struct current_user current_user; pstring fname; @@ -149,18 +149,30 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, local_flags &= ~O_TRUNC; - /* actually do the open */ - fsp->fd = fd_open(conn, fname, local_flags, mode); + if (desired_access == 0 || (desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) || + (local_flags & O_CREAT)) { - if (fsp->fd == -1) { - DEBUG(3,("Error opening file %s (%s) (local_flags=%d) (flags=%d)\n", - fname,strerror(errno),local_flags,flags)); - check_for_pipe(fname); - return False; + /* actually do the open */ + fsp->fd = fd_open(conn, fname, local_flags, mode); + + if (fsp->fd == -1) { + DEBUG(3,("Error opening file %s (%s) (local_flags=%d) (flags=%d)\n", + fname,strerror(errno),local_flags,flags)); + check_for_pipe(fname); + return False; + } } + fsp->fd == -1; /* What we used to call a stat open. */ if (!VALID_STAT(*psbuf)) { - if (vfs_fstat(fsp,fsp->fd,psbuf) == -1) { + int ret; + + if (fsp->fd == -1) + ret = vfs_stat(conn, fname, psbuf); + else + ret = vfs_fstat(fsp,fsp->fd,psbuf); + + if (ret == -1) { DEBUG(0,("Error doing fstat on open file %s (%s)\n", fname,strerror(errno) )); fd_close(conn, fsp); return False; @@ -194,7 +206,6 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, 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; string_set(&fsp->fsp_name,fname); @@ -783,7 +794,8 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ * 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. */ - fsp_open = open_file(fsp,conn,fname,psbuf,flags|(flags2&~(O_TRUNC|O_CREAT)),mode); + fsp_open = open_file(fsp,conn,fname,psbuf, + flags|(flags2&~(O_TRUNC|O_CREAT)),mode,desired_access); DEBUG(4,("open_file_shared : share_mode deny - calling open_file with \ flags=0x%X flags2=0x%X mode=0%o returned %d\n", @@ -816,10 +828,10 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", * open_file strips any O_TRUNC flags itself. */ - fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,mode); + fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,mode,desired_access); if (!fsp_open && (flags == O_RDWR) && (errno != ENOENT) && fcbopen) { - if((fsp_open = open_file(fsp,conn,fname,psbuf,O_RDONLY,mode)) == True) + if((fsp_open = open_file(fsp,conn,fname,psbuf,O_RDONLY,mode,desired_access)) == True) flags = O_RDONLY; } @@ -977,65 +989,6 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", return fsp; } -/**************************************************************************** - Open a file for permissions read only. Return a pseudo file entry - with the 'stat_open' flag set -****************************************************************************/ - -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 = NULL; - - 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(psbuf->st_mode)) { - DEBUG(0,("open_file_stat: %s is a directory !\n", fname )); - return NULL; - } - - fsp = file_new(conn); - if(!fsp) - return NULL; - - *action = FILE_WAS_OPENED; - - DEBUG(5,("open_file_stat: opening file %s as a stat entry\n", fname)); - - /* - * Setup the files_struct for it. - */ - - fsp->mode = psbuf->st_mode; - fsp->inode = psbuf->st_ino; - fsp->dev = psbuf->st_dev; - fsp->size = psbuf->st_size; - fsp->vuid = current_user.vuid; - fsp->pos = -1; - fsp->can_lock = False; - fsp->can_read = False; - fsp->can_write = False; - 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 = True; - fsp->directory_delete_on_close = False; - fsp->conn = conn; - string_set(&fsp->fsp_name,fname); - fsp->wcp = NULL; /* Write cache pointer. */ - - conn->num_files_open++; - - return fsp; -} - /**************************************************************************** Open a file for for write to ensure that we can fchmod it. ****************************************************************************/ @@ -1052,7 +1005,7 @@ files_struct *open_file_fchmod(connection_struct *conn, char *fname, SMB_STRUCT_ if(!fsp) return NULL; - fsp_open = open_file(fsp,conn,fname,psbuf,O_WRONLY,0); + fsp_open = open_file(fsp,conn,fname,psbuf,O_WRONLY,0,0); /* * This is not a user visible file open. -- cgit From bffc69a877497c91f3acd77a229e9840b67f9087 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 21 Mar 2002 21:23:22 +0000 Subject: Fix stupid typo ! Jeremy. (This used to be commit d0b58f66edeac516bde2dff79ab5cf529c37954b) --- source3/smbd/open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 0aaf5fd1c7..c36dbdd522 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -161,8 +161,8 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, check_for_pipe(fname); return False; } - } - fsp->fd == -1; /* What we used to call a stat open. */ + } else + fsp->fd = -1; /* What we used to call a stat open. */ if (!VALID_STAT(*psbuf)) { int ret; -- cgit From c90cd26e9430b2fc065f620bdb6aaf4be0372fcc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 23 Mar 2002 02:57:44 +0000 Subject: Fix the mp3 rename bug - also tidy up our open code and remove the special cases for rename and unlink. Had to add desired_access into the share mode record. Jeremy. (This used to be commit 3b1b8ac43535fb0839c5474fa55bf7150f6cde31) --- source3/smbd/open.c | 331 ++++++++++++++++++++++++++-------------------------- 1 file changed, 164 insertions(+), 167 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index c36dbdd522..bcb866c378 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -149,7 +149,7 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, local_flags &= ~O_TRUNC; - if (desired_access == 0 || (desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) || + if ((desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) || (local_flags & O_CREAT)) { /* actually do the open */ @@ -201,6 +201,7 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->can_read = ((flags & O_WRONLY)==0); fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0); fsp->share_mode = 0; + fsp->desired_access = desired_access; fsp->print_file = False; fsp->modified = False; fsp->oplock_type = NO_OPLOCK; @@ -354,7 +355,7 @@ static int access_table(int new_deny,int old_deny,int old_mode, check if we can open a file with a share mode ****************************************************************************/ -static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, int share_mode, +static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, int share_mode, uint32 desired_access, const char *fname, BOOL fcbopen, int *flags) { int deny_mode = GET_DENY_MODE(share_mode); @@ -382,12 +383,43 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i return False; } + /* this is a nasty hack, but necessary until we rewrite our open + handling to use a NTCreateX call as the basic call. + NT may open a file with neither read nor write access, and in + this case it expects the open not to conflict with any + existing deny modes. This happens (for example) during a + "xcopy /o" where the second file descriptor is used for + ACL sets + (tridge) + */ + + /* + * This is a bit wierd - the test for desired access not having the + * critical bits seems seems odd. Firstly, if both opens have no + * critical bits then always ignore. Then check the "allow delete" + * then check for either. This probably isn't quite right yet but + * gets us much closer. JRA. + */ + + /* + * If desired_access doesn't contain READ_DATA,WRITE_DATA,APPEND_DATA or EXECUTE + * and the existing desired_acces then share modes don't conflict. + */ + + if ( !(desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) && + !(share->desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ) { + DEBUG(5,("check_share_mode: Allowing open on file %s as both desired access (0x%x) \ +and existing desired access (0x%x) are non-data opens\n", + fname, (unsigned int)desired_access, (unsigned int)share->desired_access )); + return True; + } + /* * If delete access was requested and the existing share mode doesn't have * ALLOW_SHARE_DELETE then deny. */ - if (GET_DELETE_ACCESS_REQUESTED(share_mode) && !GET_ALLOW_SHARE_DELETE(share->share_mode)) { + if ((desired_access & DELETE_ACCESS) && !GET_ALLOW_SHARE_DELETE(share->share_mode)) { DEBUG(5,("check_share_mode: Failing open on file %s as delete access requested and allow share delete not set.\n", fname )); unix_ERR_class = ERRDOS; @@ -402,7 +434,7 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i * ALLOW_SHARE_DELETE then deny. */ - if (GET_DELETE_ACCESS_REQUESTED(share->share_mode) && !GET_ALLOW_SHARE_DELETE(share_mode)) { + if ((share->desired_access & DELETE_ACCESS) && !GET_ALLOW_SHARE_DELETE(share_mode)) { DEBUG(5,("check_share_mode: Failing open on file %s as delete access granted and allow share delete not requested.\n", fname )); unix_ERR_class = ERRDOS; @@ -411,9 +443,21 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i return False; } + /* + * If desired_access doesn't contain READ_DATA,WRITE_DATA,APPEND_DATA or EXECUTE + * then share modes don't conflict. Likewise with existing desired access. + */ + + if ( !(desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) || + !(share->desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ) { + DEBUG(5,("check_share_mode: Allowing open on file %s as desired access (0x%x) doesn't conflict with\ +existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsigned int)share->desired_access )); + return True; + } + { int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode, - (share->pid == sys_getpid()),is_executable(fname)); + (share->pid == sys_getpid()),is_executable(fname)); if ((access_allowed == AFAIL) || (!fcbopen && (access_allowed == AREAD && *flags == O_RDWR)) || @@ -523,28 +567,13 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou *p_all_current_opens_are_level_II = False; } - /* this is a nasty hack, but necessary until we rewrite our open - handling to use a NTCreateX call as the basic call. - NT may open a file with neither read nor write access, and in - this case it expects the open not to conflict with any - existing deny modes. This happens (for example) during a - "xcopy /o" where the second file descriptor is used for - ACL sets - This code should be removed once we have a propoer ntcreateX - open functions - (tridge) - */ - if (desired_access == 0 || - (desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE))) { - /* someone else has a share lock on it, check to see - if we can too */ - if (!check_share_mode(conn, share_entry, share_mode, - fname, fcbopen, p_flags)) { - SAFE_FREE(old_shares); - errno = EACCES; - return -1; - } - } + /* 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, + fname, fcbopen, p_flags)) { + SAFE_FREE(old_shares); + errno = EACCES; + return -1; + } } /* end for */ @@ -653,7 +682,6 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ int flags2=0; int deny_mode = GET_DENY_MODE(share_mode); BOOL allow_share_delete = GET_ALLOW_SHARE_DELETE(share_mode); - BOOL delete_access_requested = GET_DELETE_ACCESS_REQUESTED(share_mode); BOOL delete_on_close = GET_DELETE_ON_CLOSE_FLAG(share_mode); BOOL file_existed = VALID_STAT(*psbuf); BOOL fcbopen = False; @@ -732,16 +760,24 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ switch (GET_OPEN_MODE(share_mode)) { case DOS_OPEN_WRONLY: flags = O_WRONLY; + if (desired_access == 0) + desired_access = FILE_WRITE_DATA; break; case DOS_OPEN_FCB: fcbopen = True; flags = O_RDWR; + if (desired_access == 0) + desired_access = FILE_READ_DATA|FILE_WRITE_DATA; break; case DOS_OPEN_RDWR: flags = O_RDWR; + if (desired_access == 0) + desired_access = FILE_READ_DATA|FILE_WRITE_DATA; break; default: flags = O_RDONLY; + if (desired_access == 0) + desired_access = FILE_READ_DATA; break; } @@ -922,8 +958,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", fsp->share_mode = SET_DENY_MODE(deny_mode) | SET_OPEN_MODE(open_mode) | - SET_ALLOW_SHARE_DELETE(allow_share_delete) | - SET_DELETE_ACCESS_REQUESTED(delete_access_requested); + SET_ALLOW_SHARE_DELETE(allow_share_delete); DEBUG(10,("open_file_shared : share_mode = %x\n", fsp->share_mode )); @@ -1036,8 +1071,8 @@ int close_file_fchmod(files_struct *fsp) Open a directory from an NT SMB call. ****************************************************************************/ -files_struct *open_directory(connection_struct *conn, char *fname, - SMB_STRUCT_STAT *psbuf, int share_mode, int smb_ofun, mode_t unixmode, int *action) +files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_STAT *psbuf, + uint32 desired_access, int share_mode, int smb_ofun, mode_t unixmode, int *action) { extern struct current_user current_user; BOOL got_stat = False; @@ -1136,6 +1171,7 @@ files_struct *open_directory(connection_struct *conn, char *fname, fsp->can_read = False; fsp->can_write = False; fsp->share_mode = share_mode; + fsp->desired_access = desired_access; fsp->print_file = False; fsp->modified = False; fsp->oplock_type = NO_OPLOCK; @@ -1157,6 +1193,9 @@ files_struct *open_directory(connection_struct *conn, char *fname, return fsp; } +#if 0 + +Old code - I have replaced with correct desired_access checking. JRA. /******************************************************************* Check if the share mode on a file allows it to be deleted or unlinked. @@ -1165,149 +1204,107 @@ files_struct *open_directory(connection_struct *conn, char *fname, BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) { - int i; - int ret = False; - share_mode_entry *old_shares = 0; - int num_share_modes; - SMB_STRUCT_STAT sbuf; - pid_t pid = sys_getpid(); - SMB_DEV_T dev; - SMB_INO_T inode; - - if (vfs_stat(conn,fname,&sbuf) == -1) - return(True); - - dev = sbuf.st_dev; - inode = sbuf.st_ino; - - lock_share_entry(conn, dev, inode); - num_share_modes = get_share_modes(conn, dev, inode, &old_shares); - - /* - * Check if the share modes will give us access. - */ - - if(num_share_modes != 0) - { - BOOL broke_oplock; - - do - { - - broke_oplock = False; - for(i = 0; i < num_share_modes; i++) - { - share_mode_entry *share_entry = &old_shares[i]; - - /* - * Break oplocks before checking share modes. See comment in - * open_file_shared for details. - * Check if someone has an oplock on this file. If so we must - * break it before continuing. - */ - if(BATCH_OPLOCK_TYPE(share_entry->op_type)) - { + int i; + int ret = False; + share_mode_entry *old_shares = 0; + int num_share_modes; + SMB_STRUCT_STAT sbuf; + pid_t pid = sys_getpid(); + SMB_DEV_T dev; + SMB_INO_T inode; -#if 0 + if (vfs_stat(conn,fname,&sbuf) == -1) + return(True); -/* JRA. Try removing this code to see if the new oplock changes - fix the problem. I'm dubious, but Andrew is recommending we - try this.... -*/ + dev = sbuf.st_dev; + inode = sbuf.st_ino; - /* - * It appears that the NT redirector may have a bug, in that - * it tries to do an SMBmv on a file that it has open with a - * batch oplock, and then fails to respond to the oplock break - * request. This only seems to occur when the client is doing an - * SMBmv to the smbd it is using - thus we try and detect this - * condition by checking if the file being moved is open and oplocked by - * this smbd process, and then not sending the oplock break in this - * special case. If the file was open with a deny mode that - * prevents the move the SMBmv will fail anyway with a share - * violation error. JRA. - */ - if(rename_op && (share_entry->pid == pid)) - { - - 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)); - - /* - * This next line is a test that allows the deny-mode - * processing to be skipped. This seems to be needed as - * NT insists on the rename succeeding (in Office 9x no less !). - * This should be removed as soon as (a) MS fix the redirector - * bug or (b) NT SMB support in Samba makes NT not issue the - * call (as is my fervent hope). JRA. - */ - continue; - } - else -#endif /* 0 */ - { - - DEBUG(5,("check_file_sharing: breaking oplock (%x) on file %s, \ + lock_share_entry(conn, dev, inode); + num_share_modes = get_share_modes(conn, dev, inode, &old_shares); + + /* + * Check if the share modes will give us access. + */ + + if(num_share_modes != 0) { + BOOL broke_oplock; + + do { + + broke_oplock = False; + for(i = 0; i < num_share_modes; i++) { + share_mode_entry *share_entry = &old_shares[i]; + + /* + * Break oplocks before checking share modes. See comment in + * open_file_shared for details. + * Check if someone has an oplock on this file. If so we must + * break it before continuing. + */ + if(BATCH_OPLOCK_TYPE(share_entry->op_type)) { + + 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)); - /* Oplock break.... */ - unlock_share_entry(conn, dev, inode); - if(request_oplock_break(share_entry) == False) - { - DEBUG(0,("check_file_sharing: FAILED when breaking oplock (%x) on file %s, \ + /* Oplock break.... */ + unlock_share_entry(conn, dev, inode); + + if(request_oplock_break(share_entry) == False) { + 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)); - SAFE_FREE(old_shares); - return False; - } - lock_share_entry(conn, dev, inode); - broke_oplock = True; - break; - } - } - - /* - * 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 */ - - if(broke_oplock) - { - SAFE_FREE(old_shares); - num_share_modes = get_share_modes(conn, dev, inode, &old_shares); - } - } while(broke_oplock); - } - - /* 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() or - * delete access was requested and all share modes had the - * ALLOW_SHARE_DELETE bit set (takes precedence over other - * share modes). - */ - - ret = True; + SAFE_FREE(old_shares); + return False; + } + lock_share_entry(conn, dev, inode); + broke_oplock = True; + break; + } + + /* + * 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 */ + + if(broke_oplock) { + SAFE_FREE(old_shares); + num_share_modes = get_share_modes(conn, dev, inode, &old_shares); + } + } while(broke_oplock); + } + + /* + * 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() 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: - unlock_share_entry(conn, dev, inode); - SAFE_FREE(old_shares); - return(ret); + unlock_share_entry(conn, dev, inode); + SAFE_FREE(old_shares); + return(ret); } +#endif -- cgit From 81a0d5b5e92d7c8d5d426f8bd13d43ff394fe7e8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 26 Mar 2002 00:38:12 +0000 Subject: Matched W2K *insane* open semantics.... Jeremy. (This used to be commit 6819e81da490914d2db91c4d2419d408b8d4c818) --- source3/smbd/open.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index bcb866c378..29a854a397 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -408,6 +408,24 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i if ( !(desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) && !(share->desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ) { + + /* + * Wrinkle discovered by smbtorture.... + * If both are non-io open and requester is asking for delete and current open has delete access + * but neither open has allowed file share delete then deny.... this is very strange and + * seems to be the only case in which non-io opens conflict. JRA. + */ + + if ((desired_access & DELETE_ACCESS) && (share->desired_access & DELETE_ACCESS) && + (!GET_ALLOW_SHARE_DELETE(share->share_mode) || !GET_ALLOW_SHARE_DELETE(share_mode))) { + DEBUG(5,("check_share_mode: Failing open on file %s as delete access requests conflict.\n", + fname )); + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + + return False; + } + DEBUG(5,("check_share_mode: Allowing open on file %s as both desired access (0x%x) \ and existing desired access (0x%x) are non-data opens\n", fname, (unsigned int)desired_access, (unsigned int)share->desired_access )); -- cgit From e90b65284812aaa5ff9e9935ce9bbad7791cbbcd Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 15 Jul 2002 10:35:28 +0000 Subject: updated the 3.0 branch from the head branch - ready for alpha18 (This used to be commit 03ac082dcb375b6f3ca3d810a6a6367542bc23ce) --- source3/smbd/open.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 29a854a397..8c6e8ed805 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -87,7 +87,7 @@ static void check_for_pipe(char *fname) ****************************************************************************/ static BOOL open_file(files_struct *fsp,connection_struct *conn, - char *fname1,SMB_STRUCT_STAT *psbuf,int flags,mode_t mode, uint32 desired_access) + const char *fname1,SMB_STRUCT_STAT *psbuf,int flags,mode_t mode, uint32 desired_access) { extern struct current_user current_user; pstring fname; @@ -169,11 +169,15 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, if (fsp->fd == -1) ret = vfs_stat(conn, fname, psbuf); - else + else { ret = vfs_fstat(fsp,fsp->fd,psbuf); + /* If we have an fd, this stat should succeed. */ + if (ret == -1) + DEBUG(0,("Error doing fstat on open file %s (%s)\n", fname,strerror(errno) )); + } + /* For a non-io open, this stat failing means file not found. JRA */ if (ret == -1) { - DEBUG(0,("Error doing fstat on open file %s (%s)\n", fname,strerror(errno) )); fd_close(conn, fsp); return False; } @@ -1046,7 +1050,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", Open a file for for write to ensure that we can fchmod it. ****************************************************************************/ -files_struct *open_file_fchmod(connection_struct *conn, char *fname, SMB_STRUCT_STAT *psbuf) +files_struct *open_file_fchmod(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf) { files_struct *fsp = NULL; BOOL fsp_open; @@ -1058,7 +1062,9 @@ files_struct *open_file_fchmod(connection_struct *conn, char *fname, SMB_STRUCT_ if(!fsp) return NULL; - fsp_open = open_file(fsp,conn,fname,psbuf,O_WRONLY,0,0); + /* note! we must use a non-zero desired access or we don't get + a real file descriptor. Oh what a twisted web we weave. */ + fsp_open = open_file(fsp,conn,fname,psbuf,O_WRONLY,0,FILE_WRITE_DATA); /* * This is not a user visible file open. @@ -1158,7 +1164,7 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST */ if(!got_stat) { - DEBUG(0,("open_directory: unable to stat name = %s. Error was %s\n", + DEBUG(3,("open_directory: unable to stat name = %s. Error was %s\n", fname, strerror(errno) )); file_free(fsp); return NULL; -- cgit From a834a73e341059be154426390304a42e4a011f72 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 25 Sep 2002 15:19:00 +0000 Subject: sync'ing up for 3.0alpha20 release (This used to be commit 65e7b5273bb58802bf0c389b77f7fcae0a1f6139) --- source3/smbd/open.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 57 insertions(+), 8 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 8c6e8ed805..a95793a050 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -139,18 +139,31 @@ 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)) + if ((accmode == O_RDONLY) && ((flags & O_TRUNC) == O_TRUNC)) { + DEBUG(10,("open_file: truncate requested on read-only open for file %s\n",fname )); local_flags = (flags & ~O_ACCMODE)|O_RDWR; + } - /* - * We can't actually truncate here as the file may be locked. - * open_file_shared will take care of the truncate later. JRA. - */ + if ((desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) || + (local_flags & O_CREAT) || ((local_flags & O_TRUNC) == O_TRUNC) ) { - local_flags &= ~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. + */ - if ((desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) || - (local_flags & O_CREAT)) { + 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. + */ + + if (VALID_STAT(*psbuf) && S_ISFIFO(psbuf->st_mode)) + local_flags |= O_NONBLOCK; +#endif /* actually do the open */ fsp->fd = fd_open(conn, fname, local_flags, mode); @@ -679,6 +692,31 @@ 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 @@ -773,6 +811,17 @@ 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; -- cgit From f735551b9edef66b152261cf6eb2f29b7b69d65b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 23 Oct 2002 01:22:32 +0000 Subject: First cut of new ACL mapping code from Andreas Gruenbacher . This is not 100% the same as what SuSE shipped in their Samba, there is a crash bug fix, a race condition fix, and a few logic changes I'd like to discuss with Andreas. Added Andreas to (C) notices for posix_acls.c Jeremy. (This used to be commit 40eafb9dde113af9f7f1808fda22908953f7e8c3) --- source3/smbd/open.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index a95793a050..417a9dd039 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -165,9 +165,13 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, local_flags |= O_NONBLOCK; #endif - /* actually do the open */ + /* Actually do the open */ fsp->fd = fd_open(conn, fname, local_flags, mode); + /* Inherit the ACL if the file was created. */ + if ((local_flags & O_CREAT) && !VALID_STAT(*psbuf)) + inherit_access_acl(conn, fname, mode); + if (fsp->fd == -1) { DEBUG(3,("Error opening file %s (%s) (local_flags=%d) (flags=%d)\n", fname,strerror(errno),local_flags,flags)); -- cgit From b51160452eb992fd15bf45b9616a56bae9d16e37 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 5 Nov 2002 21:47:03 +0000 Subject: Fix to correctly return NT_STATUS_DELETE_PENDING. Jeremy. (This used to be commit 4ec381d64249203e0924b86600fe8e67ada1cb5b) --- source3/smbd/open.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 417a9dd039..94a705e6b6 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -401,6 +401,7 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i fname )); unix_ERR_class = ERRDOS; unix_ERR_code = ERRnoaccess; + unix_ERR_ntstatus = NT_STATUS_DELETE_PENDING; return False; } -- cgit From faf1f0df4d8f047fb2dcbd27305c61a1e70a8db3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 19 Nov 2002 01:46:10 +0000 Subject: Very curious. It turns out attribute matching on truncate only matters when opening truncate with current SYSTEM|HIDDEN -> NONE. It's fine to truncate on open with current NONE -> SYSTEM | HIDDEN. Jeremy. (This used to be commit 3bf21ca936973efcd74b826bc750131c6ab2c701) --- source3/smbd/open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 94a705e6b6..cee2b37184 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -712,11 +712,11 @@ static BOOL open_match_attributes(connection_struct *conn, char *path, mode_t ex /* 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)) + 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)) + if ((old_dos_mode & FILE_ATTRIBUTE_HIDDEN) && !(new_dos_mode & FILE_ATTRIBUTE_HIDDEN)) return False; } return True; -- cgit From 20f1cf6cdcf9fc74d18fb9401e627a3455183ef3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 3 Jan 2003 18:50:13 +0000 Subject: Fix problem with "hide unreadable". stat file opens are baaack :-). Jeremy. (This used to be commit 62038a0abf193d4dc4f37c31ac77216a10f6f326) --- source3/smbd/open.c | 144 ++++++++++++++++------------------------------------ 1 file changed, 45 insertions(+), 99 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index cee2b37184..d5521f7f47 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -228,6 +228,7 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = False; + fsp->is_stat = False; fsp->directory_delete_on_close = False; fsp->conn = conn; string_set(&fsp->fsp_name,fname); @@ -1255,6 +1256,7 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = True; + fsp->is_stat = False; fsp->directory_delete_on_close = False; fsp->conn = conn; string_set(&fsp->fsp_name,fname); @@ -1271,118 +1273,62 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST return fsp; } -#if 0 -Old code - I have replaced with correct desired_access checking. JRA. - -/******************************************************************* - Check if the share mode on a file allows it to be deleted or unlinked. - Return True if sharing doesn't prevent the operation. -********************************************************************/ +/**************************************************************************** + Open a pseudo-file (no locking checks - a 'stat' open). +****************************************************************************/ -BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) +files_struct *open_file_stat(connection_struct *conn, char *fname, SMB_STRUCT_STAT *psbuf) { - int i; - int ret = False; - share_mode_entry *old_shares = 0; - int num_share_modes; - SMB_STRUCT_STAT sbuf; - pid_t pid = sys_getpid(); - SMB_DEV_T dev; - SMB_INO_T inode; - - if (vfs_stat(conn,fname,&sbuf) == -1) - return(True); - - dev = sbuf.st_dev; - inode = sbuf.st_ino; - - lock_share_entry(conn, dev, inode); - num_share_modes = get_share_modes(conn, dev, inode, &old_shares); - - /* - * Check if the share modes will give us access. - */ - - if(num_share_modes != 0) { - BOOL broke_oplock; - - do { - - broke_oplock = False; - for(i = 0; i < num_share_modes; i++) { - share_mode_entry *share_entry = &old_shares[i]; - - /* - * Break oplocks before checking share modes. See comment in - * open_file_shared for details. - * Check if someone has an oplock on this file. If so we must - * break it before continuing. - */ - if(BATCH_OPLOCK_TYPE(share_entry->op_type)) { - - 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)); + extern struct current_user current_user; + BOOL got_stat = False; + files_struct *fsp = NULL; - /* Oplock break.... */ - unlock_share_entry(conn, dev, inode); + if (!VALID_STAT(*psbuf)) + return NULL; - if(request_oplock_break(share_entry) == False) { - 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)); + /* Can't 'stat' open directories. */ + if(S_ISDIR(psbuf->st_mode)) + return NULL; - SAFE_FREE(old_shares); - return False; - } - lock_share_entry(conn, dev, inode); - broke_oplock = True; - break; - } + fsp = file_new(conn); + if(!fsp) + return NULL; - /* - * 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 */ + fsp->conn = conn; /* The vfs_fXXX() macros need this. */ - if(broke_oplock) { - SAFE_FREE(old_shares); - num_share_modes = get_share_modes(conn, dev, inode, &old_shares); - } - } while(broke_oplock); - } + DEBUG(5,("open_file_stat: 'opening' file %s\n", fname)); /* - * XXXX exactly what share mode combinations should be allowed for - * deleting/renaming? + * Setup the files_struct for it. */ - + + fsp->mode = psbuf->st_mode; /* - * 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). + * Don't store dev or inode, we don't want any iterator + * to see this. */ + fsp->inode = (SMB_INO_T)0; + fsp->dev = (SMB_DEV_T)0; + fsp->size = psbuf->st_size; + fsp->vuid = current_user.vuid; + fsp->pos = -1; + fsp->can_lock = False; + fsp->can_read = False; + fsp->can_write = False; + fsp->share_mode = 0; + fsp->desired_access = 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->is_stat = True; + fsp->directory_delete_on_close = False; + fsp->conn = conn; + string_set(&fsp->fsp_name,fname); - ret = True; - -free_and_exit: + conn->num_files_open++; - unlock_share_entry(conn, dev, inode); - SAFE_FREE(old_shares); - return(ret); + return fsp; } -#endif -- cgit From 7f4177aa9e85c5d801aefabf39e08e40bce04f7d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 8 Jan 2003 02:09:18 +0000 Subject: Fix open problem with changing attributes on an existing file - based on work by . Jeremy. (This used to be commit 1cff725e37d04e25d2cd5523683b35c82d5040fa) --- source3/smbd/open.c | 53 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 8 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index d5521f7f47..5c3359fc6b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -698,7 +698,8 @@ 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) +static BOOL open_match_attributes(connection_struct *conn, char *path, mode_t existing_mode, + mode_t new_mode, mode_t *returned_mode) { uint32 old_dos_mode, new_dos_mode; SMB_STRUCT_STAT sbuf; @@ -711,22 +712,33 @@ static BOOL open_match_attributes(connection_struct *conn, char *path, mode_t ex sbuf.st_mode = new_mode; new_dos_mode = dos_mode(conn, path, &sbuf); + /* + * We only set returned mode to be the same as new_mode if + * the file attributes need to be changed. + */ + + *returned_mode = (mode_t)0; + /* 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 (!(old_dos_mode & FILE_ATTRIBUTE_SYSTEM) && (new_dos_mode & FILE_ATTRIBUTE_SYSTEM)) + *returned_mode = new_mode; } if (lp_map_hidden(SNUM(conn))) { if ((old_dos_mode & FILE_ATTRIBUTE_HIDDEN) && !(new_dos_mode & FILE_ATTRIBUTE_HIDDEN)) return False; + if (!(old_dos_mode & FILE_ATTRIBUTE_HIDDEN) && (new_dos_mode & FILE_ATTRIBUTE_HIDDEN)) + *returned_mode = new_mode; } 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. ****************************************************************************/ + 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) @@ -736,9 +748,9 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S } /**************************************************************************** - Open a file with a share mode. On output from this open we are guarenteeing - that + Open a file with a share mode. ****************************************************************************/ + 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, @@ -760,6 +772,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ files_struct *fsp = NULL; int open_mode=0; uint16 port = 0; + mode_t new_mode = (mode_t)0; if (conn->printer) { /* printers are handled completely differently. Most of the passed parameters are @@ -819,7 +832,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ /* 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)) { + if (!open_match_attributes(conn, fname, psbuf->st_mode, mode, &new_mode)) { DEBUG(5,("open_file_shared: attributes missmatch for file %s (0%o, 0%o)\n", fname, psbuf->st_mode, mode )); file_free(fsp); @@ -1089,11 +1102,36 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", */ if (!file_existed && !def_acl && (conn->vfs_ops.fchmod_acl != NULL)) { + int saved_errno = errno; /* We might get ENOSYS in the next call.. */ + if (conn->vfs_ops.fchmod_acl(fsp, fsp->fd, mode) == -1 && errno == ENOSYS) errno = saved_errno; /* Ignore ENOSYS */ + + } else if (new_mode) { + + int ret = -1; + + /* Attributes need changing. File already existed. */ + + if (conn->vfs_ops.fchmod_acl != NULL) { + int saved_errno = errno; /* We might get ENOSYS in the next call.. */ + ret = conn->vfs_ops.fchmod_acl(fsp, fsp->fd, new_mode); + + if (ret == -1 && errno == ENOSYS) { + errno = saved_errno; /* Ignore ENOSYS */ + } else { + DEBUG(5, ("open_file_shared: failed to reset attributes of file %s to 0%o\n", + fname, (int)new_mode)); + ret = 0; /* Don't do the fchmod below. */ + } + } + + if ((ret == -1) && (conn->vfs_ops.fchmod(fsp, fsp->fd, new_mode) == -1)) + DEBUG(5, ("open_file_shared: failed to reset attributes of file %s to 0%o\n", + fname, (int)new_mode)); } - + unlock_share_entry_fsp(fsp); conn->num_files_open++; @@ -1281,7 +1319,6 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST files_struct *open_file_stat(connection_struct *conn, char *fname, SMB_STRUCT_STAT *psbuf) { extern struct current_user current_user; - BOOL got_stat = False; files_struct *fsp = NULL; if (!VALID_STAT(*psbuf)) -- cgit From b61f89826f2b7ee8ca7bd388b66c3f5b78ed3e60 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 30 Jan 2003 01:41:46 +0000 Subject: Fix for interesting resource constraint condition. When all opens are level 2 and a request for open with no oplock is received then the smbd should send *synchronous* break messages, not asynchronous, otherwise it spins very rapidly, releasing the lock, sending the 'break to none' messages and then re-acquiring the lock before any other process has a chance to get the lock and remove it's own oplock (at least on linux). Jeremy (This used to be commit 33e3e863eb7f35b852384e689f3272784261fc39) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 5c3359fc6b..29048bca02 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -585,7 +585,7 @@ dev = %x, inode = %.0f\n", *p_oplock_request, share_entry->op_type, fname, (unsi /* Oplock break - unlock to request it. */ unlock_share_entry(conn, dev, inode); - opb_ret = request_oplock_break(share_entry); + opb_ret = request_oplock_break(share_entry, False); /* Now relock. */ lock_share_entry(conn, dev, inode); -- cgit From 70a03079a78d8305221106a4c21102fd088a4362 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 4 Feb 2003 01:11:56 +0000 Subject: Ensure Samba passes the open attribute truncate tests in smbtorture. Jeremy. (This used to be commit b3df40bc803e7dc3b66a95eccb335e2b1775560e) --- source3/smbd/open.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 29048bca02..dea7edc528 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -702,6 +702,7 @@ static BOOL open_match_attributes(connection_struct *conn, char *path, mode_t ex mode_t new_mode, mode_t *returned_mode) { uint32 old_dos_mode, new_dos_mode; + uint32 noarch_old_dos_mode, noarch_new_dos_mode; SMB_STRUCT_STAT sbuf; ZERO_STRUCT(sbuf); @@ -712,25 +713,27 @@ static BOOL open_match_attributes(connection_struct *conn, char *path, mode_t ex sbuf.st_mode = new_mode; new_dos_mode = dos_mode(conn, path, &sbuf); - /* - * We only set returned mode to be the same as new_mode if - * the file attributes need to be changed. - */ + noarch_old_dos_mode = (old_dos_mode & ~FILE_ATTRIBUTE_ARCHIVE); + noarch_new_dos_mode = (new_dos_mode & ~FILE_ATTRIBUTE_ARCHIVE); + + if((noarch_old_dos_mode == 0 && noarch_new_dos_mode != 0) || + (noarch_old_dos_mode != 0 && ((noarch_old_dos_mode & noarch_new_dos_mode) == noarch_old_dos_mode))) + *returned_mode = new_mode; + else + *returned_mode = (mode_t)0; - *returned_mode = (mode_t)0; + DEBUG(10,("open_match_attributes: file %s old_dos_mode = 0x%x, existing_mode = 0%o, new_dos_mode = 0x%x returned_mode = 0%o\n", + path, + old_dos_mode, (unsigned int)existing_mode, new_dos_mode, (unsigned int)*returned_mode )); /* 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 (!(old_dos_mode & FILE_ATTRIBUTE_SYSTEM) && (new_dos_mode & FILE_ATTRIBUTE_SYSTEM)) - *returned_mode = new_mode; } if (lp_map_hidden(SNUM(conn))) { if ((old_dos_mode & FILE_ATTRIBUTE_HIDDEN) && !(new_dos_mode & FILE_ATTRIBUTE_HIDDEN)) return False; - if (!(old_dos_mode & FILE_ATTRIBUTE_HIDDEN) && (new_dos_mode & FILE_ATTRIBUTE_HIDDEN)) - *returned_mode = new_mode; } return True; } -- cgit From ce85e52eff9d8a61a58c559bdf4beb5e1284060d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 4 Feb 2003 01:43:10 +0000 Subject: Ensure we only ever set fsp->conn in one place. Jeremy. (This used to be commit d8a42753cc1e1a94aa6b816222343e1569521f14) --- source3/smbd/open.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index dea7edc528..6570745816 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -230,7 +230,6 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->is_directory = False; fsp->is_stat = False; fsp->directory_delete_on_close = False; - fsp->conn = conn; string_set(&fsp->fsp_name,fname); fsp->wcp = NULL; /* Write cache pointer. */ @@ -1202,8 +1201,6 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST if(!fsp) return NULL; - fsp->conn = conn; /* The vfs_fXXX() macros need this. */ - if (VALID_STAT(*psbuf)) got_stat = True; @@ -1299,7 +1296,6 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST fsp->is_directory = True; fsp->is_stat = False; fsp->directory_delete_on_close = False; - fsp->conn = conn; string_set(&fsp->fsp_name,fname); if (delete_on_close) { @@ -1335,8 +1331,6 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, SMB_STRUCT_ST if(!fsp) return NULL; - fsp->conn = conn; /* The vfs_fXXX() macros need this. */ - DEBUG(5,("open_file_stat: 'opening' file %s\n", fname)); /* @@ -1365,7 +1359,6 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, SMB_STRUCT_ST fsp->is_directory = False; fsp->is_stat = True; fsp->directory_delete_on_close = False; - fsp->conn = conn; string_set(&fsp->fsp_name,fname); conn->num_files_open++; -- cgit From 7d4eef34e3a1eb080c580385ef68892180b6847b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Feb 2003 01:13:35 +0000 Subject: Correctly return access denied on share mode deny when we can't open the file. This is a regression that was damaged by other code. Jeremy. (This used to be commit 7844a53df72af8fd2f70d51b784352aeb1298ed2) --- source3/smbd/open.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 6570745816..6b3dcbe71b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -79,6 +79,7 @@ static void check_for_pipe(char *fname) DEBUG(3,("Rejecting named pipe open for %s\n",fname)); unix_ERR_class = ERRSRV; unix_ERR_code = ERRaccess; + unix_ERR_ntstatus = NT_STATUS_ACCESS_DENIED; } } @@ -255,6 +256,7 @@ static int truncate_unless_locked(struct connection_struct *conn, files_struct * errno = EACCES; unix_ERR_class = ERRDOS; unix_ERR_code = ERRlock; + unix_ERR_ntstatus = dos_to_ntstatus(ERRDOS, ERRlock); return -1; } else { return conn->vfs_ops.ftruncate(fsp,fsp->fd,0); @@ -399,9 +401,10 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i 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; - unix_ERR_ntstatus = NT_STATUS_DELETE_PENDING; + /* Use errno to map to correct error. */ + unix_ERR_class = SMB_SUCCESS; + unix_ERR_code = 0; + unix_ERR_ntstatus = NT_STATUS_OK; return False; } @@ -444,6 +447,7 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i fname )); unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadshare; + unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; return False; } @@ -464,6 +468,7 @@ and existing desired access (0x%x) are non-data opens\n", fname )); unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadshare; + unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; return False; } @@ -479,6 +484,7 @@ and existing desired access (0x%x) are non-data opens\n", fname )); unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadshare; + unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; return False; } @@ -510,6 +516,7 @@ existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsign unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadshare; + unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; return False; } @@ -596,6 +603,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou errno = EACCES; unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadshare; + unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; return -1; } @@ -646,6 +654,7 @@ dev = %x, inode = %.0f. Deleting it to continue...\n", (int)broken_entry.pid, fn errno = EACCES; unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadshare; + unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; return -1; } @@ -922,6 +931,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ * 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. */ + errno = 0; fsp_open = open_file(fsp,conn,fname,psbuf, flags|(flags2&~(O_TRUNC|O_CREAT)),mode,desired_access); @@ -929,6 +939,12 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ flags=0x%X flags2=0x%X mode=0%o returned %d\n", flags,(flags2&~(O_TRUNC|O_CREAT)),(int)mode,(int)fsp_open )); + if (!fsp_open && errno) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRnoaccess; + unix_ERR_ntstatus = NT_STATUS_ACCESS_DENIED; + } + unlock_share_entry(conn, dev, inode); if (fsp_open) fd_close(conn, fsp); -- cgit From 2aa7b1573c940d7a0381ac33f97ee5bd185c16bd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 22 Apr 2003 17:30:53 +0000 Subject: Add runtime tests for "impossible" case with -DDEVELOPER. Trying to catch logic error on Linux. Jeremy. (This used to be commit 546d1a941b63a538702f2fb668019d2b89f63bdc) --- source3/smbd/open.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 6b3dcbe71b..5e4f3caca7 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -532,6 +532,29 @@ existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsign return True; } + +#if defined(DEVELOPER) +static void validate_my_share_entries(share_mode_entry *share_entry) +{ + files_struct *fsp; + + if (share_entry->pid != sys_getpid()) + return; + + fsp = file_find_dif(share_entry->dev, share_entry->inode, share_entry->share_file_id); + if (!fsp) { + smb_panic("validate_my_share_entries: Cannot match a share entry with an open file\n"); + } + + if (((uint16)fsp->oplock_type) != share_entry->op_type) { + pstring str; + slprintf(str, sizeof(str)-1, "validate_my_share_entries: file %s, oplock_type = 0x%x, op_type = 0x%x\n", + fsp->fsp_name, (unsigned int)fsp->oplock_type, (unsigned int)share_entry->op_type ); + smb_panic(str); + } +} +#endif + /**************************************************************************** Deal with open deny mode and oplock break processing. Invarient: Share mode must be locked on entry and exit. @@ -572,6 +595,10 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T for(i = 0; i < num_share_modes; i++) { share_mode_entry *share_entry = &old_shares[i]; +#if defined(DEVELOPER) + validate_my_share_entries(share_entry); +#endif + /* * By observation of NetBench, oplocks are broken *before* share * modes are checked. This allows a file to be closed by the client -- cgit From 2a3a9f0bf43c3bf99a71f7296bb5ff6199893fea Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 23 Apr 2003 13:27:35 +0000 Subject: Merge the 'safe' parts of my StrnCpy patch - many of the users really wanted a pstrcpy/fstrcpy or at most a safe_strcpy(). These have the advantage of being compiler-verifiable. Get these out of the way, along with a rewrite of 'get_short_archi' in the spoolss client and server. (This pushes around const string pointers, rather than copied strings). Andrew Bartlett (This used to be commit 32fb801ddc035e8971e9911ed4b6e51892e9d1cc) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 5e4f3caca7..9e49a0bc22 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -73,7 +73,7 @@ static void check_for_pipe(char *fname) { /* special case of pipe opens */ char s[10]; - StrnCpy(s,fname,sizeof(s)-1); + safe_strcpy(s,fname,sizeof(s)-1); strlower(s); if (strstr(s,"pipe/")) { DEBUG(3,("Rejecting named pipe open for %s\n",fname)); -- cgit From 29133d967761908a0f1492c1b907350a076f4a01 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 24 Apr 2003 05:43:45 +0000 Subject: This is really trying to be a StrnCpy (most names will overflow the 10 char limit) (This used to be commit 0e04761abe375bfea48fa2c9ba9e1dc0d56d39f7) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 9e49a0bc22..5e4f3caca7 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -73,7 +73,7 @@ static void check_for_pipe(char *fname) { /* special case of pipe opens */ char s[10]; - safe_strcpy(s,fname,sizeof(s)-1); + StrnCpy(s,fname,sizeof(s)-1); strlower(s); if (strstr(s,"pipe/")) { DEBUG(3,("Rejecting named pipe open for %s\n",fname)); -- cgit From 7ce38082f3dcf01dd9818757f32658adf609d830 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 1 May 2003 17:45:38 +0000 Subject: Fix for bugid 51 from Dragan Krnic. Jeremy. (This used to be commit a2af45154d0e1bb76e78fbde1572d4fcd1ba0da2) --- source3/smbd/open.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 5e4f3caca7..906c4b40d9 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -168,17 +168,17 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, /* Actually do the open */ fsp->fd = fd_open(conn, fname, local_flags, mode); - - /* Inherit the ACL if the file was created. */ - if ((local_flags & O_CREAT) && !VALID_STAT(*psbuf)) - inherit_access_acl(conn, fname, mode); - if (fsp->fd == -1) { DEBUG(3,("Error opening file %s (%s) (local_flags=%d) (flags=%d)\n", fname,strerror(errno),local_flags,flags)); check_for_pipe(fname); return False; } + + /* Inherit the ACL if the file was created. */ + if ((local_flags & O_CREAT) && !VALID_STAT(*psbuf)) + inherit_access_acl(conn, fname, mode); + } else fsp->fd = -1; /* What we used to call a stat open. */ -- cgit From e7c8c15888454043c73967635deb4d3419a489e9 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Sun, 11 May 2003 23:34:18 +0000 Subject: Fix VFS layer: 1. Finally work with cascaded modules with private data storage per module 2. Convert VFS API to macro calls to simplify cascading 3. Add quota support to VFS layer (prepare to NT quota support) Patch by Stefan (metze) Metzemacher, with review of Jelmer and me Tested in past few weeks. Documentation to new VFS API for third-party developers to follow (This used to be commit 91984ef5caa2d13c5d52e1f535bd3bbbae1ec978) --- source3/smbd/open.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 906c4b40d9..412a0dfc50 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -38,13 +38,13 @@ static int fd_open(struct connection_struct *conn, char *fname, flags |= O_NOFOLLOW; #endif - fd = conn->vfs_ops.open(conn,fname,flags,mode); + fd = VFS_OPEN(conn,fname,flags,mode); /* Fix for files ending in '.' */ if((fd == -1) && (errno == ENOENT) && (strchr_m(fname,'.')==NULL)) { pstrcat(fname,"."); - fd = conn->vfs_ops.open(conn,fname,flags,mode); + fd = VFS_OPEN(conn,fname,flags,mode); } DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n", fname, @@ -186,9 +186,9 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, int ret; if (fsp->fd == -1) - ret = vfs_stat(conn, fname, psbuf); + ret = VFS_STAT(conn, fname, psbuf); else { - ret = vfs_fstat(fsp,fsp->fd,psbuf); + ret = VFS_FSTAT(fsp,fsp->fd,psbuf); /* If we have an fd, this stat should succeed. */ if (ret == -1) DEBUG(0,("Error doing fstat on open file %s (%s)\n", fname,strerror(errno) )); @@ -259,7 +259,7 @@ static int truncate_unless_locked(struct connection_struct *conn, files_struct * unix_ERR_ntstatus = dos_to_ntstatus(ERRDOS, ERRlock); return -1; } else { - return conn->vfs_ops.ftruncate(fsp,fsp->fd,0); + return VFS_FTRUNCATE(fsp,fsp->fd,0); } } @@ -1071,7 +1071,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", /* * 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)) { + 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); @@ -1146,11 +1146,11 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", * selected. */ - if (!file_existed && !def_acl && (conn->vfs_ops.fchmod_acl != NULL)) { + if (!file_existed && !def_acl && (conn->vfs.ops.fchmod_acl != NULL)) { int saved_errno = errno; /* We might get ENOSYS in the next call.. */ - if (conn->vfs_ops.fchmod_acl(fsp, fsp->fd, mode) == -1 && errno == ENOSYS) + if (VFS_FCHMOD_ACL(fsp, fsp->fd, mode) == -1 && errno == ENOSYS) errno = saved_errno; /* Ignore ENOSYS */ } else if (new_mode) { @@ -1159,9 +1159,9 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", /* Attributes need changing. File already existed. */ - if (conn->vfs_ops.fchmod_acl != NULL) { + if (conn->vfs.ops.fchmod_acl != NULL) { int saved_errno = errno; /* We might get ENOSYS in the next call.. */ - ret = conn->vfs_ops.fchmod_acl(fsp, fsp->fd, new_mode); + ret = VFS_FCHMOD_ACL(fsp, fsp->fd, new_mode); if (ret == -1 && errno == ENOSYS) { errno = saved_errno; /* Ignore ENOSYS */ @@ -1172,7 +1172,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", } } - if ((ret == -1) && (conn->vfs_ops.fchmod(fsp, fsp->fd, new_mode) == -1)) + if ((ret == -1) && (VFS_FCHMOD(fsp, fsp->fd, new_mode) == -1)) DEBUG(5, ("open_file_shared: failed to reset attributes of file %s to 0%o\n", fname, (int)new_mode)); } @@ -1278,14 +1278,14 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST return NULL; } - if(vfs_mkdir(conn,fname, unix_mode(conn,aDIR, fname)) < 0) { + if(vfs_MkDir(conn,fname, unix_mode(conn,aDIR, fname)) < 0) { DEBUG(2,("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) { + if(VFS_STAT(conn,fname, psbuf) != 0) { file_free(fsp); return NULL; } -- cgit From c9bfb7660bf60d32c51bfe368ce874770adb6f10 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Mon, 12 May 2003 16:03:16 +0000 Subject: Eliminate NULL pointers from VFS interface. All hooks now really callable, producing either correct result or returning error if the feature isn't supported in the configuration (This used to be commit af0a17349e6986eef2e2fd07b4b9f0bcd33bbe1f) --- source3/smbd/open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 412a0dfc50..959439a1b2 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1146,7 +1146,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", * selected. */ - if (!file_existed && !def_acl && (conn->vfs.ops.fchmod_acl != NULL)) { + if (!file_existed && !def_acl) { int saved_errno = errno; /* We might get ENOSYS in the next call.. */ @@ -1159,7 +1159,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", /* Attributes need changing. File already existed. */ - if (conn->vfs.ops.fchmod_acl != NULL) { + { int saved_errno = errno; /* We might get ENOSYS in the next call.. */ ret = VFS_FCHMOD_ACL(fsp, fsp->fd, new_mode); -- cgit From bc2a3748e9caa8f60f7c2387e7eecd7fb3fae899 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Wed, 14 May 2003 10:59:01 +0000 Subject: Prefix VFS API macros with SMB_ for consistency and to avoid problems with VFS_ macros at system side. We currently have one clash with AIX and its VFS_LOCK. Compiled and tested -- no new functionality or code, just plain rename of macros for yet-unreleased VFS API version. Needs to be done before a24 is out (This used to be commit c2689ed118b490e49497a76ed6a2251262018769) --- source3/smbd/open.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 959439a1b2..e3bd530c17 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -38,13 +38,13 @@ static int fd_open(struct connection_struct *conn, char *fname, flags |= O_NOFOLLOW; #endif - fd = VFS_OPEN(conn,fname,flags,mode); + fd = SMB_VFS_OPEN(conn,fname,flags,mode); /* Fix for files ending in '.' */ if((fd == -1) && (errno == ENOENT) && (strchr_m(fname,'.')==NULL)) { pstrcat(fname,"."); - fd = VFS_OPEN(conn,fname,flags,mode); + fd = SMB_VFS_OPEN(conn,fname,flags,mode); } DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n", fname, @@ -186,9 +186,9 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, int ret; if (fsp->fd == -1) - ret = VFS_STAT(conn, fname, psbuf); + ret = SMB_VFS_STAT(conn, fname, psbuf); else { - ret = VFS_FSTAT(fsp,fsp->fd,psbuf); + ret = SMB_VFS_FSTAT(fsp,fsp->fd,psbuf); /* If we have an fd, this stat should succeed. */ if (ret == -1) DEBUG(0,("Error doing fstat on open file %s (%s)\n", fname,strerror(errno) )); @@ -259,7 +259,7 @@ static int truncate_unless_locked(struct connection_struct *conn, files_struct * unix_ERR_ntstatus = dos_to_ntstatus(ERRDOS, ERRlock); return -1; } else { - return VFS_FTRUNCATE(fsp,fsp->fd,0); + return SMB_VFS_FTRUNCATE(fsp,fsp->fd,0); } } @@ -1071,7 +1071,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", /* * 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)) { + if ((truncate_unless_locked(conn,fsp) == -1) || (SMB_VFS_FSTAT(fsp,fsp->fd,psbuf)==-1)) { unlock_share_entry_fsp(fsp); fd_close(conn,fsp); file_free(fsp); @@ -1150,7 +1150,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", int saved_errno = errno; /* We might get ENOSYS in the next call.. */ - if (VFS_FCHMOD_ACL(fsp, fsp->fd, mode) == -1 && errno == ENOSYS) + if (SMB_VFS_FCHMOD_ACL(fsp, fsp->fd, mode) == -1 && errno == ENOSYS) errno = saved_errno; /* Ignore ENOSYS */ } else if (new_mode) { @@ -1161,7 +1161,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", { int saved_errno = errno; /* We might get ENOSYS in the next call.. */ - ret = VFS_FCHMOD_ACL(fsp, fsp->fd, new_mode); + ret = SMB_VFS_FCHMOD_ACL(fsp, fsp->fd, new_mode); if (ret == -1 && errno == ENOSYS) { errno = saved_errno; /* Ignore ENOSYS */ @@ -1172,7 +1172,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", } } - if ((ret == -1) && (VFS_FCHMOD(fsp, fsp->fd, new_mode) == -1)) + if ((ret == -1) && (SMB_VFS_FCHMOD(fsp, fsp->fd, new_mode) == -1)) DEBUG(5, ("open_file_shared: failed to reset attributes of file %s to 0%o\n", fname, (int)new_mode)); } @@ -1285,7 +1285,7 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST return NULL; } - if(VFS_STAT(conn,fname, psbuf) != 0) { + if(SMB_VFS_STAT(conn,fname, psbuf) != 0) { file_free(fsp); return NULL; } -- cgit From 4f7e6108bdbb6da29f7d75851e3be5c4567b6fb0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 22 May 2003 18:45:24 +0000 Subject: Add more info to debug info... Jeremy. (This used to be commit 6d3b72b4994a5115a1e7f0ca3912692a33fc690e) --- source3/smbd/open.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index e3bd530c17..55fbee372c 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -543,7 +543,11 @@ static void validate_my_share_entries(share_mode_entry *share_entry) fsp = file_find_dif(share_entry->dev, share_entry->inode, share_entry->share_file_id); if (!fsp) { - smb_panic("validate_my_share_entries: Cannot match a share entry with an open file\n"); + pstring str; + slprintf(str, sizeof(str)-1, "validate_my_share_entries: Cannot match a share entry with an open file \ +dev = %x, inode = %.0f file_id = %u\n", (unsigned int)share_entry->dev, (double)share_entry->inode, + (unsigned int)share_entry->share_file_id ); + smb_panic(str); } if (((uint16)fsp->oplock_type) != share_entry->op_type) { -- cgit From 78a4f6fc4b8938fcab5bb3b7ae9c3a151f7070f8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 22 May 2003 18:56:51 +0000 Subject: More fixes for debug log to catch logic error. Jeremy. (This used to be commit 84a7714eba801fefa7ad56493f20813de3943bc5) --- source3/smbd/open.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 55fbee372c..15171ce9e3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -534,7 +534,7 @@ existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsign #if defined(DEVELOPER) -static void validate_my_share_entries(share_mode_entry *share_entry) +static void validate_my_share_entries(int num, share_mode_entry *share_entry) { files_struct *fsp; @@ -543,15 +543,13 @@ static void validate_my_share_entries(share_mode_entry *share_entry) fsp = file_find_dif(share_entry->dev, share_entry->inode, share_entry->share_file_id); if (!fsp) { - pstring str; - slprintf(str, sizeof(str)-1, "validate_my_share_entries: Cannot match a share entry with an open file \ -dev = %x, inode = %.0f file_id = %u\n", (unsigned int)share_entry->dev, (double)share_entry->inode, - (unsigned int)share_entry->share_file_id ); - smb_panic(str); + DEBUG(0,("validate_my_share_entries: PANIC : %s\n", share_mode_str(num, share_entry) )); + smb_panic("validate_my_share_entries: Cannot match a share entry with an open file\n"); } if (((uint16)fsp->oplock_type) != share_entry->op_type) { pstring str; + DEBUG(0,("validate_my_share_entries: PANIC : %s\n", share_mode_str(num, share_entry) )); slprintf(str, sizeof(str)-1, "validate_my_share_entries: file %s, oplock_type = 0x%x, op_type = 0x%x\n", fsp->fsp_name, (unsigned int)fsp->oplock_type, (unsigned int)share_entry->op_type ); smb_panic(str); @@ -600,7 +598,7 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T share_mode_entry *share_entry = &old_shares[i]; #if defined(DEVELOPER) - validate_my_share_entries(share_entry); + validate_my_share_entries(i, share_entry); #endif /* -- cgit From ce72beb2b558d86fb49063c6b1fa00e07952ce56 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 3 Jul 2003 19:11:31 +0000 Subject: Removed strupper/strlower macros that automatically map to strupper_m/strlower_m. I really want people to think about when they're using multibyte strings. Jeremy. (This used to be commit ff222716a08af65d26ad842ce4c2841cc6540959) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 15171ce9e3..85d115a3bf 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -74,7 +74,7 @@ static void check_for_pipe(char *fname) /* special case of pipe opens */ char s[10]; StrnCpy(s,fname,sizeof(s)-1); - strlower(s); + strlower_m(s); if (strstr(s,"pipe/")) { DEBUG(3,("Rejecting named pipe open for %s\n",fname)); unix_ERR_class = ERRSRV; -- cgit From e5aa73dab14634fa7741aeb41f7f811f0ab241b3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 7 Jul 2003 22:29:40 +0000 Subject: Fix spotted by Nadav Danieli - ensure dev and inode to fix open mode race condition. Jeremy. (This used to be commit cbde1c8dfcd9d3bef956fe073e7108a54b48844b) --- source3/smbd/open.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 85d115a3bf..6d03eaa29a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1024,6 +1024,16 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", if (!file_existed) { + /* + * Now the file exists and fsp is successfully opened, + * fsp->dev and fsp->inode are valid and should replace the + * dev=0,inode=0 from a non existent file. Spotted by + * Nadav Danieli . JRA. + */ + + dev = fsp->dev; + inode = fsp->inode; + lock_share_entry_fsp(fsp); num_share_modes = open_mode_check(conn, fname, dev, inode, -- cgit From 80c1f1d865b13a63c7a60876b63458119566e044 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 22 Jul 2003 04:31:20 +0000 Subject: Fixup a bunch of printf-style functions and debugs to use unsigned long when displaying pid_t, uid_t and gid_t values. This removes a whole lot of warnings on some of the 64-bit build farm machines as well as help us out when 64-bit uid/gid/pid values come along. (This used to be commit f93528ba007c8800a850678f35f499fb7360fb9a) --- source3/smbd/open.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 6d03eaa29a..5f6ed74f09 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -675,8 +675,8 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou 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 %lu left active oplock.\n", + (unsigned long)broken_entry.pid )); } if (del_share_entry(dev, inode, &broken_entry, NULL) == -1) { @@ -874,7 +874,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ if (file_existed && (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_TRUNCATE)) { if (!open_match_attributes(conn, fname, psbuf->st_mode, mode, &new_mode)) { DEBUG(5,("open_file_shared: attributes missmatch for file %s (0%o, 0%o)\n", - fname, psbuf->st_mode, mode )); + fname, (int)psbuf->st_mode, (int)mode )); file_free(fsp); errno = EACCES; return NULL; -- cgit From 60097e0d8d3db07eecf1773d74f8376ea4059b05 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 Jul 2003 19:10:52 +0000 Subject: Fix from matt.zinkevicius@hp.com to stop files being created on read-only shares in some circumstances. Jeremy. (This used to be commit b826e8c8980d26e932da55384f109f0fe6a124c7) --- source3/smbd/open.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 5f6ed74f09..8f83983023 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -125,6 +125,7 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, directory. */ flags &= ~O_CREAT; + local_flags &= ~O_CREAT; } } -- cgit From 79a5d2e31bd1d5711d4fe7f9161abfc4ff81e7af Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 29 Jul 2003 17:34:20 +0000 Subject: Finish tridge's patch as referenced here : make sure we don't allow the creation of directories containing wildcard characters. I've only put this in mkdir at the moment, but I suspect this will apply to all places that can create new filenames. We need to allow the opening of existing filenames that contain wildcards, but not allow the creation of new ones. Jeremy. (This used to be commit 7f111e545d198faa5fa89f6d360db0d5c32a8bd7) --- source3/smbd/open.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 8f83983023..5f49640aa4 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -167,6 +167,14 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, local_flags |= O_NONBLOCK; #endif + /* Don't create files with Microsoft wildcard characters. */ + if ((local_flags & O_CREAT) && !VALID_STAT(*psbuf) && ms_has_wild(fname)) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRinvalidname; + unix_ERR_ntstatus = NT_STATUS_OBJECT_NAME_INVALID; + return False; + } + /* Actually do the open */ fsp->fd = fd_open(conn, fname, local_flags, mode); if (fsp->fd == -1) { @@ -1291,6 +1299,15 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST return NULL; } + if (ms_has_wild(fname)) { + file_free(fsp); + DEBUG(5,("open_directory: failing create on filename %s with wildcards\n", fname)); + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRinvalidname; + unix_ERR_ntstatus = NT_STATUS_OBJECT_NAME_INVALID; + return NULL; + } + if(vfs_MkDir(conn,fname, unix_mode(conn,aDIR, fname)) < 0) { DEBUG(2,("open_directory: unable to create %s. Error was %s\n", fname, strerror(errno) )); -- cgit From 3bbe9c0869ea8653f684afa9a1345f6fa2f80b4b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 7 Aug 2003 05:36:08 +0000 Subject: An oplock break reply from the client causes the sequence number to be updated by 2 if there is no open reply outstanding, else by one.... Yes - this makes no sense.... Jeremy. (This used to be commit b43ce1ff6109f6422a621329ceb713b42df40040) --- source3/smbd/open.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 5f49640aa4..2c9d3290d8 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -626,6 +626,12 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T 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)); + /* Ensure the reply for the open uses the correct sequence number. */ + /* This isn't a real deferred packet as it's response will also increment + * the sequence. + */ + srv_defer_sign_response(get_current_mid(), False); + /* Oplock break - unlock to request it. */ unlock_share_entry(conn, dev, inode); -- cgit From 4e8b36a5749f4801022617b8fec1fe5d48529fef Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 14 Aug 2003 21:16:06 +0000 Subject: Fix SMBseek and get/set position information SMBs. Works against Samba4 tester. You will need a make clean; make all after this ! Jeremy. (This used to be commit 10d90171ed58bee3e5ab6476341059b585034134) --- source3/smbd/open.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 2c9d3290d8..06f1ddfcf2 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -227,7 +227,6 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->dev = psbuf->st_dev; fsp->vuid = current_user.vuid; fsp->size = psbuf->st_size; - fsp->pos = -1; fsp->can_lock = True; fsp->can_read = ((flags & O_WRONLY)==0); fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0); @@ -1362,7 +1361,6 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST fsp->dev = psbuf->st_dev; fsp->size = psbuf->st_size; fsp->vuid = current_user.vuid; - fsp->pos = -1; fsp->can_lock = True; fsp->can_read = False; fsp->can_write = False; @@ -1425,7 +1423,6 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, SMB_STRUCT_ST fsp->dev = (SMB_DEV_T)0; fsp->size = psbuf->st_size; fsp->vuid = current_user.vuid; - fsp->pos = -1; fsp->can_lock = False; fsp->can_read = False; fsp->can_write = False; -- cgit From 6d6401a67a9985c8c51175db520114dc2ef421ce Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 19 Aug 2003 01:53:45 +0000 Subject: Implement SMBexit properly. Found by Samba4 tester. You must do a make clean proto all; after this commit. Jeremy. (This used to be commit 27af1f9feab12542dc538bfceac4593e644ba3b4) --- source3/smbd/open.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 06f1ddfcf2..71af23aaf9 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -23,6 +23,7 @@ extern userdom_struct current_user_info; extern uint16 global_oplock_port; +extern uint16 global_smbpid; extern BOOL global_client_failed_oplock_break; /**************************************************************************** @@ -226,6 +227,7 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->inode = psbuf->st_ino; fsp->dev = psbuf->st_dev; fsp->vuid = current_user.vuid; + fsp->file_pid = global_smbpid; fsp->size = psbuf->st_size; fsp->can_lock = True; fsp->can_read = ((flags & O_WRONLY)==0); @@ -1361,6 +1363,7 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST fsp->dev = psbuf->st_dev; fsp->size = psbuf->st_size; fsp->vuid = current_user.vuid; + fsp->file_pid = global_smbpid; fsp->can_lock = True; fsp->can_read = False; fsp->can_write = False; @@ -1423,6 +1426,7 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, SMB_STRUCT_ST fsp->dev = (SMB_DEV_T)0; fsp->size = psbuf->st_size; fsp->vuid = current_user.vuid; + fsp->file_pid = global_smbpid; fsp->can_lock = False; fsp->can_read = False; fsp->can_write = False; -- cgit From 3fe18a46a33cc1c0a0ecfefc61618356d7746a15 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 21 Oct 2003 17:40:58 +0000 Subject: Fix signing miss-sequence noticed by Stefan Metzmacher Jeremy. (This used to be commit 63f331564396e7a4f16dce95bb98d3b6c4b75351) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 71af23aaf9..ef7ace862a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -631,7 +631,7 @@ dev = %x, inode = %.0f\n", *p_oplock_request, share_entry->op_type, fname, (unsi /* This isn't a real deferred packet as it's response will also increment * the sequence. */ - srv_defer_sign_response(get_current_mid(), False); + srv_defer_sign_response(get_current_mid()); /* Oplock break - unlock to request it. */ unlock_share_entry(conn, dev, inode); -- cgit From 013a0511030729bf84f4c703dca3fa39ded5fe12 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 18 Nov 2003 02:06:41 +0000 Subject: Remove unneeded second open for filename ending in '.' now we know it's a mangled name. Added const. Fix inspired by Andrew Bartlett ideas. Jeremy. (This used to be commit 87eb336d659dfa5e92b495dd76a0f2e534931293) --- source3/smbd/open.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index ef7ace862a..3807c18e78 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -30,7 +30,7 @@ extern BOOL global_client_failed_oplock_break; fd support routines - attempt to do a dos_open. ****************************************************************************/ -static int fd_open(struct connection_struct *conn, char *fname, +static int fd_open(struct connection_struct *conn, const char *fname, int flags, mode_t mode) { int fd; @@ -41,13 +41,6 @@ static int fd_open(struct connection_struct *conn, char *fname, fd = SMB_VFS_OPEN(conn,fname,flags,mode); - /* Fix for files ending in '.' */ - if((fd == -1) && (errno == ENOENT) && - (strchr_m(fname,'.')==NULL)) { - pstrcat(fname,"."); - fd = SMB_VFS_OPEN(conn,fname,flags,mode); - } - DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n", fname, flags, (int)mode, fd, (fd == -1) ? strerror(errno) : "" )); @@ -70,7 +63,7 @@ int fd_close(struct connection_struct *conn, files_struct *fsp) Check a filename for the pipe string. ****************************************************************************/ -static void check_for_pipe(char *fname) +static void check_for_pipe(const char *fname) { /* special case of pipe opens */ char s[10]; @@ -89,10 +82,9 @@ static void check_for_pipe(char *fname) ****************************************************************************/ static BOOL open_file(files_struct *fsp,connection_struct *conn, - const char *fname1,SMB_STRUCT_STAT *psbuf,int flags,mode_t mode, uint32 desired_access) + const char *fname,SMB_STRUCT_STAT *psbuf,int flags,mode_t mode, uint32 desired_access) { extern struct current_user current_user; - pstring fname; int accmode = (flags & O_ACCMODE); int local_flags = flags; @@ -100,8 +92,6 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->oplock_type = NO_OPLOCK; errno = EPERM; - pstrcpy(fname,fname1); - /* Check permissions */ /* -- cgit From 5447f1f4677bd4a3b9da43a835dd8c662ed86bfa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 24 Feb 2004 00:55:05 +0000 Subject: More gentest error fixups. Jeremy. (This used to be commit 00f71fc8361919b87b62389ada8bd9a73f9f98b5) --- source3/smbd/open.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 3807c18e78..dd10a87055 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1305,6 +1305,15 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST return NULL; } + if( strchr_m(fname, ':')) { + file_free(fsp); + DEBUG(5,("open_directory: failing create on filename %s with colon in name\n", fname)); + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRinvalidname; + unix_ERR_ntstatus = NT_STATUS_NOT_A_DIRECTORY; + return NULL; + } + if(vfs_MkDir(conn,fname, unix_mode(conn,aDIR, fname)) < 0) { DEBUG(2,("open_directory: unable to create %s. Error was %s\n", fname, strerror(errno) )); -- cgit From 3fb52e5cc0fe632584704e807dde5f0ae6612413 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 28 Feb 2004 01:53:30 +0000 Subject: Can't set allocation size on directories, return correct error code on fail if file exists and target is a directory. gentest. Jeremy. (This used to be commit f4a7ea6dc2b9f379a9c735670a49ac63818754c7) --- source3/smbd/open.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index dd10a87055..e688f8de48 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -866,7 +866,11 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ DEBUG(5,("open_file_shared: create new requested for file %s and file already exists.\n", fname )); file_free(fsp); - errno = EEXIST; + if (S_ISDIR(psbuf->st_mode)) { + errno = EISDIR; + } else { + errno = EEXIST; + } return NULL; } -- cgit From 7cea655424467770600a7866eb3ac909ddf8fcab Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 19 Mar 2004 23:46:48 +0000 Subject: Fix for #1064 - ensure truncate attribute checking is done correctly on "hidden" dot files. Jeremy. (This used to be commit a6045c904fbe7df111c520134581bfd4f1ca67a8) --- source3/smbd/open.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index e688f8de48..084ae9a1bf 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -754,7 +754,8 @@ static BOOL open_match_attributes(connection_struct *conn, char *path, mode_t ex old_dos_mode = dos_mode(conn, path, &sbuf); sbuf.st_mode = new_mode; - new_dos_mode = dos_mode(conn, path, &sbuf); + /* The new mode conversion shouldn't look at pathname. */ + new_dos_mode = dos_mode_from_sbuf(conn, &sbuf); noarch_old_dos_mode = (old_dos_mode & ~FILE_ATTRIBUTE_ARCHIVE); noarch_new_dos_mode = (new_dos_mode & ~FILE_ATTRIBUTE_ARCHIVE); -- cgit From 722aa118c66b020c2b9f2b595e1af50429f13986 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 2 Apr 2004 18:46:19 +0000 Subject: Added per-share parameter "store dos attributes". When set, will store dos attributes in an EA. Based on an original patch from tridge, but modified somewhat to cover all cases. Jeremy. (This used to be commit ed653cd468213e0be901bc654aa3748ce5837947) --- source3/smbd/open.c | 81 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 35 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 084ae9a1bf..8ab5dab6ac 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -741,21 +741,10 @@ 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, mode_t *returned_mode) +static BOOL open_match_attributes(connection_struct *conn, const char *path, uint32 old_dos_mode, uint32 new_dos_mode, + mode_t existing_mode, mode_t new_mode, mode_t *returned_mode) { - uint32 old_dos_mode, new_dos_mode; uint32 noarch_old_dos_mode, noarch_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; - /* The new mode conversion shouldn't look at pathname. */ - new_dos_mode = dos_mode_from_sbuf(conn, &sbuf); noarch_old_dos_mode = (old_dos_mode & ~FILE_ATTRIBUTE_ARCHIVE); noarch_new_dos_mode = (new_dos_mode & ~FILE_ATTRIBUTE_ARCHIVE); @@ -771,11 +760,11 @@ static BOOL open_match_attributes(connection_struct *conn, char *path, mode_t ex old_dos_mode, (unsigned int)existing_mode, new_dos_mode, (unsigned int)*returned_mode )); /* If we're mapping SYSTEM and HIDDEN ensure they match. */ - if (lp_map_system(SNUM(conn))) { + if (lp_map_system(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) { if ((old_dos_mode & FILE_ATTRIBUTE_SYSTEM) && !(new_dos_mode & FILE_ATTRIBUTE_SYSTEM)) return False; } - if (lp_map_hidden(SNUM(conn))) { + if (lp_map_hidden(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) { if ((old_dos_mode & FILE_ATTRIBUTE_HIDDEN) && !(new_dos_mode & FILE_ATTRIBUTE_HIDDEN)) return False; } @@ -787,10 +776,10 @@ static BOOL open_match_attributes(connection_struct *conn, char *path, mode_t ex ****************************************************************************/ 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 share_mode,int ofun, uint32 new_dos_mode, int oplock_request, int *Access,int *action) { - return open_file_shared1(conn, fname, psbuf, 0, share_mode, ofun, mode, + return open_file_shared1(conn, fname, psbuf, 0, share_mode, ofun, new_dos_mode, oplock_request, Access, action); } @@ -800,8 +789,9 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S 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, - int *Access,int *action) + int share_mode,int ofun, uint32 new_dos_mode, + int oplock_request, + int *Access,int *paction) { int flags=0; int flags2=0; @@ -820,6 +810,10 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ int open_mode=0; uint16 port = 0; mode_t new_mode = (mode_t)0; + int action; + uint32 existing_dos_mode = 0; + /* We add aARCH to this as this mode is only used if the file is created new. */ + mode_t mode = unix_mode(conn,new_dos_mode | aARCH,fname); if (conn->printer) { /* printers are handled completely differently. Most of the passed parameters are @@ -827,7 +821,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ if (Access) *Access = DOS_OPEN_WRONLY; if (action) - *action = FILE_WAS_CREATED; + *paction = FILE_WAS_CREATED; return print_fsp_open(conn, fname); } @@ -835,14 +829,19 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ if(!fsp) return NULL; - 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 )); + DEBUG(10,("open_file_shared: fname = %s, dos_attrs = %x, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n", + fname, new_dos_mode, share_mode, ofun, (int)mode, oplock_request )); if (!check_name(fname,conn)) { file_free(fsp); return NULL; } + new_dos_mode &= SAMBA_ATTRIBUTES_MASK; + if (file_existed) { + existing_dos_mode = dos_mode(conn, fname, psbuf); + } + /* ignore any oplock requests if oplocks are disabled */ if (!lp_oplocks(SNUM(conn)) || global_client_failed_oplock_break) { oplock_request = 0; @@ -883,9 +882,11 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ /* 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, &new_mode)) { - DEBUG(5,("open_file_shared: attributes missmatch for file %s (0%o, 0%o)\n", - fname, (int)psbuf->st_mode, (int)mode )); + if (!open_match_attributes(conn, fname, existing_dos_mode, new_dos_mode, + psbuf->st_mode, mode, &new_mode)) { + DEBUG(5,("open_file_shared: attributes missmatch for file %s (%x %x) (0%o, 0%o)\n", + fname, existing_dos_mode, new_dos_mode, + (int)psbuf->st_mode, (int)mode )); file_free(fsp); errno = EACCES; return NULL; @@ -929,7 +930,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ #endif /* O_SYNC */ if (flags != O_RDONLY && file_existed && - (!CAN_WRITE(conn) || IS_DOS_READONLY(dos_mode(conn,fname,psbuf)))) { + (!CAN_WRITE(conn) || IS_DOS_READONLY(existing_dos_mode))) { 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" )); @@ -1120,16 +1121,19 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", DEBUG(10,("open_file_shared : share_mode = %x\n", fsp->share_mode )); - if (Access) + if (Access) { (*Access) = open_mode; + } - if (action) { - if (file_existed && !(flags2 & O_TRUNC)) - *action = FILE_WAS_OPENED; - if (!file_existed) - *action = FILE_WAS_CREATED; - if (file_existed && (flags2 & O_TRUNC)) - *action = FILE_WAS_OVERWRITTEN; + if (file_existed && !(flags2 & O_TRUNC)) + action = FILE_WAS_OPENED; + if (file_existed && (flags2 & O_TRUNC)) + action = FILE_WAS_OVERWRITTEN; + if (!file_existed) + action = FILE_WAS_CREATED; + + if (paction) { + *paction = action; } /* @@ -1164,6 +1168,13 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", } } + if (action == FILE_WAS_OVERWRITTEN || action == FILE_WAS_CREATED) { + /* Files should be initially set as archive */ + if (lp_map_archive(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) { + file_set_dosmode(conn, fname, new_dos_mode | aARCH, NULL); + } + } + /* * Take care of inherited ACLs on created files - if default ACL not * selected. @@ -1257,7 +1268,7 @@ int close_file_fchmod(files_struct *fsp) ****************************************************************************/ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_STAT *psbuf, - uint32 desired_access, int share_mode, int smb_ofun, mode_t unixmode, int *action) + uint32 desired_access, int share_mode, int smb_ofun, int *action) { extern struct current_user current_user; BOOL got_stat = False; -- cgit From 80f72a63009eac05a91877893a802cf1a8a62d98 Mon Sep 17 00:00:00 2001 From: Richard Sharpe Date: Fri, 14 May 2004 20:58:26 +0000 Subject: r740: Fix Bug #1301. Return NT_STATUS_SHARING_VIOLATION when share mode locking requests fail. (This used to be commit 5082eb30d0d7c3a4c79b7578457682523a4e80a3) --- source3/smbd/open.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 8ab5dab6ac..235a455f30 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -990,6 +990,13 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", if (fsp_open) fd_close(conn, fsp); file_free(fsp); + /* + * We have detected a sharing violation here + * so return the correct error code + */ + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; return NULL; } @@ -1057,6 +1064,13 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", unlock_share_entry_fsp(fsp); fd_close(conn,fsp); file_free(fsp); + /* + * We have detected a sharing violation here, so + * return the correct code. + */ + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; return NULL; } -- cgit From 8b9a044b58cfcf070d5158ffc4533d2a27226e44 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 14 May 2004 22:08:19 +0000 Subject: r742: Volker discovered that we can truncate a locked file. Well I never ! :-). Jeremy (This used to be commit 1099d60113c2d7b2e5a27a10666cdf885c668778) --- source3/smbd/open.c | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 235a455f30..f072dc4be4 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -242,30 +242,10 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, return True; } -/**************************************************************************** - C. Hoch 11/22/95 - Helper for open_file_shared. - Truncate a file after checking locking; close file if locked. - **************************************************************************/ - -static int truncate_unless_locked(struct connection_struct *conn, files_struct *fsp) -{ - SMB_BIG_UINT mask = (SMB_BIG_UINT)-1; - - if (is_locked(fsp,fsp->conn,mask,0,WRITE_LOCK,True)){ - errno = EACCES; - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRlock; - unix_ERR_ntstatus = dos_to_ntstatus(ERRDOS, ERRlock); - return -1; - } else { - return SMB_VFS_FTRUNCATE(fsp,fsp->fd,0); - } -} - /******************************************************************* return True if the filename is one of the special executable types ********************************************************************/ + static BOOL is_executable(const char *fname) { if ((fname = strrchr_m(fname,'.'))) { @@ -1109,7 +1089,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", /* * We are modifing the file after open - update the stat struct.. */ - if ((truncate_unless_locked(conn,fsp) == -1) || (SMB_VFS_FSTAT(fsp,fsp->fd,psbuf)==-1)) { + if ((SMB_VFS_FTRUNCATE(fsp,fsp->fd,0) == -1) || (SMB_VFS_FSTAT(fsp,fsp->fd,psbuf)==-1)) { unlock_share_entry_fsp(fsp); fd_close(conn,fsp); file_free(fsp); -- cgit From 28cbc5f8f9489673b0c766f450a681659a2a0387 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 19 May 2004 02:25:48 +0000 Subject: r779: Fix specific case of open that doesn't cause oplock break, or share mode check. Test case provided by Volker will be added later. There may be other tests needed. Jeremy. (This used to be commit 1f8e7946edbb2930ba5f9738688dc843bc368fbf) --- source3/smbd/open.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index f072dc4be4..3b4f50b065 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -805,6 +805,25 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ return print_fsp_open(conn, fname); } + if (desired_access && ((desired_access & ~(SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES))==0) && + ((desired_access & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) != 0)) { + /* Stat open that doesn't trigger oplock breaks or share mode checks... ! JRA. */ + oplock_request = 0; + fsp = open_file_stat(conn, fname, psbuf); + if (!fsp) + return NULL; + + fsp->desired_access = desired_access; + if (Access) + *Access = DOS_OPEN_RDONLY; + if (paction) + *paction = FILE_WAS_OPENED; + + DEBUG(10,("open_file_shared: stat open for fname = %s share_mode = %x\n", + fname, share_mode )); + return fsp; + } + fsp = file_new(conn); if(!fsp) return NULL; @@ -1427,12 +1446,8 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, SMB_STRUCT_ST */ fsp->mode = psbuf->st_mode; - /* - * Don't store dev or inode, we don't want any iterator - * to see this. - */ - fsp->inode = (SMB_INO_T)0; - fsp->dev = (SMB_DEV_T)0; + fsp->inode = psbuf->st_ino; + fsp->dev = psbuf->st_dev; fsp->size = psbuf->st_size; fsp->vuid = current_user.vuid; fsp->file_pid = global_smbpid; -- cgit From e003407584a82bd9752b7191f1ed27b5e89e524c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 30 May 2004 07:21:50 +0000 Subject: r945: "Correct" (as in, more correct) way to handle stat opens. Doesn't regress the torture tester. Passes OPEN tests in Samba3 and Samba4 and oplock tests in Samba4. Last thing to check, can an "attribute only" open actually create a file. I think it can.... Jeremy. (This used to be commit d8177a42d4a2a2b6df5d0593f2f92bddc29ffe94) --- source3/smbd/open.c | 47 +++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 22 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 3b4f50b065..cc6f014ceb 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -555,7 +555,7 @@ 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; @@ -564,6 +564,13 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T if(num_share_modes == 0) return 0; + if (desired_access && ((desired_access & ~(SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES))==0) && + ((desired_access & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) != 0)) { + /* Stat open that doesn't trigger oplock breaks or share mode checks... ! JRA. */ + *p_oplock_request = 0; + return num_share_modes; + } + /* * Check if the share modes will give us access. */ @@ -781,6 +788,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ BOOL file_existed = VALID_STAT(*psbuf); BOOL fcbopen = False; BOOL def_acl = False; + BOOL add_share_mode = True; SMB_DEV_T dev = 0; SMB_INO_T inode = 0; int num_share_modes = 0; @@ -805,25 +813,6 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ return print_fsp_open(conn, fname); } - if (desired_access && ((desired_access & ~(SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES))==0) && - ((desired_access & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) != 0)) { - /* Stat open that doesn't trigger oplock breaks or share mode checks... ! JRA. */ - oplock_request = 0; - fsp = open_file_stat(conn, fname, psbuf); - if (!fsp) - return NULL; - - fsp->desired_access = desired_access; - if (Access) - *Access = DOS_OPEN_RDONLY; - if (paction) - *paction = FILE_WAS_OPENED; - - DEBUG(10,("open_file_shared: stat open for fname = %s share_mode = %x\n", - fname, share_mode )); - return fsp; - } - fsp = file_new(conn); if(!fsp) return NULL; @@ -947,6 +936,16 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ return NULL; } + if (desired_access && ((desired_access & ~(SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES))==0) && + ((desired_access & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) != 0)) { + /* Stat open that doesn't trigger oplock breaks or share mode checks... ! JRA. */ + oplock_request = 0; + add_share_mode = False; + if (file_existed) { + flags2 &= ~O_CREAT; + } + } + if (file_existed) { dev = psbuf->st_dev; @@ -1166,14 +1165,18 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", oplock_request = 0; } - set_share_mode(fsp, port, oplock_request); + if (add_share_mode) { + set_share_mode(fsp, port, oplock_request); + } if (delete_on_close) { NTSTATUS result = set_delete_on_close_internal(fsp, delete_on_close); if (NT_STATUS_V(result) != NT_STATUS_V(NT_STATUS_OK)) { /* Remember to delete the mode we just added. */ - del_share_mode(fsp, NULL); + if (add_share_mode) { + del_share_mode(fsp, NULL); + } unlock_share_entry_fsp(fsp); fd_close(conn,fsp); file_free(fsp); -- cgit From efc96df3d5b415ca9c19527a44d0619992712b6d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 2 Jun 2004 02:12:54 +0000 Subject: r974: Fix open code to pass more torture tests. We now pass the Samba4 oplock test. We do this be changing the algorithm when breaking oplocks slightly. Previously we broke an oplock, then re-loaded the share modes and re-iterated. Now we break all oplocks, then re-load the share modes and check the share details - then iterate. This seems to match the way Win2k3 does it. Jeremy. (This used to be commit 5ec4f4e4e6596ea0f52aca5c9e1a75bf35612e37) --- source3/smbd/open.c | 115 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 87 insertions(+), 28 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index cc6f014ceb..ab5ea236fa 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -364,6 +364,8 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i int deny_mode = GET_DENY_MODE(share_mode); int old_open_mode = GET_OPEN_MODE(share->share_mode); int old_deny_mode = GET_DENY_MODE(share->share_mode); + BOOL non_io_open_request; + BOOL non_io_open_existing; /* * share modes = false means don't bother to check for @@ -373,6 +375,18 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i if(!lp_share_modes(SNUM(conn))) return True; + if (desired_access & ~(SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) { + non_io_open_request = False; + } else { + non_io_open_request = True; + } + + if (share->desired_access & ~(SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) { + non_io_open_existing = False; + } else { + non_io_open_existing = True; + } + /* * Don't allow any opens once the delete on close flag has been * set. @@ -411,8 +425,7 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i * and the existing desired_acces then share modes don't conflict. */ - if ( !(desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) && - !(share->desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ) { + if (non_io_open_request && non_io_open_existing) { /* * Wrinkle discovered by smbtorture.... @@ -436,6 +449,13 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i and existing desired access (0x%x) are non-data opens\n", fname, (unsigned int)desired_access, (unsigned int)share->desired_access )); return True; + } else if (non_io_open_request || non_io_open_existing) { + /* + * If either are non-io opens then share modes don't conflict. + */ + DEBUG(5,("check_share_mode: One non-io open. Allowing open on file %s as desired access (0x%x) doesn't conflict with\ +existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsigned int)share->desired_access )); + return True; } /* @@ -537,6 +557,20 @@ static void validate_my_share_entries(int num, share_mode_entry *share_entry) } #endif +struct share_mode_entry_list { + struct share_mode_entry_list *next, *prev; + share_mode_entry entry; +}; + +static void free_broken_entry_list(struct share_mode_entry_list *broken_entry_list) +{ + while (broken_entry_list) { + struct share_mode_entry_list *broken_entry = broken_entry_list; + DLIST_REMOVE(broken_entry_list, broken_entry); + SAFE_FREE(broken_entry); + } +} + /**************************************************************************** Deal with open deny mode and oplock break processing. Invarient: Share mode must be locked on entry and exit. @@ -554,7 +588,7 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T int oplock_contention_count = 0; share_mode_entry *old_shares = 0; BOOL fcbopen = False; - BOOL broke_oplock; + BOOL broke_oplock; if(GET_OPEN_MODE(share_mode) == DOS_OPEN_FCB) fcbopen = True; @@ -567,7 +601,6 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T if (desired_access && ((desired_access & ~(SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES))==0) && ((desired_access & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) != 0)) { /* Stat open that doesn't trigger oplock breaks or share mode checks... ! JRA. */ - *p_oplock_request = 0; return num_share_modes; } @@ -576,12 +609,14 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T */ do { - share_mode_entry broken_entry; - + struct share_mode_entry_list *broken_entry_list = NULL; + struct share_mode_entry_list *broken_entry = NULL; + broke_oplock = False; *p_all_current_opens_are_level_II = True; for(i = 0; i < num_share_modes; i++) { + BOOL cause_oplock_break = False; share_mode_entry *share_entry = &old_shares[i]; #if defined(DEVELOPER) @@ -596,9 +631,17 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T * it before continuing. */ - if((*p_oplock_request && EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type)) || + /* Was this a delete this file request ? */ + if (!*p_oplock_request && desired_access == DELETE_ACCESS && + !BATCH_OPLOCK_TYPE(share_entry->op_type)) { + /* Don't break the oplock in this case. */ + cause_oplock_break = False; + } else if((*p_oplock_request && EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type)) || (!*p_oplock_request && (share_entry->op_type != NO_OPLOCK))) { - + cause_oplock_break = True; + } + + if(cause_oplock_break) { BOOL opb_ret; DEBUG(5,("open_mode_check: oplock_request = %d, breaking oplock (%x) on file %s, \ @@ -629,50 +672,65 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou return -1; } + broken_entry = malloc(sizeof(struct share_mode_entry_list)); + if (!broken_entry) { + smb_panic("open_mode_check: malloc fail.\n"); + } + broken_entry->entry = *share_entry; + DLIST_ADD(broken_entry_list, broken_entry); 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; } - + } /* end for */ + + if (broke_oplock) { + /* Update the current open table. */ + SAFE_FREE(old_shares); + num_share_modes = get_share_modes(conn, dev, inode, &old_shares); + } + + /* Now we check the share modes, after any oplock breaks. */ + for(i = 0; i < num_share_modes; i++) { + share_mode_entry *share_entry = &old_shares[i]; + /* 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, fname, fcbopen, p_flags)) { SAFE_FREE(old_shares); + free_broken_entry_list(broken_entry_list); errno = EACCES; return -1; } - - } /* end for */ - - if(broke_oplock) { - SAFE_FREE(old_shares); - num_share_modes = get_share_modes(conn, dev, inode, &old_shares); + } + + for(broken_entry = broken_entry_list; broken_entry; broken_entry = broken_entry->next) { 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) ) { + if (share_modes_identical(&broken_entry->entry, share_entry) && + 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)); + 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->entry.pid, fname, (unsigned int)dev, (double)inode)); - if (process_exists(broken_entry.pid)) { + if (process_exists(broken_entry->entry.pid)) { DEBUG(0,("open_mode_check: Existent process %lu left active oplock.\n", - (unsigned long)broken_entry.pid )); + (unsigned long)broken_entry->entry.pid )); } - if (del_share_entry(dev, inode, &broken_entry, NULL) == -1) { + if (del_share_entry(dev, inode, &broken_entry->entry, NULL) == -1) { + free_broken_entry_list(broken_entry_list); errno = EACCES; unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadshare; @@ -690,8 +748,8 @@ dev = %x, inode = %.0f. Deleting it to continue...\n", (int)broken_entry.pid, fn break; } } /* end for paranoia... */ - } /* end if broke_oplock */ - + } /* end for broken_entry */ + free_broken_entry_list(broken_entry_list); } while(broke_oplock); if(old_shares != 0) @@ -939,9 +997,10 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ if (desired_access && ((desired_access & ~(SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES))==0) && ((desired_access & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) != 0)) { /* Stat open that doesn't trigger oplock breaks or share mode checks... ! JRA. */ - oplock_request = 0; - add_share_mode = False; + deny_mode = DENY_NONE; if (file_existed) { + oplock_request = 0; + add_share_mode = False; flags2 &= ~O_CREAT; } } -- cgit From 2fc57c9a2ce3a266534dd20e6fed4883e052c557 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 8 Jun 2004 16:14:31 +0000 Subject: r1085: Now it's had some proper user testing, merge in the deferred open fix. I'm still doing more testing, but it fixes a behaviour that we've been wrong on ever since the start of Samba. Jeremy. (This used to be commit 894cc6d16296b934c112786eec896846156aee5d) --- source3/smbd/open.c | 200 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 181 insertions(+), 19 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index ab5ea236fa..04e074d56e 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2,7 +2,7 @@ Unix SMB/CIFS implementation. file opening and share modes Copyright (C) Andrew Tridgell 1992-1998 - Copyright (C) Jeremy Allison 2001 + Copyright (C) Jeremy Allison 2001-2004 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,6 +26,11 @@ extern uint16 global_oplock_port; extern uint16 global_smbpid; extern BOOL global_client_failed_oplock_break; +struct dev_inode_bundle { + SMB_DEV_T dev; + SMB_INO_T inode; +}; + /**************************************************************************** fd support routines - attempt to do a dos_open. ****************************************************************************/ @@ -243,7 +248,7 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, } /******************************************************************* -return True if the filename is one of the special executable types + Return True if the filename is one of the special executable types. ********************************************************************/ static BOOL is_executable(const char *fname) @@ -262,12 +267,13 @@ static BOOL is_executable(const char *fname) enum {AFAIL,AREAD,AWRITE,AALL}; /******************************************************************* -reproduce the share mode access table -this is horrendoously complex, and really can't be justified on any -rational grounds except that this is _exactly_ what NT does. See -the DENY1 and DENY2 tests in smbtorture for a comprehensive set of -test routines. + Reproduce the share mode access table. + This is horrendoously complex, and really can't be justified on any + rational grounds except that this is _exactly_ what NT does. See + the DENY1 and DENY2 tests in smbtorture for a comprehensive set of + test routines. ********************************************************************/ + static int access_table(int new_deny,int old_deny,int old_mode, BOOL same_pid, BOOL isexe) { @@ -353,9 +359,8 @@ static int access_table(int new_deny,int old_deny,int old_mode, return(AFAIL); } - /**************************************************************************** -check if we can open a file with a share mode + Check if we can open a file with a share mode. ****************************************************************************/ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, int share_mode, uint32 desired_access, @@ -770,9 +775,101 @@ after break ! For file %s, dev = %x, inode = %.0f. Deleting it to continue...\n" } /**************************************************************************** -set a kernel flock on a file for NFS interoperability -this requires a patch to Linux + Delete the record for a handled deferred open entry. +****************************************************************************/ + +static void delete_defered_open_entry_record(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode) +{ + uint16 mid = get_current_mid(); + pid_t mypid = sys_getpid(); + deferred_open_entry *de_array = NULL; + int num_de_entries, i; + + num_de_entries = get_deferred_opens(conn, dev, inode, &de_array); + for (i = 0; i < num_de_entries; i++) { + deferred_open_entry *entry = &de_array[i]; + if (entry->pid == mypid && entry->mid == mid && entry->dev == dev && + entry->inode == inode) { + + /* Remove the deferred open entry from the array. */ + delete_deferred_open_entry(entry); + SAFE_FREE(de_array); + return; + } + } + SAFE_FREE(de_array); +} + +/**************************************************************************** + Handle the 1 second delay in returning a SHARING_VIOLATION error. +****************************************************************************/ + +void defer_open_sharing_error(connection_struct *conn, struct timeval *ptv, + char *fname, SMB_DEV_T dev, SMB_INO_T inode) +{ + uint16 mid = get_current_mid(); + pid_t mypid = sys_getpid(); + deferred_open_entry *de_array = NULL; + int num_de_entries, i; + struct dev_inode_bundle dib; + + dib.dev = dev; + dib.inode = inode; + + num_de_entries = get_deferred_opens(conn, dev, inode, &de_array); + for (i = 0; i < num_de_entries; i++) { + deferred_open_entry *entry = &de_array[i]; + if (entry->pid == mypid && entry->mid == mid) { + /* + * Check if a 1 second timeout has expired. + */ + if (usec_time_diff(ptv, &entry->time) > SHARING_VIOLATION_USEC_WAIT) { + DEBUG(10,("defer_open_sharing_error: Deleting deferred open entry for mid %u, \ +file %s\n", + (unsigned int)mid, fname )); + + /* Expired, return a real error. */ + /* Remove the deferred open entry from the array. */ + + delete_deferred_open_entry(entry); + SAFE_FREE(de_array); + return; + } + /* + * If the timeout hasn't expired yet and we still have a sharing violation, + * just leave the entry in the deferred open array alone. We do need to + * reschedule this open call though (with the original created time). + */ + DEBUG(10,("defer_open_sharing_error: time [%u.%06u] updating \ +deferred open entry for mid %u, file %s\n", + (unsigned int)entry->time.tv_sec, + (unsigned int)entry->time.tv_usec, + (unsigned int)mid, fname )); + + push_sharing_violation_open_smb_message(&entry->time, (char *)&dib, sizeof(dib)); + SAFE_FREE(de_array); + return; + } + } + + DEBUG(10,("defer_open_sharing_error: time [%u.%06u] adding deferred open entry for mid %u, file %s\n", + (unsigned int)ptv->tv_sec, (unsigned int)ptv->tv_usec, (unsigned int)mid, fname )); + + if (!push_sharing_violation_open_smb_message(ptv, (char *)&dib, sizeof(dib))) { + SAFE_FREE(de_array); + return; + } + if (!add_deferred_open(mid, ptv, dev, inode, global_oplock_port, fname)) { + remove_sharing_violation_open_smb_message(mid); + } + SAFE_FREE(de_array); +} + +/**************************************************************************** + Set a kernel flock on a file for NFS interoperability. + This requires a patch to Linux. ****************************************************************************/ + static void kernel_flock(files_struct *fsp, int deny_mode) { #if HAVE_KERNEL_SHARE_MODES @@ -847,6 +944,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ BOOL fcbopen = False; BOOL def_acl = False; BOOL add_share_mode = True; + BOOL internal_only_open = False; SMB_DEV_T dev = 0; SMB_INO_T inode = 0; int num_share_modes = 0; @@ -858,9 +956,50 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ mode_t new_mode = (mode_t)0; int action; uint32 existing_dos_mode = 0; + struct pending_message_list *pml = NULL; + uint16 mid = get_current_mid(); /* We add aARCH to this as this mode is only used if the file is created new. */ mode_t mode = unix_mode(conn,new_dos_mode | aARCH,fname); + if (oplock_request == INTERNAL_OPEN_ONLY) { + internal_only_open = True; + oplock_request = 0; + } + + if ((pml = get_open_deferred_message(mid)) != NULL) { + struct dev_inode_bundle dib; + + memcpy(&dib, pml->private_data.data, sizeof(dib)); + + /* There could be a race condition where the dev/inode pair + has changed since we deferred the message. If so, just + remove the deferred open entry and return sharing violation. */ + + /* If the timeout value is non-zero, we need to just + return sharing violation. Don't retry the open + as we were not notified of a close and we don't want to + trigger another spurious oplock break. */ + + if (!file_existed || dib.dev != psbuf->st_dev || dib.inode != psbuf->st_ino || + pml->msg_time.tv_sec || pml->msg_time.tv_usec) { + /* Ensure we don't reprocess this message. */ + remove_sharing_violation_open_smb_message(mid); + + /* Now remove the deferred open entry under lock. */ + lock_share_entry(conn, dib.dev, dib.inode); + delete_defered_open_entry_record(conn, dib.dev, dib.inode); + unlock_share_entry(conn, dib.dev, dib.inode); + + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; + return NULL; + } + /* Ensure we don't reprocess this message. */ + remove_sharing_violation_open_smb_message(mid); + + } + if (conn->printer) { /* printers are handled completely differently. Most of the passed parameters are ignored */ @@ -1043,17 +1182,28 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", unix_ERR_ntstatus = NT_STATUS_ACCESS_DENIED; } + /* + * If we're returning a share violation, ensure we cope with + * the braindead 1 second delay. + */ + + if (!internal_only_open && NT_STATUS_EQUAL(unix_ERR_ntstatus,NT_STATUS_SHARING_VIOLATION)) { + /* The fsp->open_time here represents the current time of day. */ + defer_open_sharing_error(conn, &fsp->open_time, fname, dev, inode); + } + unlock_share_entry(conn, dev, inode); - if (fsp_open) + if (fsp_open) { fd_close(conn, fsp); + /* + * We have detected a sharing violation here + * so return the correct error code + */ + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; + } file_free(fsp); - /* - * We have detected a sharing violation here - * so return the correct error code - */ - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; return NULL; } @@ -1118,6 +1268,16 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", &flags, &oplock_request, &all_current_opens_are_level_II); if(num_share_modes == -1) { + /* + * If we're returning a share violation, ensure we cope with + * the braindead 1 second delay. + */ + + if (!internal_only_open && NT_STATUS_EQUAL(unix_ERR_ntstatus,NT_STATUS_SHARING_VIOLATION)) { + /* The fsp->open_time here represents the current time of day. */ + defer_open_sharing_error(conn, &fsp->open_time, fname, dev, inode); + } + unlock_share_entry_fsp(fsp); fd_close(conn,fsp); file_free(fsp); @@ -1286,6 +1446,8 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", fname, (int)new_mode)); } + /* If this is a successful open, we must remove any deferred open records. */ + delete_defered_open_entry_record(conn, fsp->dev, fsp->inode); unlock_share_entry_fsp(fsp); conn->num_files_open++; -- cgit From effd4a33856bf315122df9e4fbbb241a161caa62 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 8 Jun 2004 22:13:59 +0000 Subject: r1089: Removed spurious oplock message in deferred open processing. Fix smb signing sequence counts. Jeremy. (This used to be commit 7e2a5c36614282b6bd50b60360f443549426dd4b) --- source3/smbd/open.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 04e074d56e..aca9756628 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -862,6 +862,16 @@ deferred open entry for mid %u, file %s\n", if (!add_deferred_open(mid, ptv, dev, inode, global_oplock_port, fname)) { remove_sharing_violation_open_smb_message(mid); } + + /* + * Push the MID of this packet on the signing queue. + * We only do this once, the first time we push the packet + * onto the deferred open queue, as this has a side effect + * of incrementing the response sequence number. + */ + + srv_defer_sign_response(mid); + SAFE_FREE(de_array); } -- cgit From 459cb00785c1eb71a1886c5960b5176e85c48d57 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 9 Jun 2004 21:03:50 +0000 Subject: r1097: Fix errno being incorrectly set. Noticed by Richard. Jeremy. (This used to be commit c8a55e92dd9622fa2a408b5a16f1adcf22253fc5) --- source3/smbd/open.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index aca9756628..330080353c 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -244,6 +244,7 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write), conn->num_files_open + 1)); + errno = 0; return True; } -- cgit From 7f05a7d0c85fd3deaf5e3e263cf8b0f05d4a7f01 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 26 Jun 2004 00:47:58 +0000 Subject: r1260: Added new parameter in the protocol section. "defer sharing violations", by default set to "yes" (to correctly emulate Windows). I've added this to ensure if we find a critical problem with this new code when 3.0.5 ships it can be turned off to test for bugs. Jeremy. (This used to be commit bee0619cc476335e19a5f76179832802587563d1) --- source3/smbd/open.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 330080353c..119eb04e09 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -786,6 +786,10 @@ static void delete_defered_open_entry_record(connection_struct *conn, SMB_DEV_T deferred_open_entry *de_array = NULL; int num_de_entries, i; + if (!lp_defer_sharing_violations(SNUM(conn))) { + return; + } + num_de_entries = get_deferred_opens(conn, dev, inode, &de_array); for (i = 0; i < num_de_entries; i++) { deferred_open_entry *entry = &de_array[i]; @@ -814,6 +818,10 @@ void defer_open_sharing_error(connection_struct *conn, struct timeval *ptv, int num_de_entries, i; struct dev_inode_bundle dib; + if (!lp_defer_sharing_violations(SNUM(conn))) { + return; + } + dib.dev = dev; dib.inode = inode; -- cgit From 3e0f586298125bbda80b8edcced49d5bbb424b0d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 26 Jun 2004 01:04:02 +0000 Subject: r1263: Make "defer sharing violations" a global parameter. Jeremy. (This used to be commit 42cdeccc36dc5f4bd133b84d4eaeb76f42f8043b) --- source3/smbd/open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 119eb04e09..d38d94e5aa 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -786,7 +786,7 @@ static void delete_defered_open_entry_record(connection_struct *conn, SMB_DEV_T deferred_open_entry *de_array = NULL; int num_de_entries, i; - if (!lp_defer_sharing_violations(SNUM(conn))) { + if (!lp_defer_sharing_violations()) { return; } @@ -818,7 +818,7 @@ void defer_open_sharing_error(connection_struct *conn, struct timeval *ptv, int num_de_entries, i; struct dev_inode_bundle dib; - if (!lp_defer_sharing_violations(SNUM(conn))) { + if (!lp_defer_sharing_violations()) { return; } -- cgit From 57c07e27853442e95e19c7f746ef1f4681bda48a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 30 Jun 2004 01:35:01 +0000 Subject: r1304: Turns out non-io opens that cause oplock breaks are a *different* set of desired access flags from those that cause sharing violations. Oplock breaks are caused by : ~(SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES) Sharing violations are caused by : ~(SYNCHRONIZE_ACCESS|READ_CONTROL_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES) We now pass the torture rename test again. I still need to work out if subsequent opens will cause sharing violations with an existing open mode of SYNCHRONIZE_ACCESS|READ_CONTROL_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES; Jeremy. (This used to be commit 38002bfc1c0981a2dba3f2319624c1ef055a3648) --- source3/smbd/open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index d38d94e5aa..65500c65ce 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -381,13 +381,13 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i if(!lp_share_modes(SNUM(conn))) return True; - if (desired_access & ~(SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) { + if (desired_access & ~(SYNCHRONIZE_ACCESS|READ_CONTROL_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) { non_io_open_request = False; } else { non_io_open_request = True; } - if (share->desired_access & ~(SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) { + if (share->desired_access & ~(SYNCHRONIZE_ACCESS|READ_CONTROL_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) { non_io_open_existing = False; } else { non_io_open_existing = True; -- cgit From a96dfe038e98234698e1967c54be5f4a2a47fa09 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 24 Aug 2004 23:36:33 +0000 Subject: r2027: Fix for but #1657, used initialized variable, from Helmut Heinreichsberger . Jeremy. (This used to be commit 07f7aa6afb0945bb0e108981c4984a6c04c42a53) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 65500c65ce..b08ca0f58b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1024,7 +1024,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ ignored */ if (Access) *Access = DOS_OPEN_WRONLY; - if (action) + if (paction) *paction = FILE_WAS_CREATED; return print_fsp_open(conn, fname); } -- cgit From 69e87ef8c3005c1cdf23e0ac46beb718986d7daa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 27 Aug 2004 01:16:25 +0000 Subject: r2083: Fix memleak on return code path. Jeremy. (This used to be commit b0af241fd1fc58c1cbaadcbf6832b608923382ff) --- source3/smbd/open.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index b08ca0f58b..6d559ac828 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -592,7 +592,7 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T int i; int num_share_modes; int oplock_contention_count = 0; - share_mode_entry *old_shares = 0; + share_mode_entry *old_shares = NULL; BOOL fcbopen = False; BOOL broke_oplock; @@ -601,12 +601,15 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T num_share_modes = get_share_modes(conn, dev, inode, &old_shares); - if(num_share_modes == 0) + if(num_share_modes == 0) { + SAFE_FREE(old_shares); return 0; + } if (desired_access && ((desired_access & ~(SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES))==0) && ((desired_access & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) != 0)) { /* Stat open that doesn't trigger oplock breaks or share mode checks... ! JRA. */ + SAFE_FREE(old_shares); return num_share_modes; } @@ -758,9 +761,6 @@ after break ! For file %s, dev = %x, inode = %.0f. Deleting it to continue...\n" free_broken_entry_list(broken_entry_list); } while(broke_oplock); - if(old_shares != 0) - SAFE_FREE(old_shares); - /* * Refuse to grant an oplock in case the contention limit is * reached when going through the lock list multiple times. @@ -772,6 +772,7 @@ after break ! For file %s, dev = %x, inode = %.0f. Deleting it to continue...\n" oplock_contention_count )); } + SAFE_FREE(old_shares); return num_share_modes; } -- cgit From 2efbc238d4f32e810f42393ea2f1f022030d97c5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 16 Oct 2004 03:04:40 +0000 Subject: r3002: Fix for bug #1886 - prevent delete on close being set for readonly files (and return the correct error code). We now pass the Samba4 test suite on this. Jeremy. (This used to be commit 6ae417f12cc6f8d2ad00bea27ce0a20242f76325) --- source3/smbd/open.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 6d559ac828..55970493fa 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1409,9 +1409,17 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", } if (delete_on_close) { - NTSTATUS result = set_delete_on_close_internal(fsp, delete_on_close); + uint32 dosmode = existing_dos_mode; + NTSTATUS result; + + if (action == FILE_WAS_OVERWRITTEN || action == FILE_WAS_CREATED) { + dosmode = new_dos_mode; + } + result = set_delete_on_close_internal(fsp, delete_on_close, dosmode); if (NT_STATUS_V(result) != NT_STATUS_V(NT_STATUS_OK)) { + uint8 u_e_c; + uint32 u_e_code; /* Remember to delete the mode we just added. */ if (add_share_mode) { del_share_mode(fsp, NULL); @@ -1419,6 +1427,10 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", unlock_share_entry_fsp(fsp); fd_close(conn,fsp); file_free(fsp); + ntstatus_to_dos(result, &u_e_c, &u_e_code); + unix_ERR_ntstatus = result; + unix_ERR_class = u_e_c; + unix_ERR_code = u_e_code; return NULL; } } @@ -1651,7 +1663,7 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST string_set(&fsp->fsp_name,fname); if (delete_on_close) { - NTSTATUS result = set_delete_on_close_internal(fsp, delete_on_close); + NTSTATUS result = set_delete_on_close_internal(fsp, delete_on_close, 0); if (NT_STATUS_V(result) != NT_STATUS_V(NT_STATUS_OK)) { file_free(fsp); -- cgit From ea9f97886b8b76bc0d74f10eb7dfa53323b7e159 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 18 Nov 2004 16:14:13 +0000 Subject: r3853: Fix an uninitialized variable warning. Jeremy, there are some of these in charcnv.c. Volker (This used to be commit 650d52648dbf67f71d7619ffb8bf32d93a15ae9c) --- source3/smbd/open.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 55970493fa..1b5ba1228f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1376,6 +1376,8 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", (*Access) = open_mode; } + action = 0; + if (file_existed && !(flags2 & O_TRUNC)) action = FILE_WAS_OPENED; if (file_existed && (flags2 & O_TRUNC)) -- cgit From 46f546571bc2429c4ee6ef86866520c4b5d4bcc7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 30 Nov 2004 00:22:04 +0000 Subject: r4007: Fix bug #2088 - ensure inherit permissions is only applied on a new file, not an existing one. Jeremy. (This used to be commit fbbdb72cf1adfe567112556626f26b031747f440) --- source3/smbd/open.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 1b5ba1228f..7cadf5adba 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -979,7 +979,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ struct pending_message_list *pml = NULL; uint16 mid = get_current_mid(); /* We add aARCH to this as this mode is only used if the file is created new. */ - mode_t mode = unix_mode(conn,new_dos_mode | aARCH,fname); + mode_t mode = unix_mode(conn,new_dos_mode | aARCH,fname, True); if (oplock_request == INTERNAL_OPEN_ONLY) { internal_only_open = True; @@ -1440,7 +1440,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", if (action == FILE_WAS_OVERWRITTEN || action == FILE_WAS_CREATED) { /* Files should be initially set as archive */ if (lp_map_archive(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) { - file_set_dosmode(conn, fname, new_dos_mode | aARCH, NULL); + file_set_dosmode(conn, fname, new_dos_mode | aARCH, NULL, True); } } @@ -1601,7 +1601,7 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST return NULL; } - if(vfs_MkDir(conn,fname, unix_mode(conn,aDIR, fname)) < 0) { + if(vfs_MkDir(conn,fname, unix_mode(conn,aDIR, fname, True)) < 0) { DEBUG(2,("open_directory: unable to create %s. Error was %s\n", fname, strerror(errno) )); file_free(fsp); -- cgit From acf9d61421faa6c0055d57fdee7db300dc5431aa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 7 Dec 2004 18:25:53 +0000 Subject: r4088: Get medieval on our ass about malloc.... :-). Take control of all our allocation functions so we can funnel through some well known functions. Should help greatly with malloc checking. HEAD patch to follow. Jeremy. (This used to be commit 620f2e608f70ba92f032720c031283d295c5c06a) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 7cadf5adba..bf3fbf7fec 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -681,7 +681,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou return -1; } - broken_entry = malloc(sizeof(struct share_mode_entry_list)); + broken_entry = SMB_MALLOC_P(struct share_mode_entry_list); if (!broken_entry) { smb_panic("open_mode_check: malloc fail.\n"); } -- cgit From 02c25a2683204d8b20a1e69ea354b9e08b0fd94d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 26 Jan 2005 20:01:21 +0000 Subject: r5014: Split out the request to send an async level II oplock break into a new function to make it clear when it's called. Remove async parameter that had been overloaded into request_oplock_break. Inspired by work from Nadav Danieli . Jeremy. (This used to be commit 05697fb50236dfc28e81f8b3900eac17cace57c1) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index bf3fbf7fec..70632a20eb 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -665,7 +665,7 @@ dev = %x, inode = %.0f\n", *p_oplock_request, share_entry->op_type, fname, (unsi /* Oplock break - unlock to request it. */ unlock_share_entry(conn, dev, inode); - opb_ret = request_oplock_break(share_entry, False); + opb_ret = request_oplock_break(share_entry); /* Now relock. */ lock_share_entry(conn, dev, inode); -- cgit From 02bce09010f66422affc478a1d2fd7bc3d1d4b4b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 2 Mar 2005 18:19:32 +0000 Subject: r5623: Horrible band-aid patch to fix Blue-Arc torture tester. I know this isn't right but will work until I can refactor the deny mode code with the Samba4 algorithm. Jeremy. (This used to be commit f38f464c722a441402e2d6e2622bcce9227c33b5) --- source3/smbd/open.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 70632a20eb..fc4f97ad16 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -491,7 +491,13 @@ existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsign unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadshare; unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; + return False; + } + if (deny_mode == DENY_ALL || old_deny_mode == DENY_ALL) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; return False; } @@ -502,7 +508,7 @@ existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsign if ( !(desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) || !(share->desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ) { - DEBUG(5,("check_share_mode: Allowing open on file %s as desired access (0x%x) doesn't conflict with\ + DEBUG(5,("check_share_mode: Allowing open on file %s as desired access (0x%x) doesn't conflict with \ existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsigned int)share->desired_access )); return True; } -- cgit From a4deaac09f93530e8b8e6b7310c9d8c68eff259c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 2 Mar 2005 21:43:54 +0000 Subject: r5630: This may be a mistake ... needs more cthon investigation. Jeremy. (This used to be commit 0322c5884666bf62a37de069a1cd0ae888ac4285) --- source3/smbd/open.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index fc4f97ad16..a552dc5b61 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -494,12 +494,15 @@ existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsign return False; } +#if 0 + /* Bluarc test may need this ... needs further investigation. */ if (deny_mode == DENY_ALL || old_deny_mode == DENY_ALL) { unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadshare; unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; return False; } +#endif /* * If desired_access doesn't contain READ_DATA,WRITE_DATA,APPEND_DATA or EXECUTE -- cgit From cc5ba986bf4c7b704ae5c3787f2f3881145e719c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 15 Mar 2005 01:19:58 +0000 Subject: r5792: Added new parameter "inherit owner". If set on a share, the created file/directory will be owned by the same uid as the containing directory. Doing this for directories in a race-free mannor has only been tested on Linux (it depends on being able to open a directory and then do a fchown on that file descriptor). If this functionality is not available then the code silently downgrades to not changing the ownership of a new directory. This new parameter (docs to follow) finally makes it possible to create "drop boxes" on Samba, which requires all files within a directory to be commonly owned. A HOWTO on how to use this will follow. Jeremy. (This used to be commit 2e1f727184b9d025d2e3413bdd3d01d5ca803a41) --- source3/smbd/open.c | 152 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 125 insertions(+), 27 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index a552dc5b61..3124526c7e 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -82,6 +82,103 @@ static void check_for_pipe(const char *fname) } } +/**************************************************************************** + Change the ownership of a file to that of the parent directory. + Do this by fd if possible. +****************************************************************************/ + +void change_owner_to_parent(connection_struct *conn, files_struct *fsp, const char *fname, SMB_STRUCT_STAT *psbuf) +{ + const char *parent_path = parent_dirname(fname); + SMB_STRUCT_STAT parent_st; + int ret; + + ret = SMB_VFS_STAT(conn, parent_path, &parent_st); + if (ret == -1) { + DEBUG(0,("change_owner_to_parent: failed to stat parent directory %s. Error was %s\n", + parent_path, strerror(errno) )); + return; + } + + if (fsp && fsp->fd != -1) { + become_root(); + ret = SMB_VFS_FCHOWN(fsp, fsp->fd, parent_st.st_uid, (gid_t)-1); + unbecome_root(); + if (ret == -1) { + DEBUG(0,("change_owner_to_parent: failed to fchown file %s to parent directory uid %u. \ +Error was %s\n", + fname, (unsigned int)parent_st.st_uid, strerror(errno) )); + } + + DEBUG(10,("change_owner_to_parent: changed new file %s to parent directory uid %u.\n", + fname, (unsigned int)parent_st.st_uid )); + + } else { + /* We've already done an lstat into psbuf, and we know it's a directory. If + we can do an open/fstat and the dev/ino are the same then we can safely + fchown without races. This works under Linux - but should just fail gracefully + if any step on the way fails. JRA */ + + BOOL need_close_fsp = False; + SMB_STRUCT_STAT sbuf; + int fd = -1; + + if (!fsp) { + int action; + fsp = open_directory(conn, fname, psbuf, FILE_GENERIC_READ, + SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY), + FILE_EXISTS_OPEN, &action); + if (!fsp) { + DEBUG(10,("change_owner_to_parent: open_directory on %s failed. Error was %s\n", + fname, strerror(errno) )); + return; + } + need_close_fsp = True; + } + fd = SMB_VFS_OPEN(conn,fname,O_RDONLY,0); + if (fd == -1) { + DEBUG(10,("change_owner_to_parent: failed to VFS_OPEN directory %s. Error was %s\n", + fname, strerror(errno) )); + goto out; + } + ret = SMB_VFS_FSTAT(fsp,fd,&sbuf); + if (ret == -1) { + DEBUG(10,("change_owner_to_parent: failed to VFS_STAT directory %s. Error was %s\n", + fname, strerror(errno) )); + goto out; + } + + /* Ensure we're pointing at the same place. */ + if (sbuf.st_dev != psbuf->st_dev || sbuf.st_ino != psbuf->st_ino || !S_ISDIR(sbuf.st_mode)) { + DEBUG(0,("change_owner_to_parent: device/inode/mode on director %s changed. Refusing to fchown !\n", + fname )); + goto out; + } + + become_root(); + ret = SMB_VFS_FCHOWN(fsp, fd, parent_st.st_uid, (gid_t)-1); + unbecome_root(); + if (ret == -1) { + DEBUG(10,("change_owner_to_parent: failed to fchown directory %s to parent directory uid %u. \ +Error was %s\n", + fname, (unsigned int)parent_st.st_uid, strerror(errno) )); + goto out; + } + + DEBUG(10,("change_owner_to_parent: changed new directory %s to parent directory uid %u.\n", + fname, (unsigned int)parent_st.st_uid )); + + out: + + if (fd != -1) { + SMB_VFS_CLOSE(fsp,fd); + } + if (need_close_fsp) { + close_file(fsp, False); + } + } +} + /**************************************************************************** Open a file. ****************************************************************************/ @@ -1391,8 +1488,13 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", action = FILE_WAS_OPENED; if (file_existed && (flags2 & O_TRUNC)) action = FILE_WAS_OVERWRITTEN; - if (!file_existed) + if (!file_existed) { action = FILE_WAS_CREATED; + /* Change the owner if required. */ + if (lp_inherit_owner(SNUM(conn))) { + change_owner_to_parent(conn, fsp, fsp->fsp_name, psbuf); + } + } if (paction) { *paction = action; @@ -1547,7 +1649,7 @@ int close_file_fchmod(files_struct *fsp) Open a directory from an NT SMB call. ****************************************************************************/ -files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_STAT *psbuf, +files_struct *open_directory(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 desired_access, int share_mode, int smb_ofun, int *action) { extern struct current_user current_user; @@ -1585,39 +1687,29 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST * Try and create the directory. */ - if(!CAN_WRITE(conn)) { - DEBUG(2,("open_directory: failing create on read-only share\n")); - file_free(fsp); - errno = EACCES; - return NULL; - } + /* We know bad_path is false as it's caught earlier. */ - if (ms_has_wild(fname)) { - file_free(fsp); - DEBUG(5,("open_directory: failing create on filename %s with wildcards\n", fname)); - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRinvalidname; - unix_ERR_ntstatus = NT_STATUS_OBJECT_NAME_INVALID; - return NULL; - } + NTSTATUS status = mkdir_internal(conn, fname, False); - if( strchr_m(fname, ':')) { + if (!NT_STATUS_IS_OK(status)) { + DEBUG(2,("open_directory: unable to create %s. Error was %s\n", + fname, strerror(errno) )); file_free(fsp); - DEBUG(5,("open_directory: failing create on filename %s with colon in name\n", fname)); - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRinvalidname; - unix_ERR_ntstatus = NT_STATUS_NOT_A_DIRECTORY; + /* Ensure we return the correct NT status to the client. */ + unix_ERR_ntstatus = status; return NULL; } - if(vfs_MkDir(conn,fname, unix_mode(conn,aDIR, fname, True)) < 0) { - DEBUG(2,("open_directory: unable to create %s. Error was %s\n", - fname, strerror(errno) )); + /* Ensure we're checking for a symlink here.... */ + /* We don't want to get caught by a symlink racer. */ + + if(SMB_VFS_LSTAT(conn,fname, psbuf) != 0) { file_free(fsp); return NULL; } - if(SMB_VFS_STAT(conn,fname, psbuf) != 0) { + if(!S_ISDIR(psbuf->st_mode)) { + DEBUG(0,("open_directory: %s is not a directory !\n", fname )); file_free(fsp); return NULL; } @@ -1674,13 +1766,19 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST string_set(&fsp->fsp_name,fname); if (delete_on_close) { - NTSTATUS result = set_delete_on_close_internal(fsp, delete_on_close, 0); + NTSTATUS status = set_delete_on_close_internal(fsp, delete_on_close, 0); - if (NT_STATUS_V(result) != NT_STATUS_V(NT_STATUS_OK)) { + if (!NT_STATUS_IS_OK(status)) { file_free(fsp); return NULL; } } + + /* Change the owner if required. */ + if ((*action == FILE_WAS_CREATED) && lp_inherit_owner(SNUM(conn))) { + change_owner_to_parent(conn, fsp, fsp->fsp_name, psbuf); + } + conn->num_files_open++; return fsp; -- cgit From 56b22250f478ca2cce43a274589e42a28ea88002 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 17 Mar 2005 01:50:09 +0000 Subject: r5848: Fix inherit owner to chown directories in a porable and secure way (from just secure on Linux). Idea from tridge. Jeremy. (This used to be commit c0924a497b51c126a1db55f48cbf461855dd6c6a) --- source3/smbd/open.c | 62 +++++++++++++++++++++-------------------------------- 1 file changed, 25 insertions(+), 37 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 3124526c7e..79c27388dc 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -115,67 +115,55 @@ Error was %s\n", } else { /* We've already done an lstat into psbuf, and we know it's a directory. If - we can do an open/fstat and the dev/ino are the same then we can safely - fchown without races. This works under Linux - but should just fail gracefully - if any step on the way fails. JRA */ + we can cd into the directory and the dev/ino are the same then we can safely + chown without races as we're locking the directory in place by being in it. + This should work on any UNIX (thanks tridge :-). JRA. + */ - BOOL need_close_fsp = False; + pstring saved_dir; SMB_STRUCT_STAT sbuf; - int fd = -1; - - if (!fsp) { - int action; - fsp = open_directory(conn, fname, psbuf, FILE_GENERIC_READ, - SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY), - FILE_EXISTS_OPEN, &action); - if (!fsp) { - DEBUG(10,("change_owner_to_parent: open_directory on %s failed. Error was %s\n", - fname, strerror(errno) )); - return; - } - need_close_fsp = True; - } - fd = SMB_VFS_OPEN(conn,fname,O_RDONLY,0); - if (fd == -1) { - DEBUG(10,("change_owner_to_parent: failed to VFS_OPEN directory %s. Error was %s\n", - fname, strerror(errno) )); + + if (!vfs_GetWd(conn,saved_dir)) { + DEBUG(0,("change_owner_to_parent: failed to get current working directory\n")); + return; + } + + /* Chdir into the new path. */ + if (vfs_ChDir(conn, fname) == -1) { + DEBUG(0,("change_owner_to_parent: failed to change current working directory to %s. \ +Error was %s\n", fname, strerror(errno) )); goto out; } - ret = SMB_VFS_FSTAT(fsp,fd,&sbuf); - if (ret == -1) { - DEBUG(10,("change_owner_to_parent: failed to VFS_STAT directory %s. Error was %s\n", - fname, strerror(errno) )); + + if (SMB_VFS_STAT(conn,".",&sbuf) == -1) { + DEBUG(0,("change_owner_to_parent: failed to stat directory '.' (%s) \ +Error was %s\n", fname, strerror(errno))); goto out; } /* Ensure we're pointing at the same place. */ - if (sbuf.st_dev != psbuf->st_dev || sbuf.st_ino != psbuf->st_ino || !S_ISDIR(sbuf.st_mode)) { - DEBUG(0,("change_owner_to_parent: device/inode/mode on director %s changed. Refusing to fchown !\n", + if (sbuf.st_dev != psbuf->st_dev || sbuf.st_ino != psbuf->st_ino || sbuf.st_mode != psbuf->st_mode ) { + DEBUG(0,("change_owner_to_parent: device/inode/mode on directory %s changed. Refusing to chown !\n", fname )); goto out; } become_root(); - ret = SMB_VFS_FCHOWN(fsp, fd, parent_st.st_uid, (gid_t)-1); + ret = SMB_VFS_CHOWN(conn, ".", parent_st.st_uid, (gid_t)-1); unbecome_root(); if (ret == -1) { - DEBUG(10,("change_owner_to_parent: failed to fchown directory %s to parent directory uid %u. \ + DEBUG(10,("change_owner_to_parent: failed to chown directory %s to parent directory uid %u. \ Error was %s\n", fname, (unsigned int)parent_st.st_uid, strerror(errno) )); goto out; } - DEBUG(10,("change_owner_to_parent: changed new directory %s to parent directory uid %u.\n", + DEBUG(10,("change_owner_to_parent: changed ownership of new directory %s to parent directory uid %u.\n", fname, (unsigned int)parent_st.st_uid )); out: - if (fd != -1) { - SMB_VFS_CLOSE(fsp,fd); - } - if (need_close_fsp) { - close_file(fsp, False); - } + vfs_ChDir(conn,saved_dir); } } -- cgit From 99509cb0b502c34815dfe9ad33c0ba9c4c524713 Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Thu, 17 Mar 2005 14:32:52 +0000 Subject: r5854: Fix coredump when OS/2 checks for long file name support (with .+,;=[].). Bugzilla 2338. Thanks to Guenter Kukkukk (This used to be commit c13736287104d96fcc87ada0784eb43c6e373171) --- source3/smbd/open.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 79c27388dc..9d9d9d9208 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1146,17 +1146,15 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ oplock_request = 0; } - /* this is for OS/2 EAs - try and say we don't support them */ + /* this is for OS/2 long file names - say we don't support them */ if (strstr(fname,".+,;=[].")) { unix_ERR_class = ERRDOS; /* OS/2 Workplace shell fix may be main code stream in a later release. */ -#if 1 /* OS2_WPS_FIX - Recent versions of OS/2 need this. */ unix_ERR_code = ERRcannotopen; -#else /* OS2_WPS_FIX */ - unix_ERR_code = ERROR_EAS_NOT_SUPPORTED; -#endif /* OS2_WPS_FIX */ - - DEBUG(5,("open_file_shared: OS/2 EA's are not supported.\n")); + unix_ERR_ntstatus = NT_STATUS_OBJECT_NAME_NOT_FOUND; + DEBUG(5,("open_file_shared: OS/2 long filenames are not supported.\n")); + /* need to reset errno or DEVELOPER will cause us to coredump */ + errno = 0; file_free(fsp); return NULL; } -- cgit From 67425afa3ebc9a105b9b11aebe036c0ca0c5d6e7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 31 Mar 2005 19:10:59 +0000 Subject: r6152: Correctly check OpenX open modes. Jeremy. (This used to be commit 326124a7b366feaca6162f7defae89618b005adc) --- source3/smbd/open.c | 48 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 13 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 9d9d9d9208..baea165d2a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1124,15 +1124,30 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ return print_fsp_open(conn, fname); } - fsp = file_new(conn); - if(!fsp) - return NULL; + switch(ofun) { + case FILE_EXISTS_OPEN: + case FILE_EXISTS_TRUNCATE: + case FILE_EXISTS_FAIL | FILE_CREATE_IF_NOT_EXIST: + case FILE_EXISTS_OPEN | FILE_CREATE_IF_NOT_EXIST: + case FILE_EXISTS_TRUNCATE | FILE_CREATE_IF_NOT_EXIST: + break; /* These are ok. */ + default: + if (GET_OPEN_MODE(share_mode) == DOS_OPEN_EXEC) { + ofun = FILE_EXISTS_FAIL | FILE_CREATE_IF_NOT_EXIST; + break; + } + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRinvalidparam; + unix_ERR_ntstatus = NT_STATUS_INVALID_LOCK_SEQUENCE; + /* need to reset errno or DEVELOPER will cause us to coredump */ + errno = 0; + return NULL; + } DEBUG(10,("open_file_shared: fname = %s, dos_attrs = %x, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n", fname, new_dos_mode, share_mode, ofun, (int)mode, oplock_request )); if (!check_name(fname,conn)) { - file_free(fsp); return NULL; } @@ -1155,14 +1170,12 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ DEBUG(5,("open_file_shared: OS/2 long filenames are not supported.\n")); /* need to reset errno or DEVELOPER will cause us to coredump */ errno = 0; - file_free(fsp); return NULL; } 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 )); - file_free(fsp); if (S_ISDIR(psbuf->st_mode)) { errno = EISDIR; } else { @@ -1184,7 +1197,6 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ DEBUG(5,("open_file_shared: attributes missmatch for file %s (%x %x) (0%o, 0%o)\n", fname, existing_dos_mode, new_dos_mode, (int)psbuf->st_mode, (int)mode )); - file_free(fsp); errno = EACCES; return NULL; } @@ -1197,6 +1209,11 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ append does not mean the same thing under dos and unix */ switch (GET_OPEN_MODE(share_mode)) { + case DOS_OPEN_RDONLY: + flags = O_RDONLY; + if (desired_access == 0) + desired_access = FILE_READ_DATA; + break; case DOS_OPEN_WRONLY: flags = O_WRONLY; if (desired_access == 0) @@ -1209,15 +1226,18 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ desired_access = FILE_READ_DATA|FILE_WRITE_DATA; break; case DOS_OPEN_RDWR: + case DOS_OPEN_EXEC: flags = O_RDWR; if (desired_access == 0) desired_access = FILE_READ_DATA|FILE_WRITE_DATA; break; default: - flags = O_RDONLY; - if (desired_access == 0) - desired_access = FILE_READ_DATA; - break; + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRinvalidparam; + unix_ERR_ntstatus = NT_STATUS_INVALID_LOCK_SEQUENCE; + /* need to reset errno or DEVELOPER will cause us to coredump */ + errno = 0; + return NULL; } #if defined(O_SYNC) @@ -1231,7 +1251,6 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ 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" )); - file_free(fsp); errno = EACCES; return NULL; } @@ -1240,7 +1259,6 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) { DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname)); - file_free(fsp); errno = EINVAL; return NULL; } @@ -1256,6 +1274,10 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ } } + fsp = file_new(conn); + if(!fsp) + return NULL; + if (file_existed) { dev = psbuf->st_dev; -- cgit From 0557c6cba2a21c9df547fbc8ff4db2899bc1c171 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 1 Apr 2005 23:11:28 +0000 Subject: r6172: Tidy up error processing significantly. Remove unix_ERR_XXX global nastyness. Jeremy. (This used to be commit d3379fe61bb934082b51a37adac232a96bafcf46) --- source3/smbd/open.c | 101 +++++++++++++++++----------------------------------- 1 file changed, 32 insertions(+), 69 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index baea165d2a..41ced42034 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -76,9 +76,7 @@ static void check_for_pipe(const char *fname) strlower_m(s); if (strstr(s,"pipe/")) { DEBUG(3,("Rejecting named pipe open for %s\n",fname)); - unix_ERR_class = ERRSRV; - unix_ERR_code = ERRaccess; - unix_ERR_ntstatus = NT_STATUS_ACCESS_DENIED; + set_saved_error_triple(ERRSRV, ERRaccess, NT_STATUS_ACCESS_DENIED); } } @@ -250,9 +248,7 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, /* Don't create files with Microsoft wildcard characters. */ if ((local_flags & O_CREAT) && !VALID_STAT(*psbuf) && ms_has_wild(fname)) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRinvalidname; - unix_ERR_ntstatus = NT_STATUS_OBJECT_NAME_INVALID; + set_saved_error_triple(ERRDOS, ERRinvalidname, NT_STATUS_OBJECT_NAME_INVALID); return False; } @@ -487,9 +483,7 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i DEBUG(5,("check_share_mode: Failing open on file %s as delete on close flag is set.\n", fname )); /* Use errno to map to correct error. */ - unix_ERR_class = SMB_SUCCESS; - unix_ERR_code = 0; - unix_ERR_ntstatus = NT_STATUS_OK; + set_saved_error_triple(SMB_SUCCESS, 0, NT_STATUS_OK); return False; } @@ -529,10 +523,7 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i (!GET_ALLOW_SHARE_DELETE(share->share_mode) || !GET_ALLOW_SHARE_DELETE(share_mode))) { DEBUG(5,("check_share_mode: Failing open on file %s as delete access requests conflict.\n", fname )); - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; - + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); return False; } @@ -557,10 +548,7 @@ existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsign if ((desired_access & DELETE_ACCESS) && !GET_ALLOW_SHARE_DELETE(share->share_mode)) { DEBUG(5,("check_share_mode: Failing open on file %s as delete access requested and allow share delete not set.\n", fname )); - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; - + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); return False; } @@ -573,18 +561,14 @@ existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsign if ((share->desired_access & DELETE_ACCESS) && !GET_ALLOW_SHARE_DELETE(share_mode)) { DEBUG(5,("check_share_mode: Failing open on file %s as delete access granted and allow share delete not requested.\n", fname )); - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); return False; } #if 0 /* Bluarc test may need this ... needs further investigation. */ if (deny_mode == DENY_ALL || old_deny_mode == DENY_ALL) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); return False; } #endif @@ -614,10 +598,7 @@ existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsign deny_mode,old_deny_mode,old_open_mode, (int)share->pid,fname, fcbopen, *flags, access_allowed)); - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; - + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); return False; } @@ -768,10 +749,7 @@ dev = %x, inode = %.0f\n", *p_oplock_request, share_entry->op_type, fname, (unsi 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)); SAFE_FREE(old_shares); - errno = EACCES; - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); return -1; } @@ -835,9 +813,7 @@ after break ! For file %s, dev = %x, inode = %.0f. Deleting it to continue...\n" if (del_share_entry(dev, inode, &broken_entry->entry, NULL) == -1) { free_broken_entry_list(broken_entry_list); errno = EACCES; - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); return -1; } @@ -1104,9 +1080,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ delete_defered_open_entry_record(conn, dib.dev, dib.inode); unlock_share_entry(conn, dib.dev, dib.inode); - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); return NULL; } /* Ensure we don't reprocess this message. */ @@ -1136,11 +1110,8 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ ofun = FILE_EXISTS_FAIL | FILE_CREATE_IF_NOT_EXIST; break; } - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRinvalidparam; - unix_ERR_ntstatus = NT_STATUS_INVALID_LOCK_SEQUENCE; - /* need to reset errno or DEVELOPER will cause us to coredump */ - errno = 0; + /* Cause caller to force dos errors. */ + set_saved_error_triple(ERRDOS, ERRbadaccess, NT_STATUS_INVALID); return NULL; } @@ -1163,13 +1134,9 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ /* this is for OS/2 long file names - say we don't support them */ if (strstr(fname,".+,;=[].")) { - unix_ERR_class = ERRDOS; /* OS/2 Workplace shell fix may be main code stream in a later release. */ - unix_ERR_code = ERRcannotopen; - unix_ERR_ntstatus = NT_STATUS_OBJECT_NAME_NOT_FOUND; + set_saved_error_triple(ERRDOS, ERRcannotopen, NT_STATUS_OBJECT_NAME_NOT_FOUND); DEBUG(5,("open_file_shared: OS/2 long filenames are not supported.\n")); - /* need to reset errno or DEVELOPER will cause us to coredump */ - errno = 0; return NULL; } @@ -1232,11 +1199,8 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ desired_access = FILE_READ_DATA|FILE_WRITE_DATA; break; default: - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRinvalidparam; - unix_ERR_ntstatus = NT_STATUS_INVALID_LOCK_SEQUENCE; - /* need to reset errno or DEVELOPER will cause us to coredump */ - errno = 0; + /* Force DOS error. */ + set_saved_error_triple(ERRDOS, ERRinvalidparam, NT_STATUS_INVALID); return NULL; } @@ -1311,9 +1275,8 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", flags,(flags2&~(O_TRUNC|O_CREAT)),(int)mode,(int)fsp_open )); if (!fsp_open && errno) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRnoaccess; - unix_ERR_ntstatus = NT_STATUS_ACCESS_DENIED; + /* Default error. */ + set_saved_error_triple(ERRDOS, ERRnoaccess, NT_STATUS_ACCESS_DENIED); } /* @@ -1321,9 +1284,13 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", * the braindead 1 second delay. */ - if (!internal_only_open && NT_STATUS_EQUAL(unix_ERR_ntstatus,NT_STATUS_SHARING_VIOLATION)) { - /* The fsp->open_time here represents the current time of day. */ - defer_open_sharing_error(conn, &fsp->open_time, fname, dev, inode); + if (!internal_only_open) { + NTSTATUS status; + get_saved_error_triple(NULL, NULL, &status); + if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION)) { + /* The fsp->open_time here represents the current time of day. */ + defer_open_sharing_error(conn, &fsp->open_time, fname, dev, inode); + } } unlock_share_entry(conn, dev, inode); @@ -1333,9 +1300,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", * We have detected a sharing violation here * so return the correct error code */ - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); } file_free(fsp); return NULL; @@ -1407,7 +1372,9 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", * the braindead 1 second delay. */ - if (!internal_only_open && NT_STATUS_EQUAL(unix_ERR_ntstatus,NT_STATUS_SHARING_VIOLATION)) { + NTSTATUS status; + get_saved_error_triple(NULL, NULL, &status); + if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION)) { /* The fsp->open_time here represents the current time of day. */ defer_open_sharing_error(conn, &fsp->open_time, fname, dev, inode); } @@ -1419,9 +1386,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", * We have detected a sharing violation here, so * return the correct code. */ - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); return NULL; } @@ -1549,9 +1514,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", fd_close(conn,fsp); file_free(fsp); ntstatus_to_dos(result, &u_e_c, &u_e_code); - unix_ERR_ntstatus = result; - unix_ERR_class = u_e_c; - unix_ERR_code = u_e_code; + set_saved_error_triple(u_e_c, u_e_code, result); return NULL; } } @@ -1704,7 +1667,7 @@ files_struct *open_directory(connection_struct *conn, const char *fname, SMB_STR fname, strerror(errno) )); file_free(fsp); /* Ensure we return the correct NT status to the client. */ - unix_ERR_ntstatus = status; + set_saved_error_triple(0, 0, status); return NULL; } -- cgit From 1045c786246658f5d8e289d46cb4bdfc87655c71 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 2 Apr 2005 00:13:27 +0000 Subject: r6174: Fixup T2 open call - we were returning 2 bytes short. Jeremy. (This used to be commit 0c7de7615bf0edbb36a3afee445db13a71e26d2e) --- source3/smbd/open.c | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 41ced42034..fbe763ab0a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1098,23 +1098,6 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ return print_fsp_open(conn, fname); } - switch(ofun) { - case FILE_EXISTS_OPEN: - case FILE_EXISTS_TRUNCATE: - case FILE_EXISTS_FAIL | FILE_CREATE_IF_NOT_EXIST: - case FILE_EXISTS_OPEN | FILE_CREATE_IF_NOT_EXIST: - case FILE_EXISTS_TRUNCATE | FILE_CREATE_IF_NOT_EXIST: - break; /* These are ok. */ - default: - if (GET_OPEN_MODE(share_mode) == DOS_OPEN_EXEC) { - ofun = FILE_EXISTS_FAIL | FILE_CREATE_IF_NOT_EXIST; - break; - } - /* Cause caller to force dos errors. */ - set_saved_error_triple(ERRDOS, ERRbadaccess, NT_STATUS_INVALID); - return NULL; - } - DEBUG(10,("open_file_shared: fname = %s, dos_attrs = %x, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n", fname, new_dos_mode, share_mode, ofun, (int)mode, oplock_request )); -- cgit From d318fe4025755b68f88fd9f0605732ee8b94c57f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 4 Apr 2005 20:46:16 +0000 Subject: r6200: Returned access should contain share mode as well as open mode. Jeremy. (This used to be commit 3aa784c07723430b429adc9abab9cc7c1325cb35) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index fbe763ab0a..5b349e2e44 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1435,7 +1435,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", DEBUG(10,("open_file_shared : share_mode = %x\n", fsp->share_mode )); if (Access) { - (*Access) = open_mode; + (*Access) = (SET_DENY_MODE(deny_mode) | SET_OPEN_MODE(open_mode)); } action = 0; -- cgit From 978ca8486031e43754a3c23757f361bf3a85f335 Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Wed, 6 Apr 2005 16:28:04 +0000 Subject: r6225: get rid of warnings from my compiler about nested externs (This used to be commit efea76ac71412f8622cd233912309e91b9ea52da) --- source3/smbd/open.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 5b349e2e44..559994ca46 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -21,6 +21,7 @@ #include "includes.h" +extern struct current_user current_user; extern userdom_struct current_user_info; extern uint16 global_oplock_port; extern uint16 global_smbpid; @@ -172,7 +173,6 @@ Error was %s\n", static BOOL open_file(files_struct *fsp,connection_struct *conn, const char *fname,SMB_STRUCT_STAT *psbuf,int flags,mode_t mode, uint32 desired_access) { - extern struct current_user current_user; int accmode = (flags & O_ACCMODE); int local_flags = flags; @@ -1606,7 +1606,6 @@ int close_file_fchmod(files_struct *fsp) files_struct *open_directory(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 desired_access, int share_mode, int smb_ofun, int *action) { - extern struct current_user current_user; BOOL got_stat = False; files_struct *fsp = file_new(conn); BOOL delete_on_close = GET_DELETE_ON_CLOSE_FLAG(share_mode); @@ -1744,7 +1743,6 @@ files_struct *open_directory(connection_struct *conn, const char *fname, SMB_STR files_struct *open_file_stat(connection_struct *conn, char *fname, SMB_STRUCT_STAT *psbuf) { - extern struct current_user current_user; files_struct *fsp = NULL; if (!VALID_STAT(*psbuf)) -- cgit From da70ef7c06ef55b9049697f13fdaecf8a2f31e35 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 14 Apr 2005 21:01:01 +0000 Subject: r6344: Fix bug #2601 - it seems that DOS_OPEN_EXEC does mean readonly. Needed for Win9x and OS/2 clients. More Samba4 tests against W2k3 will be needed to confirm this but in the meantime get it up and running. Jeremy. (This used to be commit 77c0ade9fa1e6a31739823be0faa50799bac2775) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 559994ca46..a3bc4a922d 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1159,6 +1159,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ append does not mean the same thing under dos and unix */ switch (GET_OPEN_MODE(share_mode)) { + case DOS_OPEN_EXEC: case DOS_OPEN_RDONLY: flags = O_RDONLY; if (desired_access == 0) @@ -1176,7 +1177,6 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ desired_access = FILE_READ_DATA|FILE_WRITE_DATA; break; case DOS_OPEN_RDWR: - case DOS_OPEN_EXEC: flags = O_RDWR; if (desired_access == 0) desired_access = FILE_READ_DATA|FILE_WRITE_DATA; -- cgit From 08355754151b2d02b2102bc76e94b63ffffdf408 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 8 May 2005 23:16:28 +0000 Subject: r6673: Fix the write cache based on some VERY good detective work from Ingo Kilian . You must do a make clean after updating this. Jeremy. (This used to be commit 3b2cd19fcb8ce38578b122fd6ae722b73081dcda) --- source3/smbd/open.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index a3bc4a922d..8b30776fdd 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -304,7 +304,6 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->dev = psbuf->st_dev; fsp->vuid = current_user.vuid; fsp->file_pid = global_smbpid; - fsp->size = psbuf->st_size; fsp->can_lock = True; fsp->can_read = ((flags & O_WRONLY)==0); fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0); @@ -1701,7 +1700,6 @@ files_struct *open_directory(connection_struct *conn, const char *fname, SMB_STR fsp->mode = psbuf->st_mode; fsp->inode = psbuf->st_ino; fsp->dev = psbuf->st_dev; - fsp->size = psbuf->st_size; fsp->vuid = current_user.vuid; fsp->file_pid = global_smbpid; fsp->can_lock = True; @@ -1765,7 +1763,6 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, SMB_STRUCT_ST fsp->mode = psbuf->st_mode; fsp->inode = psbuf->st_ino; fsp->dev = psbuf->st_dev; - fsp->size = psbuf->st_size; fsp->vuid = current_user.vuid; fsp->file_pid = global_smbpid; fsp->can_lock = False; -- cgit From f2f55d703d0dd549a83809d3e5cc5151569b48d6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 27 Jun 2005 22:53:56 +0000 Subject: r7963: Add aio support to 3.0. Jeremy. (This used to be commit 1de27da47051af08790317f5b48b02719d6b9934) --- source3/smbd/open.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 8b30776fdd..9da53a5057 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -316,6 +316,10 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->is_directory = False; fsp->is_stat = False; fsp->directory_delete_on_close = False; + if (conn->aio_write_behind_list && is_in_path(fname, conn->aio_write_behind_list, conn->case_sensitive)) { + fsp->aio_write_behind = True; + } + string_set(&fsp->fsp_name,fname); fsp->wcp = NULL; /* Write cache pointer. */ -- cgit From af8a691db11a5072865f8b03fd1cbd3aab5cb6d7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 8 Jul 2005 04:51:27 +0000 Subject: r8219: Merge the new open code from HEAD to 3.0. Haven't yet run the torture tests on this as it's very late NY time (just wanted to get this work into the tree). I'll test this over the weekend.... Jerry - in looking at the difference between the two trees there seem to be some printing/ntprinting.c and registry changes we might want to examine to try keep in sync. Jeremy. (This used to be commit c7fe18761e2c753afbffd3a78abff46472a9b8eb) --- source3/smbd/open.c | 1906 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 1127 insertions(+), 779 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 9da53a5057..810913c025 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -3,6 +3,7 @@ file opening and share modes Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Jeremy Allison 2001-2004 + Copyright (C) Volker Lendecke 2005 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -36,13 +37,16 @@ struct dev_inode_bundle { fd support routines - attempt to do a dos_open. ****************************************************************************/ -static int fd_open(struct connection_struct *conn, const char *fname, - int flags, mode_t mode) +static int fd_open(struct connection_struct *conn, + const char *fname, + int flags, + mode_t mode) { int fd; #ifdef O_NOFOLLOW - if (!lp_symlinks(SNUM(conn))) + if (!lp_symlinks(SNUM(conn))) { flags |= O_NOFOLLOW; + } #endif fd = SMB_VFS_OPEN(conn,fname,flags,mode); @@ -57,10 +61,15 @@ static int fd_open(struct connection_struct *conn, const char *fname, Close the file associated with a fsp. ****************************************************************************/ -int fd_close(struct connection_struct *conn, files_struct *fsp) +int fd_close(struct connection_struct *conn, + files_struct *fsp) { - if (fsp->fd == -1) - return 0; /* what we used to call a stat open. */ + if (fsp->fh->fd == -1) { + return 0; /* What we used to call a stat open. */ + } + if (fsp->fh->ref_count > 1) { + return 0; /* Shared handle. Only close last reference. */ + } return fd_close_posix(conn, fsp); } @@ -86,7 +95,10 @@ static void check_for_pipe(const char *fname) Do this by fd if possible. ****************************************************************************/ -void change_owner_to_parent(connection_struct *conn, files_struct *fsp, const char *fname, SMB_STRUCT_STAT *psbuf) +void change_owner_to_parent(connection_struct *conn, + files_struct *fsp, + const char *fname, + SMB_STRUCT_STAT *psbuf) { const char *parent_path = parent_dirname(fname); SMB_STRUCT_STAT parent_st; @@ -94,56 +106,67 @@ void change_owner_to_parent(connection_struct *conn, files_struct *fsp, const ch ret = SMB_VFS_STAT(conn, parent_path, &parent_st); if (ret == -1) { - DEBUG(0,("change_owner_to_parent: failed to stat parent directory %s. Error was %s\n", - parent_path, strerror(errno) )); + DEBUG(0,("change_owner_to_parent: failed to stat parent " + "directory %s. Error was %s\n", + parent_path, strerror(errno) )); return; } - if (fsp && fsp->fd != -1) { + if (fsp && fsp->fh->fd != -1) { become_root(); - ret = SMB_VFS_FCHOWN(fsp, fsp->fd, parent_st.st_uid, (gid_t)-1); + ret = SMB_VFS_FCHOWN(fsp, fsp->fh->fd, parent_st.st_uid, (gid_t)-1); unbecome_root(); if (ret == -1) { - DEBUG(0,("change_owner_to_parent: failed to fchown file %s to parent directory uid %u. \ -Error was %s\n", - fname, (unsigned int)parent_st.st_uid, strerror(errno) )); + DEBUG(0,("change_owner_to_parent: failed to fchown " + "file %s to parent directory uid %u. Error " + "was %s\n", fname, + (unsigned int)parent_st.st_uid, + strerror(errno) )); } - DEBUG(10,("change_owner_to_parent: changed new file %s to parent directory uid %u.\n", - fname, (unsigned int)parent_st.st_uid )); + DEBUG(10,("change_owner_to_parent: changed new file %s to " + "parent directory uid %u.\n", fname, + (unsigned int)parent_st.st_uid )); } else { - /* We've already done an lstat into psbuf, and we know it's a directory. If - we can cd into the directory and the dev/ino are the same then we can safely - chown without races as we're locking the directory in place by being in it. - This should work on any UNIX (thanks tridge :-). JRA. + /* We've already done an lstat into psbuf, and we know it's a + directory. If we can cd into the directory and the dev/ino + are the same then we can safely chown without races as + we're locking the directory in place by being in it. This + should work on any UNIX (thanks tridge :-). JRA. */ pstring saved_dir; SMB_STRUCT_STAT sbuf; if (!vfs_GetWd(conn,saved_dir)) { - DEBUG(0,("change_owner_to_parent: failed to get current working directory\n")); + DEBUG(0,("change_owner_to_parent: failed to get " + "current working directory\n")); return; } /* Chdir into the new path. */ if (vfs_ChDir(conn, fname) == -1) { - DEBUG(0,("change_owner_to_parent: failed to change current working directory to %s. \ -Error was %s\n", fname, strerror(errno) )); + DEBUG(0,("change_owner_to_parent: failed to change " + "current working directory to %s. Error " + "was %s\n", fname, strerror(errno) )); goto out; } if (SMB_VFS_STAT(conn,".",&sbuf) == -1) { - DEBUG(0,("change_owner_to_parent: failed to stat directory '.' (%s) \ -Error was %s\n", fname, strerror(errno))); + DEBUG(0,("change_owner_to_parent: failed to stat " + "directory '.' (%s) Error was %s\n", + fname, strerror(errno))); goto out; } /* Ensure we're pointing at the same place. */ - if (sbuf.st_dev != psbuf->st_dev || sbuf.st_ino != psbuf->st_ino || sbuf.st_mode != psbuf->st_mode ) { - DEBUG(0,("change_owner_to_parent: device/inode/mode on directory %s changed. Refusing to chown !\n", - fname )); + if (sbuf.st_dev != psbuf->st_dev || + sbuf.st_ino != psbuf->st_ino || + sbuf.st_mode != psbuf->st_mode ) { + DEBUG(0,("change_owner_to_parent: " + "device/inode/mode on directory %s changed. " + "Refusing to chown !\n", fname )); goto out; } @@ -151,14 +174,16 @@ Error was %s\n", fname, strerror(errno))); ret = SMB_VFS_CHOWN(conn, ".", parent_st.st_uid, (gid_t)-1); unbecome_root(); if (ret == -1) { - DEBUG(10,("change_owner_to_parent: failed to chown directory %s to parent directory uid %u. \ -Error was %s\n", - fname, (unsigned int)parent_st.st_uid, strerror(errno) )); + DEBUG(10,("change_owner_to_parent: failed to chown " + "directory %s to parent directory uid %u. " + "Error was %s\n", fname, + (unsigned int)parent_st.st_uid, strerror(errno) )); goto out; } - DEBUG(10,("change_owner_to_parent: changed ownership of new directory %s to parent directory uid %u.\n", - fname, (unsigned int)parent_st.st_uid )); + DEBUG(10,("change_owner_to_parent: changed ownership of new " + "directory %s to parent directory uid %u.\n", + fname, (unsigned int)parent_st.st_uid )); out: @@ -170,13 +195,19 @@ Error was %s\n", Open a file. ****************************************************************************/ -static BOOL open_file(files_struct *fsp,connection_struct *conn, - const char *fname,SMB_STRUCT_STAT *psbuf,int flags,mode_t mode, uint32 desired_access) +static BOOL open_file(files_struct *fsp, + connection_struct *conn, + const char *fname, + SMB_STRUCT_STAT *psbuf, + int flags, + mode_t unx_mode, + uint32 access_mask) { int accmode = (flags & O_ACCMODE); int local_flags = flags; + BOOL file_existed = VALID_STAT(*psbuf); - fsp->fd = -1; + fsp->fh->fd = -1; fsp->oplock_type = NO_OPLOCK; errno = EPERM; @@ -199,9 +230,9 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, check_for_pipe(fname); return False; } 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. + /* 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; local_flags &= ~O_CREAT; @@ -221,12 +252,14 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, */ if ((accmode == O_RDONLY) && ((flags & O_TRUNC) == O_TRUNC)) { - DEBUG(10,("open_file: truncate requested on read-only open for file %s\n",fname )); + DEBUG(10,("open_file: truncate requested on read-only open " + "for file %s\n",fname )); 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) ) { + if ((access_mask & (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. @@ -242,42 +275,50 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, * open flags. JRA. */ - if (VALID_STAT(*psbuf) && S_ISFIFO(psbuf->st_mode)) + if (file_existed && S_ISFIFO(psbuf->st_mode)) { local_flags |= O_NONBLOCK; + } #endif /* Don't create files with Microsoft wildcard characters. */ - if ((local_flags & O_CREAT) && !VALID_STAT(*psbuf) && ms_has_wild(fname)) { - set_saved_error_triple(ERRDOS, ERRinvalidname, NT_STATUS_OBJECT_NAME_INVALID); + if ((local_flags & O_CREAT) && !file_existed && + ms_has_wild(fname)) { + set_saved_error_triple(ERRDOS, ERRinvalidname, + NT_STATUS_OBJECT_NAME_INVALID); return False; } /* Actually do the open */ - fsp->fd = fd_open(conn, fname, local_flags, mode); - if (fsp->fd == -1) { - DEBUG(3,("Error opening file %s (%s) (local_flags=%d) (flags=%d)\n", + fsp->fh->fd = fd_open(conn, fname, local_flags, unx_mode); + if (fsp->fh->fd == -1) { + DEBUG(3,("Error opening file %s (%s) (local_flags=%d) " + "(flags=%d)\n", fname,strerror(errno),local_flags,flags)); check_for_pipe(fname); return False; } /* Inherit the ACL if the file was created. */ - if ((local_flags & O_CREAT) && !VALID_STAT(*psbuf)) - inherit_access_acl(conn, fname, mode); + if ((local_flags & O_CREAT) && !file_existed) { + inherit_access_acl(conn, fname, unx_mode); + } - } else - fsp->fd = -1; /* What we used to call a stat open. */ + } else { + fsp->fh->fd = -1; /* What we used to call a stat open. */ + } - if (!VALID_STAT(*psbuf)) { + if (!file_existed) { int ret; - if (fsp->fd == -1) + if (fsp->fh->fd == -1) { ret = SMB_VFS_STAT(conn, fname, psbuf); - else { - ret = SMB_VFS_FSTAT(fsp,fsp->fd,psbuf); + } else { + ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf); /* If we have an fd, this stat should succeed. */ - if (ret == -1) - DEBUG(0,("Error doing fstat on open file %s (%s)\n", fname,strerror(errno) )); + if (ret == -1) { + DEBUG(0,("Error doing fstat on open file %s " + "(%s)\n", fname,strerror(errno) )); + } } /* For a non-io open, this stat failing means file not found. JRA */ @@ -305,18 +346,20 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->vuid = current_user.vuid; fsp->file_pid = global_smbpid; 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->desired_access = desired_access; + fsp->can_read = (access_mask & (FILE_READ_DATA)) ? True : False; + if (!CAN_WRITE(conn)) { + fsp->can_write = False; + } else { + fsp->can_write = (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ? True : False; + } fsp->print_file = False; fsp->modified = False; fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = False; fsp->is_stat = False; - fsp->directory_delete_on_close = False; - if (conn->aio_write_behind_list && is_in_path(fname, conn->aio_write_behind_list, conn->case_sensitive)) { + if (conn->aio_write_behind_list && + is_in_path(fname, conn->aio_write_behind_list, conn->case_sensitive)) { fsp->aio_write_behind = True; } @@ -349,293 +392,119 @@ static BOOL is_executable(const char *fname) return False; } -enum {AFAIL,AREAD,AWRITE,AALL}; - -/******************************************************************* - Reproduce the share mode access table. - This is horrendoously complex, and really can't be justified on any - rational grounds except that this is _exactly_ what NT does. See - the DENY1 and DENY2 tests in smbtorture for a comprehensive set of - test routines. -********************************************************************/ - -static int access_table(int new_deny,int old_deny,int old_mode, - BOOL same_pid, BOOL isexe) -{ - if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL); - - if (same_pid) { - if (isexe && old_mode == DOS_OPEN_RDONLY && - old_deny == DENY_DOS && new_deny == DENY_READ) { - return AFAIL; - } - if (!isexe && old_mode == DOS_OPEN_RDONLY && - old_deny == DENY_DOS && new_deny == DENY_DOS) { - return AREAD; - } - if (new_deny == DENY_FCB && old_deny == DENY_DOS) { - if (isexe) return AFAIL; - if (old_mode == DOS_OPEN_RDONLY) return AFAIL; - return AALL; - } - if (old_mode == DOS_OPEN_RDONLY && old_deny == DENY_DOS) { - if (new_deny == DENY_FCB || new_deny == DENY_READ) { - if (isexe) return AREAD; - return AFAIL; - } - } - if (old_deny == DENY_FCB) { - if (new_deny == DENY_DOS || new_deny == DENY_FCB) return AALL; - return AFAIL; - } - } - - if (old_deny == DENY_DOS || new_deny == DENY_DOS || - old_deny == DENY_FCB || new_deny == DENY_FCB) { - if (isexe) { - if (old_deny == DENY_FCB || new_deny == DENY_FCB) { - return AFAIL; - } - if (old_deny == DENY_DOS) { - if (new_deny == DENY_READ && - (old_mode == DOS_OPEN_RDONLY || - old_mode == DOS_OPEN_RDWR)) { - return AFAIL; - } - if (new_deny == DENY_WRITE && - (old_mode == DOS_OPEN_WRONLY || - old_mode == DOS_OPEN_RDWR)) { - return AFAIL; - } - return AALL; - } - if (old_deny == DENY_NONE) return AALL; - if (old_deny == DENY_READ) return AWRITE; - if (old_deny == DENY_WRITE) return AREAD; - } - /* it isn't a exe, dll, sym or com file */ - if (old_deny == new_deny && same_pid) - return(AALL); - - if (old_deny == DENY_READ || new_deny == DENY_READ) return AFAIL; - if (old_mode == DOS_OPEN_RDONLY) return(AREAD); - - return(AFAIL); - } - - switch (new_deny) - { - case DENY_WRITE: - if (old_deny==DENY_WRITE && old_mode==DOS_OPEN_RDONLY) return(AREAD); - if (old_deny==DENY_READ && old_mode==DOS_OPEN_RDONLY) return(AWRITE); - if (old_deny==DENY_NONE && old_mode==DOS_OPEN_RDONLY) return(AALL); - return(AFAIL); - case DENY_READ: - if (old_deny==DENY_WRITE && old_mode==DOS_OPEN_WRONLY) return(AREAD); - if (old_deny==DENY_READ && old_mode==DOS_OPEN_WRONLY) return(AWRITE); - if (old_deny==DENY_NONE && old_mode==DOS_OPEN_WRONLY) 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. + Returns True if conflict, False if not. ****************************************************************************/ -static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, int share_mode, uint32 desired_access, - const char *fname, BOOL fcbopen, int *flags) +static BOOL share_conflict(share_mode_entry *entry, + uint32 access_mask, + uint32 share_access) { - int deny_mode = GET_DENY_MODE(share_mode); - int old_open_mode = GET_OPEN_MODE(share->share_mode); - int old_deny_mode = GET_DENY_MODE(share->share_mode); - BOOL non_io_open_request; - BOOL non_io_open_existing; - - /* - * share modes = false means don't bother to check for - * DENY mode conflict. This is a *really* bad idea :-). JRA. - */ - - if(!lp_share_modes(SNUM(conn))) - return True; - - if (desired_access & ~(SYNCHRONIZE_ACCESS|READ_CONTROL_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) { - non_io_open_request = False; - } else { - non_io_open_request = True; - } - - if (share->desired_access & ~(SYNCHRONIZE_ACCESS|READ_CONTROL_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) { - non_io_open_existing = False; - } else { - non_io_open_existing = True; - } - - /* - * Don't allow any opens 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 )); - /* Use errno to map to correct error. */ - set_saved_error_triple(SMB_SUCCESS, 0, NT_STATUS_OK); + DEBUG(10,("share_conflict: entry->access_mask = 0x%x, " + "entry->share_access = 0x%x, " + "entry->private_options = 0x%x\n", + (unsigned int)entry->access_mask, + (unsigned int)entry->share_access, + (unsigned int)entry->private_options)); + + DEBUG(10,("share_conflict: access_mask = 0x%x, share_access = 0x%x\n", + (unsigned int)access_mask, (unsigned int)share_access)); + + if ((entry->access_mask & (FILE_WRITE_DATA| + FILE_APPEND_DATA| + FILE_READ_DATA| + FILE_EXECUTE| + DELETE_ACCESS)) == 0) { + DEBUG(10,("share_conflict: No conflict due to " + "entry->access_mask = 0x%x\n", + (unsigned int)entry->access_mask )); return False; } - /* this is a nasty hack, but necessary until we rewrite our open - handling to use a NTCreateX call as the basic call. - NT may open a file with neither read nor write access, and in - this case it expects the open not to conflict with any - existing deny modes. This happens (for example) during a - "xcopy /o" where the second file descriptor is used for - ACL sets - (tridge) - */ - - /* - * This is a bit wierd - the test for desired access not having the - * critical bits seems seems odd. Firstly, if both opens have no - * critical bits then always ignore. Then check the "allow delete" - * then check for either. This probably isn't quite right yet but - * gets us much closer. JRA. - */ - - /* - * If desired_access doesn't contain READ_DATA,WRITE_DATA,APPEND_DATA or EXECUTE - * and the existing desired_acces then share modes don't conflict. - */ - - if (non_io_open_request && non_io_open_existing) { - - /* - * Wrinkle discovered by smbtorture.... - * If both are non-io open and requester is asking for delete and current open has delete access - * but neither open has allowed file share delete then deny.... this is very strange and - * seems to be the only case in which non-io opens conflict. JRA. - */ - - if ((desired_access & DELETE_ACCESS) && (share->desired_access & DELETE_ACCESS) && - (!GET_ALLOW_SHARE_DELETE(share->share_mode) || !GET_ALLOW_SHARE_DELETE(share_mode))) { - DEBUG(5,("check_share_mode: Failing open on file %s as delete access requests conflict.\n", - fname )); - set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); - return False; - } - - DEBUG(5,("check_share_mode: Allowing open on file %s as both desired access (0x%x) \ -and existing desired access (0x%x) are non-data opens\n", - fname, (unsigned int)desired_access, (unsigned int)share->desired_access )); - return True; - } else if (non_io_open_request || non_io_open_existing) { - /* - * If either are non-io opens then share modes don't conflict. - */ - DEBUG(5,("check_share_mode: One non-io open. Allowing open on file %s as desired access (0x%x) doesn't conflict with\ -existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsigned int)share->desired_access )); - return True; - } - - /* - * If delete access was requested and the existing share mode doesn't have - * ALLOW_SHARE_DELETE then deny. - */ - - if ((desired_access & DELETE_ACCESS) && !GET_ALLOW_SHARE_DELETE(share->share_mode)) { - DEBUG(5,("check_share_mode: Failing open on file %s as delete access requested and allow share delete not set.\n", - fname )); - set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); + if ((access_mask & (FILE_WRITE_DATA| + FILE_APPEND_DATA| + FILE_READ_DATA| + FILE_EXECUTE| + DELETE_ACCESS)) == 0) { + DEBUG(10,("share_conflict: No conflict due to " + "access_mask = 0x%x\n", + (unsigned int)access_mask )); return False; } - /* - * The inverse of the above. - * If delete access was granted and the new share mode doesn't have - * ALLOW_SHARE_DELETE then deny. - */ - - if ((share->desired_access & DELETE_ACCESS) && !GET_ALLOW_SHARE_DELETE(share_mode)) { - DEBUG(5,("check_share_mode: Failing open on file %s as delete access granted and allow share delete not requested.\n", - fname )); - set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); - return False; - } - -#if 0 - /* Bluarc test may need this ... needs further investigation. */ - if (deny_mode == DENY_ALL || old_deny_mode == DENY_ALL) { - set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); - return False; +#if 1 /* JRA TEST - Superdebug. */ +#define CHECK_MASK(num, am, right, sa, share) \ + DEBUG(10,("share_conflict: [%d] am (0x%x) & right (0x%x) = 0x%x\n", \ + (unsigned int)(num), (unsigned int)(am), \ + (unsigned int)(right), (unsigned int)(am)&(right) )); \ + DEBUG(10,("share_conflict: [%d] sa (0x%x) & share (0x%x) = 0x%x\n", \ + (unsigned int)(num), (unsigned int)(sa), \ + (unsigned int)(share), (unsigned int)(sa)&(share) )); \ + if (((am) & (right)) && !((sa) & (share))) { \ + DEBUG(10,("share_conflict: check %d conflict am = 0x%x, right = 0x%x, \ +sa = 0x%x, share = 0x%x\n", (num), (unsigned int)(am), (unsigned int)(right), (unsigned int)(sa), \ + (unsigned int)(share) )); \ + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); \ + return True; \ + } +#else +#define CHECK_MASK(num, am, right, sa, share) \ + if (((am) & (right)) && !((sa) & (share))) { \ + DEBUG(10,("share_conflict: check %d conflict am = 0x%x, right = 0x%x, \ +sa = 0x%x, share = 0x%x\n", (num), (unsigned int)(am), (unsigned int)(right), (unsigned int)(sa), \ + (unsigned int)(share) )); \ + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); \ + return True; \ } #endif - /* - * If desired_access doesn't contain READ_DATA,WRITE_DATA,APPEND_DATA or EXECUTE - * then share modes don't conflict. Likewise with existing desired access. - */ - - if ( !(desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) || - !(share->desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ) { - DEBUG(5,("check_share_mode: Allowing open on file %s as desired access (0x%x) doesn't conflict with \ -existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsigned int)share->desired_access )); - return True; - } - - { - int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode, - (share->pid == sys_getpid()),is_executable(fname)); - - if ((access_allowed == AFAIL) || - (!fcbopen && (access_allowed == AREAD && *flags == O_RDWR)) || - (access_allowed == AREAD && *flags != O_RDONLY) || - (access_allowed == AWRITE && *flags != O_WRONLY)) { - - 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, - (int)share->pid,fname, fcbopen, *flags, access_allowed)); - - set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); - return False; - } - - if (access_allowed == AREAD) - *flags = O_RDONLY; - - if (access_allowed == AWRITE) - *flags = O_WRONLY; + CHECK_MASK(1, entry->access_mask, FILE_WRITE_DATA | FILE_APPEND_DATA, + share_access, FILE_SHARE_WRITE); + CHECK_MASK(2, access_mask, FILE_WRITE_DATA | FILE_APPEND_DATA, + entry->share_access, FILE_SHARE_WRITE); + + CHECK_MASK(3, entry->access_mask, FILE_READ_DATA | FILE_EXECUTE, + share_access, FILE_SHARE_READ); + CHECK_MASK(4, access_mask, FILE_READ_DATA | FILE_EXECUTE, + entry->share_access, FILE_SHARE_READ); - } + CHECK_MASK(5, entry->access_mask, DELETE_ACCESS, + share_access, FILE_SHARE_DELETE); + CHECK_MASK(6, access_mask, DELETE_ACCESS, + entry->share_access, FILE_SHARE_DELETE); - return True; + DEBUG(10,("share_conflict: No conflict.\n")); + return False; } - #if defined(DEVELOPER) -static void validate_my_share_entries(int num, share_mode_entry *share_entry) +static void validate_my_share_entries(int num, + share_mode_entry *share_entry) { files_struct *fsp; - if (share_entry->pid != sys_getpid()) + if (share_entry->pid != sys_getpid()) { return; + } - fsp = file_find_dif(share_entry->dev, share_entry->inode, share_entry->share_file_id); + fsp = file_find_dif(share_entry->dev, share_entry->inode, + share_entry->share_file_id); if (!fsp) { - DEBUG(0,("validate_my_share_entries: PANIC : %s\n", share_mode_str(num, share_entry) )); - smb_panic("validate_my_share_entries: Cannot match a share entry with an open file\n"); + DEBUG(0,("validate_my_share_entries: PANIC : %s\n", + share_mode_str(num, share_entry) )); + smb_panic("validate_my_share_entries: Cannot match a " + "share entry with an open file\n"); } if (((uint16)fsp->oplock_type) != share_entry->op_type) { pstring str; - DEBUG(0,("validate_my_share_entries: PANIC : %s\n", share_mode_str(num, share_entry) )); - slprintf(str, sizeof(str)-1, "validate_my_share_entries: file %s, oplock_type = 0x%x, op_type = 0x%x\n", - fsp->fsp_name, (unsigned int)fsp->oplock_type, (unsigned int)share_entry->op_type ); + DEBUG(0,("validate_my_share_entries: PANIC : %s\n", + share_mode_str(num, share_entry) )); + slprintf(str, sizeof(str)-1, "validate_my_share_entries: " + "file %s, oplock_type = 0x%x, op_type = 0x%x\n", + fsp->fsp_name, (unsigned int)fsp->oplock_type, + (unsigned int)share_entry->op_type ); smb_panic(str); } } @@ -655,42 +524,75 @@ static void free_broken_entry_list(struct share_mode_entry_list *broken_entry_li } } +static BOOL cause_oplock_break(int request, int existing, uint32 access_mask) +{ + if ((access_mask == DELETE_ACCESS) && + (request == NO_OPLOCK)) { + /* This is a delete request */ + return (BATCH_OPLOCK_TYPE(existing) != 0); + } + + if (EXCLUSIVE_OPLOCK_TYPE(existing) && (request != NO_OPLOCK)) { + return True; + } + + if ((existing != NO_OPLOCK) && (request == NO_OPLOCK)) { + return True; + } + + return False; +} + /**************************************************************************** Deal with open deny mode and oplock break processing. Invarient: Share mode must be locked on entry and exit. Returns -1 on error, or number of share modes on success (may be zero). ****************************************************************************/ -static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T dev, +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, + uint32 access_mask, + uint32 share_access, + uint32 create_options, + int *p_flags, + int *p_oplock_request, BOOL *p_all_current_opens_are_level_II) { int i; int num_share_modes; int oplock_contention_count = 0; share_mode_entry *old_shares = NULL; - BOOL fcbopen = False; BOOL broke_oplock; + BOOL delete_on_close; - if(GET_OPEN_MODE(share_mode) == DOS_OPEN_FCB) - fcbopen = True; - - num_share_modes = get_share_modes(conn, dev, inode, &old_shares); + num_share_modes = get_share_modes(dev, inode, &old_shares, &delete_on_close); if(num_share_modes == 0) { SAFE_FREE(old_shares); return 0; } - if (desired_access && ((desired_access & ~(SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES))==0) && - ((desired_access & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) != 0)) { - /* Stat open that doesn't trigger oplock breaks or share mode checks... ! JRA. */ + if (access_mask && + ((access_mask & ~(SYNCHRONIZE_ACCESS| FILE_READ_ATTRIBUTES| + FILE_WRITE_ATTRIBUTES))==0) && + ((access_mask & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES| + FILE_WRITE_ATTRIBUTES)) != 0)) { + /* Stat open that doesn't trigger oplock breaks or share mode + * checks... ! JRA. */ SAFE_FREE(old_shares); return num_share_modes; } + /* A delete on close prohibits everything */ + + if (delete_on_close) { + SAFE_FREE(old_shares); + errno = EACCES; + return -1; + } + /* * Check if the share modes will give us access. */ @@ -703,132 +605,152 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T *p_all_current_opens_are_level_II = True; for(i = 0; i < num_share_modes; i++) { - BOOL cause_oplock_break = False; share_mode_entry *share_entry = &old_shares[i]; + BOOL opb_ret; #if defined(DEVELOPER) validate_my_share_entries(i, share_entry); #endif /* - * By observation of NetBench, oplocks are broken *before* share - * modes are checked. This allows a file to be closed by the client - * if the share mode would deny access and the client has an oplock. - * Check if someone has an oplock on this file. If so we must break - * it before continuing. + * By observation of NetBench, oplocks are broken + * *before* share modes are checked. This allows a + * file to be closed by the client if the share mode + * would deny access and the client has an oplock. + * Check if someone has an oplock on this file. If so + * we must break it before continuing. */ - - /* Was this a delete this file request ? */ - if (!*p_oplock_request && desired_access == DELETE_ACCESS && - !BATCH_OPLOCK_TYPE(share_entry->op_type)) { - /* Don't break the oplock in this case. */ - cause_oplock_break = False; - } else if((*p_oplock_request && EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type)) || - (!*p_oplock_request && (share_entry->op_type != NO_OPLOCK))) { - cause_oplock_break = True; + + if (!cause_oplock_break(*p_oplock_request, + share_entry->op_type, + access_mask)) { + if (!LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) { + *p_all_current_opens_are_level_II = False; + } + continue; } - if(cause_oplock_break) { - BOOL opb_ret; + /* This is an oplock break */ - 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)); + 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)); - /* Ensure the reply for the open uses the correct sequence number. */ - /* This isn't a real deferred packet as it's response will also increment - * the sequence. - */ - srv_defer_sign_response(get_current_mid()); + /* Ensure the reply for the open uses the correct + * sequence number. */ + /* This isn't a real deferred packet as it's response + * will also increment the sequence. + */ + srv_defer_sign_response(get_current_mid()); - /* Oplock break - unlock to request it. */ - unlock_share_entry(conn, dev, inode); - - opb_ret = request_oplock_break(share_entry); + /* Oplock break - unlock to request it. */ + unlock_share_entry(conn, dev, inode); - /* Now relock. */ - lock_share_entry(conn, dev, inode); + opb_ret = request_oplock_break(share_entry); - 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)); - SAFE_FREE(old_shares); - set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); - return -1; - } + /* Now relock. */ + lock_share_entry(conn, dev, inode); - broken_entry = SMB_MALLOC_P(struct share_mode_entry_list); - if (!broken_entry) { - smb_panic("open_mode_check: malloc fail.\n"); - } - broken_entry->entry = *share_entry; - DLIST_ADD(broken_entry_list, broken_entry); - broke_oplock = True; + if (!opb_ret) { + 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)); + SAFE_FREE(old_shares); + set_saved_error_triple(ERRDOS, ERRbadshare, + NT_STATUS_SHARING_VIOLATION); + return -1; + } - } else if (!LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) { - *p_all_current_opens_are_level_II = False; + broken_entry = SMB_MALLOC_P(struct share_mode_entry_list); + if (!broken_entry) { + smb_panic("open_mode_check: malloc fail.\n"); } + broken_entry->entry = *share_entry; + DLIST_ADD(broken_entry_list, broken_entry); + broke_oplock = True; + } /* end for */ if (broke_oplock) { /* Update the current open table. */ SAFE_FREE(old_shares); - num_share_modes = get_share_modes(conn, dev, inode, &old_shares); + num_share_modes = get_share_modes(dev, inode, + &old_shares, + &delete_on_close); } - /* Now we check the share modes, after any oplock breaks. */ - for(i = 0; i < num_share_modes; i++) { - share_mode_entry *share_entry = &old_shares[i]; + if (lp_share_modes(SNUM(conn))) { + /* Now we check the share modes, after any oplock breaks. */ + for(i = 0; i < num_share_modes; i++) { + share_mode_entry *share_entry = &old_shares[i]; - /* 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, - fname, fcbopen, p_flags)) { - SAFE_FREE(old_shares); - free_broken_entry_list(broken_entry_list); - errno = EACCES; - return -1; - } + /* someone else has a share lock on it, check to see + * if we can too */ + if (share_conflict(share_entry, access_mask, + share_access)) { + SAFE_FREE(old_shares); + free_broken_entry_list(broken_entry_list); + errno = EACCES; + return -1; + } + } } - for(broken_entry = broken_entry_list; broken_entry; broken_entry = broken_entry->next) { + for(broken_entry = broken_entry_list; broken_entry; + broken_entry = broken_entry->next) { 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->entry, share_entry) && - EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type) ) { + if (!(share_modes_identical(&broken_entry->entry, + share_entry) && + EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type))) { + continue; + } - /* - * This should not happen. The target left this oplock - * as exlusive.... The process *must* be dead.... - */ + /* + * 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->entry.pid, fname, (unsigned int)dev, (double)inode)); + 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->entry.pid, fname, + (unsigned int)dev, (double)inode)); - if (process_exists(broken_entry->entry.pid)) { - DEBUG(0,("open_mode_check: Existent process %lu left active oplock.\n", - (unsigned long)broken_entry->entry.pid )); - } + if (process_exists(broken_entry->entry.pid)) { + DEBUG(0,("open_mode_check: Existent process " + "%lu left active oplock.\n", + (unsigned long)broken_entry->entry.pid )); + } - if (del_share_entry(dev, inode, &broken_entry->entry, NULL) == -1) { - free_broken_entry_list(broken_entry_list); - errno = EACCES; - set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); - return -1; - } + if (del_share_entry(dev, inode, &broken_entry->entry, + NULL, &delete_on_close) == -1) { + free_broken_entry_list(broken_entry_list); + errno = EACCES; + set_saved_error_triple(ERRDOS, ERRbadshare, + NT_STATUS_SHARING_VIOLATION); + return -1; + } - /* - * We must reload the share modes after deleting the - * other process's entry. - */ + /* + * 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; - } + SAFE_FREE(old_shares); + num_share_modes = get_share_modes(dev, inode, + &old_shares, + &delete_on_close); + break; } /* end for paranoia... */ } /* end for broken_entry */ free_broken_entry_list(broken_entry_list); @@ -853,7 +775,9 @@ after break ! For file %s, dev = %x, inode = %.0f. Deleting it to continue...\n" Delete the record for a handled deferred open entry. ****************************************************************************/ -static void delete_defered_open_entry_record(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode) +static void delete_defered_open_entry_record(connection_struct *conn, + SMB_DEV_T dev, + SMB_INO_T inode) { uint16 mid = get_current_mid(); pid_t mypid = sys_getpid(); @@ -868,7 +792,7 @@ static void delete_defered_open_entry_record(connection_struct *conn, SMB_DEV_T for (i = 0; i < num_de_entries; i++) { deferred_open_entry *entry = &de_array[i]; if (entry->pid == mypid && entry->mid == mid && entry->dev == dev && - entry->inode == inode) { + entry->inode == inode) { /* Remove the deferred open entry from the array. */ delete_deferred_open_entry(entry); @@ -883,8 +807,11 @@ static void delete_defered_open_entry_record(connection_struct *conn, SMB_DEV_T Handle the 1 second delay in returning a SHARING_VIOLATION error. ****************************************************************************/ -void defer_open_sharing_error(connection_struct *conn, struct timeval *ptv, - char *fname, SMB_DEV_T dev, SMB_INO_T inode) +static void defer_open_sharing_error(connection_struct *conn, + struct timeval *ptv, + const char *fname, + SMB_DEV_T dev, + SMB_INO_T inode) { uint16 mid = get_current_mid(); pid_t mypid = sys_getpid(); @@ -906,10 +833,12 @@ void defer_open_sharing_error(connection_struct *conn, struct timeval *ptv, /* * Check if a 1 second timeout has expired. */ - if (usec_time_diff(ptv, &entry->time) > SHARING_VIOLATION_USEC_WAIT) { - DEBUG(10,("defer_open_sharing_error: Deleting deferred open entry for mid %u, \ -file %s\n", - (unsigned int)mid, fname )); + if (usec_time_diff(ptv, &entry->time) > + SHARING_VIOLATION_USEC_WAIT) { + DEBUG(10,("defer_open_sharing_error: Deleting " + "deferred open entry for mid %u, " + "file %s\n", + (unsigned int)mid, fname )); /* Expired, return a real error. */ /* Remove the deferred open entry from the array. */ @@ -919,24 +848,30 @@ file %s\n", return; } /* - * If the timeout hasn't expired yet and we still have a sharing violation, - * just leave the entry in the deferred open array alone. We do need to - * reschedule this open call though (with the original created time). + * If the timeout hasn't expired yet and we still have + * a sharing violation, just leave the entry in the + * deferred open array alone. We do need to reschedule + * this open call though (with the original created + * time). */ - DEBUG(10,("defer_open_sharing_error: time [%u.%06u] updating \ -deferred open entry for mid %u, file %s\n", - (unsigned int)entry->time.tv_sec, - (unsigned int)entry->time.tv_usec, - (unsigned int)mid, fname )); - - push_sharing_violation_open_smb_message(&entry->time, (char *)&dib, sizeof(dib)); + DEBUG(10,("defer_open_sharing_error: time [%u.%06u] " + "updating deferred open entry for mid %u, file %s\n", + (unsigned int)entry->time.tv_sec, + (unsigned int)entry->time.tv_usec, + (unsigned int)mid, fname )); + + push_sharing_violation_open_smb_message(&entry->time, + (char *)&dib, + sizeof(dib)); SAFE_FREE(de_array); return; } } - DEBUG(10,("defer_open_sharing_error: time [%u.%06u] adding deferred open entry for mid %u, file %s\n", - (unsigned int)ptv->tv_sec, (unsigned int)ptv->tv_usec, (unsigned int)mid, fname )); + DEBUG(10,("defer_open_sharing_error: time [%u.%06u] adding deferred " + "open entry for mid %u, file %s\n", + (unsigned int)ptv->tv_sec, (unsigned int)ptv->tv_usec, + (unsigned int)mid, fname )); if (!push_sharing_violation_open_smb_message(ptv, (char *)&dib, sizeof(dib))) { SAFE_FREE(de_array); @@ -963,80 +898,302 @@ deferred open entry for mid %u, file %s\n", This requires a patch to Linux. ****************************************************************************/ -static void kernel_flock(files_struct *fsp, int deny_mode) +static void kernel_flock(files_struct *fsp, uint32 share_mode) { #if HAVE_KERNEL_SHARE_MODES int kernel_mode = 0; - if (deny_mode == DENY_READ) kernel_mode = LOCK_MAND|LOCK_WRITE; - else if (deny_mode == DENY_WRITE) kernel_mode = LOCK_MAND|LOCK_READ; - else if (deny_mode == DENY_ALL) kernel_mode = LOCK_MAND; - if (kernel_mode) flock(fsp->fd, kernel_mode); + if (share_mode == FILE_SHARE_WRITE) { + kernel_mode = LOCK_MAND|LOCK_WRITE; + } else if (share_mode == FILE_SHARE_READ) { + kernel_mode = LOCK_MAND|LOCK_READ; + } else if (share_mode == FILE_SHARE_NONE) { + kernel_mode = LOCK_MAND; + } + if (kernel_mode) { + flock(fsp->fh->fd, kernel_mode); + } #endif - ;; + ; } +/**************************************************************************** + On overwrite open ensure that the attributes match. +****************************************************************************/ -static BOOL open_match_attributes(connection_struct *conn, const char *path, uint32 old_dos_mode, uint32 new_dos_mode, - mode_t existing_mode, mode_t new_mode, mode_t *returned_mode) +static BOOL open_match_attributes(connection_struct *conn, + const char *path, + uint32 old_dos_attr, + uint32 new_dos_attr, + mode_t existing_unx_mode, + mode_t new_unx_mode, + mode_t *returned_unx_mode) { - uint32 noarch_old_dos_mode, noarch_new_dos_mode; + uint32 noarch_old_dos_attr, noarch_new_dos_attr; - noarch_old_dos_mode = (old_dos_mode & ~FILE_ATTRIBUTE_ARCHIVE); - noarch_new_dos_mode = (new_dos_mode & ~FILE_ATTRIBUTE_ARCHIVE); + noarch_old_dos_attr = (old_dos_attr & ~FILE_ATTRIBUTE_ARCHIVE); + noarch_new_dos_attr = (new_dos_attr & ~FILE_ATTRIBUTE_ARCHIVE); - if((noarch_old_dos_mode == 0 && noarch_new_dos_mode != 0) || - (noarch_old_dos_mode != 0 && ((noarch_old_dos_mode & noarch_new_dos_mode) == noarch_old_dos_mode))) - *returned_mode = new_mode; - else - *returned_mode = (mode_t)0; + if((noarch_old_dos_attr == 0 && noarch_new_dos_attr != 0) || + (noarch_old_dos_attr != 0 && ((noarch_old_dos_attr & noarch_new_dos_attr) == noarch_old_dos_attr))) { + *returned_unx_mode = new_unx_mode; + } else { + *returned_unx_mode = (mode_t)0; + } - DEBUG(10,("open_match_attributes: file %s old_dos_mode = 0x%x, existing_mode = 0%o, new_dos_mode = 0x%x returned_mode = 0%o\n", - path, - old_dos_mode, (unsigned int)existing_mode, new_dos_mode, (unsigned int)*returned_mode )); + DEBUG(10,("open_match_attributes: file %s old_dos_attr = 0x%x, " + "existing_unx_mode = 0%o, new_dos_attr = 0x%x " + "returned_unx_mode = 0%o\n", + path, + (unsigned int)old_dos_attr, + (unsigned int)existing_unx_mode, + (unsigned int)new_dos_attr, + (unsigned int)*returned_unx_mode )); /* If we're mapping SYSTEM and HIDDEN ensure they match. */ if (lp_map_system(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) { - if ((old_dos_mode & FILE_ATTRIBUTE_SYSTEM) && !(new_dos_mode & FILE_ATTRIBUTE_SYSTEM)) + if ((old_dos_attr & FILE_ATTRIBUTE_SYSTEM) && + !(new_dos_attr & FILE_ATTRIBUTE_SYSTEM)) { return False; + } } if (lp_map_hidden(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) { - if ((old_dos_mode & FILE_ATTRIBUTE_HIDDEN) && !(new_dos_mode & FILE_ATTRIBUTE_HIDDEN)) + if ((old_dos_attr & FILE_ATTRIBUTE_HIDDEN) && + !(new_dos_attr & FILE_ATTRIBUTE_HIDDEN)) { return False; + } } return True; } /**************************************************************************** - Open a file with a share mode. + Special FCB or DOS processing in the case of a sharing violation. + Try and find a duplicated file handle. ****************************************************************************/ -files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_STAT *psbuf, - int share_mode,int ofun, uint32 new_dos_mode, int oplock_request, - int *Access,int *action) +static files_struct *fcb_or_dos_open(connection_struct *conn, + const char *fname, SMB_DEV_T dev, + SMB_INO_T inode, + uint32 access_mask, + uint32 share_access, + uint32 create_options) { - return open_file_shared1(conn, fname, psbuf, 0, share_mode, ofun, new_dos_mode, - oplock_request, Access, action); + files_struct *fsp; + files_struct *dup_fsp; + + DEBUG(5,("fcb_or_dos_open: attempting old open semantics for " + "file %s.\n", fname )); + + for(fsp = file_find_di_first(dev, inode); fsp; + fsp = file_find_di_next(fsp)) { + + DEBUG(10,("fcb_or_dos_open: checking file %s, fd = %d, " + "vuid = %u, file_pid = %u, private_options = 0x%x " + "access_mask = 0x%x\n", fsp->fsp_name, + fsp->fh->fd, (unsigned int)fsp->vuid, + (unsigned int)fsp->file_pid, + (unsigned int)fsp->fh->private_options, + (unsigned int)fsp->access_mask )); + + if (fsp->fh->fd != -1 && + fsp->vuid == current_user.vuid && + fsp->file_pid == global_smbpid && + (fsp->fh->private_options & (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS | + NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) && + (fsp->access_mask & FILE_WRITE_DATA) && + strequal(fsp->fsp_name, fname)) { + DEBUG(10,("fcb_or_dos_open: file match\n")); + break; + } + } + + if (!fsp) { + return NULL; + } + + /* quite an insane set of semantics ... */ + if (is_executable(fname) && + (fsp->fh->private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS)) { + DEBUG(10,("fcb_or_dos_open: file fail due to is_executable.\n")); + return NULL; + } + + /* We need to duplicate this fsp. */ + dup_fsp = dup_file_fsp(fsp, access_mask, share_access, create_options); + if (!dup_fsp) { + return NULL; + } + + return dup_fsp; +} + +/**************************************************************************** + Open a file with a share mode - old openX method - map into NTCreate. +****************************************************************************/ + +BOOL map_open_params_to_ntcreate(const char *fname, int deny_mode, int open_func, + uint32 *paccess_mask, + uint32 *pshare_mode, + uint32 *pcreate_disposition, + uint32 *pcreate_options) +{ + uint32 access_mask; + uint32 share_mode; + uint32 create_disposition; + uint32 create_options = 0; + + DEBUG(10,("map_open_params_to_ntcreate: fname = %s, deny_mode = 0x%x, " + "open_func = 0x%x\n", + fname, (unsigned int)deny_mode, (unsigned int)open_func )); + + /* Create the NT compatible access_mask. */ + switch (GET_OPENX_MODE(deny_mode)) { + case DOS_OPEN_RDONLY: + access_mask = FILE_GENERIC_READ; + break; + case DOS_OPEN_WRONLY: + access_mask = FILE_GENERIC_WRITE; + break; + case DOS_OPEN_EXEC: /* This used to be FILE_READ_DATA... */ + case DOS_OPEN_RDWR: + case DOS_OPEN_FCB: + access_mask = FILE_GENERIC_READ|FILE_GENERIC_WRITE; + break; + default: + DEBUG(10,("map_open_params_to_ntcreate: bad open mode = 0x%x\n", + (unsigned int)GET_OPENX_MODE(deny_mode))); + return False; + } + + /* Create the NT compatible create_disposition. */ + switch (open_func) { + case OPENX_FILE_EXISTS_FAIL|OPENX_FILE_CREATE_IF_NOT_EXIST: + create_disposition = FILE_CREATE; + break; + + case OPENX_FILE_EXISTS_OPEN: + create_disposition = FILE_OPEN; + break; + + case OPENX_FILE_EXISTS_OPEN|OPENX_FILE_CREATE_IF_NOT_EXIST: + create_disposition = FILE_OPEN_IF; + break; + + case OPENX_FILE_EXISTS_TRUNCATE: + create_disposition = FILE_OVERWRITE; + break; + + case OPENX_FILE_EXISTS_TRUNCATE|OPENX_FILE_CREATE_IF_NOT_EXIST: + create_disposition = FILE_OVERWRITE_IF; + break; + + default: + /* From samba4 - to be confirmed. */ + if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_EXEC) { + create_disposition = FILE_CREATE; + break; + } + DEBUG(10,("map_open_params_to_ntcreate: bad " + "open_func 0x%x\n", (unsigned int)open_func)); + return False; + } + + /* Create the NT compatible share modes. */ + switch (GET_DENY_MODE(deny_mode)) { + case DENY_ALL: + share_mode = FILE_SHARE_NONE; + break; + + case DENY_WRITE: + share_mode = FILE_SHARE_READ; + break; + + case DENY_READ: + share_mode = FILE_SHARE_WRITE; + break; + + case DENY_NONE: + share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE; + break; + + case DENY_DOS: + create_options |= NTCREATEX_OPTIONS_PRIVATE_DENY_DOS; + if (is_executable(fname)) { + share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE; + } else { + if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_RDONLY) { + share_mode = FILE_SHARE_READ; + } else { + share_mode = FILE_SHARE_NONE; + } + } + break; + + case DENY_FCB: + create_options |= NTCREATEX_OPTIONS_PRIVATE_DENY_FCB; + share_mode = FILE_SHARE_NONE; + break; + + default: + DEBUG(10,("map_open_params_to_ntcreate: bad deny_mode 0x%x\n", + (unsigned int)GET_DENY_MODE(deny_mode) )); + return False; + } + + DEBUG(10,("map_open_params_to_ntcreate: file %s, access_mask = 0x%x, " + "share_mode = 0x%x, create_disposition = 0x%x, " + "create_options = 0x%x\n", + fname, + (unsigned int)access_mask, + (unsigned int)share_mode, + (unsigned int)create_disposition, + (unsigned int)create_options )); + + if (paccess_mask) { + *paccess_mask = access_mask; + } + if (pshare_mode) { + *pshare_mode = share_mode; + } + if (pcreate_disposition) { + *pcreate_disposition = create_disposition; + } + if (pcreate_options) { + *pcreate_options = create_options; + } + + return True; + } +/* Map generic permissions to file object specific permissions */ + +struct generic_mapping file_generic_mapping = { + FILE_GENERIC_READ, + FILE_GENERIC_WRITE, + FILE_GENERIC_EXECUTE, + FILE_GENERIC_ALL +}; + /**************************************************************************** Open a file with a share mode. ****************************************************************************/ -files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_STAT *psbuf, - uint32 desired_access, - int share_mode,int ofun, uint32 new_dos_mode, - int oplock_request, - int *Access,int *paction) +files_struct *open_file_ntcreate(connection_struct *conn, + const char *fname, + SMB_STRUCT_STAT *psbuf, + uint32 access_mask, /* access bits (FILE_READ_DATA etc.) */ + uint32 share_access, /* share constants (FILE_SHARE_READ etc). */ + uint32 create_disposition, /* FILE_OPEN_IF etc. */ + uint32 create_options, /* options such as delete on close. */ + uint32 new_dos_attributes, /* attributes used for new file. */ + int oplock_request, /* internal Samba oplock codes. */ + /* Information (FILE_EXISTS etc.) */ + int *pinfo) { int flags=0; int flags2=0; - int deny_mode = GET_DENY_MODE(share_mode); - BOOL allow_share_delete = GET_ALLOW_SHARE_DELETE(share_mode); - BOOL delete_on_close = GET_DELETE_ON_CLOSE_FLAG(share_mode); BOOL file_existed = VALID_STAT(*psbuf); - BOOL fcbopen = False; BOOL def_acl = False; - BOOL add_share_mode = True; BOOL internal_only_open = False; SMB_DEV_T dev = 0; SMB_INO_T inode = 0; @@ -1044,15 +1201,40 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ BOOL all_current_opens_are_level_II = False; BOOL fsp_open = False; files_struct *fsp = NULL; - int open_mode=0; - uint16 port = 0; - mode_t new_mode = (mode_t)0; - int action; - uint32 existing_dos_mode = 0; + mode_t new_unx_mode = (mode_t)0; + mode_t unx_mode = (mode_t)0; + int info; + uint32 existing_dos_attributes = 0; struct pending_message_list *pml = NULL; + uint16 port = 0; uint16 mid = get_current_mid(); - /* We add aARCH to this as this mode is only used if the file is created new. */ - mode_t mode = unix_mode(conn,new_dos_mode | aARCH,fname, True); + + if (conn->printer) { + /* + * Printers are handled completely differently. + * Most of the passed parameters are ignored. + */ + + if (pinfo) { + *pinfo = FILE_WAS_CREATED; + } + + DEBUG(10, ("open_file_ntcreate: printer open fname=%s\n", fname)); + + return print_fsp_open(conn, fname); + } + + /* We add aARCH to this as this mode is only used if the file is + * created new. */ + unx_mode = unix_mode(conn, new_dos_attributes | aARCH,fname, True); + + DEBUG(10, ("open_file_ntcreate: fname=%s, dos_attrs=0x%x " + "access_mask=0x%x share_access=0x%x " + "create_disposition = 0x%x create_options=0x%x " + "unix mode=0%o oplock_request=%d\n", + fname, new_dos_attributes, access_mask, share_access, + create_disposition, create_options, unx_mode, + oplock_request)); if (oplock_request == INTERNAL_OPEN_ONLY) { internal_only_open = True; @@ -1065,52 +1247,42 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ memcpy(&dib, pml->private_data.data, sizeof(dib)); /* There could be a race condition where the dev/inode pair - has changed since we deferred the message. If so, just - remove the deferred open entry and return sharing violation. */ - - /* If the timeout value is non-zero, we need to just - return sharing violation. Don't retry the open - as we were not notified of a close and we don't want to - trigger another spurious oplock break. */ - - if (!file_existed || dib.dev != psbuf->st_dev || dib.inode != psbuf->st_ino || - pml->msg_time.tv_sec || pml->msg_time.tv_usec) { + has changed since we deferred the message. If so, just + remove the deferred open entry and return sharing + violation. */ + + /* If the timeout value is non-zero, we need to just return + sharing violation. Don't retry the open as we were not + notified of a close and we don't want to trigger another + spurious oplock break. */ + + if (!file_existed || dib.dev != psbuf->st_dev || + dib.inode != psbuf->st_ino || pml->msg_time.tv_sec || + pml->msg_time.tv_usec) { /* Ensure we don't reprocess this message. */ remove_sharing_violation_open_smb_message(mid); /* Now remove the deferred open entry under lock. */ lock_share_entry(conn, dib.dev, dib.inode); - delete_defered_open_entry_record(conn, dib.dev, dib.inode); + delete_defered_open_entry_record(conn, dib.dev, + dib.inode); unlock_share_entry(conn, dib.dev, dib.inode); - set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); + set_saved_error_triple(ERRDOS, ERRbadshare, + NT_STATUS_SHARING_VIOLATION); return NULL; } /* Ensure we don't reprocess this message. */ remove_sharing_violation_open_smb_message(mid); - - } - - if (conn->printer) { - /* printers are handled completely differently. Most of the passed parameters are - ignored */ - if (Access) - *Access = DOS_OPEN_WRONLY; - if (paction) - *paction = FILE_WAS_CREATED; - return print_fsp_open(conn, fname); } - DEBUG(10,("open_file_shared: fname = %s, dos_attrs = %x, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n", - fname, new_dos_mode, share_mode, ofun, (int)mode, oplock_request )); - if (!check_name(fname,conn)) { return NULL; } - new_dos_mode &= SAMBA_ATTRIBUTES_MASK; + new_dos_attributes &= SAMBA_ATTRIBUTES_MASK; if (file_existed) { - existing_dos_mode = dos_mode(conn, fname, psbuf); + existing_dos_attributes = dos_mode(conn, fname, psbuf); } /* ignore any oplock requests if oplocks are disabled */ @@ -1119,114 +1291,173 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ } /* this is for OS/2 long file names - say we don't support them */ - if (strstr(fname,".+,;=[].")) { - /* OS/2 Workplace shell fix may be main code stream in a later release. */ - set_saved_error_triple(ERRDOS, ERRcannotopen, NT_STATUS_OBJECT_NAME_NOT_FOUND); - DEBUG(5,("open_file_shared: OS/2 long filenames are not supported.\n")); + if (!lp_posix_pathnames() && strstr(fname,".+,;=[].")) { + /* OS/2 Workplace shell fix may be main code stream in a later + * release. */ + set_saved_error_triple(ERRDOS, ERRcannotopen, + NT_STATUS_OBJECT_NAME_NOT_FOUND); + DEBUG(5,("open_file_ntcreate: OS/2 long filenames are not " + "supported.\n")); return NULL; } - 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 )); - if (S_ISDIR(psbuf->st_mode)) { - errno = EISDIR; - } else { - errno = EEXIST; - } - return NULL; - } - - if (CAN_WRITE(conn) && (GET_FILE_CREATE_DISPOSITION(ofun) == FILE_CREATE_IF_NOT_EXIST)) - flags2 |= O_CREAT; + switch( create_disposition ) { + /* + * Currently we're using FILE_SUPERSEDE as the same as + * FILE_OVERWRITE_IF but they really are + * different. FILE_SUPERSEDE deletes an existing file + * (requiring delete access) then recreates it. + */ + case FILE_SUPERSEDE: + /* If file exists replace/overwrite. If file doesn't + * exist create. */ + flags2 |= (O_CREAT | O_TRUNC); + break; - if (CAN_WRITE(conn) && (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_TRUNCATE)) - flags2 |= O_TRUNC; + case FILE_OVERWRITE_IF: + /* If file exists replace/overwrite. If file doesn't + * exist create. */ + flags2 |= (O_CREAT | O_TRUNC); + break; - /* 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, existing_dos_mode, new_dos_mode, - psbuf->st_mode, mode, &new_mode)) { - DEBUG(5,("open_file_shared: attributes missmatch for file %s (%x %x) (0%o, 0%o)\n", - fname, existing_dos_mode, new_dos_mode, - (int)psbuf->st_mode, (int)mode )); + case FILE_OPEN: + /* If file exists open. If file doesn't exist error. */ + if (!file_existed) { + DEBUG(5,("open_file_ntcreate: FILE_OPEN " + "requested for file %s and file " + "doesn't exist.\n", fname )); + set_saved_error_triple(ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND); + errno = ENOENT; + return NULL; + } + break; + + case FILE_OVERWRITE: + /* If file exists overwrite. If file doesn't exist + * error. */ + if (!file_existed) { + DEBUG(5,("open_file_ntcreate: FILE_OVERWRITE " + "requested for file %s and file " + "doesn't exist.\n", fname )); + set_saved_error_triple(ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND); + errno = ENOENT; + return NULL; + } + flags2 |= O_TRUNC; + break; + + case FILE_CREATE: + /* If file exists error. If file doesn't exist + * create. */ + if (file_existed) { + DEBUG(5,("open_file_ntcreate: FILE_CREATE " + "requested for file %s and file " + "already exists.\n", fname )); + if (S_ISDIR(psbuf->st_mode)) { + errno = EISDIR; + } else { + errno = EEXIST; + } + return NULL; + } + flags2 |= (O_CREAT|O_EXCL); + break; + + case FILE_OPEN_IF: + /* If file exists open. If file doesn't exist + * create. */ + flags2 |= O_CREAT; + break; + + default: + set_saved_error_triple(ERRDOS, ERRinvalidparam, + NT_STATUS_INVALID_PARAMETER); + return NULL; + } + + /* We only care about matching attributes on file exists and + * overwrite. */ + + if (file_existed && ((create_disposition == FILE_OVERWRITE) || + (create_disposition == FILE_OVERWRITE_IF))) { + if (!open_match_attributes(conn, fname, + existing_dos_attributes, + new_dos_attributes, psbuf->st_mode, + unx_mode, &new_unx_mode)) { + DEBUG(5,("open_file_ntcreate: attributes missmatch " + "for file %s (%x %x) (0%o, 0%o)\n", + fname, existing_dos_attributes, + new_dos_attributes, + (unsigned int)psbuf->st_mode, + (unsigned int)unx_mode )); errno = EACCES; return NULL; } } - if (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_FAIL) - flags2 |= O_EXCL; + /* This is a nasty hack - must fix... JRA. */ + if (access_mask == MAXIMUM_ALLOWED_ACCESS) { + access_mask = FILE_GENERIC_ALL; + } - /* note that we ignore the append flag as - append does not mean the same thing under dos and unix */ + /* + * Convert GENERIC bits to specific bits. + */ - switch (GET_OPEN_MODE(share_mode)) { - case DOS_OPEN_EXEC: - case DOS_OPEN_RDONLY: - flags = O_RDONLY; - if (desired_access == 0) - desired_access = FILE_READ_DATA; - break; - case DOS_OPEN_WRONLY: - flags = O_WRONLY; - if (desired_access == 0) - desired_access = FILE_WRITE_DATA; - break; - case DOS_OPEN_FCB: - fcbopen = True; - flags = O_RDWR; - if (desired_access == 0) - desired_access = FILE_READ_DATA|FILE_WRITE_DATA; - break; - case DOS_OPEN_RDWR: - flags = O_RDWR; - if (desired_access == 0) - desired_access = FILE_READ_DATA|FILE_WRITE_DATA; - break; - default: - /* Force DOS error. */ - set_saved_error_triple(ERRDOS, ERRinvalidparam, NT_STATUS_INVALID); - return NULL; + se_map_generic(&access_mask, &file_generic_mapping); + + DEBUG(10, ("open_file_ntcreate: fname=%s, after mapping " + "access_mask=0x%x\n", fname, access_mask )); + + /* + * Note that we ignore the append flag as append does not + * mean the same thing under DOS and Unix. + */ + + if (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) { + flags = O_RDWR; + } else { + flags = O_RDONLY; } + /* + * Currently we only look at FILE_WRITE_THROUGH for create options. + */ + #if defined(O_SYNC) - if (GET_FILE_SYNC_OPENMODE(share_mode)) { + if (create_options & FILE_WRITE_THROUGH) { flags2 |= O_SYNC; } #endif /* O_SYNC */ - if (flags != O_RDONLY && file_existed && - (!CAN_WRITE(conn) || IS_DOS_READONLY(existing_dos_mode))) { - 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 NULL; - } - flags = O_RDONLY; + if (!CAN_WRITE(conn)) { + /* + * We should really return a permission denied error if either + * O_CREAT or O_TRUNC are set, but for compatibility with + * older versions of Samba we just AND them out. + */ + flags2 &= ~(O_CREAT|O_TRUNC); } - if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) { - DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname)); - errno = EINVAL; - return NULL; - } + /* + * Ensure we can't write on a read-only share or file. + */ - if (desired_access && ((desired_access & ~(SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES))==0) && - ((desired_access & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) != 0)) { - /* Stat open that doesn't trigger oplock breaks or share mode checks... ! JRA. */ - deny_mode = DENY_NONE; - if (file_existed) { - oplock_request = 0; - add_share_mode = False; - flags2 &= ~O_CREAT; - } + if (flags != O_RDONLY && file_existed && + (!CAN_WRITE(conn) || IS_DOS_READONLY(existing_dos_attributes))) { + DEBUG(5,("open_file_ntcreate: write access requested for " + "file %s on read only %s\n", + fname, !CAN_WRITE(conn) ? "share" : "file" )); + set_saved_error_triple(ERRDOS, ERRnoaccess, + NT_STATUS_ACCESS_DENIED); + errno = EACCES; + return NULL; } fsp = file_new(conn); - if(!fsp) + if(!fsp) { return NULL; + } if (file_existed) { @@ -1235,47 +1466,86 @@ 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, + access_mask, share_access, + create_options, + &flags, &oplock_request, + &all_current_opens_are_level_II); if(num_share_modes == -1) { + if (!internal_only_open) { + NTSTATUS status; + get_saved_error_triple(NULL, NULL, &status); + if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION)) { + /* Check if this can be done with the + * deny_dos and fcb calls. */ + if (create_options & + (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS| + NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) { + files_struct *fsp_dup; + fsp_dup = fcb_or_dos_open(conn, fname, dev, + inode, access_mask, + share_access, + create_options); + + if (fsp_dup) { + unlock_share_entry(conn, dev, inode); + file_free(fsp); + if (pinfo) { + *pinfo = FILE_WAS_OPENED; + } + conn->num_files_open++; + return fsp_dup; + } + } + } + } + /* - * 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. + * 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. */ errno = 0; fsp_open = open_file(fsp,conn,fname,psbuf, - flags|(flags2&~(O_TRUNC|O_CREAT)),mode,desired_access); + flags|(flags2&~(O_TRUNC|O_CREAT)), + unx_mode,access_mask); - DEBUG(4,("open_file_shared : share_mode deny - calling open_file with \ -flags=0x%X flags2=0x%X mode=0%o returned %d\n", - flags,(flags2&~(O_TRUNC|O_CREAT)),(int)mode,(int)fsp_open )); + DEBUG(4,("open_file_ntcreate : share_mode deny - " + "calling open_file with flags=0x%X " + "flags2=0x%X mode=0%o returned %d\n", + flags, (flags2&~(O_TRUNC|O_CREAT)), + (unsigned int)unx_mode, (int)fsp_open )); if (!fsp_open && errno) { /* Default error. */ - set_saved_error_triple(ERRDOS, ERRnoaccess, NT_STATUS_ACCESS_DENIED); + set_saved_error_triple(ERRDOS, ERRnoaccess, + NT_STATUS_ACCESS_DENIED); } /* - * If we're returning a share violation, ensure we cope with - * the braindead 1 second delay. + * If we're returning a share violation, ensure we + * cope with the braindead 1 second delay. */ if (!internal_only_open) { NTSTATUS status; get_saved_error_triple(NULL, NULL, &status); if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION)) { - /* The fsp->open_time here represents the current time of day. */ - defer_open_sharing_error(conn, &fsp->open_time, fname, dev, inode); + /* The fsp->open_time here represents + * the current time of day. */ + defer_open_sharing_error(conn, + &fsp->open_time, + fname, dev, inode); } } @@ -1286,7 +1556,8 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", * We have detected a sharing violation here * so return the correct error code */ - set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); + set_saved_error_triple(ERRDOS, ERRbadshare, + NT_STATUS_SHARING_VIOLATION); } file_free(fsp); return NULL; @@ -1302,35 +1573,39 @@ 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)))) - mode = 0777; + (def_acl = directory_has_default_acl(conn, parent_dirname(fname)))) { + unx_mode = 0777; + } DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", - flags,flags2,(int)mode)); + (unsigned int)flags,(unsigned int)flags2,(unsigned int)unx_mode)); /* * open_file strips any O_TRUNC flags itself. */ - fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,mode,desired_access); + fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode,access_mask); - if (!fsp_open && (flags == O_RDWR) && (errno != ENOENT) && fcbopen) { - if((fsp_open = open_file(fsp,conn,fname,psbuf,O_RDONLY,mode,desired_access)) == True) + if (!fsp_open && (flags == O_RDWR) && (errno != ENOENT)) { + if((fsp_open = open_file(fsp,conn,fname,psbuf, + O_RDONLY,unx_mode,access_mask)) == True) { flags = O_RDONLY; + } } if (!fsp_open) { - if(file_existed) + if(file_existed) { unlock_share_entry(conn, dev, inode); + } file_free(fsp); return NULL; } /* - * 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 - * set a share mode, the other (ie. this one) should check if the - * requested share mode for this create is allowed. + * 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 set a share mode, the other (ie. this one) should check if + * the requested share mode for this create is allowed. */ if (!file_existed) { @@ -1347,22 +1622,47 @@ 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, + access_mask, share_access, + create_options, + &flags, &oplock_request, + &all_current_opens_are_level_II); if(num_share_modes == -1) { - /* - * If we're returning a share violation, ensure we cope with - * the braindead 1 second delay. - */ - NTSTATUS status; get_saved_error_triple(NULL, NULL, &status); if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION)) { - /* The fsp->open_time here represents the current time of day. */ - defer_open_sharing_error(conn, &fsp->open_time, fname, dev, inode); + /* Check if this can be done with the deny_dos + * and fcb calls. */ + if (create_options & + (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS| + NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) { + files_struct *fsp_dup; + fsp_dup = fcb_or_dos_open(conn, fname, dev, inode, + access_mask, share_access, + create_options); + if (fsp_dup) { + unlock_share_entry(conn, dev, inode); + fd_close(conn, fsp); + file_free(fsp); + if (pinfo) { + *pinfo = FILE_WAS_OPENED; + } + conn->num_files_open++; + return fsp_dup; + } + } + + /* + * If we're returning a share violation, + * ensure we cope with the braindead 1 second + * delay. + */ + + /* The fsp->open_time here represents the + * current time of day. */ + defer_open_sharing_error(conn, &fsp->open_time, + fname, dev, inode); } unlock_share_entry_fsp(fsp); @@ -1372,7 +1672,8 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", * We have detected a sharing violation here, so * return the correct code. */ - set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); + set_saved_error_triple(ERRDOS, ERRbadshare, + NT_STATUS_SHARING_VIOLATION); return NULL; } @@ -1381,8 +1682,9 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", * exist. Ensure we return the correct value for action. */ - if (num_share_modes > 0) + if (num_share_modes > 0) { file_existed = True; + } /* * We exit this block with the share entry *locked*..... @@ -1395,7 +1697,8 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", 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); + + kernel_flock(fsp, share_access); /* * At this point onwards, we can guarentee that the share entry @@ -1409,9 +1712,11 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", if (flags2&O_TRUNC) { /* - * We are modifing the file after open - update the stat struct.. + * We are modifing the file after open - update the stat + * struct.. */ - if ((SMB_VFS_FTRUNCATE(fsp,fsp->fd,0) == -1) || (SMB_VFS_FSTAT(fsp,fsp->fd,psbuf)==-1)) { + if ((SMB_VFS_FTRUNCATE(fsp,fsp->fh->fd,0) == -1) || + (SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf)==-1)) { unlock_share_entry_fsp(fsp); fd_close(conn,fsp); file_free(fsp); @@ -1419,44 +1724,28 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", } } - switch (flags) { - case O_RDONLY: - open_mode = DOS_OPEN_RDONLY; - break; - case O_RDWR: - open_mode = DOS_OPEN_RDWR; - break; - case O_WRONLY: - open_mode = DOS_OPEN_WRONLY; - break; - } + /* Record the options we were opened with. */ + fsp->share_access = share_access; + fsp->fh->private_options = create_options; + fsp->access_mask = access_mask; - fsp->share_mode = SET_DENY_MODE(deny_mode) | - SET_OPEN_MODE(open_mode) | - SET_ALLOW_SHARE_DELETE(allow_share_delete); - - DEBUG(10,("open_file_shared : share_mode = %x\n", fsp->share_mode )); - - if (Access) { - (*Access) = (SET_DENY_MODE(deny_mode) | SET_OPEN_MODE(open_mode)); - } - - action = 0; - - if (file_existed && !(flags2 & O_TRUNC)) - action = FILE_WAS_OPENED; - if (file_existed && (flags2 & O_TRUNC)) - action = FILE_WAS_OVERWRITTEN; - if (!file_existed) { - action = FILE_WAS_CREATED; + if (file_existed) { + if (!(flags2 & O_TRUNC)) { + info = FILE_WAS_OPENED; + } else { + info = FILE_WAS_OVERWRITTEN; + } + } else { + info = FILE_WAS_CREATED; /* Change the owner if required. */ if (lp_inherit_owner(SNUM(conn))) { - change_owner_to_parent(conn, fsp, fsp->fsp_name, psbuf); + change_owner_to_parent(conn, fsp, fsp->fsp_name, + psbuf); } } - if (paction) { - *paction = action; + if (pinfo) { + *pinfo = info; } /* @@ -1465,7 +1754,8 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", */ if(oplock_request && (num_share_modes == 0) && - !IS_VETO_OPLOCK_PATH(conn,fname) && set_file_oplock(fsp, oplock_request) ) { + !IS_VETO_OPLOCK_PATH(conn,fname) && + set_file_oplock(fsp, oplock_request) ) { port = global_oplock_port; } else if (oplock_request && all_current_opens_are_level_II) { port = global_oplock_port; @@ -1476,26 +1766,25 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", oplock_request = 0; } - if (add_share_mode) { - set_share_mode(fsp, port, oplock_request); - } + set_share_mode(fsp, port, oplock_request); - if (delete_on_close) { - uint32 dosmode = existing_dos_mode; + if (create_options & FILE_DELETE_ON_CLOSE) { + uint32 dosattr= existing_dos_attributes; NTSTATUS result; - if (action == FILE_WAS_OVERWRITTEN || action == FILE_WAS_CREATED) { - dosmode = new_dos_mode; + if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || + info == FILE_WAS_SUPERSEDED) { + dosattr = new_dos_attributes; } - result = set_delete_on_close_internal(fsp, delete_on_close, dosmode); - if (NT_STATUS_V(result) != NT_STATUS_V(NT_STATUS_OK)) { + result = can_set_delete_on_close(fsp, True, dosattr); + + if (!NT_STATUS_IS_OK(result)) { uint8 u_e_c; uint32 u_e_code; + BOOL dummy_del_on_close; /* Remember to delete the mode we just added. */ - if (add_share_mode) { - del_share_mode(fsp, NULL); - } + del_share_mode(fsp, NULL, &dummy_del_on_close); unlock_share_entry_fsp(fsp); fd_close(conn,fsp); file_free(fsp); @@ -1503,12 +1792,17 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", set_saved_error_triple(u_e_c, u_e_code, result); return NULL; } + set_delete_on_close(fsp, True); } - if (action == FILE_WAS_OVERWRITTEN || action == FILE_WAS_CREATED) { + if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || + info == FILE_WAS_SUPERSEDED) { /* Files should be initially set as archive */ - if (lp_map_archive(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) { - file_set_dosmode(conn, fname, new_dos_mode | aARCH, NULL, True); + if (lp_map_archive(SNUM(conn)) || + lp_store_dos_attributes(SNUM(conn))) { + file_set_dosmode(conn, fname, + new_dos_attributes | aARCH, NULL, + True); } } @@ -1519,36 +1813,45 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", if (!file_existed && !def_acl) { - int saved_errno = errno; /* We might get ENOSYS in the next call.. */ + int saved_errno = errno; /* We might get ENOSYS in the next + * call.. */ - if (SMB_VFS_FCHMOD_ACL(fsp, fsp->fd, mode) == -1 && errno == ENOSYS) + if (SMB_VFS_FCHMOD_ACL(fsp, fsp->fh->fd, unx_mode) == -1 + && errno == ENOSYS) { errno = saved_errno; /* Ignore ENOSYS */ + } - } else if (new_mode) { + } else if (new_unx_mode) { int ret = -1; /* Attributes need changing. File already existed. */ { - int saved_errno = errno; /* We might get ENOSYS in the next call.. */ - ret = SMB_VFS_FCHMOD_ACL(fsp, fsp->fd, new_mode); + int saved_errno = errno; /* We might get ENOSYS in the + * next call.. */ + ret = SMB_VFS_FCHMOD_ACL(fsp, fsp->fh->fd, + new_unx_mode); if (ret == -1 && errno == ENOSYS) { errno = saved_errno; /* Ignore ENOSYS */ } else { - DEBUG(5, ("open_file_shared: failed to reset attributes of file %s to 0%o\n", - fname, (int)new_mode)); + DEBUG(5, ("open_file_shared: failed to reset " + "attributes of file %s to 0%o\n", + fname, (unsigned int)new_unx_mode)); ret = 0; /* Don't do the fchmod below. */ } } - if ((ret == -1) && (SMB_VFS_FCHMOD(fsp, fsp->fd, new_mode) == -1)) - DEBUG(5, ("open_file_shared: failed to reset attributes of file %s to 0%o\n", - fname, (int)new_mode)); + if ((ret == -1) && + (SMB_VFS_FCHMOD(fsp, fsp->fh->fd, new_unx_mode) == -1)) + DEBUG(5, ("open_file_shared: failed to reset " + "attributes of file %s to 0%o\n", + fname, (unsigned int)new_unx_mode)); } - /* If this is a successful open, we must remove any deferred open records. */ + /* If this is a successful open, we must remove any deferred open + * records. */ delete_defered_open_entry_record(conn, fsp->dev, fsp->inode); unlock_share_entry_fsp(fsp); @@ -1561,17 +1864,20 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", Open a file for for write to ensure that we can fchmod it. ****************************************************************************/ -files_struct *open_file_fchmod(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf) +files_struct *open_file_fchmod(connection_struct *conn, const char *fname, + SMB_STRUCT_STAT *psbuf) { files_struct *fsp = NULL; BOOL fsp_open; - if (!VALID_STAT(*psbuf)) + if (!VALID_STAT(*psbuf)) { return NULL; + } fsp = file_new(conn); - if(!fsp) + if(!fsp) { return NULL; + } /* note! we must use a non-zero desired access or we don't get a real file descriptor. Oh what a twisted web we weave. */ @@ -1606,96 +1912,135 @@ int close_file_fchmod(files_struct *fsp) Open a directory from an NT SMB call. ****************************************************************************/ -files_struct *open_directory(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, - uint32 desired_access, int share_mode, int smb_ofun, int *action) +files_struct *open_directory(connection_struct *conn, + const char *fname, + SMB_STRUCT_STAT *psbuf, + uint32 access_mask, + uint32 share_access, + uint32 create_disposition, + uint32 create_options, + int *pinfo) { - BOOL got_stat = False; - files_struct *fsp = file_new(conn); - BOOL delete_on_close = GET_DELETE_ON_CLOSE_FLAG(share_mode); - - if(!fsp) + files_struct *fsp = NULL; + BOOL dir_existed = VALID_STAT(*psbuf) ? True : False; + BOOL create_dir = False; + int info = 0; + + DEBUG(5,("open_directory: opening directory %s, access_mask = 0x%x, " + "share_access = 0x%x create_options = 0x%x, " + "create_disposition = 0x%x\n", + fname, + (unsigned int)access_mask, + (unsigned int)share_access, + (unsigned int)create_options, + (unsigned int)create_disposition)); + + if (is_ntfs_stream_name(fname)) { + DEBUG(0,("open_directory: %s is a stream name!\n", fname )); + /* NB. Is the DOS error ERRbadpath or ERRbaddirectory ? */ + set_saved_error_triple(ERRDOS, ERRbadpath, + NT_STATUS_NOT_A_DIRECTORY); return NULL; + } - if (VALID_STAT(*psbuf)) - got_stat = True; - - if (got_stat && (GET_FILE_OPEN_DISPOSITION(smb_ofun) == FILE_EXISTS_FAIL)) { - file_free(fsp); - errno = EEXIST; /* Setup so correct error is returned to client. */ + if (dir_existed && !S_ISDIR(psbuf->st_mode)) { + DEBUG(0,("open_directory: %s is not a directory !\n", fname )); + /* NB. Is the DOS error ERRbadpath or ERRbaddirectory ? */ + set_saved_error_triple(ERRDOS, ERRbadpath, + NT_STATUS_NOT_A_DIRECTORY); return NULL; } - if (GET_FILE_CREATE_DISPOSITION(smb_ofun) == FILE_CREATE_IF_NOT_EXIST) { - - if (got_stat) { - - if(!S_ISDIR(psbuf->st_mode)) { - DEBUG(0,("open_directory: %s is not a directory !\n", fname )); - file_free(fsp); - errno = EACCES; + switch( create_disposition ) { + case FILE_OPEN: + /* If directory exists open. If directory doesn't + * exist error. */ + if (!dir_existed) { + DEBUG(5,("open_directory: FILE_OPEN requested " + "for directory %s and it doesn't " + "exist.\n", fname )); + set_saved_error_triple(ERRDOS, ERRbadfile, + NT_STATUS_OBJECT_NAME_NOT_FOUND); return NULL; } - *action = FILE_WAS_OPENED; - - } else { - - /* - * Try and create the directory. - */ - - /* We know bad_path is false as it's caught earlier. */ - - NTSTATUS status = mkdir_internal(conn, fname, False); + info = FILE_WAS_OPENED; + break; - if (!NT_STATUS_IS_OK(status)) { - DEBUG(2,("open_directory: unable to create %s. Error was %s\n", - fname, strerror(errno) )); - file_free(fsp); - /* Ensure we return the correct NT status to the client. */ - set_saved_error_triple(0, 0, status); + case FILE_CREATE: + /* If directory exists error. If directory doesn't + * exist create. */ + if (dir_existed) { + DEBUG(5,("open_directory: FILE_CREATE " + "requested for directory %s and it " + "already exists.\n", fname )); + set_saved_error_triple(ERRDOS, ERRfilexists, + NT_STATUS_OBJECT_NAME_COLLISION); return NULL; } + create_dir = True; + info = FILE_WAS_CREATED; + break; - /* Ensure we're checking for a symlink here.... */ - /* We don't want to get caught by a symlink racer. */ - - if(SMB_VFS_LSTAT(conn,fname, psbuf) != 0) { - file_free(fsp); - return NULL; + case FILE_OPEN_IF: + /* If directory exists open. If directory doesn't + * exist create. */ + if (!dir_existed) { + create_dir = True; + info = FILE_WAS_CREATED; + } else { + info = FILE_WAS_OPENED; } + break; - if(!S_ISDIR(psbuf->st_mode)) { - DEBUG(0,("open_directory: %s is not a directory !\n", fname )); - file_free(fsp); - return NULL; - } + case FILE_SUPERSEDE: + case FILE_OVERWRITE: + case FILE_OVERWRITE_IF: + default: + DEBUG(5,("open_directory: invalid create_disposition " + "0x%x for directory %s\n", + (unsigned int)create_disposition, fname)); + file_free(fsp); + set_saved_error_triple(ERRDOS, ERRinvalidparam, + NT_STATUS_INVALID_PARAMETER); + return NULL; + } + + if (create_dir) { + /* + * Try and create the directory. + */ - *action = FILE_WAS_CREATED; + /* We know bad_path is false as it's caught earlier. */ + NTSTATUS status = mkdir_internal(conn, fname, False); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(2,("open_directory: unable to create %s. " + "Error was %s\n", fname, strerror(errno) )); + /* Ensure we return the correct NT status to the + * client. */ + set_saved_error_triple(0, 0, status); + return NULL; } - } else { - /* - * Don't create - just check that it *was* a directory. - */ + /* Ensure we're checking for a symlink here.... */ + /* We don't want to get caught by a symlink racer. */ - if(!got_stat) { - DEBUG(3,("open_directory: unable to stat name = %s. Error was %s\n", - fname, strerror(errno) )); - file_free(fsp); + if(SMB_VFS_LSTAT(conn,fname, psbuf) != 0) { return NULL; } if(!S_ISDIR(psbuf->st_mode)) { - DEBUG(0,("open_directory: %s is not a directory !\n", fname )); - file_free(fsp); + DEBUG(0,("open_directory: %s is not a directory !\n", + fname )); return NULL; } + } - *action = FILE_WAS_OPENED; + fsp = file_new(conn); + if(!fsp) { + return NULL; } - - DEBUG(5,("open_directory: opening directory %s\n", fname)); /* * Setup the files_struct for it. @@ -1709,20 +2054,21 @@ files_struct *open_directory(connection_struct *conn, const char *fname, SMB_STR fsp->can_lock = True; fsp->can_read = False; fsp->can_write = False; - fsp->share_mode = share_mode; - fsp->desired_access = desired_access; + + fsp->share_access = share_access; + fsp->fh->private_options = create_options; + fsp->access_mask = access_mask; + fsp->print_file = False; fsp->modified = False; fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = True; fsp->is_stat = False; - fsp->directory_delete_on_close = False; string_set(&fsp->fsp_name,fname); - if (delete_on_close) { - NTSTATUS status = set_delete_on_close_internal(fsp, delete_on_close, 0); - + if (create_options & FILE_DELETE_ON_CLOSE) { + NTSTATUS status = can_set_delete_on_close(fsp, True, 0); if (!NT_STATUS_IS_OK(status)) { file_free(fsp); return NULL; @@ -1730,10 +2076,14 @@ files_struct *open_directory(connection_struct *conn, const char *fname, SMB_STR } /* Change the owner if required. */ - if ((*action == FILE_WAS_CREATED) && lp_inherit_owner(SNUM(conn))) { + if ((info == FILE_WAS_CREATED) && lp_inherit_owner(SNUM(conn))) { change_owner_to_parent(conn, fsp, fsp->fsp_name, psbuf); } + if (pinfo) { + *pinfo = info; + } + conn->num_files_open++; return fsp; @@ -1743,7 +2093,8 @@ files_struct *open_directory(connection_struct *conn, const char *fname, SMB_STR Open a pseudo-file (no locking checks - a 'stat' open). ****************************************************************************/ -files_struct *open_file_stat(connection_struct *conn, char *fname, SMB_STRUCT_STAT *psbuf) +files_struct *open_file_stat(connection_struct *conn, char *fname, + SMB_STRUCT_STAT *psbuf) { files_struct *fsp = NULL; @@ -1772,15 +2123,12 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, SMB_STRUCT_ST fsp->can_lock = False; fsp->can_read = False; fsp->can_write = False; - fsp->share_mode = 0; - fsp->desired_access = 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->is_stat = True; - fsp->directory_delete_on_close = False; string_set(&fsp->fsp_name,fname); conn->num_files_open++; -- cgit From 4fffd271d04fca6e305fda1aba99d88a60fc5271 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 15 Jul 2005 11:52:07 +0000 Subject: r8492: open_mode_check does not use the parameter p_flags, so remove it. Volker (This used to be commit ed9cb0061dbbc7677d5968581fde46c89febb6c0) --- source3/smbd/open.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 810913c025..3cd553f55b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -556,7 +556,6 @@ static int open_mode_check(connection_struct *conn, uint32 access_mask, uint32 share_access, uint32 create_options, - int *p_flags, int *p_oplock_request, BOOL *p_all_current_opens_are_level_II) { @@ -1469,7 +1468,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, num_share_modes = open_mode_check(conn, fname, dev, inode, access_mask, share_access, create_options, - &flags, &oplock_request, + &oplock_request, &all_current_opens_are_level_II); if(num_share_modes == -1) { @@ -1625,7 +1624,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, num_share_modes = open_mode_check(conn, fname, dev, inode, access_mask, share_access, create_options, - &flags, &oplock_request, + &oplock_request, &all_current_opens_are_level_II); if(num_share_modes == -1) { -- cgit From fa2ec3651ec88777930e478c888096907006fd8b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 24 Aug 2005 13:15:01 +0000 Subject: r9584: Fix a race condition in Samba 3. If two files are opened simultaneously with NTCREATEX_DISP_CREATE (create if not exists, else fail) they might end up with two or more times NT_STATUS_OK as EEXIST is not correctly handled. Jeremy, please look closely at this. You can easily verify this by adding a smb_msleep(100) to the top of open_file_ntcreate and run the new samba4 torture test. It does also happen without the msleep, but not as reliably. Thanks, Volker (This used to be commit 58b9e48df03098160f39607d869a3c8e10860ba4) --- source3/smbd/open.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 3cd553f55b..98c2997a97 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1585,6 +1585,15 @@ files_struct *open_file_ntcreate(connection_struct *conn, fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode,access_mask); + if (!fsp_open && (flags2 & O_EXCL) && (errno == EEXIST)) { + /* + * Two smbd's tried to open exclusively, but only one of them + * succeeded. + */ + file_free(fsp); + return NULL; + } + if (!fsp_open && (flags == O_RDWR) && (errno != ENOENT)) { if((fsp_open = open_file(fsp,conn,fname,psbuf, O_RDONLY,unx_mode,access_mask)) == True) { -- cgit From 11c79fa98fd41be7d770d7e1da8053dd4f3082a8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 9 Sep 2005 21:49:16 +0000 Subject: r10133: Fix bug #3044. open-exec is read-only. Jeremy. (This used to be commit ed644d4014c3dc6c0508e94470c277599b1db933) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 98c2997a97..ed847826d5 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1046,13 +1046,13 @@ BOOL map_open_params_to_ntcreate(const char *fname, int deny_mode, int open_func /* Create the NT compatible access_mask. */ switch (GET_OPENX_MODE(deny_mode)) { + case DOS_OPEN_EXEC: /* Implies read-only - used to be FILE_READ_DATA */ case DOS_OPEN_RDONLY: access_mask = FILE_GENERIC_READ; break; case DOS_OPEN_WRONLY: access_mask = FILE_GENERIC_WRITE; break; - case DOS_OPEN_EXEC: /* This used to be FILE_READ_DATA... */ case DOS_OPEN_RDWR: case DOS_OPEN_FCB: access_mask = FILE_GENERIC_READ|FILE_GENERIC_WRITE; -- cgit From 54abd2aa66069e6baf7769c496f46d9dba18db39 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 30 Sep 2005 17:13:37 +0000 Subject: r10656: BIG merge from trunk. Features not copied over * \PIPE\unixinfo * winbindd's {group,alias}membership new functions * winbindd's lookupsids() functionality * swat (trunk changes to be reverted as per discussion with Deryck) (This used to be commit 939c3cb5d78e3a2236209b296aa8aba8bdce32d3) --- source3/smbd/open.c | 879 +++++++++++++++++++++++----------------------------- 1 file changed, 380 insertions(+), 499 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index ed847826d5..56d31c6940 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -24,11 +24,11 @@ extern struct current_user current_user; extern userdom_struct current_user_info; -extern uint16 global_oplock_port; extern uint16 global_smbpid; extern BOOL global_client_failed_oplock_break; -struct dev_inode_bundle { +struct deferred_open_record { + BOOL delayed_for_oplocks; SMB_DEV_T dev; SMB_INO_T inode; }; @@ -208,7 +208,6 @@ static BOOL open_file(files_struct *fsp, BOOL file_existed = VALID_STAT(*psbuf); fsp->fh->fd = -1; - fsp->oplock_type = NO_OPLOCK; errno = EPERM; /* Check permissions */ @@ -283,8 +282,7 @@ static BOOL open_file(files_struct *fsp, /* Don't create files with Microsoft wildcard characters. */ if ((local_flags & O_CREAT) && !file_existed && ms_has_wild(fname)) { - set_saved_error_triple(ERRDOS, ERRinvalidname, - NT_STATUS_OBJECT_NAME_INVALID); + set_saved_ntstatus(NT_STATUS_OBJECT_NAME_INVALID); return False; } @@ -354,7 +352,6 @@ static BOOL open_file(files_struct *fsp, } fsp->print_file = False; fsp->modified = False; - fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = False; fsp->is_stat = False; @@ -397,7 +394,7 @@ static BOOL is_executable(const char *fname) Returns True if conflict, False if not. ****************************************************************************/ -static BOOL share_conflict(share_mode_entry *entry, +static BOOL share_conflict(struct share_mode_entry *entry, uint32 access_mask, uint32 share_access) { @@ -445,7 +442,6 @@ static BOOL share_conflict(share_mode_entry *entry, DEBUG(10,("share_conflict: check %d conflict am = 0x%x, right = 0x%x, \ sa = 0x%x, share = 0x%x\n", (num), (unsigned int)(am), (unsigned int)(right), (unsigned int)(sa), \ (unsigned int)(share) )); \ - set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); \ return True; \ } #else @@ -454,7 +450,6 @@ sa = 0x%x, share = 0x%x\n", (num), (unsigned int)(am), (unsigned int)(right), (u DEBUG(10,("share_conflict: check %d conflict am = 0x%x, right = 0x%x, \ sa = 0x%x, share = 0x%x\n", (num), (unsigned int)(am), (unsigned int)(right), (unsigned int)(sa), \ (unsigned int)(share) )); \ - set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); \ return True; \ } #endif @@ -480,11 +475,23 @@ sa = 0x%x, share = 0x%x\n", (num), (unsigned int)(am), (unsigned int)(right), (u #if defined(DEVELOPER) static void validate_my_share_entries(int num, - share_mode_entry *share_entry) + struct share_mode_entry *share_entry) { files_struct *fsp; - if (share_entry->pid != sys_getpid()) { + if (!procid_is_me(&share_entry->pid)) { + return; + } + + if (is_deferred_open_entry(share_entry) && + !open_was_deferred(share_entry->op_mid)) { + pstring str; + DEBUG(0, ("Got a deferred entry without a request: " + "PANIC: %s\n", share_mode_str(num, share_entry))); + smb_panic(str); + } + + if (!is_valid_share_mode_entry(share_entry)) { return; } @@ -497,7 +504,26 @@ static void validate_my_share_entries(int num, "share entry with an open file\n"); } + if (is_deferred_open_entry(share_entry) || + is_unused_share_mode_entry(share_entry)) { + goto panic; + } + + if ((share_entry->op_type == NO_OPLOCK) && + (fsp->oplock_type == FAKE_LEVEL_II_OPLOCK)) { + /* Someone has already written to it, but I haven't yet + * noticed */ + return; + } + if (((uint16)fsp->oplock_type) != share_entry->op_type) { + goto panic; + } + + return; + + panic: + { pstring str; DEBUG(0,("validate_my_share_entries: PANIC : %s\n", share_mode_str(num, share_entry) )); @@ -510,375 +536,217 @@ static void validate_my_share_entries(int num, } #endif -struct share_mode_entry_list { - struct share_mode_entry_list *next, *prev; - share_mode_entry entry; -}; - -static void free_broken_entry_list(struct share_mode_entry_list *broken_entry_list) +static BOOL is_stat_open(uint32 access_mask) { - while (broken_entry_list) { - struct share_mode_entry_list *broken_entry = broken_entry_list; - DLIST_REMOVE(broken_entry_list, broken_entry); - SAFE_FREE(broken_entry); - } -} - -static BOOL cause_oplock_break(int request, int existing, uint32 access_mask) -{ - if ((access_mask == DELETE_ACCESS) && - (request == NO_OPLOCK)) { - /* This is a delete request */ - return (BATCH_OPLOCK_TYPE(existing) != 0); - } - - if (EXCLUSIVE_OPLOCK_TYPE(existing) && (request != NO_OPLOCK)) { - return True; - } - - if ((existing != NO_OPLOCK) && (request == NO_OPLOCK)) { - return True; - } - - return False; + return (access_mask && + ((access_mask & ~(SYNCHRONIZE_ACCESS| FILE_READ_ATTRIBUTES| + FILE_WRITE_ATTRIBUTES))==0) && + ((access_mask & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES| + FILE_WRITE_ATTRIBUTES)) != 0)); } /**************************************************************************** - Deal with open deny mode and oplock break processing. + Deal with share modes Invarient: Share mode must be locked on entry and exit. Returns -1 on error, or number of share modes on success (may be zero). ****************************************************************************/ -static int open_mode_check(connection_struct *conn, - const char *fname, - SMB_DEV_T dev, - SMB_INO_T inode, - uint32 access_mask, - uint32 share_access, - uint32 create_options, - int *p_oplock_request, - BOOL *p_all_current_opens_are_level_II) +static NTSTATUS open_mode_check(connection_struct *conn, + const char *fname, + struct share_mode_lock *lck, + uint32 access_mask, + uint32 share_access, + uint32 create_options, + BOOL *file_existed) { int i; - int num_share_modes; - int oplock_contention_count = 0; - share_mode_entry *old_shares = NULL; - BOOL broke_oplock; - BOOL delete_on_close; - num_share_modes = get_share_modes(dev, inode, &old_shares, &delete_on_close); - - if(num_share_modes == 0) { - SAFE_FREE(old_shares); - return 0; + if(lck->num_share_modes == 0) { + return NT_STATUS_OK; } + + *file_existed = True; - if (access_mask && - ((access_mask & ~(SYNCHRONIZE_ACCESS| FILE_READ_ATTRIBUTES| - FILE_WRITE_ATTRIBUTES))==0) && - ((access_mask & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES| - FILE_WRITE_ATTRIBUTES)) != 0)) { + if (is_stat_open(access_mask)) { /* Stat open that doesn't trigger oplock breaks or share mode * checks... ! JRA. */ - SAFE_FREE(old_shares); - return num_share_modes; + return NT_STATUS_OK; } /* A delete on close prohibits everything */ - if (delete_on_close) { - SAFE_FREE(old_shares); - errno = EACCES; - return -1; + if (lck->delete_on_close) { + return NT_STATUS_DELETE_PENDING; } /* * Check if the share modes will give us access. */ - do { - struct share_mode_entry_list *broken_entry_list = NULL; - struct share_mode_entry_list *broken_entry = NULL; - - 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]; - BOOL opb_ret; - #if defined(DEVELOPER) - validate_my_share_entries(i, share_entry); + for(i = 0; i < lck->num_share_modes; i++) { + validate_my_share_entries(i, &lck->share_modes[i]); + } #endif - /* - * By observation of NetBench, oplocks are broken - * *before* share modes are checked. This allows a - * file to be closed by the client if the share mode - * would deny access and the client has an oplock. - * Check if someone has an oplock on this file. If so - * we must break it before continuing. - */ + if (!lp_share_modes(SNUM(conn))) { + return NT_STATUS_OK; + } - if (!cause_oplock_break(*p_oplock_request, - share_entry->op_type, - access_mask)) { - if (!LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) { - *p_all_current_opens_are_level_II = False; - } - continue; - } + /* Now we check the share modes, after any oplock breaks. */ + for(i = 0; i < lck->num_share_modes; i++) { - /* This is an oplock break */ - - 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)); - - /* Ensure the reply for the open uses the correct - * sequence number. */ - /* This isn't a real deferred packet as it's response - * will also increment the sequence. - */ - srv_defer_sign_response(get_current_mid()); - - /* 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) { - 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)); - SAFE_FREE(old_shares); - set_saved_error_triple(ERRDOS, ERRbadshare, - NT_STATUS_SHARING_VIOLATION); - return -1; - } - - broken_entry = SMB_MALLOC_P(struct share_mode_entry_list); - if (!broken_entry) { - smb_panic("open_mode_check: malloc fail.\n"); - } - broken_entry->entry = *share_entry; - DLIST_ADD(broken_entry_list, broken_entry); - broke_oplock = True; - - } /* end for */ - - if (broke_oplock) { - /* Update the current open table. */ - SAFE_FREE(old_shares); - num_share_modes = get_share_modes(dev, inode, - &old_shares, - &delete_on_close); + if (!is_valid_share_mode_entry(&lck->share_modes[i])) { + continue; } - if (lp_share_modes(SNUM(conn))) { - /* Now we check the share modes, after any oplock breaks. */ - for(i = 0; i < num_share_modes; i++) { - share_mode_entry *share_entry = &old_shares[i]; - - /* someone else has a share lock on it, check to see - * if we can too */ - if (share_conflict(share_entry, access_mask, - share_access)) { - SAFE_FREE(old_shares); - free_broken_entry_list(broken_entry_list); - errno = EACCES; - return -1; - } - } + /* someone else has a share lock on it, check to see if we can + * too */ + if (share_conflict(&lck->share_modes[i], + access_mask, share_access)) { + return NT_STATUS_SHARING_VIOLATION; } - - for(broken_entry = broken_entry_list; broken_entry; - broken_entry = broken_entry->next) { - 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->entry, - share_entry) && - EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type))) { - continue; - } - - /* - * 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->entry.pid, fname, - (unsigned int)dev, (double)inode)); - - if (process_exists(broken_entry->entry.pid)) { - DEBUG(0,("open_mode_check: Existent process " - "%lu left active oplock.\n", - (unsigned long)broken_entry->entry.pid )); - } - - if (del_share_entry(dev, inode, &broken_entry->entry, - NULL, &delete_on_close) == -1) { - free_broken_entry_list(broken_entry_list); - errno = EACCES; - set_saved_error_triple(ERRDOS, ERRbadshare, - NT_STATUS_SHARING_VIOLATION); - 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(dev, inode, - &old_shares, - &delete_on_close); - break; - } /* end for paranoia... */ - } /* end for broken_entry */ - free_broken_entry_list(broken_entry_list); - } while(broke_oplock); - - /* - * 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 )); } - SAFE_FREE(old_shares); - return num_share_modes; + return NT_STATUS_OK; } -/**************************************************************************** - Delete the record for a handled deferred open entry. -****************************************************************************/ +static BOOL is_delete_request(files_struct *fsp) { + return ((fsp->access_mask == DELETE_ACCESS) && + (fsp->oplock_type == NO_OPLOCK)); +} -static void delete_defered_open_entry_record(connection_struct *conn, - SMB_DEV_T dev, - SMB_INO_T inode) +/* + * 1) No files open at all: Grant whatever the client wants. + * + * 2) Exclusive (or batch) oplock around: If the requested access is a delete + * request, break if the oplock around is a batch oplock. If it's another + * requested access type, break. + * + * 3) Only level2 around: Grant level2 and do nothing else. + */ + +static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp) { - uint16 mid = get_current_mid(); - pid_t mypid = sys_getpid(); - deferred_open_entry *de_array = NULL; - int num_de_entries, i; + int i, num_level2; + struct share_mode_entry *exclusive = NULL; + BOOL delay_it = False; + BOOL have_level2 = False; - if (!lp_defer_sharing_violations()) { - return; + if (is_stat_open(fsp->access_mask)) { + fsp->oplock_type = NO_OPLOCK; + return False; } - num_de_entries = get_deferred_opens(conn, dev, inode, &de_array); - for (i = 0; i < num_de_entries; i++) { - deferred_open_entry *entry = &de_array[i]; - if (entry->pid == mypid && entry->mid == mid && entry->dev == dev && - entry->inode == inode) { + num_level2 = 0; - /* Remove the deferred open entry from the array. */ - delete_deferred_open_entry(entry); - SAFE_FREE(de_array); - return; + if (lck->num_share_modes == 0) { + /* No files open at all: Directly grant whatever the client + * wants. */ + + if (fsp->oplock_type == NO_OPLOCK) { + /* Store a level2 oplock, but don't tell the client */ + fsp->oplock_type = FAKE_LEVEL_II_OPLOCK; + } + return False; + } + + for (i=0; inum_share_modes; i++) { + + if (!is_valid_share_mode_entry(&lck->share_modes[i])) { + continue; + } + + if (EXCLUSIVE_OPLOCK_TYPE(lck->share_modes[i].op_type)) { + SMB_ASSERT(exclusive == NULL); + exclusive = &lck->share_modes[i]; + } + + if (lck->share_modes[i].op_type == LEVEL_II_OPLOCK) { + have_level2 = True; } } - SAFE_FREE(de_array); + + if (exclusive != NULL) { /* Found an exclusive oplock */ + SMB_ASSERT(!have_level2); + delay_it = is_delete_request(fsp) ? + BATCH_OPLOCK_TYPE(exclusive->op_type) : True; + } + + if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { + /* We can at most grant level2 */ + fsp->oplock_type = LEVEL_II_OPLOCK; + } + + if ((fsp->oplock_type == NO_OPLOCK) && have_level2) { + /* Store a level2 oplock, but don't tell the client */ + fsp->oplock_type = FAKE_LEVEL_II_OPLOCK; + } + + if (delay_it) { + DEBUG(10, ("Sending break request to PID %s\n", + procid_str_static(&exclusive->pid))); + exclusive->op_mid = get_current_mid(); + if (!message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST, + exclusive, sizeof(*exclusive), True)) { + DEBUG(3, ("Could not send oplock break message\n")); + } + file_free(fsp); + } + + return delay_it; +} + +static BOOL request_timed_out(struct timeval request_time, + struct timeval timeout) +{ + struct timeval now, end_time; + GetTimeOfDay(&now); + end_time = timeval_sum(&request_time, &timeout); + return (timeval_compare(&end_time, &now) < 0); } /**************************************************************************** Handle the 1 second delay in returning a SHARING_VIOLATION error. ****************************************************************************/ -static void defer_open_sharing_error(connection_struct *conn, - struct timeval *ptv, - const char *fname, - SMB_DEV_T dev, - SMB_INO_T inode) +static void defer_open(struct share_mode_lock *lck, + struct timeval request_time, + struct timeval timeout, + struct deferred_open_record *state) { uint16 mid = get_current_mid(); - pid_t mypid = sys_getpid(); - deferred_open_entry *de_array = NULL; - int num_de_entries, i; - struct dev_inode_bundle dib; + int i; - if (!lp_defer_sharing_violations()) { - return; - } + /* Paranoia check */ - dib.dev = dev; - dib.inode = inode; + for (i=0; inum_share_modes; i++) { + struct share_mode_entry *e = &lck->share_modes[i]; - num_de_entries = get_deferred_opens(conn, dev, inode, &de_array); - for (i = 0; i < num_de_entries; i++) { - deferred_open_entry *entry = &de_array[i]; - if (entry->pid == mypid && entry->mid == mid) { - /* - * Check if a 1 second timeout has expired. - */ - if (usec_time_diff(ptv, &entry->time) > - SHARING_VIOLATION_USEC_WAIT) { - DEBUG(10,("defer_open_sharing_error: Deleting " - "deferred open entry for mid %u, " - "file %s\n", - (unsigned int)mid, fname )); - - /* Expired, return a real error. */ - /* Remove the deferred open entry from the array. */ - - delete_deferred_open_entry(entry); - SAFE_FREE(de_array); - return; - } - /* - * If the timeout hasn't expired yet and we still have - * a sharing violation, just leave the entry in the - * deferred open array alone. We do need to reschedule - * this open call though (with the original created - * time). - */ - DEBUG(10,("defer_open_sharing_error: time [%u.%06u] " - "updating deferred open entry for mid %u, file %s\n", - (unsigned int)entry->time.tv_sec, - (unsigned int)entry->time.tv_usec, - (unsigned int)mid, fname )); - - push_sharing_violation_open_smb_message(&entry->time, - (char *)&dib, - sizeof(dib)); - SAFE_FREE(de_array); - return; + if (!is_deferred_open_entry(e)) { + continue; + } + + if (procid_is_me(&e->pid) && (e->op_mid == mid)) { + DEBUG(0, ("Trying to defer an already deferred " + "request: mid=%d, exiting\n", mid)); + exit_server("exiting"); } } + /* End paranoia check */ + DEBUG(10,("defer_open_sharing_error: time [%u.%06u] adding deferred " - "open entry for mid %u, file %s\n", - (unsigned int)ptv->tv_sec, (unsigned int)ptv->tv_usec, - (unsigned int)mid, fname )); + "open entry for mid %u\n", + (unsigned int)request_time.tv_sec, + (unsigned int)request_time.tv_usec, + (unsigned int)mid)); - if (!push_sharing_violation_open_smb_message(ptv, (char *)&dib, sizeof(dib))) { - SAFE_FREE(de_array); - return; - } - if (!add_deferred_open(mid, ptv, dev, inode, global_oplock_port, fname)) { - remove_sharing_violation_open_smb_message(mid); + if (!push_deferred_smb_message(mid, request_time, timeout, + (char *)state, sizeof(*state))) { + exit_server("push_deferred_smb_message failed\n"); } + add_deferred_open(lck, mid, request_time, state->dev, state->inode); /* * Push the MID of this packet on the signing queue. @@ -888,8 +756,6 @@ static void defer_open_sharing_error(connection_struct *conn, */ srv_defer_sign_response(mid); - - SAFE_FREE(de_array); } /**************************************************************************** @@ -1196,8 +1062,6 @@ files_struct *open_file_ntcreate(connection_struct *conn, BOOL internal_only_open = False; SMB_DEV_T dev = 0; SMB_INO_T inode = 0; - int num_share_modes = 0; - BOOL all_current_opens_are_level_II = False; BOOL fsp_open = False; files_struct *fsp = NULL; mode_t new_unx_mode = (mode_t)0; @@ -1205,8 +1069,11 @@ files_struct *open_file_ntcreate(connection_struct *conn, int info; uint32 existing_dos_attributes = 0; struct pending_message_list *pml = NULL; - uint16 port = 0; uint16 mid = get_current_mid(); + BOOL delayed_for_oplocks = False; + struct timeval request_time = timeval_zero(); + struct share_mode_lock *lck = NULL; + NTSTATUS status; if (conn->printer) { /* @@ -1241,9 +1108,11 @@ files_struct *open_file_ntcreate(connection_struct *conn, } if ((pml = get_open_deferred_message(mid)) != NULL) { - struct dev_inode_bundle dib; + struct deferred_open_record *state = + (struct deferred_open_record *)pml->private_data.data; - memcpy(&dib, pml->private_data.data, sizeof(dib)); + request_time = pml->request_time; + delayed_for_oplocks = state->delayed_for_oplocks; /* There could be a race condition where the dev/inode pair has changed since we deferred the message. If so, just @@ -1255,24 +1124,18 @@ files_struct *open_file_ntcreate(connection_struct *conn, notified of a close and we don't want to trigger another spurious oplock break. */ - if (!file_existed || dib.dev != psbuf->st_dev || - dib.inode != psbuf->st_ino || pml->msg_time.tv_sec || - pml->msg_time.tv_usec) { - /* Ensure we don't reprocess this message. */ - remove_sharing_violation_open_smb_message(mid); - - /* Now remove the deferred open entry under lock. */ - lock_share_entry(conn, dib.dev, dib.inode); - delete_defered_open_entry_record(conn, dib.dev, - dib.inode); - unlock_share_entry(conn, dib.dev, dib.inode); - - set_saved_error_triple(ERRDOS, ERRbadshare, - NT_STATUS_SHARING_VIOLATION); - return NULL; + /* Now remove the deferred open entry under lock. */ + lck = get_share_mode_lock(NULL, state->dev, state->inode, + fname); + if (lck == NULL) { + DEBUG(0, ("could not get share mode lock\n")); + } else { + del_deferred_open_entry(lck, mid); + talloc_destroy(lck); } + /* Ensure we don't reprocess this message. */ - remove_sharing_violation_open_smb_message(mid); + remove_deferred_open_smb_message(mid); } if (!check_name(fname,conn)) { @@ -1285,7 +1148,8 @@ files_struct *open_file_ntcreate(connection_struct *conn, } /* ignore any oplock requests if oplocks are disabled */ - if (!lp_oplocks(SNUM(conn)) || global_client_failed_oplock_break) { + if (!lp_oplocks(SNUM(conn)) || global_client_failed_oplock_break || + IS_VETO_OPLOCK_PATH(conn, fname)) { oplock_request = 0; } @@ -1325,7 +1189,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, DEBUG(5,("open_file_ntcreate: FILE_OPEN " "requested for file %s and file " "doesn't exist.\n", fname )); - set_saved_error_triple(ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND); + set_saved_ntstatus(NT_STATUS_OBJECT_NAME_NOT_FOUND); errno = ENOENT; return NULL; } @@ -1338,7 +1202,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, DEBUG(5,("open_file_ntcreate: FILE_OVERWRITE " "requested for file %s and file " "doesn't exist.\n", fname )); - set_saved_error_triple(ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND); + set_saved_ntstatus(NT_STATUS_OBJECT_NAME_NOT_FOUND); errno = ENOENT; return NULL; } @@ -1369,8 +1233,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, break; default: - set_saved_error_triple(ERRDOS, ERRinvalidparam, - NT_STATUS_INVALID_PARAMETER); + set_saved_ntstatus(NT_STATUS_INVALID_PARAMETER); return NULL; } @@ -1447,8 +1310,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, DEBUG(5,("open_file_ntcreate: write access requested for " "file %s on read only %s\n", fname, !CAN_WRITE(conn) ? "share" : "file" )); - set_saved_error_triple(ERRDOS, ERRnoaccess, - NT_STATUS_ACCESS_DENIED); + set_saved_ntstatus(NT_STATUS_ACCESS_DENIED); errno = EACCES; return NULL; } @@ -1458,45 +1320,96 @@ files_struct *open_file_ntcreate(connection_struct *conn, return NULL; } + fsp->dev = psbuf->st_dev; + fsp->inode = psbuf->st_ino; + fsp->share_access = share_access; + fsp->fh->private_options = create_options; + fsp->access_mask = access_mask; + fsp->oplock_type = oplock_request; + + if (timeval_is_zero(&request_time)) { + request_time = fsp->open_time; + } + if (file_existed) { dev = psbuf->st_dev; inode = psbuf->st_ino; - lock_share_entry(conn, dev, inode); - - num_share_modes = open_mode_check(conn, fname, dev, inode, - access_mask, share_access, - create_options, - &oplock_request, - &all_current_opens_are_level_II); - if(num_share_modes == -1) { - - if (!internal_only_open) { - NTSTATUS status; - get_saved_error_triple(NULL, NULL, &status); - if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION)) { - /* Check if this can be done with the - * deny_dos and fcb calls. */ - if (create_options & - (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS| - NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) { - files_struct *fsp_dup; - fsp_dup = fcb_or_dos_open(conn, fname, dev, - inode, access_mask, - share_access, - create_options); - - if (fsp_dup) { - unlock_share_entry(conn, dev, inode); - file_free(fsp); - if (pinfo) { - *pinfo = FILE_WAS_OPENED; - } - conn->num_files_open++; - return fsp_dup; - } + lck = get_share_mode_lock(NULL, dev, inode, fname); + + if (lck == NULL) { + DEBUG(0, ("Could not get share mode lock\n")); + set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION); + return NULL; + } + + if (delay_for_oplocks(lck, fsp)) { + struct deferred_open_record state; + struct timeval timeout; + + if (delayed_for_oplocks) { + DEBUG(0, ("Trying to delay for oplocks " + "twice\n")); + exit_server("exiting"); + } + + timeout = timeval_set(OPLOCK_BREAK_TIMEOUT*2, 0); + + /* Normally the smbd we asked should respond within + * OPLOCK_BREAK_TIMEOUT seconds regardless of whether + * the client did, give twice the timeout as a safety + * measure here in case the other smbd is stuck + * somewhere else. */ + + state.delayed_for_oplocks = True; + state.dev = dev; + state.inode = inode; + + if (!request_timed_out(request_time, timeout)) { + defer_open(lck, request_time, timeout, + &state); + } + + talloc_free(lck); + return NULL; + } + + status = open_mode_check(conn, fname, lck, + access_mask, share_access, + create_options, &file_existed); + + if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) { + /* DELETE_PENDING is not deferred for a second */ + set_saved_ntstatus(status); + talloc_free(lck); + file_free(fsp); + return NULL; + } + + if (!NT_STATUS_IS_OK(status)) { + + SMB_ASSERT(NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)); + + /* Check if this can be done with the deny_dos and fcb + * calls. */ + if (create_options & + (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS| + NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) { + files_struct *fsp_dup; + fsp_dup = fcb_or_dos_open(conn, fname, dev, + inode, access_mask, + share_access, + create_options); + + if (fsp_dup) { + talloc_free(lck); + file_free(fsp); + if (pinfo) { + *pinfo = FILE_WAS_OPENED; } + conn->num_files_open++; + return fsp_dup; } } @@ -1527,8 +1440,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, if (!fsp_open && errno) { /* Default error. */ - set_saved_error_triple(ERRDOS, ERRnoaccess, - NT_STATUS_ACCESS_DENIED); + set_saved_ntstatus(NT_STATUS_ACCESS_DENIED); } /* @@ -1536,27 +1448,32 @@ files_struct *open_file_ntcreate(connection_struct *conn, * cope with the braindead 1 second delay. */ - if (!internal_only_open) { - NTSTATUS status; - get_saved_error_triple(NULL, NULL, &status); - if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION)) { - /* The fsp->open_time here represents - * the current time of day. */ - defer_open_sharing_error(conn, - &fsp->open_time, - fname, dev, inode); + if (!internal_only_open && + lp_defer_sharing_violations()) { + struct timeval timeout; + struct deferred_open_record state; + + timeout = timeval_set(0, SHARING_VIOLATION_USEC_WAIT); + + state.delayed_for_oplocks = False; + state.dev = dev; + state.inode = inode; + + if (!request_timed_out(request_time, + timeout)) { + defer_open(lck, request_time, timeout, + &state); } } - unlock_share_entry(conn, dev, inode); + talloc_free(lck); if (fsp_open) { fd_close(conn, fsp); /* * We have detected a sharing violation here * so return the correct error code */ - set_saved_error_triple(ERRDOS, ERRbadshare, - NT_STATUS_SHARING_VIOLATION); + set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION); } file_free(fsp); return NULL; @@ -1567,23 +1484,28 @@ files_struct *open_file_ntcreate(connection_struct *conn, */ } + SMB_ASSERT(!file_existed || (lck != NULL)); + /* * Ensure we pay attention to default ACLs on directories if required. */ 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, + parent_dirname(fname)))) { unx_mode = 0777; } DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", - (unsigned int)flags,(unsigned int)flags2,(unsigned int)unx_mode)); + (unsigned int)flags, (unsigned int)flags2, + (unsigned int)unx_mode)); /* * open_file strips any O_TRUNC flags itself. */ - fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode,access_mask); + fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode, + access_mask); if (!fsp_open && (flags2 & O_EXCL) && (errno == EEXIST)) { /* @@ -1602,22 +1524,23 @@ files_struct *open_file_ntcreate(connection_struct *conn, } if (!fsp_open) { - if(file_existed) { - unlock_share_entry(conn, dev, inode); + if (lck != NULL) { + talloc_free(lck); } file_free(fsp); return NULL; } - /* - * 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 set a share mode, the other (ie. this one) should check if - * the requested share mode for this create is allowed. - */ - if (!file_existed) { + /* + * 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 set a share mode, the other (ie. this + * one) should check if the requested share mode for this + * create is allowed. + */ + /* * Now the file exists and fsp is successfully opened, * fsp->dev and fsp->inode are valid and should replace the @@ -1628,70 +1551,41 @@ files_struct *open_file_ntcreate(connection_struct *conn, dev = fsp->dev; inode = fsp->inode; - lock_share_entry_fsp(fsp); - - num_share_modes = open_mode_check(conn, fname, dev, inode, - access_mask, share_access, - create_options, - &oplock_request, - &all_current_opens_are_level_II); - - if(num_share_modes == -1) { - NTSTATUS status; - get_saved_error_triple(NULL, NULL, &status); - if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION)) { - /* Check if this can be done with the deny_dos - * and fcb calls. */ - if (create_options & - (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS| - NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) { - files_struct *fsp_dup; - fsp_dup = fcb_or_dos_open(conn, fname, dev, inode, - access_mask, share_access, - create_options); - if (fsp_dup) { - unlock_share_entry(conn, dev, inode); - fd_close(conn, fsp); - file_free(fsp); - if (pinfo) { - *pinfo = FILE_WAS_OPENED; - } - conn->num_files_open++; - return fsp_dup; - } - } - - /* - * If we're returning a share violation, - * ensure we cope with the braindead 1 second - * delay. - */ - - /* The fsp->open_time here represents the - * current time of day. */ - defer_open_sharing_error(conn, &fsp->open_time, - fname, dev, inode); - } + lck = get_share_mode_lock(NULL, dev, inode, fname); - unlock_share_entry_fsp(fsp); - fd_close(conn,fsp); + if (lck == NULL) { + DEBUG(0, ("Coult not get share mode lock\n")); + fd_close(conn, fsp); file_free(fsp); - /* - * We have detected a sharing violation here, so - * return the correct code. - */ - set_saved_error_triple(ERRDOS, ERRbadshare, - NT_STATUS_SHARING_VIOLATION); + set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION); return NULL; } - /* - * If there are any share modes set then the file *did* - * exist. Ensure we return the correct value for action. - */ + status = open_mode_check(conn, fname, lck, + access_mask, share_access, + create_options, &file_existed); + + if (!NT_STATUS_IS_OK(status)) { + struct deferred_open_record state; - if (num_share_modes > 0) { - file_existed = True; + fd_close(conn, fsp); + file_free(fsp); + + state.delayed_for_oplocks = False; + state.dev = dev; + state.inode = inode; + + /* Do it all over again immediately. In the second + * round we will find that the file existed and handle + * the DELETE_PENDING and FCB cases correctly. No need + * to duplicate the code here. Essentially this is a + * "goto top of this function", but don't tell + * anybody... */ + + defer_open(lck, request_time, timeval_zero(), + &state); + talloc_free(lck); + return NULL; } /* @@ -1699,6 +1593,8 @@ files_struct *open_file_ntcreate(connection_struct *conn, */ } + SMB_ASSERT(lck != NULL); + /* 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 @@ -1725,7 +1621,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, */ if ((SMB_VFS_FTRUNCATE(fsp,fsp->fh->fd,0) == -1) || (SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf)==-1)) { - unlock_share_entry_fsp(fsp); + talloc_free(lck); fd_close(conn,fsp); file_free(fsp); return NULL; @@ -1761,20 +1657,14 @@ files_struct *open_file_ntcreate(connection_struct *conn, * file structs. */ - if(oplock_request && (num_share_modes == 0) && - !IS_VETO_OPLOCK_PATH(conn,fname) && - set_file_oplock(fsp, oplock_request) ) { - port = global_oplock_port; - } else if (oplock_request && all_current_opens_are_level_II) { - port = global_oplock_port; - oplock_request = LEVEL_II_OPLOCK; - set_file_oplock(fsp, oplock_request); - } else { - port = 0; - oplock_request = 0; + if ((fsp->oplock_type != NO_OPLOCK) && + (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK)) { + if (!set_file_oplock(fsp, fsp->oplock_type)) { + /* Could not get the kernel oplock */ + fsp->oplock_type = NO_OPLOCK; + } } - - set_share_mode(fsp, port, oplock_request); + set_share_mode(lck, fsp, 0, fsp->oplock_type); if (create_options & FILE_DELETE_ON_CLOSE) { uint32 dosattr= existing_dos_attributes; @@ -1788,19 +1678,16 @@ files_struct *open_file_ntcreate(connection_struct *conn, result = can_set_delete_on_close(fsp, True, dosattr); if (!NT_STATUS_IS_OK(result)) { - uint8 u_e_c; - uint32 u_e_code; - BOOL dummy_del_on_close; /* Remember to delete the mode we just added. */ - del_share_mode(fsp, NULL, &dummy_del_on_close); - unlock_share_entry_fsp(fsp); + del_share_mode(lck, fsp); + talloc_free(lck); fd_close(conn,fsp); file_free(fsp); - ntstatus_to_dos(result, &u_e_c, &u_e_code); - set_saved_error_triple(u_e_c, u_e_code, result); + set_saved_ntstatus(result); return NULL; } - set_delete_on_close(fsp, True); + lck->delete_on_close = True; + lck->modified = True; } if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || @@ -1860,8 +1747,8 @@ files_struct *open_file_ntcreate(connection_struct *conn, /* If this is a successful open, we must remove any deferred open * records. */ - delete_defered_open_entry_record(conn, fsp->dev, fsp->inode); - unlock_share_entry_fsp(fsp); + del_deferred_open_entry(lck, mid); + talloc_free(lck); conn->num_files_open++; @@ -1945,17 +1832,13 @@ files_struct *open_directory(connection_struct *conn, if (is_ntfs_stream_name(fname)) { DEBUG(0,("open_directory: %s is a stream name!\n", fname )); - /* NB. Is the DOS error ERRbadpath or ERRbaddirectory ? */ - set_saved_error_triple(ERRDOS, ERRbadpath, - NT_STATUS_NOT_A_DIRECTORY); + set_saved_ntstatus(NT_STATUS_NOT_A_DIRECTORY); return NULL; } if (dir_existed && !S_ISDIR(psbuf->st_mode)) { DEBUG(0,("open_directory: %s is not a directory !\n", fname )); - /* NB. Is the DOS error ERRbadpath or ERRbaddirectory ? */ - set_saved_error_triple(ERRDOS, ERRbadpath, - NT_STATUS_NOT_A_DIRECTORY); + set_saved_ntstatus(NT_STATUS_NOT_A_DIRECTORY); return NULL; } @@ -1967,8 +1850,7 @@ files_struct *open_directory(connection_struct *conn, DEBUG(5,("open_directory: FILE_OPEN requested " "for directory %s and it doesn't " "exist.\n", fname )); - set_saved_error_triple(ERRDOS, ERRbadfile, - NT_STATUS_OBJECT_NAME_NOT_FOUND); + set_saved_ntstatus(NT_STATUS_OBJECT_NAME_NOT_FOUND); return NULL; } info = FILE_WAS_OPENED; @@ -2008,8 +1890,7 @@ files_struct *open_directory(connection_struct *conn, "0x%x for directory %s\n", (unsigned int)create_disposition, fname)); file_free(fsp); - set_saved_error_triple(ERRDOS, ERRinvalidparam, - NT_STATUS_INVALID_PARAMETER); + set_saved_ntstatus(NT_STATUS_INVALID_PARAMETER); return NULL; } -- cgit From 94fe079be747ea5899f483dd8d00fdd247de4e33 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 5 Oct 2005 22:41:16 +0000 Subject: r10744: Fix for the second incarnation of bug #3088, pushed by Alex Masterov . A fcbopen specific part of the code was erroneously being called as part of the mainline open. Note, that this patch superceeds and replaces the fix that Volker added for this bug (which he added a Samba4 torture test for ) : "Fix a race condition in Samba 3. If two files are opened simultaneously with NTCREATEX_DISP_CREATE (create if not exists, else fail) they might end up with two or more times NT_STATUS_OK as EEXIST is not correctly handled." Jeremy. (This used to be commit 5d7ab9a17e793c05409a16675ac2aa2861c4f89e) --- source3/smbd/open.c | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 56d31c6940..a8fb8ed38f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1507,22 +1507,6 @@ files_struct *open_file_ntcreate(connection_struct *conn, fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode, access_mask); - if (!fsp_open && (flags2 & O_EXCL) && (errno == EEXIST)) { - /* - * Two smbd's tried to open exclusively, but only one of them - * succeeded. - */ - file_free(fsp); - return NULL; - } - - if (!fsp_open && (flags == O_RDWR) && (errno != ENOENT)) { - if((fsp_open = open_file(fsp,conn,fname,psbuf, - O_RDONLY,unx_mode,access_mask)) == True) { - flags = O_RDONLY; - } - } - if (!fsp_open) { if (lck != NULL) { talloc_free(lck); -- cgit From bd87876a8bbefaed700884653ffcc5e1567cac96 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Oct 2005 18:20:34 +0000 Subject: r10930: Fix erroneous debug spotted by Herb. Jeremy. (This used to be commit b2e22e7d128dc22d62f56fda294dc7abc076dc64) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index a8fb8ed38f..fac3925b10 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1715,7 +1715,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, if (ret == -1 && errno == ENOSYS) { errno = saved_errno; /* Ignore ENOSYS */ } else { - DEBUG(5, ("open_file_shared: failed to reset " + DEBUG(5, ("open_file_shared: reset " "attributes of file %s to 0%o\n", fname, (unsigned int)new_unx_mode)); ret = 0; /* Don't do the fchmod below. */ -- cgit From c5260e733c417642a30a59ebe46ed60b8ef18f6c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Oct 2005 21:42:03 +0000 Subject: r10943: Unused variable. Bug #3160 from jason@ncac.gwu.edu Jeremy. (This used to be commit 5647a5d4b0b7e9083963bfe899e9e0f348ec8bf2) --- source3/smbd/open.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index fac3925b10..70687ff580 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -628,7 +628,7 @@ static BOOL is_delete_request(files_struct *fsp) { static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp) { - int i, num_level2; + int i; struct share_mode_entry *exclusive = NULL; BOOL delay_it = False; BOOL have_level2 = False; @@ -638,8 +638,6 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp) return False; } - num_level2 = 0; - if (lck->num_share_modes == 0) { /* No files open at all: Directly grant whatever the client * wants. */ -- cgit From 533da83852b13c2e008938a026f99937ef320f3c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Oct 2005 22:35:08 +0000 Subject: r11341: Put directory opens into the share mode db so we can treat them similarly to file opens (delete on close, share mode violations etc.). This fixes bug #3216 I will up the default hash size on the locking db in a later commit as this means more entries. Jeremy. (This used to be commit 1134abbbb3fd8e8b88e1a5817aae106476a4c126) --- source3/smbd/open.c | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 70687ff580..42e1da839f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1536,7 +1536,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, lck = get_share_mode_lock(NULL, dev, inode, fname); if (lck == NULL) { - DEBUG(0, ("Coult not get share mode lock\n")); + DEBUG(0, ("open_file_ntcreate: Could not get share mode lock for %s\n", fname)); fd_close(conn, fsp); file_free(fsp); set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION); @@ -1801,6 +1801,8 @@ files_struct *open_directory(connection_struct *conn, files_struct *fsp = NULL; BOOL dir_existed = VALID_STAT(*psbuf) ? True : False; BOOL create_dir = False; + struct share_mode_lock *lck = NULL; + NTSTATUS status; int info = 0; DEBUG(5,("open_directory: opening directory %s, access_mask = 0x%x, " @@ -1883,7 +1885,7 @@ files_struct *open_directory(connection_struct *conn, /* We know bad_path is false as it's caught earlier. */ - NTSTATUS status = mkdir_internal(conn, fname, False); + status = mkdir_internal(conn, fname, False); if (!NT_STATUS_IS_OK(status)) { DEBUG(2,("open_directory: unable to create %s. " @@ -1938,14 +1940,43 @@ files_struct *open_directory(connection_struct *conn, fsp->is_stat = False; string_set(&fsp->fsp_name,fname); + lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, fname); + + if (lck == NULL) { + DEBUG(0, ("open_directory: Could not get share mode lock for %s\n", fname)); + file_free(fsp); + set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION); + return NULL; + } + + status = open_mode_check(conn, fname, lck, + access_mask, share_access, + create_options, &dir_existed); + + if (!NT_STATUS_IS_OK(status)) { + set_saved_ntstatus(status); + talloc_free(lck); + file_free(fsp); + return NULL; + } + + set_share_mode(lck, fsp, 0, NO_OPLOCK); + if (create_options & FILE_DELETE_ON_CLOSE) { - NTSTATUS status = can_set_delete_on_close(fsp, True, 0); + status = can_set_delete_on_close(fsp, True, 0); if (!NT_STATUS_IS_OK(status)) { + set_saved_ntstatus(status); + talloc_free(lck); file_free(fsp); return NULL; } + + lck->delete_on_close = True; + lck->modified = True; } + talloc_free(lck); + /* Change the owner if required. */ if ((info == FILE_WAS_CREATED) && lp_inherit_owner(SNUM(conn))) { change_owner_to_parent(conn, fsp, fsp->fsp_name, psbuf); -- cgit From 7d2771e758d4e8ef0adb45e55775b524de4dba9a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 12 Dec 2005 22:07:36 +0000 Subject: r12203: Add the share path into the sharemode db. This involves revving the minor version number for libsmbsharemodes (we now have a new _ex interface that takes the share path as well as the filename). Needed for #3303. Some code written by SATOH Fumiyasu included in the changes to locking/locking.c. The smbstatus output is a bit of a mess and needs overhauling... Jeremy. (This used to be commit 9d93af713f8520ca506730dd32aa2b994937eaba) --- source3/smbd/open.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 42e1da839f..b3f0589dc7 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1123,8 +1123,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, spurious oplock break. */ /* Now remove the deferred open entry under lock. */ - lck = get_share_mode_lock(NULL, state->dev, state->inode, - fname); + lck = get_share_mode_lock(NULL, state->dev, state->inode, NULL, NULL); if (lck == NULL) { DEBUG(0, ("could not get share mode lock\n")); } else { @@ -1334,7 +1333,9 @@ files_struct *open_file_ntcreate(connection_struct *conn, dev = psbuf->st_dev; inode = psbuf->st_ino; - lck = get_share_mode_lock(NULL, dev, inode, fname); + lck = get_share_mode_lock(NULL, dev, inode, + conn->connectpath, + fname); if (lck == NULL) { DEBUG(0, ("Could not get share mode lock\n")); @@ -1533,7 +1534,9 @@ files_struct *open_file_ntcreate(connection_struct *conn, dev = fsp->dev; inode = fsp->inode; - lck = get_share_mode_lock(NULL, dev, inode, fname); + lck = get_share_mode_lock(NULL, dev, inode, + conn->connectpath, + fname); if (lck == NULL) { DEBUG(0, ("open_file_ntcreate: Could not get share mode lock for %s\n", fname)); @@ -1940,7 +1943,9 @@ files_struct *open_directory(connection_struct *conn, fsp->is_stat = False; string_set(&fsp->fsp_name,fname); - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, fname); + lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, + conn->connectpath, + fname); if (lck == NULL) { DEBUG(0, ("open_directory: Could not get share mode lock for %s\n", fname)); -- cgit From ab7a4f7e8e4b946a8acd0a205c16dbf6a3afecad Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 13 Dec 2005 18:11:50 +0000 Subject: r12213: Final fix for #3303 - send rename messages to smbd's that have open file handles to allow them to correctly implement delete on close. There is a further correctness fix I'm intending to add to this to cope with different share paths, but not right now... Jeremy. (This used to be commit 932e337db8788e75344e1c7cf1ef009d090cb039) --- source3/smbd/open.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index b3f0589dc7..7621ee001d 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2042,3 +2042,50 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, return fsp; } + +/**************************************************************************** + Receive notification that one of our open files has been renamed by another + smbd process. +****************************************************************************/ + +void msg_file_was_renamed(int msg_type, struct process_id src, void *buf, size_t len) +{ + files_struct *fsp; + struct file_renamed_message *frm = (struct file_renamed_message *)buf; + const char *sharepath; + const char *newname; + size_t sp_len; + + if (buf == NULL || len < sizeof(*frm)) { + DEBUG(0, ("msg_file_was_renamed: Got invalid msg len %d\n", (int)len)); + return; + } + + sharepath = &frm->names[0]; + newname = sharepath + strlen(sharepath) + 1; + sp_len = strlen(sharepath); + + DEBUG(10,("msg_file_was_renamed: Got rename message for sharepath %s, new name %s, " + "dev %x, inode %.0f\n", + sharepath, newname, (unsigned int)frm->dev, (double)frm->inode )); + + for(fsp = file_find_di_first(frm->dev, frm->inode); fsp; fsp = file_find_di_next(fsp)) { + if (memcmp(fsp->conn->connectpath, sharepath, sp_len) == 0) { + DEBUG(10,("msg_file_was_renamed: renaming file fnum %d from %s -> %s\n", + fsp->fnum, fsp->fsp_name, newname )); + string_set(&fsp->fsp_name, newname); + } else { + /* TODO. JRA. */ + /* Now we have the complete path we can work out if this is + actually within this share and adjust newname accordingly. */ + DEBUG(10,("msg_file_was_renamed: share mismatch (sharepath %s " + "not sharepath %s) " + "fnum %d from %s -> %s\n", + fsp->conn->connectpath, + sharepath, + fsp->fnum, + fsp->fsp_name, + newname )); + } + } +} -- cgit From 67706697c5d8302e0d05d179de90c219531db8c7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 24 Dec 2005 21:06:41 +0000 Subject: r12460: Fixes for bug 3349 (This used to be commit 040eda6bf0517204d5650702eea7e1d1c5eeb3d5) --- source3/smbd/open.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 7621ee001d..e6c749fab9 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -682,11 +682,15 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp) } if (delay_it) { + BOOL ret; DEBUG(10, ("Sending break request to PID %s\n", procid_str_static(&exclusive->pid))); exclusive->op_mid = get_current_mid(); - if (!message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST, - exclusive, sizeof(*exclusive), True)) { + become_root(); + ret = message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST, + exclusive, sizeof(*exclusive), True); + unbecome_root(); + if (!ret) { DEBUG(3, ("Could not send oplock break message\n")); } file_free(fsp); -- cgit From a189257c15725e36e68970ed723f3365d4496792 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 5 Jan 2006 11:35:29 +0000 Subject: r12721: GPFS 2.4 on Linux will contain some windows semantics, ie share modes and oplocks across the cluster. Adapt Samba to it. The gpfs API is called via libgpfs.so. This code is written with dlopen(), so that you can compile on a system with gpfs installed and later on run on systems without gpfs available. So to actually make Samba call gpfs share mode calls you need to compile with gpfs.h and libgpfs.so around and set 'gpfs share = yes' on the shares you export from GPFS. Volker (This used to be commit 2253b17a1a88555291b59d52c826c81c2b8f7e7f) --- source3/smbd/open.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index e6c749fab9..2f82f04b63 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1599,6 +1599,20 @@ files_struct *open_file_ntcreate(connection_struct *conn, * deny mode is compatible with all current opens. */ + if (lp_gpfs_share(SNUM(fsp->conn)) && + !set_gpfs_sharemode(fsp, access_mask, share_access)) { + + /* GPFS does have share mode support, so the comment above wrt + * NFS being wrong is not correct here. */ + + set_saved_error_triple(ERRDOS, ERRbadshare, + NT_STATUS_SHARING_VIOLATION); + talloc_free(lck); + fd_close(conn, fsp); + file_free(fsp); + return NULL; + } + /* * If requested, truncate the file. */ -- cgit From 4d1d826be44ec82e3778e89cbd2873e0aacfc134 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 6 Jan 2006 10:27:12 +0000 Subject: r12735: After talking to Tridge and Jeremy... This needs to be made more generic before it goes in. Volker (This used to be commit 2c3d5c029a31111e1fe84ddc13c1bfc183d8bfde) --- source3/smbd/open.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 2f82f04b63..e6c749fab9 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1599,20 +1599,6 @@ files_struct *open_file_ntcreate(connection_struct *conn, * deny mode is compatible with all current opens. */ - if (lp_gpfs_share(SNUM(fsp->conn)) && - !set_gpfs_sharemode(fsp, access_mask, share_access)) { - - /* GPFS does have share mode support, so the comment above wrt - * NFS being wrong is not correct here. */ - - set_saved_error_triple(ERRDOS, ERRbadshare, - NT_STATUS_SHARING_VIOLATION); - talloc_free(lck); - fd_close(conn, fsp); - file_free(fsp); - return NULL; - } - /* * If requested, truncate the file. */ -- cgit From 33174847994128387a36a8103f147fe5a96c15fd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 12 Jan 2006 22:17:54 +0000 Subject: r12877: Stop passing structs around in smb messages, instead always linearize into little-endian. Should fix all Solaris issues with this, plus provide a cleaner base moving forward for cluster-aware Samba where smbd's can communicate across different compilers/architectures (eventually these message will have to go cross-machine). Jeremy. (This used to be commit d01824b78576a034428e1cef73868d1169057991) --- source3/smbd/open.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index e6c749fab9..0ccac592d6 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -683,12 +683,17 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp) if (delay_it) { BOOL ret; + char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE]; + DEBUG(10, ("Sending break request to PID %s\n", procid_str_static(&exclusive->pid))); exclusive->op_mid = get_current_mid(); + + share_mode_entry_to_message(msg, exclusive); + become_root(); ret = message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST, - exclusive, sizeof(*exclusive), True); + msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); unbecome_root(); if (!ret) { DEBUG(3, ("Could not send oplock break message\n")); @@ -2055,25 +2060,30 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, void msg_file_was_renamed(int msg_type, struct process_id src, void *buf, size_t len) { files_struct *fsp; - struct file_renamed_message *frm = (struct file_renamed_message *)buf; + char *frm = (char *)buf; + SMB_DEV_T dev; + SMB_INO_T inode; const char *sharepath; const char *newname; size_t sp_len; - if (buf == NULL || len < sizeof(*frm)) { + if (buf == NULL || len < MSG_FILE_RENAMED_MIN_SIZE + 2) { DEBUG(0, ("msg_file_was_renamed: Got invalid msg len %d\n", (int)len)); return; } - sharepath = &frm->names[0]; + /* Unpack the message. */ + dev = DEV_T_VAL(frm,0); + inode = INO_T_VAL(frm,8); + sharepath = &frm[16]; newname = sharepath + strlen(sharepath) + 1; sp_len = strlen(sharepath); DEBUG(10,("msg_file_was_renamed: Got rename message for sharepath %s, new name %s, " "dev %x, inode %.0f\n", - sharepath, newname, (unsigned int)frm->dev, (double)frm->inode )); + sharepath, newname, (unsigned int)dev, (double)inode )); - for(fsp = file_find_di_first(frm->dev, frm->inode); fsp; fsp = file_find_di_next(fsp)) { + for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) { if (memcmp(fsp->conn->connectpath, sharepath, sp_len) == 0) { DEBUG(10,("msg_file_was_renamed: renaming file fnum %d from %s -> %s\n", fsp->fnum, fsp->fsp_name, newname )); -- cgit From 86c9bac4c31df1606e3758ec42672506dde26cc6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 1 Feb 2006 04:14:07 +0000 Subject: r13274: Fix for bug #3467. Not a show stopper. jason qian was a *fantastic* help in tracking this down. Jeremy. (This used to be commit 9f4a9c70fa232047868e5d8a3f132a2dd6bfee82) --- source3/smbd/open.c | 46 ++++++++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 24 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 0ccac592d6..dd2731c897 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1660,32 +1660,28 @@ files_struct *open_file_ntcreate(connection_struct *conn, } set_share_mode(lck, fsp, 0, fsp->oplock_type); - if (create_options & FILE_DELETE_ON_CLOSE) { - uint32 dosattr= existing_dos_attributes; - NTSTATUS result; - - if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || + if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || info == FILE_WAS_SUPERSEDED) { - dosattr = new_dos_attributes; - } - - result = can_set_delete_on_close(fsp, True, dosattr); - if (!NT_STATUS_IS_OK(result)) { - /* Remember to delete the mode we just added. */ - del_share_mode(lck, fsp); - talloc_free(lck); - fd_close(conn,fsp); - file_free(fsp); - set_saved_ntstatus(result); - return NULL; + /* Handle strange delete on close create semantics. */ + if (create_options & FILE_DELETE_ON_CLOSE) { + NTSTATUS result = can_set_delete_on_close(fsp, True, new_dos_attributes); + + if (!NT_STATUS_IS_OK(result)) { + /* Remember to delete the mode we just added. */ + del_share_mode(lck, fsp); + talloc_free(lck); + fd_close(conn,fsp); + file_free(fsp); + set_saved_ntstatus(result); + return NULL; + } + /* Note that here we set the *inital* delete on close flag, + not the regular one. */ + lck->initial_delete_on_close = True; + lck->modified = True; } - lck->delete_on_close = True; - lck->modified = True; - } - if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || - info == FILE_WAS_SUPERSEDED) { /* Files should be initially set as archive */ if (lp_map_archive(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) { @@ -1976,7 +1972,9 @@ files_struct *open_directory(connection_struct *conn, set_share_mode(lck, fsp, 0, NO_OPLOCK); - if (create_options & FILE_DELETE_ON_CLOSE) { + if ((create_options & FILE_DELETE_ON_CLOSE) && + (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || + info == FILE_WAS_SUPERSEDED)) { status = can_set_delete_on_close(fsp, True, 0); if (!NT_STATUS_IS_OK(status)) { set_saved_ntstatus(status); @@ -1985,7 +1983,7 @@ files_struct *open_directory(connection_struct *conn, return NULL; } - lck->delete_on_close = True; + lck->initial_delete_on_close = True; lck->modified = True; } -- cgit From d14af63e6ab600eb3ac705f2f425c860e927553a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 2 Feb 2006 20:44:50 +0000 Subject: r13293: Rather a big patch I'm afraid, but this should fix bug #3347 by saving the UNIX token used to set a delete on close flag, and using it when doing the delete. libsmbsharemodes.so still needs updating to cope with this change. Samba4 torture tests to follow. Jeremy. (This used to be commit 23f16cbc2e8cde97c486831e26bcafd4ab4a9654) --- source3/smbd/open.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index dd2731c897..15e814aae3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1678,6 +1678,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, } /* Note that here we set the *inital* delete on close flag, not the regular one. */ + set_delete_on_close_token(lck, ¤t_user.ut); lck->initial_delete_on_close = True; lck->modified = True; } @@ -1983,6 +1984,7 @@ files_struct *open_directory(connection_struct *conn, return NULL; } + set_delete_on_close_token(lck, ¤t_user.ut); lck->initial_delete_on_close = True; lck->modified = True; } -- cgit From 66d5a32d9cae13ddceb9b4710722d86cdc343043 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 3 Feb 2006 02:16:35 +0000 Subject: r13299: From testing W2K3 and W2K the delete on close bit seems to be always honored (ie. the file gets deleted) for derectories when set at open time - even though it doesn't show in the qfileinfo call. This is not true of files.... (if anyone from the EU is listening, it's stuff like this that makes CIFS non-documentable :-). Jeremy. (This used to be commit e2fc8a196a06f76aa47fabc30872c701a2f7ccec) --- source3/smbd/open.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 15e814aae3..f75bc55b46 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1973,9 +1973,9 @@ files_struct *open_directory(connection_struct *conn, set_share_mode(lck, fsp, 0, NO_OPLOCK); - if ((create_options & FILE_DELETE_ON_CLOSE) && - (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || - info == FILE_WAS_SUPERSEDED)) { + /* For directories the delete on close bit at open time seems + always to be honored on close... See test 19 in Samba4 BASE-DELETE. */ + if (create_options & FILE_DELETE_ON_CLOSE) { status = can_set_delete_on_close(fsp, True, 0); if (!NT_STATUS_IS_OK(status)) { set_saved_ntstatus(status); -- cgit From 21a30a1346c9f9a25659a0cea0d276d8c2e6ddca Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 3 Feb 2006 22:10:37 +0000 Subject: r13314: This code has been causing problems since 1.9.x I think. Remove check_for_pipe() - Volker was completely correct. If it gets re-added it will be in a old open call path, not in the generic code path. Jeremy. (This used to be commit 50c894a6e949d4d3579926650674f381a821a671) --- source3/smbd/open.c | 19 ------------------- 1 file changed, 19 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index f75bc55b46..4b13e28f8e 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -73,23 +73,6 @@ int fd_close(struct connection_struct *conn, return fd_close_posix(conn, fsp); } - -/**************************************************************************** - Check a filename for the pipe string. -****************************************************************************/ - -static void check_for_pipe(const char *fname) -{ - /* special case of pipe opens */ - char s[10]; - StrnCpy(s,fname,sizeof(s)-1); - strlower_m(s); - if (strstr(s,"pipe/")) { - DEBUG(3,("Rejecting named pipe open for %s\n",fname)); - set_saved_error_triple(ERRSRV, ERRaccess, NT_STATUS_ACCESS_DENIED); - } -} - /**************************************************************************** Change the ownership of a file to that of the parent directory. Do this by fd if possible. @@ -226,7 +209,6 @@ static BOOL open_file(files_struct *fsp, /* 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 False; } else if(flags & O_CREAT) { /* We don't want to write - but we must make sure that @@ -292,7 +274,6 @@ static BOOL open_file(files_struct *fsp, DEBUG(3,("Error opening file %s (%s) (local_flags=%d) " "(flags=%d)\n", fname,strerror(errno),local_flags,flags)); - check_for_pipe(fname); return False; } -- cgit From 0af1500fc0bafe61019f1b2ab1d9e1d369221240 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 3 Feb 2006 22:19:41 +0000 Subject: r13316: Let the carnage begin.... Sync with trunk as off r13315 (This used to be commit 17e63ac4ed8325c0d44fe62b2442449f3298559f) --- source3/smbd/open.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 4b13e28f8e..4f28e291cd 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -22,6 +22,7 @@ #include "includes.h" +extern struct generic_mapping file_generic_mapping; extern struct current_user current_user; extern userdom_struct current_user_info; extern uint16 global_smbpid; @@ -1018,15 +1019,6 @@ BOOL map_open_params_to_ntcreate(const char *fname, int deny_mode, int open_func } -/* Map generic permissions to file object specific permissions */ - -struct generic_mapping file_generic_mapping = { - FILE_GENERIC_READ, - FILE_GENERIC_WRITE, - FILE_GENERIC_EXECUTE, - FILE_GENERIC_ALL -}; - /**************************************************************************** Open a file with a share mode. ****************************************************************************/ -- cgit From 51e8dc417bdfe009d0fd2dc3eb77cb1346016318 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 18 Feb 2006 02:02:11 +0000 Subject: r13559: Fix bug #3522 reported by Sandeep Tamhankar . mkdir foo returns the wrong error message when file foo exists. Jeremy. (This used to be commit c8185e7f94cbcf2125bf0e84db02fb8d19111f60) --- source3/smbd/open.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 4f28e291cd..3e555a8f31 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1802,12 +1802,6 @@ files_struct *open_directory(connection_struct *conn, return NULL; } - if (dir_existed && !S_ISDIR(psbuf->st_mode)) { - DEBUG(0,("open_directory: %s is not a directory !\n", fname )); - set_saved_ntstatus(NT_STATUS_NOT_A_DIRECTORY); - return NULL; - } - switch( create_disposition ) { case FILE_OPEN: /* If directory exists open. If directory doesn't -- cgit From fb5362c069b5b6548478b2217a0519c56d856705 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Mon, 20 Feb 2006 17:59:58 +0000 Subject: r13571: Replace all calls to talloc_free() with thye TALLOC_FREE() macro which sets the freed pointer to NULL. (This used to be commit b65be8874a2efe5a4b167448960a4fcf6bd995e2) --- source3/smbd/open.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 3e555a8f31..258e0e6021 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1352,7 +1352,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, &state); } - talloc_free(lck); + TALLOC_FREE(lck); return NULL; } @@ -1363,7 +1363,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) { /* DELETE_PENDING is not deferred for a second */ set_saved_ntstatus(status); - talloc_free(lck); + TALLOC_FREE(lck); file_free(fsp); return NULL; } @@ -1384,7 +1384,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, create_options); if (fsp_dup) { - talloc_free(lck); + TALLOC_FREE(lck); file_free(fsp); if (pinfo) { *pinfo = FILE_WAS_OPENED; @@ -1447,7 +1447,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, } } - talloc_free(lck); + TALLOC_FREE(lck); if (fsp_open) { fd_close(conn, fsp); /* @@ -1490,7 +1490,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, if (!fsp_open) { if (lck != NULL) { - talloc_free(lck); + TALLOC_FREE(lck); } file_free(fsp); return NULL; @@ -1551,7 +1551,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, defer_open(lck, request_time, timeval_zero(), &state); - talloc_free(lck); + TALLOC_FREE(lck); return NULL; } @@ -1588,7 +1588,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, */ if ((SMB_VFS_FTRUNCATE(fsp,fsp->fh->fd,0) == -1) || (SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf)==-1)) { - talloc_free(lck); + TALLOC_FREE(lck); fd_close(conn,fsp); file_free(fsp); return NULL; @@ -1643,7 +1643,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, if (!NT_STATUS_IS_OK(result)) { /* Remember to delete the mode we just added. */ del_share_mode(lck, fsp); - talloc_free(lck); + TALLOC_FREE(lck); fd_close(conn,fsp); file_free(fsp); set_saved_ntstatus(result); @@ -1712,7 +1712,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, /* If this is a successful open, we must remove any deferred open * records. */ del_deferred_open_entry(lck, mid); - talloc_free(lck); + TALLOC_FREE(lck); conn->num_files_open++; @@ -1933,7 +1933,7 @@ files_struct *open_directory(connection_struct *conn, if (!NT_STATUS_IS_OK(status)) { set_saved_ntstatus(status); - talloc_free(lck); + TALLOC_FREE(lck); file_free(fsp); return NULL; } @@ -1946,7 +1946,7 @@ files_struct *open_directory(connection_struct *conn, status = can_set_delete_on_close(fsp, True, 0); if (!NT_STATUS_IS_OK(status)) { set_saved_ntstatus(status); - talloc_free(lck); + TALLOC_FREE(lck); file_free(fsp); return NULL; } @@ -1956,7 +1956,7 @@ files_struct *open_directory(connection_struct *conn, lck->modified = True; } - talloc_free(lck); + TALLOC_FREE(lck); /* Change the owner if required. */ if ((info == FILE_WAS_CREATED) && lp_inherit_owner(SNUM(conn))) { -- cgit From f8fccdfd370d6a0291bd38c2cd081a605f0bceac Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 26 Feb 2006 14:20:29 +0000 Subject: r13694: Committing patch from Aleksey Fedoseev to NULL out a pointer after talloc_destroy(). Volker (This used to be commit 788e52eb5d17a8f5b41b6ad5244ccf448fc81a36) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 258e0e6021..8913db8380 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1110,7 +1110,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, DEBUG(0, ("could not get share mode lock\n")); } else { del_deferred_open_entry(lck, mid); - talloc_destroy(lck); + TALLOC_FREE(lck); } /* Ensure we don't reprocess this message. */ -- cgit From 292afdba59de411f9d6d4ff69d11b1da068df5da Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 20 Mar 2006 23:40:43 +0000 Subject: r14596: Fix a logic bug with multiple oplock contention. The sad thing is the core of this bug fix is just removing a paranoia "exit_server" call, as the rest of the logic was already correct :-). Lots of comments to explain the logic added. I will look at adding tests to exercise this, might be possible. Jeremy. (This used to be commit c2488db727e1a00f112be7b169de9e6208e311f3) --- source3/smbd/open.c | 51 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 18 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 8913db8380..0cf8b68c28 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1091,20 +1091,14 @@ files_struct *open_file_ntcreate(connection_struct *conn, struct deferred_open_record *state = (struct deferred_open_record *)pml->private_data.data; + /* Remember the absolute time of the original + request with this mid. We'll use it later to + see if this has timed out. */ + request_time = pml->request_time; delayed_for_oplocks = state->delayed_for_oplocks; - /* There could be a race condition where the dev/inode pair - has changed since we deferred the message. If so, just - remove the deferred open entry and return sharing - violation. */ - - /* If the timeout value is non-zero, we need to just return - sharing violation. Don't retry the open as we were not - notified of a close and we don't want to trigger another - spurious oplock break. */ - - /* Now remove the deferred open entry under lock. */ + /* Remove the deferred open entry under lock. */ lck = get_share_mode_lock(NULL, state->dev, state->inode, NULL, NULL); if (lck == NULL) { DEBUG(0, ("could not get share mode lock\n")); @@ -1327,15 +1321,16 @@ files_struct *open_file_ntcreate(connection_struct *conn, if (delay_for_oplocks(lck, fsp)) { struct deferred_open_record state; - struct timeval timeout; - if (delayed_for_oplocks) { - DEBUG(0, ("Trying to delay for oplocks " - "twice\n")); - exit_server("exiting"); - } + /* This is a relative time, added to the absolute + request_time value to get the absolute timeout time. + Note that if this is the second or greater time we enter + this codepath for this particular request mid then + request_time is left as the absolute time of the *first* + time this request mid was processed. This is what allows + the request to eventually time out. */ - timeout = timeval_set(OPLOCK_BREAK_TIMEOUT*2, 0); + struct timeval timeout; /* Normally the smbd we asked should respond within * OPLOCK_BREAK_TIMEOUT seconds regardless of whether @@ -1343,6 +1338,13 @@ files_struct *open_file_ntcreate(connection_struct *conn, * measure here in case the other smbd is stuck * somewhere else. */ + timeout = timeval_set(OPLOCK_BREAK_TIMEOUT*2, 0); + + /* Nothing actually uses state.delayed_for_oplocks + but it's handy to differentiate in debug messages + between a 30 second delay due to oplock break, and + a 1 second delay for share mode conflicts. */ + state.delayed_for_oplocks = True; state.dev = dev; state.inode = inode; @@ -1434,8 +1436,21 @@ files_struct *open_file_ntcreate(connection_struct *conn, struct timeval timeout; struct deferred_open_record state; + /* This is a relative time, added to the absolute + request_time value to get the absolute timeout time. + Note that if this is the second or greater time we enter + this codepath for this particular request mid then + request_time is left as the absolute time of the *first* + time this request mid was processed. This is what allows + the request to eventually time out. */ + timeout = timeval_set(0, SHARING_VIOLATION_USEC_WAIT); + /* Nothing actually uses state.delayed_for_oplocks + but it's handy to differentiate in debug messages + between a 30 second delay due to oplock break, and + a 1 second delay for share mode conflicts. */ + state.delayed_for_oplocks = False; state.dev = dev; state.inode = inode; -- cgit From 5067cca077ab8dde110f79ea9e60611dc25ddf64 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 21 Mar 2006 06:53:49 +0000 Subject: r14602: Fix another logic bug in new oplock handling. Just because lck->num_share_modes != 0 doesn't mean that there *are* other valid share modes. They may be all marked "UNUSED" or be deferred open entries. In that case don't downgrade the granted oplock to level2 needlessly - a client can have an exclusive oplock in this case. The original code handled this correctly in the lck->num_share_modes == 0 case but not in the case where there were no valid share modes but lck->num_share_modes != 0. I'll clean up my Samba4 torture tester for this and commit it tomorrow. Jeremy. (This used to be commit 306061c93d9181262298516fefd83444f5a65ce5) --- source3/smbd/open.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 0cf8b68c28..5de03b8dd7 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -612,6 +612,7 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp) { int i; struct share_mode_entry *exclusive = NULL; + BOOL valid_entry = False; BOOL delay_it = False; BOOL have_level2 = False; @@ -620,33 +621,36 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp) return False; } - if (lck->num_share_modes == 0) { - /* No files open at all: Directly grant whatever the client - * wants. */ - - if (fsp->oplock_type == NO_OPLOCK) { - /* Store a level2 oplock, but don't tell the client */ - fsp->oplock_type = FAKE_LEVEL_II_OPLOCK; - } - return False; - } - for (i=0; inum_share_modes; i++) { if (!is_valid_share_mode_entry(&lck->share_modes[i])) { continue; } + /* At least one entry is not an invalid or deferred entry. */ + valid_entry = True; + if (EXCLUSIVE_OPLOCK_TYPE(lck->share_modes[i].op_type)) { SMB_ASSERT(exclusive == NULL); exclusive = &lck->share_modes[i]; } if (lck->share_modes[i].op_type == LEVEL_II_OPLOCK) { + SMB_ASSERT(exclusive == NULL); have_level2 = True; } } + if (!valid_entry) { + /* All entries are placeholders or deferred. + * Directly grant whatever the client wants. */ + if (fsp->oplock_type == NO_OPLOCK) { + /* Store a level2 oplock, but don't tell the client */ + fsp->oplock_type = FAKE_LEVEL_II_OPLOCK; + } + return False; + } + if (exclusive != NULL) { /* Found an exclusive oplock */ SMB_ASSERT(!have_level2); delay_it = is_delete_request(fsp) ? @@ -654,7 +658,8 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp) } if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { - /* We can at most grant level2 */ + /* We can at most grant level2 as there are other + * level2 or NO_OPLOCK entries. */ fsp->oplock_type = LEVEL_II_OPLOCK; } -- cgit From 18e93247aa417eaf7c8fbf649ce45726ccba7433 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 3 Apr 2006 10:43:34 +0000 Subject: r14883: add 'smbd:sharedelay' option, so that we can speed up BASE-DENY2 in make test as done in samba4 metze (This used to be commit b98dd258a74a1e1b4e967e6176a5a92986d03123) --- source3/smbd/open.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 5de03b8dd7..ba0a16035a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1440,6 +1440,13 @@ files_struct *open_file_ntcreate(connection_struct *conn, lp_defer_sharing_violations()) { struct timeval timeout; struct deferred_open_record state; + int timeout_usecs; + + /* this is a hack to speed up torture tests + in 'make test' */ + timeout_usecs = lp_parm_int(conn->service, + "smbd","sharedelay", + SHARING_VIOLATION_USEC_WAIT); /* This is a relative time, added to the absolute request_time value to get the absolute timeout time. @@ -1449,7 +1456,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, time this request mid was processed. This is what allows the request to eventually time out. */ - timeout = timeval_set(0, SHARING_VIOLATION_USEC_WAIT); + timeout = timeval_set(0, timeout_usecs); /* Nothing actually uses state.delayed_for_oplocks but it's handy to differentiate in debug messages -- cgit From 4fa555980070d78b39711ef21d77628d26055bc2 Mon Sep 17 00:00:00 2001 From: James Peach Date: Tue, 4 Apr 2006 00:27:50 +0000 Subject: r14898: This change is an attempt to improve the quality of the information that is produced when a process exits abnormally. First, we coalesce the core dumping code so that we greatly improve our odds of being able to produce a core file, even in the case of a memory fault. I've removed duplicates of dump_core() and split it in two to reduce the amount of work needed to actually do the dump. Second, we refactor the exit_server code path to always log an explanation and a stack trace. My goal is to always produce enough log information for us to be able to explain any server exit, though there is a risk that this could produce too much log information on a flaky network. Finally, smbcontrol has gained a smbd fault injection operation to test the changes above. This is only enabled for developer builds. (This used to be commit 56bc02d64498eb3faf89f0c5452b9299daea8e95) --- source3/smbd/open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index ba0a16035a..99a7894762 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -724,7 +724,7 @@ static void defer_open(struct share_mode_lock *lck, if (procid_is_me(&e->pid) && (e->op_mid == mid)) { DEBUG(0, ("Trying to defer an already deferred " "request: mid=%d, exiting\n", mid)); - exit_server("exiting"); + exit_server("attempt to defer a deferred request"); } } @@ -738,7 +738,7 @@ static void defer_open(struct share_mode_lock *lck, if (!push_deferred_smb_message(mid, request_time, timeout, (char *)state, sizeof(*state))) { - exit_server("push_deferred_smb_message failed\n"); + exit_server("push_deferred_smb_message failed"); } add_deferred_open(lck, mid, request_time, state->dev, state->inode); -- cgit From f60111e074eba237ef2ad416bfd3847ce314e773 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 19 Apr 2006 18:48:14 +0000 Subject: r15138: Teach Samba the difference between exclusive and batch oplocks. Pass Samba4 oplock test (with kernel oplocks off). Jeremy. (This used to be commit 3c260bcce2de76d724279e07dca61eadddfb8782) --- source3/smbd/open.c | 100 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 60 insertions(+), 40 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 99a7894762..edc5bc98b6 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -608,7 +608,7 @@ static BOOL is_delete_request(files_struct *fsp) { * 3) Only level2 around: Grant level2 and do nothing else. */ -static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp) +static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp, int pass_number) { int i; struct share_mode_entry *exclusive = NULL; @@ -630,9 +630,16 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp) /* At least one entry is not an invalid or deferred entry. */ valid_entry = True; - if (EXCLUSIVE_OPLOCK_TYPE(lck->share_modes[i].op_type)) { - SMB_ASSERT(exclusive == NULL); - exclusive = &lck->share_modes[i]; + if (pass_number == 1) { + if (BATCH_OPLOCK_TYPE(lck->share_modes[i].op_type)) { + SMB_ASSERT(exclusive == NULL); + exclusive = &lck->share_modes[i]; + } + } else { + if (EXCLUSIVE_OPLOCK_TYPE(lck->share_modes[i].op_type)) { + SMB_ASSERT(exclusive == NULL); + exclusive = &lck->share_modes[i]; + } } if (lck->share_modes[i].op_type == LEVEL_II_OPLOCK) { @@ -1024,6 +1031,42 @@ BOOL map_open_params_to_ntcreate(const char *fname, int deny_mode, int open_func } +static void schedule_defer_open(struct share_mode_lock *lck, struct timeval request_time) +{ + struct deferred_open_record state; + + /* This is a relative time, added to the absolute + request_time value to get the absolute timeout time. + Note that if this is the second or greater time we enter + this codepath for this particular request mid then + request_time is left as the absolute time of the *first* + time this request mid was processed. This is what allows + the request to eventually time out. */ + + struct timeval timeout; + + /* Normally the smbd we asked should respond within + * OPLOCK_BREAK_TIMEOUT seconds regardless of whether + * the client did, give twice the timeout as a safety + * measure here in case the other smbd is stuck + * somewhere else. */ + + timeout = timeval_set(OPLOCK_BREAK_TIMEOUT*2, 0); + + /* Nothing actually uses state.delayed_for_oplocks + but it's handy to differentiate in debug messages + between a 30 second delay due to oplock break, and + a 1 second delay for share mode conflicts. */ + + state.delayed_for_oplocks = True; + state.dev = lck->dev; + state.inode = lck->ino; + + if (!request_timed_out(request_time, timeout)) { + defer_open(lck, request_time, timeout, &state); + } +} + /**************************************************************************** Open a file with a share mode. ****************************************************************************/ @@ -1310,7 +1353,6 @@ files_struct *open_file_ntcreate(connection_struct *conn, } if (file_existed) { - dev = psbuf->st_dev; inode = psbuf->st_ino; @@ -1324,41 +1366,9 @@ files_struct *open_file_ntcreate(connection_struct *conn, return NULL; } - if (delay_for_oplocks(lck, fsp)) { - struct deferred_open_record state; - - /* This is a relative time, added to the absolute - request_time value to get the absolute timeout time. - Note that if this is the second or greater time we enter - this codepath for this particular request mid then - request_time is left as the absolute time of the *first* - time this request mid was processed. This is what allows - the request to eventually time out. */ - - struct timeval timeout; - - /* Normally the smbd we asked should respond within - * OPLOCK_BREAK_TIMEOUT seconds regardless of whether - * the client did, give twice the timeout as a safety - * measure here in case the other smbd is stuck - * somewhere else. */ - - timeout = timeval_set(OPLOCK_BREAK_TIMEOUT*2, 0); - - /* Nothing actually uses state.delayed_for_oplocks - but it's handy to differentiate in debug messages - between a 30 second delay due to oplock break, and - a 1 second delay for share mode conflicts. */ - - state.delayed_for_oplocks = True; - state.dev = dev; - state.inode = inode; - - if (!request_timed_out(request_time, timeout)) { - defer_open(lck, request_time, timeout, - &state); - } - + /* First pass - send break only on batch oplocks. */ + if (delay_for_oplocks(lck, fsp, 1)) { + schedule_defer_open(lck, request_time); TALLOC_FREE(lck); return NULL; } @@ -1367,6 +1377,16 @@ files_struct *open_file_ntcreate(connection_struct *conn, access_mask, share_access, create_options, &file_existed); + if (NT_STATUS_IS_OK(status)) { + /* We might be going to allow this open. Check oplock status again. */ + /* Second pass - send break for both batch or exclusive oplocks. */ + if (delay_for_oplocks(lck, fsp, 2)) { + schedule_defer_open(lck, request_time); + TALLOC_FREE(lck); + return NULL; + } + } + if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) { /* DELETE_PENDING is not deferred for a second */ set_saved_ntstatus(status); -- cgit From ec8b810a16e1f08ceb64486be7447e6cf703261d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Apr 2006 13:42:18 +0000 Subject: r15293: Don't ever set O_SYNC on open unless "strict sync = yes". This could be the cause of the perf. problem reported between 3.0.14a and 3.0.2x. Lufthansa has *wireless* on their flights to the USA now... (I'm in heaven ! :-). Jeremy. (This used to be commit dbc03125f2643f8ecff8e901cb23fa6408cce011) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index edc5bc98b6..1c8716abda 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1308,7 +1308,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, */ #if defined(O_SYNC) - if (create_options & FILE_WRITE_THROUGH) { + if (lp_strict_sync(SNUM(conn)) && (create_options & FILE_WRITE_THROUGH)) { flags2 |= O_SYNC; } #endif /* O_SYNC */ -- cgit From aca0a3ad3a9646e821f2d4c3d30f3a14592df4ae Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 3 May 2006 03:42:56 +0000 Subject: r15404: Check for WRITE_THOUGH before calling lp_ fn. I hate extra fn calls. Jeremy. (This used to be commit e468e1e5c2dbee29066f0efe4141d8705def5d6f) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 1c8716abda..3d537b2f39 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1308,7 +1308,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, */ #if defined(O_SYNC) - if (lp_strict_sync(SNUM(conn)) && (create_options & FILE_WRITE_THROUGH)) { + if ((create_options & FILE_WRITE_THROUGH) && lp_strict_sync(SNUM(conn))) { flags2 |= O_SYNC; } #endif /* O_SYNC */ -- cgit From 0a1ca7fa3d19f46c4bcb0c80c78a619c90fe5f2a Mon Sep 17 00:00:00 2001 From: James Peach Date: Mon, 29 May 2006 23:54:53 +0000 Subject: r15943: Update misleading DEBUG statements and comments that refer to open_file_shared. (This used to be commit 784126edff942d1c2f79f7c9feb59980426f331e) --- source3/smbd/open.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 3d537b2f39..f1d1b776dd 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -245,7 +245,7 @@ static BOOL open_file(files_struct *fsp, /* * We can't actually truncate here as the file may be locked. - * open_file_shared will take care of the truncate later. JRA. + * open_file_ntcreate will take care of the truncate later. JRA. */ local_flags &= ~O_TRUNC; @@ -1742,7 +1742,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, if (ret == -1 && errno == ENOSYS) { errno = saved_errno; /* Ignore ENOSYS */ } else { - DEBUG(5, ("open_file_shared: reset " + DEBUG(5, ("open_file_ntcreate: reset " "attributes of file %s to 0%o\n", fname, (unsigned int)new_unx_mode)); ret = 0; /* Don't do the fchmod below. */ @@ -1751,7 +1751,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, if ((ret == -1) && (SMB_VFS_FCHMOD(fsp, fsp->fh->fd, new_unx_mode) == -1)) - DEBUG(5, ("open_file_shared: failed to reset " + DEBUG(5, ("open_file_ntcreate: failed to reset " "attributes of file %s to 0%o\n", fname, (unsigned int)new_unx_mode)); } -- cgit From 41f139c0bbe02ac4abe15d1e540fe9bff8cff5a5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 30 May 2006 05:08:15 +0000 Subject: r15949: Patch for bug #3308 to stop us returning duplicate mid replies on path based set-eof trans2 calls. Needs modification for HEAD (as in head open_file_ntcreateX properly returns NTSTATUS - I'll fix this tomorrow my time). Secondly it still fails the Samba4 RAW-OPLOCK smbtorture because of an interesting case. Our oplock code always returns "break to level 2" if it can. In this case (path-based set-eof or set-allocation size on an exclusive oplocked file) W2K3 always sends a break-to-none. We send the break to none (from level2) after we've done the write for eof or allocation size. I need to work out some way of telling our break code to always break to none (might need to extend the message field). Jeremy. (This used to be commit ad9895c654f400e242adcd4099f7cd004521ee92) --- source3/smbd/open.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index f1d1b776dd..5b615f01e2 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -599,7 +599,7 @@ static BOOL is_delete_request(files_struct *fsp) { } /* - * 1) No files open at all: Grant whatever the client wants. + * 1) No files open at all or internal open: Grant whatever the client wants. * * 2) Exclusive (or batch) oplock around: If the requested access is a delete * request, break if the oplock around is a batch oplock. If it's another @@ -608,7 +608,10 @@ static BOOL is_delete_request(files_struct *fsp) { * 3) Only level2 around: Grant level2 and do nothing else. */ -static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp, int pass_number) +static BOOL delay_for_oplocks(struct share_mode_lock *lck, + files_struct *fsp, + int pass_number, + BOOL internal_only_open) { int i; struct share_mode_entry *exclusive = NULL; @@ -616,7 +619,7 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp, in BOOL delay_it = False; BOOL have_level2 = False; - if (is_stat_open(fsp->access_mask)) { + if (internal_only_open || is_stat_open(fsp->access_mask)) { fsp->oplock_type = NO_OPLOCK; return False; } @@ -1367,7 +1370,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, } /* First pass - send break only on batch oplocks. */ - if (delay_for_oplocks(lck, fsp, 1)) { + if (delay_for_oplocks(lck, fsp, 1, internal_only_open)) { schedule_defer_open(lck, request_time); TALLOC_FREE(lck); return NULL; @@ -1380,7 +1383,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, if (NT_STATUS_IS_OK(status)) { /* We might be going to allow this open. Check oplock status again. */ /* Second pass - send break for both batch or exclusive oplocks. */ - if (delay_for_oplocks(lck, fsp, 2)) { + if (delay_for_oplocks(lck, fsp, 2, internal_only_open)) { schedule_defer_open(lck, request_time); TALLOC_FREE(lck); return NULL; -- cgit From 7361c7a883646dd065eabf81e0b1dc60cc9d1f39 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 30 May 2006 18:17:37 +0000 Subject: r15958: Make us pass RAW-OPLOCK with kernel oplocks off. This allows a requestor to set FORCE_OPLOCK_BREAK_TO_NONE to ensure we don't break to level 2. Fixed a couple of resource leaks in error paths in open_file_ntcreatex. Jeremy. (This used to be commit c7c9adcce7f13d01445f31b07fb28a76f0a1d6df) --- source3/smbd/open.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 5b615f01e2..042d41453e 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -611,7 +611,7 @@ static BOOL is_delete_request(files_struct *fsp) { static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp, int pass_number, - BOOL internal_only_open) + int oplock_request) { int i; struct share_mode_entry *exclusive = NULL; @@ -619,7 +619,7 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, BOOL delay_it = False; BOOL have_level2 = False; - if (internal_only_open || is_stat_open(fsp->access_mask)) { + if ((oplock_request & INTERNAL_OPEN_ONLY) || is_stat_open(fsp->access_mask)) { fsp->oplock_type = NO_OPLOCK; return False; } @@ -686,8 +686,16 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, procid_str_static(&exclusive->pid))); exclusive->op_mid = get_current_mid(); + /* Create the message. */ share_mode_entry_to_message(msg, exclusive); + /* Add in the FORCE_OPLOCK_BREAK_TO_NONE bit in the message if set. We don't + want this set in the share mode struct pointed to by lck. */ + + if (oplock_request & FORCE_OPLOCK_BREAK_TO_NONE) { + SSVAL(msg,6,exclusive->op_type | FORCE_OPLOCK_BREAK_TO_NONE); + } + become_root(); ret = message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST, msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); @@ -1090,7 +1098,6 @@ files_struct *open_file_ntcreate(connection_struct *conn, int flags2=0; BOOL file_existed = VALID_STAT(*psbuf); BOOL def_acl = False; - BOOL internal_only_open = False; SMB_DEV_T dev = 0; SMB_INO_T inode = 0; BOOL fsp_open = False; @@ -1133,11 +1140,6 @@ files_struct *open_file_ntcreate(connection_struct *conn, create_disposition, create_options, unx_mode, oplock_request)); - if (oplock_request == INTERNAL_OPEN_ONLY) { - internal_only_open = True; - oplock_request = 0; - } - if ((pml = get_open_deferred_message(mid)) != NULL) { struct deferred_open_record *state = (struct deferred_open_record *)pml->private_data.data; @@ -1174,7 +1176,8 @@ files_struct *open_file_ntcreate(connection_struct *conn, /* ignore any oplock requests if oplocks are disabled */ if (!lp_oplocks(SNUM(conn)) || global_client_failed_oplock_break || IS_VETO_OPLOCK_PATH(conn, fname)) { - oplock_request = 0; + /* Mask off everything except the private Samba bits. */ + oplock_request &= SAMBA_PRIVATE_OPLOCK_MASK; } /* this is for OS/2 long file names - say we don't support them */ @@ -1349,7 +1352,8 @@ files_struct *open_file_ntcreate(connection_struct *conn, fsp->share_access = share_access; fsp->fh->private_options = create_options; fsp->access_mask = access_mask; - fsp->oplock_type = oplock_request; + /* Ensure no SAMBA_PRIVATE bits can be set. */ + fsp->oplock_type = (oplock_request & ~SAMBA_PRIVATE_OPLOCK_MASK); if (timeval_is_zero(&request_time)) { request_time = fsp->open_time; @@ -1364,15 +1368,17 @@ files_struct *open_file_ntcreate(connection_struct *conn, fname); if (lck == NULL) { + file_free_fsp(fsp); DEBUG(0, ("Could not get share mode lock\n")); set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION); return NULL; } /* First pass - send break only on batch oplocks. */ - if (delay_for_oplocks(lck, fsp, 1, internal_only_open)) { + if (delay_for_oplocks(lck, fsp, 1, oplock_request)) { schedule_defer_open(lck, request_time); TALLOC_FREE(lck); + file_free_fsp(fsp); return NULL; } @@ -1383,9 +1389,10 @@ files_struct *open_file_ntcreate(connection_struct *conn, if (NT_STATUS_IS_OK(status)) { /* We might be going to allow this open. Check oplock status again. */ /* Second pass - send break for both batch or exclusive oplocks. */ - if (delay_for_oplocks(lck, fsp, 2, internal_only_open)) { + if (delay_for_oplocks(lck, fsp, 2, oplock_request)) { schedule_defer_open(lck, request_time); TALLOC_FREE(lck); + file_free_fsp(fsp); return NULL; } } @@ -1459,7 +1466,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, * cope with the braindead 1 second delay. */ - if (!internal_only_open && + if (!(oplock_request & INTERNAL_OPEN_ONLY) && lp_defer_sharing_violations()) { struct timeval timeout; struct deferred_open_record state; -- cgit From b990e788665ec2491056f3df66156aa7c51bdb1d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 30 May 2006 18:26:49 +0000 Subject: r15959: Ooops. Use the right file_free call... Jeremy. (This used to be commit 1117a327bd4fb425d25ea63df782095701fb83bb) --- source3/smbd/open.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 042d41453e..1331863bdf 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1368,7 +1368,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, fname); if (lck == NULL) { - file_free_fsp(fsp); + file_free(fsp); DEBUG(0, ("Could not get share mode lock\n")); set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION); return NULL; @@ -1378,7 +1378,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, if (delay_for_oplocks(lck, fsp, 1, oplock_request)) { schedule_defer_open(lck, request_time); TALLOC_FREE(lck); - file_free_fsp(fsp); + file_free(fsp); return NULL; } @@ -1392,7 +1392,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, if (delay_for_oplocks(lck, fsp, 2, oplock_request)) { schedule_defer_open(lck, request_time); TALLOC_FREE(lck); - file_free_fsp(fsp); + file_free(fsp); return NULL; } } -- cgit From 73cc5f1e259fac9656df6a030a91b5005cba1da4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 30 May 2006 18:38:10 +0000 Subject: r15960: Don't double-free (ensure we always free file_fsp in the same place on error - I missed the extra free in delay_for_oplocks). Jeremy. (This used to be commit 146a2648156563b41642d42c46aff401e435a42b) --- source3/smbd/open.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 1331863bdf..633e70ac31 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -703,7 +703,6 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, if (!ret) { DEBUG(3, ("Could not send oplock break message\n")); } - file_free(fsp); } return delay_it; -- cgit From 4d1688bf6bac74df93eb4c3e8f540f541a25390d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 13 Jun 2006 18:06:12 +0000 Subject: r16198: Fix Klocwork 1023 (This used to be commit 3a7d01afbebe5c4c36935b6128998e1327c8f856) --- source3/smbd/open.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 633e70ac31..821feffd65 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1905,7 +1905,6 @@ files_struct *open_directory(connection_struct *conn, DEBUG(5,("open_directory: invalid create_disposition " "0x%x for directory %s\n", (unsigned int)create_disposition, fname)); - file_free(fsp); set_saved_ntstatus(NT_STATUS_INVALID_PARAMETER); return NULL; } -- cgit From b32d2ecf9ce39140c726d4fe96f658e50d0665c9 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 14 Jun 2006 12:00:53 +0000 Subject: r16219: BUG 3836, 3837, 3004: compile warning fixes from Jason Mader. (This used to be commit 6c1f1c091f5e87bf9464fe8ad7eb2cb683819a62) --- source3/smbd/open.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 821feffd65..2e4091d937 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1107,7 +1107,6 @@ files_struct *open_file_ntcreate(connection_struct *conn, uint32 existing_dos_attributes = 0; struct pending_message_list *pml = NULL; uint16 mid = get_current_mid(); - BOOL delayed_for_oplocks = False; struct timeval request_time = timeval_zero(); struct share_mode_lock *lck = NULL; NTSTATUS status; @@ -1148,7 +1147,6 @@ files_struct *open_file_ntcreate(connection_struct *conn, see if this has timed out. */ request_time = pml->request_time; - delayed_for_oplocks = state->delayed_for_oplocks; /* Remove the deferred open entry under lock. */ lck = get_share_mode_lock(NULL, state->dev, state->inode, NULL, NULL); -- cgit From 54ea3c23e3bfd25008198e85fdcc1f48b0325eab Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 21 Jun 2006 02:31:12 +0000 Subject: r16435: Add in the uid info that Jerry needs into the share_mode struct. Allows us to know the unix uid of the opener of the file/directory. Needed for info level queries on open files. Jeremy. (This used to be commit d929323d6f513902381369d77bcd7b714346d713) --- source3/smbd/open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 2e4091d937..832a8df755 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1685,7 +1685,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, fsp->oplock_type = NO_OPLOCK; } } - set_share_mode(lck, fsp, 0, fsp->oplock_type); + set_share_mode(lck, fsp, current_user.ut.uid, 0, fsp->oplock_type); if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || info == FILE_WAS_SUPERSEDED) { @@ -1991,7 +1991,7 @@ files_struct *open_directory(connection_struct *conn, return NULL; } - set_share_mode(lck, fsp, 0, NO_OPLOCK); + set_share_mode(lck, fsp, current_user.ut.uid, 0, NO_OPLOCK); /* For directories the delete on close bit at open time seems always to be honored on close... See test 19 in Samba4 BASE-DELETE. */ -- cgit From fbdcf2663b56007a438ac4f0d8d82436b1bfe688 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Jul 2006 18:01:26 +0000 Subject: r16945: Sync trunk -> 3.0 for 3.0.24 code. Still need to do the upper layer directories but this is what everyone is waiting for.... Jeremy. (This used to be commit 9dafb7f48ca3e7af956b0a7d1720c2546fc4cfb8) --- source3/smbd/open.c | 229 +++++++++++++++++++++++++++------------------------- 1 file changed, 117 insertions(+), 112 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 832a8df755..7c04cdbe7c 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -38,24 +38,29 @@ struct deferred_open_record { fd support routines - attempt to do a dos_open. ****************************************************************************/ -static int fd_open(struct connection_struct *conn, +static BOOL fd_open(struct connection_struct *conn, const char *fname, + files_struct *fsp, int flags, mode_t mode) { - int fd; + int sav; + #ifdef O_NOFOLLOW if (!lp_symlinks(SNUM(conn))) { flags |= O_NOFOLLOW; } #endif - fd = SMB_VFS_OPEN(conn,fname,flags,mode); + fsp->fh->fd = SMB_VFS_OPEN(conn,fname,fsp,flags,mode); + sav = errno; - DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n", fname, - flags, (int)mode, fd, (fd == -1) ? strerror(errno) : "" )); + DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n", + fname, flags, (int)mode, fsp->fh->fd, + (fsp->fh->fd == -1) ? strerror(errno) : "" )); - return fd; + errno = sav; + return fsp->fh->fd != -1; } /**************************************************************************** @@ -179,7 +184,7 @@ void change_owner_to_parent(connection_struct *conn, Open a file. ****************************************************************************/ -static BOOL open_file(files_struct *fsp, +static NTSTATUS open_file(files_struct *fsp, connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, @@ -210,7 +215,7 @@ static BOOL open_file(files_struct *fsp, /* It's a read-only share - fail if we wanted to write. */ if(accmode != O_RDONLY) { DEBUG(3,("Permission denied opening %s\n",fname)); - return False; + return NT_STATUS_ACCESS_DENIED; } 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 @@ -265,17 +270,15 @@ static BOOL open_file(files_struct *fsp, /* Don't create files with Microsoft wildcard characters. */ if ((local_flags & O_CREAT) && !file_existed && ms_has_wild(fname)) { - set_saved_ntstatus(NT_STATUS_OBJECT_NAME_INVALID); - return False; + return NT_STATUS_OBJECT_NAME_INVALID; } /* Actually do the open */ - fsp->fh->fd = fd_open(conn, fname, local_flags, unx_mode); - if (fsp->fh->fd == -1) { + if (!fd_open(conn, fname, fsp, local_flags, unx_mode)) { DEBUG(3,("Error opening file %s (%s) (local_flags=%d) " "(flags=%d)\n", fname,strerror(errno),local_flags,flags)); - return False; + return map_nt_error_from_unix(errno); } /* Inherit the ACL if the file was created. */ @@ -303,8 +306,9 @@ static BOOL open_file(files_struct *fsp, /* For a non-io open, this stat failing means file not found. JRA */ if (ret == -1) { + NTSTATUS status = map_nt_error_from_unix(errno); fd_close(conn, fsp); - return False; + return status; } } @@ -317,7 +321,7 @@ static BOOL open_file(files_struct *fsp, if(S_ISDIR(psbuf->st_mode)) { fd_close(conn, fsp); errno = EISDIR; - return False; + return NT_STATUS_FILE_IS_A_DIRECTORY; } fsp->mode = psbuf->st_mode; @@ -351,7 +355,7 @@ static BOOL open_file(files_struct *fsp, conn->num_files_open + 1)); errno = 0; - return True; + return NT_STATUS_OK; } /******************************************************************* @@ -894,8 +898,8 @@ static files_struct *fcb_or_dos_open(connection_struct *conn, } /* We need to duplicate this fsp. */ - dup_fsp = dup_file_fsp(fsp, access_mask, share_access, create_options); - if (!dup_fsp) { + if (!NT_STATUS_IS_OK(dup_file_fsp(fsp, access_mask, share_access, + create_options, &dup_fsp))) { return NULL; } @@ -1081,7 +1085,7 @@ static void schedule_defer_open(struct share_mode_lock *lck, struct timeval requ Open a file with a share mode. ****************************************************************************/ -files_struct *open_file_ntcreate(connection_struct *conn, +NTSTATUS open_file_ntcreate(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask, /* access bits (FILE_READ_DATA etc.) */ @@ -1091,7 +1095,8 @@ files_struct *open_file_ntcreate(connection_struct *conn, uint32 new_dos_attributes, /* attributes used for new file. */ int oplock_request, /* internal Samba oplock codes. */ /* Information (FILE_EXISTS etc.) */ - int *pinfo) + int *pinfo, + files_struct **result) { int flags=0; int flags2=0; @@ -1099,7 +1104,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, BOOL def_acl = False; SMB_DEV_T dev = 0; SMB_INO_T inode = 0; - BOOL fsp_open = False; + NTSTATUS fsp_open = NT_STATUS_ACCESS_DENIED; files_struct *fsp = NULL; mode_t new_unx_mode = (mode_t)0; mode_t unx_mode = (mode_t)0; @@ -1123,7 +1128,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, DEBUG(10, ("open_file_ntcreate: printer open fname=%s\n", fname)); - return print_fsp_open(conn, fname); + return print_fsp_open(conn, fname, &fsp); } /* We add aARCH to this as this mode is only used if the file is @@ -1162,7 +1167,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, } if (!check_name(fname,conn)) { - return NULL; + return map_nt_error_from_unix(errno); } new_dos_attributes &= SAMBA_ATTRIBUTES_MASK; @@ -1181,11 +1186,12 @@ files_struct *open_file_ntcreate(connection_struct *conn, if (!lp_posix_pathnames() && strstr(fname,".+,;=[].")) { /* OS/2 Workplace shell fix may be main code stream in a later * release. */ - set_saved_error_triple(ERRDOS, ERRcannotopen, - NT_STATUS_OBJECT_NAME_NOT_FOUND); DEBUG(5,("open_file_ntcreate: OS/2 long filenames are not " "supported.\n")); - return NULL; + if (use_nt_status()) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + return NT_STATUS_DOS(ERRDOS, ERRcannotopen); } switch( create_disposition ) { @@ -1213,9 +1219,8 @@ files_struct *open_file_ntcreate(connection_struct *conn, DEBUG(5,("open_file_ntcreate: FILE_OPEN " "requested for file %s and file " "doesn't exist.\n", fname )); - set_saved_ntstatus(NT_STATUS_OBJECT_NAME_NOT_FOUND); errno = ENOENT; - return NULL; + return NT_STATUS_OBJECT_NAME_NOT_FOUND; } break; @@ -1226,9 +1231,8 @@ files_struct *open_file_ntcreate(connection_struct *conn, DEBUG(5,("open_file_ntcreate: FILE_OVERWRITE " "requested for file %s and file " "doesn't exist.\n", fname )); - set_saved_ntstatus(NT_STATUS_OBJECT_NAME_NOT_FOUND); errno = ENOENT; - return NULL; + return NT_STATUS_OBJECT_NAME_NOT_FOUND; } flags2 |= O_TRUNC; break; @@ -1245,7 +1249,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, } else { errno = EEXIST; } - return NULL; + return map_nt_error_from_unix(errno); } flags2 |= (O_CREAT|O_EXCL); break; @@ -1257,8 +1261,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, break; default: - set_saved_ntstatus(NT_STATUS_INVALID_PARAMETER); - return NULL; + return NT_STATUS_INVALID_PARAMETER; } /* We only care about matching attributes on file exists and @@ -1277,7 +1280,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, (unsigned int)psbuf->st_mode, (unsigned int)unx_mode )); errno = EACCES; - return NULL; + return NT_STATUS_ACCESS_DENIED; } } @@ -1334,14 +1337,13 @@ files_struct *open_file_ntcreate(connection_struct *conn, DEBUG(5,("open_file_ntcreate: write access requested for " "file %s on read only %s\n", fname, !CAN_WRITE(conn) ? "share" : "file" )); - set_saved_ntstatus(NT_STATUS_ACCESS_DENIED); errno = EACCES; - return NULL; + return NT_STATUS_ACCESS_DENIED; } - fsp = file_new(conn); - if(!fsp) { - return NULL; + status = file_new(conn, &fsp); + if(!NT_STATUS_IS_OK(status)) { + return status; } fsp->dev = psbuf->st_dev; @@ -1367,8 +1369,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, if (lck == NULL) { file_free(fsp); DEBUG(0, ("Could not get share mode lock\n")); - set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION); - return NULL; + return NT_STATUS_SHARING_VIOLATION; } /* First pass - send break only on batch oplocks. */ @@ -1376,7 +1377,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, schedule_defer_open(lck, request_time); TALLOC_FREE(lck); file_free(fsp); - return NULL; + return NT_STATUS_SHARING_VIOLATION; } status = open_mode_check(conn, fname, lck, @@ -1390,16 +1391,15 @@ files_struct *open_file_ntcreate(connection_struct *conn, schedule_defer_open(lck, request_time); TALLOC_FREE(lck); file_free(fsp); - return NULL; + return NT_STATUS_SHARING_VIOLATION; } } if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) { /* DELETE_PENDING is not deferred for a second */ - set_saved_ntstatus(status); TALLOC_FREE(lck); file_free(fsp); - return NULL; + return status; } if (!NT_STATUS_IS_OK(status)) { @@ -1424,7 +1424,8 @@ files_struct *open_file_ntcreate(connection_struct *conn, *pinfo = FILE_WAS_OPENED; } conn->num_files_open++; - return fsp_dup; + *result = fsp_dup; + return NT_STATUS_OK; } } @@ -1449,13 +1450,13 @@ files_struct *open_file_ntcreate(connection_struct *conn, DEBUG(4,("open_file_ntcreate : share_mode deny - " "calling open_file with flags=0x%X " - "flags2=0x%X mode=0%o returned %d\n", + "flags2=0x%X mode=0%o returned %s\n", flags, (flags2&~(O_TRUNC|O_CREAT)), - (unsigned int)unx_mode, (int)fsp_open )); + (unsigned int)unx_mode, nt_errstr(fsp_open))); - if (!fsp_open && errno) { + if (!NT_STATUS_IS_OK(fsp_open) && errno) { /* Default error. */ - set_saved_ntstatus(NT_STATUS_ACCESS_DENIED); + status = NT_STATUS_ACCESS_DENIED; } /* @@ -1471,7 +1472,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, /* this is a hack to speed up torture tests in 'make test' */ - timeout_usecs = lp_parm_int(conn->service, + timeout_usecs = lp_parm_int(SNUM(conn), "smbd","sharedelay", SHARING_VIOLATION_USEC_WAIT); @@ -1502,16 +1503,16 @@ files_struct *open_file_ntcreate(connection_struct *conn, } TALLOC_FREE(lck); - if (fsp_open) { + if (NT_STATUS_IS_OK(fsp_open)) { fd_close(conn, fsp); /* * We have detected a sharing violation here * so return the correct error code */ - set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION); + status = NT_STATUS_SHARING_VIOLATION; } file_free(fsp); - return NULL; + return status; } /* @@ -1542,12 +1543,12 @@ files_struct *open_file_ntcreate(connection_struct *conn, fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode, access_mask); - if (!fsp_open) { + if (!NT_STATUS_IS_OK(fsp_open)) { if (lck != NULL) { TALLOC_FREE(lck); } file_free(fsp); - return NULL; + return fsp_open; } if (!file_existed) { @@ -1578,8 +1579,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, DEBUG(0, ("open_file_ntcreate: Could not get share mode lock for %s\n", fname)); fd_close(conn, fsp); file_free(fsp); - set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION); - return NULL; + return NT_STATUS_SHARING_VIOLATION; } status = open_mode_check(conn, fname, lck, @@ -1606,7 +1606,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, defer_open(lck, request_time, timeval_zero(), &state); TALLOC_FREE(lck); - return NULL; + return status; } /* @@ -1642,10 +1642,11 @@ files_struct *open_file_ntcreate(connection_struct *conn, */ if ((SMB_VFS_FTRUNCATE(fsp,fsp->fh->fd,0) == -1) || (SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf)==-1)) { + status = map_nt_error_from_unix(errno); TALLOC_FREE(lck); fd_close(conn,fsp); file_free(fsp); - return NULL; + return status; } } @@ -1692,16 +1693,15 @@ files_struct *open_file_ntcreate(connection_struct *conn, /* Handle strange delete on close create semantics. */ if (create_options & FILE_DELETE_ON_CLOSE) { - NTSTATUS result = can_set_delete_on_close(fsp, True, new_dos_attributes); + status = can_set_delete_on_close(fsp, True, new_dos_attributes); - if (!NT_STATUS_IS_OK(result)) { + if (!NT_STATUS_IS_OK(status)) { /* Remember to delete the mode we just added. */ del_share_mode(lck, fsp); TALLOC_FREE(lck); fd_close(conn,fsp); file_free(fsp); - set_saved_ntstatus(result); - return NULL; + return status; } /* Note that here we set the *inital* delete on close flag, not the regular one. */ @@ -1770,31 +1770,32 @@ files_struct *open_file_ntcreate(connection_struct *conn, conn->num_files_open++; - return fsp; + *result = fsp; + return NT_STATUS_OK; } /**************************************************************************** Open a file for for write to ensure that we can fchmod it. ****************************************************************************/ -files_struct *open_file_fchmod(connection_struct *conn, const char *fname, - SMB_STRUCT_STAT *psbuf) +NTSTATUS open_file_fchmod(connection_struct *conn, const char *fname, + SMB_STRUCT_STAT *psbuf, files_struct **result) { files_struct *fsp = NULL; - BOOL fsp_open; + NTSTATUS status; if (!VALID_STAT(*psbuf)) { - return NULL; + return NT_STATUS_INVALID_PARAMETER; } - fsp = file_new(conn); - if(!fsp) { - return NULL; + status = file_new(conn, &fsp); + if(!NT_STATUS_IS_OK(status)) { + return status; } /* note! we must use a non-zero desired access or we don't get a real file descriptor. Oh what a twisted web we weave. */ - fsp_open = open_file(fsp,conn,fname,psbuf,O_WRONLY,0,FILE_WRITE_DATA); + status = open_file(fsp,conn,fname,psbuf,O_WRONLY,0,FILE_WRITE_DATA); /* * This is not a user visible file open. @@ -1802,12 +1803,13 @@ files_struct *open_file_fchmod(connection_struct *conn, const char *fname, * the conn->num_files_open. */ - if (!fsp_open) { + if (!NT_STATUS_IS_OK(status)) { file_free(fsp); - return NULL; + return status; } - return fsp; + *result = fsp; + return NT_STATUS_OK; } /**************************************************************************** @@ -1825,14 +1827,15 @@ int close_file_fchmod(files_struct *fsp) Open a directory from an NT SMB call. ****************************************************************************/ -files_struct *open_directory(connection_struct *conn, +NTSTATUS open_directory(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask, uint32 share_access, uint32 create_disposition, uint32 create_options, - int *pinfo) + int *pinfo, + files_struct **result) { files_struct *fsp = NULL; BOOL dir_existed = VALID_STAT(*psbuf) ? True : False; @@ -1852,8 +1855,7 @@ files_struct *open_directory(connection_struct *conn, if (is_ntfs_stream_name(fname)) { DEBUG(0,("open_directory: %s is a stream name!\n", fname )); - set_saved_ntstatus(NT_STATUS_NOT_A_DIRECTORY); - return NULL; + return NT_STATUS_NOT_A_DIRECTORY; } switch( create_disposition ) { @@ -1864,8 +1866,7 @@ files_struct *open_directory(connection_struct *conn, DEBUG(5,("open_directory: FILE_OPEN requested " "for directory %s and it doesn't " "exist.\n", fname )); - set_saved_ntstatus(NT_STATUS_OBJECT_NAME_NOT_FOUND); - return NULL; + return NT_STATUS_OBJECT_NAME_NOT_FOUND; } info = FILE_WAS_OPENED; break; @@ -1877,9 +1878,12 @@ files_struct *open_directory(connection_struct *conn, DEBUG(5,("open_directory: FILE_CREATE " "requested for directory %s and it " "already exists.\n", fname )); - set_saved_error_triple(ERRDOS, ERRfilexists, - NT_STATUS_OBJECT_NAME_COLLISION); - return NULL; + if (use_nt_status()) { + return NT_STATUS_OBJECT_NAME_COLLISION; + } else { + return NT_STATUS_DOS(ERRDOS, + ERRfilexists); + } } create_dir = True; info = FILE_WAS_CREATED; @@ -1903,8 +1907,7 @@ files_struct *open_directory(connection_struct *conn, DEBUG(5,("open_directory: invalid create_disposition " "0x%x for directory %s\n", (unsigned int)create_disposition, fname)); - set_saved_ntstatus(NT_STATUS_INVALID_PARAMETER); - return NULL; + return NT_STATUS_INVALID_PARAMETER; } if (create_dir) { @@ -1921,27 +1924,26 @@ files_struct *open_directory(connection_struct *conn, "Error was %s\n", fname, strerror(errno) )); /* Ensure we return the correct NT status to the * client. */ - set_saved_error_triple(0, 0, status); - return NULL; + return status; } /* Ensure we're checking for a symlink here.... */ /* We don't want to get caught by a symlink racer. */ if(SMB_VFS_LSTAT(conn,fname, psbuf) != 0) { - return NULL; + return map_nt_error_from_unix(errno); } if(!S_ISDIR(psbuf->st_mode)) { DEBUG(0,("open_directory: %s is not a directory !\n", fname )); - return NULL; + return NT_STATUS_NOT_A_DIRECTORY; } } - fsp = file_new(conn); - if(!fsp) { - return NULL; + status = file_new(conn, &fsp); + if(!NT_STATUS_IS_OK(status)) { + return status; } /* @@ -1953,7 +1955,7 @@ files_struct *open_directory(connection_struct *conn, fsp->dev = psbuf->st_dev; fsp->vuid = current_user.vuid; fsp->file_pid = global_smbpid; - fsp->can_lock = True; + fsp->can_lock = False; fsp->can_read = False; fsp->can_write = False; @@ -1976,8 +1978,7 @@ files_struct *open_directory(connection_struct *conn, if (lck == NULL) { DEBUG(0, ("open_directory: Could not get share mode lock for %s\n", fname)); file_free(fsp); - set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION); - return NULL; + return NT_STATUS_SHARING_VIOLATION; } status = open_mode_check(conn, fname, lck, @@ -1985,10 +1986,9 @@ files_struct *open_directory(connection_struct *conn, create_options, &dir_existed); if (!NT_STATUS_IS_OK(status)) { - set_saved_ntstatus(status); TALLOC_FREE(lck); file_free(fsp); - return NULL; + return status; } set_share_mode(lck, fsp, current_user.ut.uid, 0, NO_OPLOCK); @@ -1998,10 +1998,9 @@ files_struct *open_directory(connection_struct *conn, if (create_options & FILE_DELETE_ON_CLOSE) { status = can_set_delete_on_close(fsp, True, 0); if (!NT_STATUS_IS_OK(status)) { - set_saved_ntstatus(status); TALLOC_FREE(lck); file_free(fsp); - return NULL; + return status; } set_delete_on_close_token(lck, ¤t_user.ut); @@ -2022,28 +2021,33 @@ files_struct *open_directory(connection_struct *conn, conn->num_files_open++; - return fsp; + *result = fsp; + return NT_STATUS_OK; } /**************************************************************************** Open a pseudo-file (no locking checks - a 'stat' open). ****************************************************************************/ -files_struct *open_file_stat(connection_struct *conn, char *fname, - SMB_STRUCT_STAT *psbuf) +NTSTATUS open_file_stat(connection_struct *conn, char *fname, + SMB_STRUCT_STAT *psbuf, files_struct **result) { files_struct *fsp = NULL; + NTSTATUS status; - if (!VALID_STAT(*psbuf)) - return NULL; + if (!VALID_STAT(*psbuf)) { + return NT_STATUS_INVALID_PARAMETER; + } /* Can't 'stat' open directories. */ - if(S_ISDIR(psbuf->st_mode)) - return NULL; + if(S_ISDIR(psbuf->st_mode)) { + return NT_STATUS_FILE_IS_A_DIRECTORY; + } - fsp = file_new(conn); - if(!fsp) - return NULL; + status = file_new(conn, &fsp); + if(!NT_STATUS_IS_OK(status)) { + return status; + } DEBUG(5,("open_file_stat: 'opening' file %s\n", fname)); @@ -2069,7 +2073,8 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, conn->num_files_open++; - return fsp; + *result = fsp; + return NT_STATUS_OK; } /**************************************************************************** -- cgit From 0e292222c30c269c17e68acf1bbef787c1e946ed Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 19 Jul 2006 00:13:28 +0000 Subject: r17125: Drastic problems require drastic solutions. There's no way to get all the cases where kernel oplocks are on and we can't open the file and get the correct semantics (think about the open with truncate with an attribute only open - we'd need a vfs change to add the truncate(fname, len) call). So always drop the share mode lock before doing any real fd opens and then re-acquire it afterwards. We're already dealing with the race in the create case, and we deal with any other races in the same way. Volker, please examine *carefully* :-). This should fix the problems people reported with kernel oplocks being on. Jeremy. (This used to be commit 8171c4c404e9f382880c65daa0232f89e560f399) --- source3/smbd/open.c | 149 +++++++++++++++++++++++++--------------------------- 1 file changed, 73 insertions(+), 76 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 7c04cdbe7c..b13b4f2a6c 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1403,6 +1403,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } if (!NT_STATUS_IS_OK(status)) { + uint32 can_access_mask; + BOOL can_access = True; SMB_ASSERT(NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)); @@ -1434,29 +1436,20 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, * 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. + * share error. We can't open the file due to kernel + * oplock deadlock (it's possible we failed above on + * the open_mode_check()) so use a userspace check. */ - errno = 0; - fsp_open = open_file(fsp,conn,fname,psbuf, - flags|(flags2&~(O_TRUNC|O_CREAT)), - unx_mode,access_mask); - - DEBUG(4,("open_file_ntcreate : share_mode deny - " - "calling open_file with flags=0x%X " - "flags2=0x%X mode=0%o returned %s\n", - flags, (flags2&~(O_TRUNC|O_CREAT)), - (unsigned int)unx_mode, nt_errstr(fsp_open))); - - if (!NT_STATUS_IS_OK(fsp_open) && errno) { - /* Default error. */ - status = NT_STATUS_ACCESS_DENIED; + + if (flags & O_RDWR) { + can_access_mask = FILE_READ_DATA|FILE_WRITE_DATA; + } else { + can_access_mask = FILE_READ_DATA; + } + + if (((flags & O_RDWR) && !CAN_WRITE(conn)) || + !can_access_file(conn,fname,psbuf,can_access_mask)) { + can_access = False; } /* @@ -1503,13 +1496,14 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } TALLOC_FREE(lck); - if (NT_STATUS_IS_OK(fsp_open)) { - fd_close(conn, fsp); + if (can_access) { /* * We have detected a sharing violation here * so return the correct error code */ status = NT_STATUS_SHARING_VIOLATION; + } else { + status = NT_STATUS_ACCESS_DENIED; } file_free(fsp); return status; @@ -1536,6 +1530,14 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, (unsigned int)flags, (unsigned int)flags2, (unsigned int)unx_mode)); + /* Drop the lock before doing any real file access. Allows kernel + oplock breaks to be processed. Handle any races after the open + call when we re-acquire the lock. */ + + if (lck) { + TALLOC_FREE(lck); + } + /* * open_file strips any O_TRUNC flags itself. */ @@ -1551,70 +1553,65 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return fsp_open; } - if (!file_existed) { - - /* - * 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 set a share mode, the other (ie. this - * one) should check if the requested share mode for this - * create is allowed. - */ - - /* - * Now the file exists and fsp is successfully opened, - * fsp->dev and fsp->inode are valid and should replace the - * dev=0,inode=0 from a non existent file. Spotted by - * Nadav Danieli . JRA. - */ + /* + * 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 set a share mode, the other (ie. this + * one) should check if the requested share mode for this + * create is allowed. + */ - dev = fsp->dev; - inode = fsp->inode; + /* + * Now the file exists and fsp is successfully opened, + * fsp->dev and fsp->inode are valid and should replace the + * dev=0,inode=0 from a non existent file. Spotted by + * Nadav Danieli . JRA. + */ - lck = get_share_mode_lock(NULL, dev, inode, - conn->connectpath, - fname); + dev = fsp->dev; + inode = fsp->inode; - if (lck == NULL) { - DEBUG(0, ("open_file_ntcreate: Could not get share mode lock for %s\n", fname)); - fd_close(conn, fsp); - file_free(fsp); - return NT_STATUS_SHARING_VIOLATION; - } + lck = get_share_mode_lock(NULL, dev, inode, + conn->connectpath, + fname); - status = open_mode_check(conn, fname, lck, - access_mask, share_access, - create_options, &file_existed); + if (lck == NULL) { + DEBUG(0, ("open_file_ntcreate: Could not get share mode lock for %s\n", fname)); + fd_close(conn, fsp); + file_free(fsp); + return NT_STATUS_SHARING_VIOLATION; + } - if (!NT_STATUS_IS_OK(status)) { - struct deferred_open_record state; + status = open_mode_check(conn, fname, lck, + access_mask, share_access, + create_options, &file_existed); - fd_close(conn, fsp); - file_free(fsp); + if (!NT_STATUS_IS_OK(status)) { + struct deferred_open_record state; - state.delayed_for_oplocks = False; - state.dev = dev; - state.inode = inode; + fd_close(conn, fsp); + file_free(fsp); - /* Do it all over again immediately. In the second - * round we will find that the file existed and handle - * the DELETE_PENDING and FCB cases correctly. No need - * to duplicate the code here. Essentially this is a - * "goto top of this function", but don't tell - * anybody... */ + state.delayed_for_oplocks = False; + state.dev = dev; + state.inode = inode; - defer_open(lck, request_time, timeval_zero(), - &state); - TALLOC_FREE(lck); - return status; - } + /* Do it all over again immediately. In the second + * round we will find that the file existed and handle + * the DELETE_PENDING and FCB cases correctly. No need + * to duplicate the code here. Essentially this is a + * "goto top of this function", but don't tell + * anybody... */ - /* - * We exit this block with the share entry *locked*..... - */ + defer_open(lck, request_time, timeval_zero(), + &state); + TALLOC_FREE(lck); + return status; } - SMB_ASSERT(lck != NULL); + /* + * The share entry is again *locked*..... + */ /* note that we ignore failure for the following. It is basically a hack for NFS, and NFS will never set one of -- cgit From 4815e2c3441ce2cb18aa7fcb9ae1fe97bbcabd80 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 19 Jul 2006 01:30:30 +0000 Subject: r17128: Missed a logic error in my last patch. Ensure we deal with any oplocks that were granted when we had released the lock. Fix strange case where stat open grants a batch oplock on file create, but grants no oplock on file open. Jeremy. (This used to be commit b7374835e6ec0c98fc4020623f0a37c0c173b8aa) --- source3/smbd/open.c | 47 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 5 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index b13b4f2a6c..2c259e7822 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -623,8 +623,11 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, BOOL delay_it = False; BOOL have_level2 = False; - if ((oplock_request & INTERNAL_OPEN_ONLY) || is_stat_open(fsp->access_mask)) { + if (oplock_request & INTERNAL_OPEN_ONLY) { fsp->oplock_type = NO_OPLOCK; + } + + if ((oplock_request & INTERNAL_OPEN_ONLY) || is_stat_open(fsp->access_mask)) { return False; } @@ -1582,10 +1585,43 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return NT_STATUS_SHARING_VIOLATION; } + /* + * The share entry is again *locked*..... + */ + + /* First pass - send break only on batch oplocks. */ + if (delay_for_oplocks(lck, fsp, 1, oplock_request)) { + schedule_defer_open(lck, request_time); + fd_close(conn, fsp); + file_free(fsp); + TALLOC_FREE(lck); + return NT_STATUS_SHARING_VIOLATION; + } + status = open_mode_check(conn, fname, lck, access_mask, share_access, create_options, &file_existed); + if (NT_STATUS_IS_OK(status)) { + /* We might be going to allow this open. Check oplock status again. */ + /* Second pass - send break for both batch or exclusive oplocks. */ + if (delay_for_oplocks(lck, fsp, 2, oplock_request)) { + schedule_defer_open(lck, request_time); + fd_close(conn, fsp); + file_free(fsp); + TALLOC_FREE(lck); + return NT_STATUS_SHARING_VIOLATION; + } + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) { + /* DELETE_PENDING is not deferred for a second */ + fd_close(conn, fsp); + file_free(fsp); + TALLOC_FREE(lck); + return status; + } + if (!NT_STATUS_IS_OK(status)) { struct deferred_open_record state; @@ -1609,10 +1645,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return status; } - /* - * The share entry is again *locked*..... - */ - /* 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 @@ -1653,6 +1685,11 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, fsp->access_mask = access_mask; if (file_existed) { + /* stat opens on existing files don't get oplocks. */ + if (is_stat_open(fsp->access_mask)) { + fsp->oplock_type = NO_OPLOCK; + } + if (!(flags2 & O_TRUNC)) { info = FILE_WAS_OPENED; } else { -- cgit From addc07be7ddc0b82dd2aa7dbb07dd6277d3e4dc9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 19 Jul 2006 05:26:51 +0000 Subject: r17130: Remove unneeded unlock call. Jeremy. (This used to be commit b3b5aec0eef3bdcae75ce79ffd3ecf21fb1279e7) --- source3/smbd/open.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 2c259e7822..53178956cd 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1549,9 +1549,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, access_mask); if (!NT_STATUS_IS_OK(fsp_open)) { - if (lck != NULL) { - TALLOC_FREE(lck); - } file_free(fsp); return fsp_open; } -- cgit From 48e1e45183270e2d56248c69e471bbcef816de08 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 19 Jul 2006 05:32:12 +0000 Subject: r17131: Optimisation - when doing a stat open don't open the file unless we really have to (ie. O_CREAT and file doesn't exist). Jeremy. (This used to be commit 788aa15ea24e6dfb61820465b5b881829a64297a) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 53178956cd..4033243888 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -245,7 +245,7 @@ static NTSTATUS open_file(files_struct *fsp, } if ((access_mask & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) || - (local_flags & O_CREAT) || + (!file_existed && (local_flags & O_CREAT)) || ((local_flags & O_TRUNC) == O_TRUNC) ) { /* -- cgit From dada5b4853ec7d7346e075ae0718eea9e64cb7b6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 19 Jul 2006 18:34:19 +0000 Subject: r17140: Get rid of the lock release/reacquire code ! Turns out that create dispositions that cause O_TRUNC break oplocks. This simplifies the code - although we have to keep separate the client requested access mask and the access mask we actually use to open the file. Jeremy. (This used to be commit 3bcd52a4752ec6c2a8f678afa3b7b3646103ad60) --- source3/smbd/open.c | 158 ++++++++++++++++++++++++---------------------------- 1 file changed, 73 insertions(+), 85 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 4033243888..2abd367597 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1117,6 +1117,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, uint16 mid = get_current_mid(); struct timeval request_time = timeval_zero(); struct share_mode_lock *lck = NULL; + uint32 open_access_mask = access_mask; NTSTATUS status; if (conn->printer) { @@ -1208,12 +1209,14 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, /* If file exists replace/overwrite. If file doesn't * exist create. */ flags2 |= (O_CREAT | O_TRUNC); + open_access_mask |= FILE_WRITE_DATA; /* This will cause oplock breaks. */ break; case FILE_OVERWRITE_IF: /* If file exists replace/overwrite. If file doesn't * exist create. */ flags2 |= (O_CREAT | O_TRUNC); + open_access_mask |= FILE_WRITE_DATA; /* This will cause oplock breaks. */ break; case FILE_OPEN: @@ -1238,6 +1241,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return NT_STATUS_OBJECT_NAME_NOT_FOUND; } flags2 |= O_TRUNC; + open_access_mask |= FILE_WRITE_DATA; /* This will cause oplock breaks. */ break; case FILE_CREATE: @@ -1289,7 +1293,10 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, /* This is a nasty hack - must fix... JRA. */ if (access_mask == MAXIMUM_ALLOWED_ACCESS) { - access_mask = FILE_GENERIC_ALL; + open_access_mask = access_mask = FILE_GENERIC_ALL; + if (flags2 & O_TRUNC) { + open_access_mask |= FILE_WRITE_DATA; /* This will cause oplock breaks. */ + } } /* @@ -1353,7 +1360,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, fsp->inode = psbuf->st_ino; fsp->share_access = share_access; fsp->fh->private_options = create_options; - fsp->access_mask = access_mask; + fsp->access_mask = open_access_mask; /* We change this to the requested access_mask after the open is done. */ /* Ensure no SAMBA_PRIVATE bits can be set. */ fsp->oplock_type = (oplock_request & ~SAMBA_PRIVATE_OPLOCK_MASK); @@ -1383,6 +1390,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return NT_STATUS_SHARING_VIOLATION; } + /* Use the client requested access mask here, not the one we open with. */ status = open_mode_check(conn, fname, lck, access_mask, share_access, create_options, &file_existed); @@ -1417,6 +1425,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS| NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) { files_struct *fsp_dup; + + /* Use the client requested access mask here, not the one we open with. */ fsp_dup = fcb_or_dos_open(conn, fname, dev, inode, access_mask, share_access, @@ -1533,115 +1543,93 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, (unsigned int)flags, (unsigned int)flags2, (unsigned int)unx_mode)); - /* Drop the lock before doing any real file access. Allows kernel - oplock breaks to be processed. Handle any races after the open - call when we re-acquire the lock. */ - - if (lck) { - TALLOC_FREE(lck); - } - /* * open_file strips any O_TRUNC flags itself. */ - fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode, - access_mask); + fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode, open_access_mask); if (!NT_STATUS_IS_OK(fsp_open)) { + if (lck != NULL) { + TALLOC_FREE(lck); + } file_free(fsp); return fsp_open; } - /* - * 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 set a share mode, the other (ie. this - * one) should check if the requested share mode for this - * create is allowed. - */ - - /* - * Now the file exists and fsp is successfully opened, - * fsp->dev and fsp->inode are valid and should replace the - * dev=0,inode=0 from a non existent file. Spotted by - * Nadav Danieli . JRA. - */ - - dev = fsp->dev; - inode = fsp->inode; - - lck = get_share_mode_lock(NULL, dev, inode, - conn->connectpath, - fname); + if (!file_existed) { - if (lck == NULL) { - DEBUG(0, ("open_file_ntcreate: Could not get share mode lock for %s\n", fname)); - fd_close(conn, fsp); - file_free(fsp); - return NT_STATUS_SHARING_VIOLATION; - } + /* + * 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 set a share mode, the other (ie. this + * one) should check if the requested share mode for this + * create is allowed. + */ - /* - * The share entry is again *locked*..... - */ + /* + * Now the file exists and fsp is successfully opened, + * fsp->dev and fsp->inode are valid and should replace the + * dev=0,inode=0 from a non existent file. Spotted by + * Nadav Danieli . JRA. + */ - /* First pass - send break only on batch oplocks. */ - if (delay_for_oplocks(lck, fsp, 1, oplock_request)) { - schedule_defer_open(lck, request_time); - fd_close(conn, fsp); - file_free(fsp); - TALLOC_FREE(lck); - return NT_STATUS_SHARING_VIOLATION; - } + dev = fsp->dev; + inode = fsp->inode; - status = open_mode_check(conn, fname, lck, - access_mask, share_access, - create_options, &file_existed); + lck = get_share_mode_lock(NULL, dev, inode, + conn->connectpath, + fname); - if (NT_STATUS_IS_OK(status)) { - /* We might be going to allow this open. Check oplock status again. */ - /* Second pass - send break for both batch or exclusive oplocks. */ - if (delay_for_oplocks(lck, fsp, 2, oplock_request)) { - schedule_defer_open(lck, request_time); + if (lck == NULL) { + DEBUG(0, ("open_file_ntcreate: Could not get share mode lock for %s\n", fname)); fd_close(conn, fsp); file_free(fsp); - TALLOC_FREE(lck); return NT_STATUS_SHARING_VIOLATION; } - } - if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) { - /* DELETE_PENDING is not deferred for a second */ - fd_close(conn, fsp); - file_free(fsp); - TALLOC_FREE(lck); - return status; - } + status = open_mode_check(conn, fname, lck, + access_mask, share_access, + create_options, &file_existed); - if (!NT_STATUS_IS_OK(status)) { - struct deferred_open_record state; + if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) { + /* DELETE_PENDING is not deferred for a second */ + TALLOC_FREE(lck); + file_free(fsp); + return status; + } - fd_close(conn, fsp); - file_free(fsp); + if (!NT_STATUS_IS_OK(status)) { + struct deferred_open_record state; - state.delayed_for_oplocks = False; - state.dev = dev; - state.inode = inode; + fd_close(conn, fsp); + file_free(fsp); - /* Do it all over again immediately. In the second - * round we will find that the file existed and handle - * the DELETE_PENDING and FCB cases correctly. No need - * to duplicate the code here. Essentially this is a - * "goto top of this function", but don't tell - * anybody... */ + state.delayed_for_oplocks = False; + state.dev = dev; + state.inode = inode; + + /* Do it all over again immediately. In the second + * round we will find that the file existed and handle + * the DELETE_PENDING and FCB cases correctly. No need + * to duplicate the code here. Essentially this is a + * "goto top of this function", but don't tell + * anybody... */ + + defer_open(lck, request_time, timeval_zero(), + &state); + TALLOC_FREE(lck); + return status; + } + + /* + * We exit this block with the share entry *locked*..... + */ - defer_open(lck, request_time, timeval_zero(), - &state); - TALLOC_FREE(lck); - return status; } + SMB_ASSERT(lck != NULL); + /* 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 @@ -1683,7 +1671,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if (file_existed) { /* stat opens on existing files don't get oplocks. */ - if (is_stat_open(fsp->access_mask)) { + if (is_stat_open(open_access_mask)) { fsp->oplock_type = NO_OPLOCK; } -- cgit From 201bd24ac39552fb22772a8eed69ccdba0b2c9e8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 19 Jul 2006 18:45:25 +0000 Subject: r17142: Ensure we record the correct can_read/can_write from the client requested access mask. Jeremy. (This used to be commit 12490fafc7f98952bf709c4c504f8f2b5646f197) --- source3/smbd/open.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 2abd367597..890f1ef45a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -190,7 +190,8 @@ static NTSTATUS open_file(files_struct *fsp, SMB_STRUCT_STAT *psbuf, int flags, mode_t unx_mode, - uint32 access_mask) + uint32 access_mask, /* client requested access mask. */ + uint32 open_access_mask) /* what we're actually using in the open. */ { int accmode = (flags & O_ACCMODE); int local_flags = flags; @@ -244,7 +245,7 @@ static NTSTATUS open_file(files_struct *fsp, local_flags = (flags & ~O_ACCMODE)|O_RDWR; } - if ((access_mask & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) || + if ((open_access_mask & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) || (!file_existed && (local_flags & O_CREAT)) || ((local_flags & O_TRUNC) == O_TRUNC) ) { @@ -1547,7 +1548,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, * open_file strips any O_TRUNC flags itself. */ - fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode, open_access_mask); + fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode, + access_mask, open_access_mask); if (!NT_STATUS_IS_OK(fsp_open)) { if (lck != NULL) { @@ -1814,7 +1816,7 @@ NTSTATUS open_file_fchmod(connection_struct *conn, const char *fname, /* note! we must use a non-zero desired access or we don't get a real file descriptor. Oh what a twisted web we weave. */ - status = open_file(fsp,conn,fname,psbuf,O_WRONLY,0,FILE_WRITE_DATA); + status = open_file(fsp,conn,fname,psbuf,O_WRONLY,0,FILE_WRITE_DATA,FILE_WRITE_DATA); /* * This is not a user visible file open. -- cgit From dc5f6687e4a4cf22103364eb4f364984700e0e22 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 19 Jul 2006 21:03:03 +0000 Subject: r17152: Don't handle the delete pending here, await reschedule. Jeremy. (This used to be commit 11bab9d57958659c71f053fe8dc0f9156c9f3c1f) --- source3/smbd/open.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 890f1ef45a..21c4bd628a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1594,13 +1594,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, access_mask, share_access, create_options, &file_existed); - if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) { - /* DELETE_PENDING is not deferred for a second */ - TALLOC_FREE(lck); - file_free(fsp); - return status; - } - if (!NT_STATUS_IS_OK(status)) { struct deferred_open_record state; -- cgit From 0e6e3c90c933db15e3a11a5672f252a963541bbc Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 25 Jul 2006 08:40:04 +0000 Subject: r17228: Modest reformatting (This used to be commit 640b4297a400fe23418e9c1c01d4c14ce3bde5b4) --- source3/smbd/open.c | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 21c4bd628a..1b67d74403 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1361,7 +1361,9 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, fsp->inode = psbuf->st_ino; fsp->share_access = share_access; fsp->fh->private_options = create_options; - fsp->access_mask = open_access_mask; /* We change this to the requested access_mask after the open is done. */ + fsp->access_mask = open_access_mask; /* We change this to the + * requested access_mask after + * the open is done. */ /* Ensure no SAMBA_PRIVATE bits can be set. */ fsp->oplock_type = (oplock_request & ~SAMBA_PRIVATE_OPLOCK_MASK); @@ -1374,8 +1376,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, inode = psbuf->st_ino; lck = get_share_mode_lock(NULL, dev, inode, - conn->connectpath, - fname); + conn->connectpath, + fname); if (lck == NULL) { file_free(fsp); @@ -1391,14 +1393,17 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return NT_STATUS_SHARING_VIOLATION; } - /* Use the client requested access mask here, not the one we open with. */ + /* Use the client requested access mask here, not the one we + * open with. */ status = open_mode_check(conn, fname, lck, access_mask, share_access, create_options, &file_existed); if (NT_STATUS_IS_OK(status)) { - /* We might be going to allow this open. Check oplock status again. */ - /* Second pass - send break for both batch or exclusive oplocks. */ + /* We might be going to allow this open. Check oplock + * status again. */ + /* Second pass - send break for both batch or + * exclusive oplocks. */ if (delay_for_oplocks(lck, fsp, 2, oplock_request)) { schedule_defer_open(lck, request_time); TALLOC_FREE(lck); @@ -1427,7 +1432,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) { files_struct *fsp_dup; - /* Use the client requested access mask here, not the one we open with. */ + /* Use the client requested access mask here, + * not the one we open with. */ fsp_dup = fcb_or_dos_open(conn, fname, dev, inode, access_mask, share_access, @@ -1462,7 +1468,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } if (((flags & O_RDWR) && !CAN_WRITE(conn)) || - !can_access_file(conn,fname,psbuf,can_access_mask)) { + !can_access_file(conn,fname,psbuf,can_access_mask)) { can_access = False; } @@ -1549,7 +1555,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, */ fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode, - access_mask, open_access_mask); + access_mask, open_access_mask); if (!NT_STATUS_IS_OK(fsp_open)) { if (lck != NULL) { @@ -1580,11 +1586,12 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, inode = fsp->inode; lck = get_share_mode_lock(NULL, dev, inode, - conn->connectpath, - fname); + conn->connectpath, + fname); if (lck == NULL) { - DEBUG(0, ("open_file_ntcreate: Could not get share mode lock for %s\n", fname)); + DEBUG(0, ("open_file_ntcreate: Could not get share " + "mode lock for %s\n", fname)); fd_close(conn, fsp); file_free(fsp); return NT_STATUS_SHARING_VIOLATION; @@ -1703,7 +1710,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, set_share_mode(lck, fsp, current_user.ut.uid, 0, fsp->oplock_type); if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || - info == FILE_WAS_SUPERSEDED) { + info == FILE_WAS_SUPERSEDED) { /* Handle strange delete on close create semantics. */ if (create_options & FILE_DELETE_ON_CLOSE) { @@ -1743,8 +1750,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, int saved_errno = errno; /* We might get ENOSYS in the next * call.. */ - if (SMB_VFS_FCHMOD_ACL(fsp, fsp->fh->fd, unx_mode) == -1 - && errno == ENOSYS) { + if (SMB_VFS_FCHMOD_ACL(fsp, fsp->fh->fd, unx_mode) == -1 && + errno == ENOSYS) { errno = saved_errno; /* Ignore ENOSYS */ } @@ -1765,7 +1772,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } else { DEBUG(5, ("open_file_ntcreate: reset " "attributes of file %s to 0%o\n", - fname, (unsigned int)new_unx_mode)); + fname, (unsigned int)new_unx_mode)); ret = 0; /* Don't do the fchmod below. */ } } @@ -1774,7 +1781,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, (SMB_VFS_FCHMOD(fsp, fsp->fh->fd, new_unx_mode) == -1)) DEBUG(5, ("open_file_ntcreate: failed to reset " "attributes of file %s to 0%o\n", - fname, (unsigned int)new_unx_mode)); + fname, (unsigned int)new_unx_mode)); } /* If this is a successful open, we must remove any deferred open -- cgit From 9bbe29ad13c604a79312da45ac238547dbb97c7b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 25 Jul 2006 08:51:54 +0000 Subject: r17229: Indent-style reformatting -- getting used to the code again :-) (This used to be commit 2e400fb0077ccef38fff28ef037f982624b7815b) --- source3/smbd/open.c | 104 ++++++++++++++++++++++++++-------------------------- 1 file changed, 53 insertions(+), 51 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 1b67d74403..74dd038381 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -39,10 +39,10 @@ struct deferred_open_record { ****************************************************************************/ static BOOL fd_open(struct connection_struct *conn, - const char *fname, - files_struct *fsp, - int flags, - mode_t mode) + const char *fname, + files_struct *fsp, + int flags, + mode_t mode) { int sav; @@ -68,7 +68,7 @@ static BOOL fd_open(struct connection_struct *conn, ****************************************************************************/ int fd_close(struct connection_struct *conn, - files_struct *fsp) + files_struct *fsp) { if (fsp->fh->fd == -1) { return 0; /* What we used to call a stat open. */ @@ -85,9 +85,9 @@ int fd_close(struct connection_struct *conn, ****************************************************************************/ void change_owner_to_parent(connection_struct *conn, - files_struct *fsp, - const char *fname, - SMB_STRUCT_STAT *psbuf) + files_struct *fsp, + const char *fname, + SMB_STRUCT_STAT *psbuf) { const char *parent_path = parent_dirname(fname); SMB_STRUCT_STAT parent_st; @@ -185,13 +185,13 @@ void change_owner_to_parent(connection_struct *conn, ****************************************************************************/ static NTSTATUS open_file(files_struct *fsp, - connection_struct *conn, - const char *fname, - SMB_STRUCT_STAT *psbuf, - int flags, - mode_t unx_mode, - uint32 access_mask, /* client requested access mask. */ - uint32 open_access_mask) /* what we're actually using in the open. */ + connection_struct *conn, + const char *fname, + SMB_STRUCT_STAT *psbuf, + int flags, + mode_t unx_mode, + uint32 access_mask, /* client requested access mask. */ + uint32 open_access_mask) /* what we're actually using in the open. */ { int accmode = (flags & O_ACCMODE); int local_flags = flags; @@ -335,7 +335,8 @@ static NTSTATUS open_file(files_struct *fsp, if (!CAN_WRITE(conn)) { fsp->can_write = False; } else { - fsp->can_write = (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ? True : False; + fsp->can_write = (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ? + True : False; } fsp->print_file = False; fsp->modified = False; @@ -351,7 +352,8 @@ static NTSTATUS open_file(files_struct *fsp, fsp->wcp = NULL; /* Write cache pointer. */ DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n", - *current_user_info.smb_name ? current_user_info.smb_name : 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)); @@ -614,9 +616,9 @@ static BOOL is_delete_request(files_struct *fsp) { */ static BOOL delay_for_oplocks(struct share_mode_lock *lck, - files_struct *fsp, - int pass_number, - int oplock_request) + files_struct *fsp, + int pass_number, + int oplock_request) { int i; struct share_mode_entry *exclusive = NULL; @@ -805,12 +807,12 @@ static void kernel_flock(files_struct *fsp, uint32 share_mode) ****************************************************************************/ static BOOL open_match_attributes(connection_struct *conn, - const char *path, - uint32 old_dos_attr, - uint32 new_dos_attr, - mode_t existing_unx_mode, - mode_t new_unx_mode, - mode_t *returned_unx_mode) + const char *path, + uint32 old_dos_attr, + uint32 new_dos_attr, + mode_t existing_unx_mode, + mode_t new_unx_mode, + mode_t *returned_unx_mode) { uint32 noarch_old_dos_attr, noarch_new_dos_attr; @@ -915,10 +917,10 @@ static files_struct *fcb_or_dos_open(connection_struct *conn, ****************************************************************************/ BOOL map_open_params_to_ntcreate(const char *fname, int deny_mode, int open_func, - uint32 *paccess_mask, - uint32 *pshare_mode, - uint32 *pcreate_disposition, - uint32 *pcreate_options) + uint32 *paccess_mask, + uint32 *pshare_mode, + uint32 *pcreate_disposition, + uint32 *pcreate_options) { uint32 access_mask; uint32 share_mode; @@ -1090,17 +1092,17 @@ static void schedule_defer_open(struct share_mode_lock *lck, struct timeval requ ****************************************************************************/ NTSTATUS open_file_ntcreate(connection_struct *conn, - const char *fname, - SMB_STRUCT_STAT *psbuf, - uint32 access_mask, /* access bits (FILE_READ_DATA etc.) */ - uint32 share_access, /* share constants (FILE_SHARE_READ etc). */ - uint32 create_disposition, /* FILE_OPEN_IF etc. */ - uint32 create_options, /* options such as delete on close. */ - uint32 new_dos_attributes, /* attributes used for new file. */ - int oplock_request, /* internal Samba oplock codes. */ - /* Information (FILE_EXISTS etc.) */ - int *pinfo, - files_struct **result) + const char *fname, + SMB_STRUCT_STAT *psbuf, + uint32 access_mask, /* access bits (FILE_READ_DATA etc.) */ + uint32 share_access, /* share constants (FILE_SHARE_READ etc) */ + uint32 create_disposition, /* FILE_OPEN_IF etc. */ + uint32 create_options, /* options such as delete on close. */ + uint32 new_dos_attributes, /* attributes used for new file. */ + int oplock_request, /* internal Samba oplock codes. */ + /* Information (FILE_EXISTS etc.) */ + int *pinfo, + files_struct **result) { int flags=0; int flags2=0; @@ -1849,14 +1851,14 @@ int close_file_fchmod(files_struct *fsp) ****************************************************************************/ NTSTATUS open_directory(connection_struct *conn, - const char *fname, - SMB_STRUCT_STAT *psbuf, - uint32 access_mask, - uint32 share_access, - uint32 create_disposition, - uint32 create_options, - int *pinfo, - files_struct **result) + const char *fname, + SMB_STRUCT_STAT *psbuf, + uint32 access_mask, + uint32 share_access, + uint32 create_disposition, + uint32 create_options, + int *pinfo, + files_struct **result) { files_struct *fsp = NULL; BOOL dir_existed = VALID_STAT(*psbuf) ? True : False; @@ -1993,8 +1995,8 @@ NTSTATUS open_directory(connection_struct *conn, string_set(&fsp->fsp_name,fname); lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, - conn->connectpath, - fname); + conn->connectpath, + fname); if (lck == NULL) { DEBUG(0, ("open_directory: Could not get share mode lock for %s\n", fname)); -- cgit From f43522856bb4a6824447524c612a98fec1f991ef Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 26 Jul 2006 01:53:23 +0000 Subject: r17247: When we map generic to specific we need to remember to copy over the copy of the access_mask, open_access_mask. Jerry - this is a definate fix for a 3.0.23b and should also be on the patches page. CIFSFS breaks without this. Jeremy. (This used to be commit d11e71ebcccf6907f2404a04aa6bf61b12ab2709) --- source3/smbd/open.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 74dd038381..95c70dff54 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1307,6 +1307,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, */ se_map_generic(&access_mask, &file_generic_mapping); + open_access_mask = access_mask; DEBUG(10, ("open_file_ntcreate: fname=%s, after mapping " "access_mask=0x%x\n", fname, access_mask )); @@ -1548,9 +1549,11 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, unx_mode = 0777; } - DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", + DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o, " + "access_mask = 0x%x, open_access_mask = 0x%x\n", (unsigned int)flags, (unsigned int)flags2, - (unsigned int)unx_mode)); + (unsigned int)unx_mode, (unsigned int)access_mask, + (unsigned int)open_access_mask)); /* * open_file strips any O_TRUNC flags itself. -- cgit From f6aeba37ff3fbfb3b7d3ff5a3878348e0b3acc39 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 26 Jul 2006 02:15:01 +0000 Subject: r17248: Ensure we definately add the WRITE_DATA on O_TRUNC. Jeremy. (This used to be commit 8eed82d5d5ba34cc0a6b99b9d0df45eec5f788fa) --- source3/smbd/open.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 95c70dff54..fd2f1ae54f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1297,9 +1297,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, /* This is a nasty hack - must fix... JRA. */ if (access_mask == MAXIMUM_ALLOWED_ACCESS) { open_access_mask = access_mask = FILE_GENERIC_ALL; - if (flags2 & O_TRUNC) { - open_access_mask |= FILE_WRITE_DATA; /* This will cause oplock breaks. */ - } } /* @@ -1309,6 +1306,10 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, se_map_generic(&access_mask, &file_generic_mapping); open_access_mask = access_mask; + if (flags2 & O_TRUNC) { + open_access_mask |= FILE_WRITE_DATA; /* This will cause oplock breaks. */ + } + DEBUG(10, ("open_file_ntcreate: fname=%s, after mapping " "access_mask=0x%x\n", fname, access_mask )); -- cgit From 999b1e01e1ee55338ff96ddf80c3852038216108 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 26 Jul 2006 04:42:18 +0000 Subject: r17249: Ensure we only set the FILE_WRITE_DATA on O_TRUNC in one place. Jeremy. (This used to be commit f326bae3e269046b6f087626240cddbb5dafb0e4) --- source3/smbd/open.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index fd2f1ae54f..9bd4e36d5a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1212,14 +1212,12 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, /* If file exists replace/overwrite. If file doesn't * exist create. */ flags2 |= (O_CREAT | O_TRUNC); - open_access_mask |= FILE_WRITE_DATA; /* This will cause oplock breaks. */ break; case FILE_OVERWRITE_IF: /* If file exists replace/overwrite. If file doesn't * exist create. */ flags2 |= (O_CREAT | O_TRUNC); - open_access_mask |= FILE_WRITE_DATA; /* This will cause oplock breaks. */ break; case FILE_OPEN: @@ -1244,7 +1242,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return NT_STATUS_OBJECT_NAME_NOT_FOUND; } flags2 |= O_TRUNC; - open_access_mask |= FILE_WRITE_DATA; /* This will cause oplock breaks. */ break; case FILE_CREATE: -- cgit From 31802698db7e2b48f01bbb0ce540e38653cd8517 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 26 Jul 2006 08:08:48 +0000 Subject: r17254: Simple flattening of an if-statement, no logic change. Jeremy, I'm sure you will look at this nevertheless :-) Volker (This used to be commit 3ef34468b55771b6f6b54454fa6c9decc183c565) --- source3/smbd/open.c | 48 +++++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 21 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 9bd4e36d5a..ef59da6447 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -625,6 +625,8 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, BOOL valid_entry = False; BOOL delay_it = False; BOOL have_level2 = False; + BOOL ret; + char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE]; if (oplock_request & INTERNAL_OPEN_ONLY) { fsp->oplock_type = NO_OPLOCK; @@ -688,34 +690,38 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, fsp->oplock_type = FAKE_LEVEL_II_OPLOCK; } - if (delay_it) { - BOOL ret; - char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE]; + if (!delay_it) { + return False; + } - DEBUG(10, ("Sending break request to PID %s\n", - procid_str_static(&exclusive->pid))); - exclusive->op_mid = get_current_mid(); + /* + * Send a break message to the oplock holder and delay the open for + * our client. + */ - /* Create the message. */ - share_mode_entry_to_message(msg, exclusive); + DEBUG(10, ("Sending break request to PID %s\n", + procid_str_static(&exclusive->pid))); + exclusive->op_mid = get_current_mid(); - /* Add in the FORCE_OPLOCK_BREAK_TO_NONE bit in the message if set. We don't - want this set in the share mode struct pointed to by lck. */ + /* Create the message. */ + share_mode_entry_to_message(msg, exclusive); - if (oplock_request & FORCE_OPLOCK_BREAK_TO_NONE) { - SSVAL(msg,6,exclusive->op_type | FORCE_OPLOCK_BREAK_TO_NONE); - } + /* Add in the FORCE_OPLOCK_BREAK_TO_NONE bit in the message if set. We + don't want this set in the share mode struct pointed to by lck. */ - become_root(); - ret = message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST, - msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); - unbecome_root(); - if (!ret) { - DEBUG(3, ("Could not send oplock break message\n")); - } + if (oplock_request & FORCE_OPLOCK_BREAK_TO_NONE) { + SSVAL(msg,6,exclusive->op_type | FORCE_OPLOCK_BREAK_TO_NONE); } - return delay_it; + become_root(); + ret = message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST, + msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); + unbecome_root(); + if (!ret) { + DEBUG(3, ("Could not send oplock break message\n")); + } + + return True; } static BOOL request_timed_out(struct timeval request_time, -- cgit From a093a76dc14303fd1c42fb2c0b87faf3748815e4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 28 Jul 2006 22:42:39 +0000 Subject: r17293: After the results from the cluster tests in Germany, fix the messaging code to call the efficient calls : save_re_uid() set_effective_uid(0); messaging_op restore_re_uid(); instead of using heavyweight become_root()/unbecome_root() pairs around all messaging code. Fixup the messaging code to ensure sec_init() is called (only once) so that non-root processes still work when sending messages. This is a lighter weight solution to become_root()/unbecome_root() (which swaps all the supplemental groups) and should be more efficient. I will migrate all server code over to using this (a similar technique should be used in the passdb backend where needed). Jeremy. (This used to be commit 4ace291278d9a44f5c577bdd3b282c1231e543df) --- source3/smbd/open.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index ef59da6447..5c10c59054 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -713,10 +713,8 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, SSVAL(msg,6,exclusive->op_type | FORCE_OPLOCK_BREAK_TO_NONE); } - become_root(); ret = message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST, msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); - unbecome_root(); if (!ret) { DEBUG(3, ("Could not send oplock break message\n")); } -- cgit From 23535f7d49d455042f60c1123bade66bbbf592f8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 21 Aug 2006 23:30:39 +0000 Subject: r17676: Fix printing bug found by kukks. Don't copy a return value into an auto on the stack that gets removed when we return from the frame :-). Jeremy. (This used to be commit 85bf8a16116e5eb9d4400e809531737d45890abb) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 5c10c59054..117d3ac595 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1139,7 +1139,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, DEBUG(10, ("open_file_ntcreate: printer open fname=%s\n", fname)); - return print_fsp_open(conn, fname, &fsp); + return print_fsp_open(conn, fname, result); } /* We add aARCH to this as this mode is only used if the file is -- cgit From 7ba2554d88a187ca1f4f40014363fdf9de2223a0 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 21 Sep 2006 23:57:32 +0000 Subject: r18802: Use the pidl-generated code for the srvsvc interface, both client and server code. This has had some basic testing. I'll do more during the next couple of days and hopefully also make RPC-SRVSVC from Samba4 pass against it. (This used to be commit ef10672399c4b82700dc431b4d93431ffdd42d98) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 117d3ac595..9601329b9e 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2057,7 +2057,7 @@ NTSTATUS open_directory(connection_struct *conn, Open a pseudo-file (no locking checks - a 'stat' open). ****************************************************************************/ -NTSTATUS open_file_stat(connection_struct *conn, char *fname, +NTSTATUS open_file_stat(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, files_struct **result) { files_struct *fsp = NULL; -- cgit From f27d5c7838eb0183baaedb3deb33cdfe7327c917 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 4 Oct 2006 20:43:56 +0000 Subject: r19077: Fix an uninitialized variable (This used to be commit 6bc2cce645af94274a5959312c52799c221b0899) --- source3/smbd/open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 9601329b9e..4e91cdfd2a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -475,8 +475,8 @@ static void validate_my_share_entries(int num, if (is_deferred_open_entry(share_entry) && !open_was_deferred(share_entry->op_mid)) { pstring str; - DEBUG(0, ("Got a deferred entry without a request: " - "PANIC: %s\n", share_mode_str(num, share_entry))); + pstr_sprintf(str, "Got a deferred entry without a request: " + "PANIC: %s\n", share_mode_str(num, share_entry)); smb_panic(str); } -- cgit From 4fe70bcee2ec8515f123d8c826631b54bbf793e7 Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Thu, 9 Nov 2006 20:29:31 +0000 Subject: r19647: Add some GPFS support in a vfs mod. Also adds the kernel flock op to the vfs layer, since gpfs supports it. Thanks to Volker, Christian, Mathias, Chetan, and Peter. (This used to be commit 0620658890fa9c68a9848538728023192319c81a) --- source3/smbd/open.c | 37 +++++++++++++------------------------ 1 file changed, 13 insertions(+), 24 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 4e91cdfd2a..1899a6fce7 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -783,28 +783,6 @@ static void defer_open(struct share_mode_lock *lck, srv_defer_sign_response(mid); } -/**************************************************************************** - Set a kernel flock on a file for NFS interoperability. - This requires a patch to Linux. -****************************************************************************/ - -static void kernel_flock(files_struct *fsp, uint32 share_mode) -{ -#if HAVE_KERNEL_SHARE_MODES - int kernel_mode = 0; - if (share_mode == FILE_SHARE_WRITE) { - kernel_mode = LOCK_MAND|LOCK_WRITE; - } else if (share_mode == FILE_SHARE_READ) { - kernel_mode = LOCK_MAND|LOCK_READ; - } else if (share_mode == FILE_SHARE_NONE) { - kernel_mode = LOCK_MAND; - } - if (kernel_mode) { - flock(fsp->fh->fd, kernel_mode); - } -#endif - ; -} /**************************************************************************** On overwrite open ensure that the attributes match. @@ -1126,6 +1104,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, struct share_mode_lock *lck = NULL; uint32 open_access_mask = access_mask; NTSTATUS status; + int ret_flock; + if (conn->printer) { /* @@ -1644,9 +1624,18 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, 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 */ + the kernel refuses the operations then the kernel is wrong. + note that GPFS supports it as well - jmcd */ + + ret_flock = SMB_VFS_KERNEL_FLOCK(fsp, fsp->fh->fd, share_access); + if(ret_flock == -1 ){ - kernel_flock(fsp, share_access); + talloc_free(lck); + fd_close(conn, fsp); + file_free(fsp); + + return NT_STATUS_SHARING_VIOLATION; + } /* * At this point onwards, we can guarentee that the share entry -- cgit From 61ea96ec79fb9807fb234fe7fc9a59458653c6e5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 1 Dec 2006 23:46:07 +0000 Subject: r19993: Fix the problem with Linux clients requesting O_WRONLY on write-only files. Jim please check. Should not affect Windows clients - I ensured all the relevent Samba4 torture tests still pass. Jeremy. (This used to be commit 6df3cac44fb1eafa84f9fc0ce4485242b4cce111) --- source3/smbd/open.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 1899a6fce7..3d5dd849b6 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1105,7 +1105,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, uint32 open_access_mask = access_mask; NTSTATUS status; int ret_flock; - if (conn->printer) { /* @@ -1300,7 +1299,15 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, */ if (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) { - flags = O_RDWR; + /* DENY_DOS opens are always underlying read-write on the + file handle, no matter what the requested access mask + says. */ + if ((create_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS) || + access_mask & (FILE_READ_ATTRIBUTES|FILE_READ_DATA|FILE_READ_EA|FILE_EXECUTE)) { + flags = O_RDWR; + } else { + flags = O_WRONLY; + } } else { flags = O_RDONLY; } @@ -1448,11 +1455,13 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if (flags & O_RDWR) { can_access_mask = FILE_READ_DATA|FILE_WRITE_DATA; + } else if (flags & O_WRONLY) { + can_access_mask = FILE_WRITE_DATA; } else { can_access_mask = FILE_READ_DATA; } - if (((flags & O_RDWR) && !CAN_WRITE(conn)) || + if (((can_access_mask & FILE_WRITE_DATA) && !CAN_WRITE(conn)) || !can_access_file(conn,fname,psbuf,can_access_mask)) { can_access = False; } -- cgit From 9933b596d1dddca68a7bcc611e1f8cffc7f2a4e6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 17 Dec 2006 18:30:44 +0000 Subject: r20228: Bring the calling conventions of inherit_access_acl and change_owner_to_parent a bit closer together: Move the lp_inherit_perms() check into the callers. Volker (This used to be commit 0874093e5fff480d8ec442072318525079add633) --- source3/smbd/open.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 3d5dd849b6..d916609769 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -283,7 +283,9 @@ static NTSTATUS open_file(files_struct *fsp, } /* Inherit the ACL if the file was created. */ - if ((local_flags & O_CREAT) && !file_existed) { + if ((local_flags & O_CREAT) + && !file_existed + && lp_inherit_perms(SNUM(conn))) { inherit_access_acl(conn, fname, unx_mode); } -- cgit From 920e1a368504228ab3a11aa58cbf12c7c95f4fd0 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 19 Dec 2006 18:08:51 +0000 Subject: r20257: Hey, change_owner_to_parent is now static :-) (This used to be commit 4090bc4bca77edafcafa52ecb7dc75ead2779cb5) --- source3/smbd/open.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index d916609769..3111f68ef5 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -84,10 +84,10 @@ int fd_close(struct connection_struct *conn, Do this by fd if possible. ****************************************************************************/ -void change_owner_to_parent(connection_struct *conn, - files_struct *fsp, - const char *fname, - SMB_STRUCT_STAT *psbuf) +static void change_owner_to_parent(connection_struct *conn, + files_struct *fsp, + const char *fname, + SMB_STRUCT_STAT *psbuf) { const char *parent_path = parent_dirname(fname); SMB_STRUCT_STAT parent_st; -- cgit From 469b42c61f73c0bd5166c33a909b3c68c1fb9dde Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 24 Dec 2006 11:13:32 +0000 Subject: r20338: Restructure open_directory a bit. This gets rid of a race condition regarding error messages: We relied upon a stat that a directory did not exist to later on then do the mkdir or not. This does the mkdir directly and copes with a potential error. The second one is more important: It's possible with Samba 3 to do a ntcreate&x with NTCREATEX_OPTIONS_DIRECTORY and we happily do a NT_STATUS_OK. Also move up the use_nt_status() logic a bit. I think this does not belong into the core routines, the smb server as such should take care of it. Jeremy, do you think this should go to 3.0.24? I'll update samba4torture when the build farm has picked up this checkin. Volker (This used to be commit 472fb11f4968d30cedc9851215c63acd3132f3db) --- source3/smbd/open.c | 88 ++++++++++++++++++++++------------------------------- 1 file changed, 36 insertions(+), 52 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 3111f68ef5..dcd1a7a36f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1867,7 +1867,6 @@ NTSTATUS open_directory(connection_struct *conn, { files_struct *fsp = NULL; BOOL dir_existed = VALID_STAT(*psbuf) ? True : False; - BOOL create_dir = False; struct share_mode_lock *lck = NULL; NTSTATUS status; int info = 0; @@ -1888,44 +1887,47 @@ NTSTATUS open_directory(connection_struct *conn, switch( create_disposition ) { case FILE_OPEN: - /* If directory exists open. If directory doesn't - * exist error. */ - if (!dir_existed) { - DEBUG(5,("open_directory: FILE_OPEN requested " - "for directory %s and it doesn't " - "exist.\n", fname )); - return NT_STATUS_OBJECT_NAME_NOT_FOUND; - } + /* + * Don't do anything. The check for existence is done + * futher down. + */ info = FILE_WAS_OPENED; break; case FILE_CREATE: + /* If directory exists error. If directory doesn't * exist create. */ - if (dir_existed) { - DEBUG(5,("open_directory: FILE_CREATE " - "requested for directory %s and it " - "already exists.\n", fname )); - if (use_nt_status()) { - return NT_STATUS_OBJECT_NAME_COLLISION; - } else { - return NT_STATUS_DOS(ERRDOS, - ERRfilexists); - } + + status = mkdir_internal(conn, fname, False); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(2, ("open_directory: unable to create " + "%s. Error was %s\n", fname, + nt_errstr(status))); + return status; } - create_dir = True; + info = FILE_WAS_CREATED; break; case FILE_OPEN_IF: - /* If directory exists open. If directory doesn't - * exist create. */ - if (!dir_existed) { - create_dir = True; + /* + * If directory exists open. If directory doesn't + * exist create. + */ + + status = mkdir_internal(conn, fname, False); + + if (NT_STATUS_IS_OK(status)) { info = FILE_WAS_CREATED; - } else { + } + + if (NT_STATUS_EQUAL(status, + NT_STATUS_OBJECT_NAME_COLLISION)) { info = FILE_WAS_OPENED; + status = NT_STATUS_OK; } + break; case FILE_SUPERSEDE: @@ -1938,35 +1940,17 @@ NTSTATUS open_directory(connection_struct *conn, return NT_STATUS_INVALID_PARAMETER; } - if (create_dir) { - /* - * Try and create the directory. - */ - - /* We know bad_path is false as it's caught earlier. */ + /* Ensure we're checking for a symlink here.... */ + /* We don't want to get caught by a symlink racer. */ - status = mkdir_internal(conn, fname, False); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(2,("open_directory: unable to create %s. " - "Error was %s\n", fname, strerror(errno) )); - /* Ensure we return the correct NT status to the - * client. */ - return status; - } - - /* Ensure we're checking for a symlink here.... */ - /* We don't want to get caught by a symlink racer. */ - - if(SMB_VFS_LSTAT(conn,fname, psbuf) != 0) { - return map_nt_error_from_unix(errno); - } + if(SMB_VFS_LSTAT(conn,fname, psbuf) != 0) { + return map_nt_error_from_unix(errno); + } - if(!S_ISDIR(psbuf->st_mode)) { - DEBUG(0,("open_directory: %s is not a directory !\n", - fname )); - return NT_STATUS_NOT_A_DIRECTORY; - } + if(!S_ISDIR(psbuf->st_mode)) { + DEBUG(0,("open_directory: %s is not a directory !\n", + fname )); + return NT_STATUS_NOT_A_DIRECTORY; } status = file_new(conn, &fsp); -- cgit From d0c6f9b728936297efd002008b69a59da6bbfabc Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 24 Dec 2006 11:45:55 +0000 Subject: r20339: Make mkdir_internal static to open.c (This used to be commit 6dd0886b49969d0edfe16861f19d35275217b2af) --- source3/smbd/open.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 3 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index dcd1a7a36f..e8536e3335 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1851,6 +1851,30 @@ int close_file_fchmod(files_struct *fsp) return ret; } +static NTSTATUS mkdir_internal(connection_struct *conn, + const pstring directory) +{ + int ret= -1; + + if(!CAN_WRITE(conn)) { + DEBUG(5,("mkdir_internal: failing create on read-only share " + "%s\n", lp_servicename(SNUM(conn)))); + return NT_STATUS_ACCESS_DENIED; + } + + if (!check_name(directory, conn)) { + return map_nt_error_from_unix(errno); + } + + ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True)); + + if (ret == -1) { + return map_nt_error_from_unix(errno); + } + + return NT_STATUS_OK; +} + /**************************************************************************** Open a directory from an NT SMB call. ****************************************************************************/ @@ -1899,7 +1923,7 @@ NTSTATUS open_directory(connection_struct *conn, /* If directory exists error. If directory doesn't * exist create. */ - status = mkdir_internal(conn, fname, False); + status = mkdir_internal(conn, fname); if (!NT_STATUS_IS_OK(status)) { DEBUG(2, ("open_directory: unable to create " "%s. Error was %s\n", fname, @@ -1916,7 +1940,7 @@ NTSTATUS open_directory(connection_struct *conn, * exist create. */ - status = mkdir_internal(conn, fname, False); + status = mkdir_internal(conn, fname); if (NT_STATUS_IS_OK(status)) { info = FILE_WAS_CREATED; @@ -1948,7 +1972,7 @@ NTSTATUS open_directory(connection_struct *conn, } if(!S_ISDIR(psbuf->st_mode)) { - DEBUG(0,("open_directory: %s is not a directory !\n", + DEBUG(5,("open_directory: %s is not a directory !\n", fname )); return NT_STATUS_NOT_A_DIRECTORY; } @@ -2037,6 +2061,26 @@ NTSTATUS open_directory(connection_struct *conn, return NT_STATUS_OK; } +NTSTATUS create_directory(connection_struct *conn, const char *directory) +{ + NTSTATUS status; + SMB_STRUCT_STAT sbuf; + files_struct *fsp; + + SET_STAT_INVALID(sbuf); + + status = open_directory(conn, directory, &sbuf, + FILE_READ_ATTRIBUTES, /* Just a stat open */ + FILE_SHARE_NONE, /* Ignored for stat opens */ + FILE_CREATE, 0, NULL, &fsp); + + if (NT_STATUS_IS_OK(status)) { + close_file(fsp, NORMAL_CLOSE); + } + + return status; +} + /**************************************************************************** Open a pseudo-file (no locking checks - a 'stat' open). ****************************************************************************/ -- cgit From af1750934d12c82b87a9d1f1ab96f24474fb9768 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 24 Dec 2006 14:29:19 +0000 Subject: r20340: Join vfs_MkDir to its only caller (This used to be commit cce911780fc52ea56dccde1879b0891cdf9ea320) --- source3/smbd/open.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index e8536e3335..1ca793fb80 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1851,27 +1851,45 @@ int close_file_fchmod(files_struct *fsp) return ret; } -static NTSTATUS mkdir_internal(connection_struct *conn, - const pstring directory) +static NTSTATUS mkdir_internal(connection_struct *conn, const char *name) { + SMB_STRUCT_STAT sbuf; int ret= -1; - + mode_t mode; + if(!CAN_WRITE(conn)) { DEBUG(5,("mkdir_internal: failing create on read-only share " "%s\n", lp_servicename(SNUM(conn)))); return NT_STATUS_ACCESS_DENIED; } - if (!check_name(directory, conn)) { + if (!check_name(name, conn)) { return map_nt_error_from_unix(errno); } - ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True)); + mode = unix_mode(conn, aDIR, name, True); - if (ret == -1) { + if ((ret=SMB_VFS_MKDIR(conn, name, mode)) != 0) { return map_nt_error_from_unix(errno); } - + + if (lp_inherit_perms(SNUM(conn))) { + inherit_access_acl(conn, name, mode); + } + + /* + * Check if high bits should have been set, + * then (if bits are missing): add them. + * Consider bits automagically set by UNIX, i.e. SGID bit from parent + * dir. + */ + if (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) + && (SMB_VFS_STAT(conn, name, &sbuf) == 0) + && (mode & ~sbuf.st_mode)) { + SMB_VFS_CHMOD(conn, name, + sbuf.st_mode | (mode & ~sbuf.st_mode)); + } + return NT_STATUS_OK; } -- cgit From 4e5a335c07c7768cf731ee4bf430ad90acad306d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 24 Dec 2006 15:11:03 +0000 Subject: r20342: Move the lstat into mkdir_internal, for the FILE_OPEN case in open_directory we want to follow symlinks. Volker (This used to be commit c20bdd219d16abcc60d67f4a21b4fcd661473835) --- source3/smbd/open.c | 48 ++++++++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 18 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 1ca793fb80..02decdc06f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1851,9 +1851,9 @@ int close_file_fchmod(files_struct *fsp) return ret; } -static NTSTATUS mkdir_internal(connection_struct *conn, const char *name) +static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, + SMB_STRUCT_STAT *psbuf) { - SMB_STRUCT_STAT sbuf; int ret= -1; mode_t mode; @@ -1873,6 +1873,21 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name) return map_nt_error_from_unix(errno); } + /* Ensure we're checking for a symlink here.... */ + /* We don't want to get caught by a symlink racer. */ + + if (SMB_VFS_LSTAT(conn, name, psbuf) == -1) { + DEBUG(2, ("Could not stat directory '%s' just created: %s\n", + name, strerror(errno))); + return map_nt_error_from_unix(errno); + } + + if (!S_ISDIR(psbuf->st_mode)) { + DEBUG(0, ("Directory just '%s' created is not a directory\n", + name)); + return NT_STATUS_ACCESS_DENIED; + } + if (lp_inherit_perms(SNUM(conn))) { inherit_access_acl(conn, name, mode); } @@ -1883,11 +1898,9 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name) * Consider bits automagically set by UNIX, i.e. SGID bit from parent * dir. */ - if (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) - && (SMB_VFS_STAT(conn, name, &sbuf) == 0) - && (mode & ~sbuf.st_mode)) { + if (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) && (mode & ~psbuf->st_mode)) { SMB_VFS_CHMOD(conn, name, - sbuf.st_mode | (mode & ~sbuf.st_mode)); + psbuf->st_mode | (mode & ~psbuf->st_mode)); } return NT_STATUS_OK; @@ -1929,11 +1942,17 @@ NTSTATUS open_directory(connection_struct *conn, switch( create_disposition ) { case FILE_OPEN: + + info = FILE_WAS_OPENED; + /* - * Don't do anything. The check for existence is done - * futher down. + * We want to follow symlinks here. */ - info = FILE_WAS_OPENED; + + if (SMB_VFS_STAT(conn, fname, psbuf) != 0) { + return map_nt_error_from_unix(errno); + } + break; case FILE_CREATE: @@ -1941,7 +1960,7 @@ NTSTATUS open_directory(connection_struct *conn, /* If directory exists error. If directory doesn't * exist create. */ - status = mkdir_internal(conn, fname); + status = mkdir_internal(conn, fname, psbuf); if (!NT_STATUS_IS_OK(status)) { DEBUG(2, ("open_directory: unable to create " "%s. Error was %s\n", fname, @@ -1958,7 +1977,7 @@ NTSTATUS open_directory(connection_struct *conn, * exist create. */ - status = mkdir_internal(conn, fname); + status = mkdir_internal(conn, fname, psbuf); if (NT_STATUS_IS_OK(status)) { info = FILE_WAS_CREATED; @@ -1982,13 +2001,6 @@ NTSTATUS open_directory(connection_struct *conn, return NT_STATUS_INVALID_PARAMETER; } - /* Ensure we're checking for a symlink here.... */ - /* We don't want to get caught by a symlink racer. */ - - if(SMB_VFS_LSTAT(conn,fname, psbuf) != 0) { - return map_nt_error_from_unix(errno); - } - if(!S_ISDIR(psbuf->st_mode)) { DEBUG(5,("open_directory: %s is not a directory !\n", fname )); -- cgit From a67757ef9c6ed421341fe948d93aff94991da053 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 24 Dec 2006 15:29:09 +0000 Subject: r20343: Split change_owner_to_parent fd-based (for file opens) and a name-based (for directory opens) routines. Volker (This used to be commit 4ca921d9aa90bc68d21d40ccf4b1ca0b1d2cbcb1) --- source3/smbd/open.c | 156 ++++++++++++++++++++++++++++------------------------ 1 file changed, 83 insertions(+), 73 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 02decdc06f..c3df5acde3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -84,11 +84,43 @@ int fd_close(struct connection_struct *conn, Do this by fd if possible. ****************************************************************************/ +static void change_fd_owner_to_parent(connection_struct *conn, + files_struct *fsp) +{ + const char *parent_path = parent_dirname(fsp->fsp_name); + SMB_STRUCT_STAT parent_st; + int ret; + + ret = SMB_VFS_STAT(conn, parent_path, &parent_st); + if (ret == -1) { + DEBUG(0,("change_fd_owner_to_parent: failed to stat parent " + "directory %s. Error was %s\n", + parent_path, strerror(errno) )); + return; + } + + become_root(); + ret = SMB_VFS_FCHOWN(fsp, fsp->fh->fd, parent_st.st_uid, (gid_t)-1); + unbecome_root(); + if (ret == -1) { + DEBUG(0,("change_fd_owner_to_parent: failed to fchown " + "file %s to parent directory uid %u. Error " + "was %s\n", fsp->fsp_name, + (unsigned int)parent_st.st_uid, + strerror(errno) )); + } + + DEBUG(10,("change_fd_owner_to_parent: changed new file %s to " + "parent directory uid %u.\n", fsp->fsp_name, + (unsigned int)parent_st.st_uid )); +} + static void change_owner_to_parent(connection_struct *conn, - files_struct *fsp, const char *fname, SMB_STRUCT_STAT *psbuf) { + pstring saved_dir; + SMB_STRUCT_STAT sbuf; const char *parent_path = parent_dirname(fname); SMB_STRUCT_STAT parent_st; int ret; @@ -101,83 +133,62 @@ static void change_owner_to_parent(connection_struct *conn, return; } - if (fsp && fsp->fh->fd != -1) { - become_root(); - ret = SMB_VFS_FCHOWN(fsp, fsp->fh->fd, parent_st.st_uid, (gid_t)-1); - unbecome_root(); - if (ret == -1) { - DEBUG(0,("change_owner_to_parent: failed to fchown " - "file %s to parent directory uid %u. Error " - "was %s\n", fname, - (unsigned int)parent_st.st_uid, - strerror(errno) )); - } - - DEBUG(10,("change_owner_to_parent: changed new file %s to " - "parent directory uid %u.\n", fname, - (unsigned int)parent_st.st_uid )); + /* We've already done an lstat into psbuf, and we know it's a + directory. If we can cd into the directory and the dev/ino + are the same then we can safely chown without races as + we're locking the directory in place by being in it. This + should work on any UNIX (thanks tridge :-). JRA. + */ - } else { - /* We've already done an lstat into psbuf, and we know it's a - directory. If we can cd into the directory and the dev/ino - are the same then we can safely chown without races as - we're locking the directory in place by being in it. This - should work on any UNIX (thanks tridge :-). JRA. - */ - - pstring saved_dir; - SMB_STRUCT_STAT sbuf; - - if (!vfs_GetWd(conn,saved_dir)) { - DEBUG(0,("change_owner_to_parent: failed to get " - "current working directory\n")); - return; - } + if (!vfs_GetWd(conn,saved_dir)) { + DEBUG(0,("change_owner_to_parent: failed to get " + "current working directory\n")); + return; + } - /* Chdir into the new path. */ - if (vfs_ChDir(conn, fname) == -1) { - DEBUG(0,("change_owner_to_parent: failed to change " - "current working directory to %s. Error " - "was %s\n", fname, strerror(errno) )); - goto out; - } + /* Chdir into the new path. */ + if (vfs_ChDir(conn, fname) == -1) { + DEBUG(0,("change_owner_to_parent: failed to change " + "current working directory to %s. Error " + "was %s\n", fname, strerror(errno) )); + goto out; + } - if (SMB_VFS_STAT(conn,".",&sbuf) == -1) { - DEBUG(0,("change_owner_to_parent: failed to stat " - "directory '.' (%s) Error was %s\n", - fname, strerror(errno))); - goto out; - } + if (SMB_VFS_STAT(conn,".",&sbuf) == -1) { + DEBUG(0,("change_owner_to_parent: failed to stat " + "directory '.' (%s) Error was %s\n", + fname, strerror(errno))); + goto out; + } - /* Ensure we're pointing at the same place. */ - if (sbuf.st_dev != psbuf->st_dev || - sbuf.st_ino != psbuf->st_ino || - sbuf.st_mode != psbuf->st_mode ) { - DEBUG(0,("change_owner_to_parent: " - "device/inode/mode on directory %s changed. " - "Refusing to chown !\n", fname )); - goto out; - } + /* Ensure we're pointing at the same place. */ + if (sbuf.st_dev != psbuf->st_dev || + sbuf.st_ino != psbuf->st_ino || + sbuf.st_mode != psbuf->st_mode ) { + DEBUG(0,("change_owner_to_parent: " + "device/inode/mode on directory %s changed. " + "Refusing to chown !\n", fname )); + goto out; + } - become_root(); - ret = SMB_VFS_CHOWN(conn, ".", parent_st.st_uid, (gid_t)-1); - unbecome_root(); - if (ret == -1) { - DEBUG(10,("change_owner_to_parent: failed to chown " - "directory %s to parent directory uid %u. " - "Error was %s\n", fname, - (unsigned int)parent_st.st_uid, strerror(errno) )); - goto out; - } + become_root(); + ret = SMB_VFS_CHOWN(conn, ".", parent_st.st_uid, (gid_t)-1); + unbecome_root(); + if (ret == -1) { + DEBUG(10,("change_owner_to_parent: failed to chown " + "directory %s to parent directory uid %u. " + "Error was %s\n", fname, + (unsigned int)parent_st.st_uid, strerror(errno) )); + goto out; + } - DEBUG(10,("change_owner_to_parent: changed ownership of new " - "directory %s to parent directory uid %u.\n", - fname, (unsigned int)parent_st.st_uid )); + DEBUG(10,("change_owner_to_parent: changed ownership of new " + "directory %s to parent directory uid %u.\n", + fname, (unsigned int)parent_st.st_uid )); - out: + out: - vfs_ChDir(conn,saved_dir); - } + vfs_ChDir(conn,saved_dir); } /**************************************************************************** @@ -1693,8 +1704,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, info = FILE_WAS_CREATED; /* Change the owner if required. */ if (lp_inherit_owner(SNUM(conn))) { - change_owner_to_parent(conn, fsp, fsp->fsp_name, - psbuf); + change_fd_owner_to_parent(conn, fsp); } } @@ -2078,7 +2088,7 @@ NTSTATUS open_directory(connection_struct *conn, /* Change the owner if required. */ if ((info == FILE_WAS_CREATED) && lp_inherit_owner(SNUM(conn))) { - change_owner_to_parent(conn, fsp, fsp->fsp_name, psbuf); + change_owner_to_parent(conn, fsp->fsp_name, psbuf); } if (pinfo) { -- cgit From e8e5c17f2e5c09dff5b2acaaab9a9659b9242c6f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 24 Dec 2006 16:37:22 +0000 Subject: r20344: Move the calls to inherit_access_acls and change_owner_to_parent together. Jeremy, I'm 100% sure you watch me closely here, I count on you :-) Volker (This used to be commit 02f85265f21607c950639da33bc8fe5d5ffd3cf9) --- source3/smbd/open.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index c3df5acde3..59cd8030af 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -293,11 +293,17 @@ static NTSTATUS open_file(files_struct *fsp, return map_nt_error_from_unix(errno); } - /* Inherit the ACL if the file was created. */ - if ((local_flags & O_CREAT) - && !file_existed - && lp_inherit_perms(SNUM(conn))) { - inherit_access_acl(conn, fname, unx_mode); + if ((local_flags & O_CREAT) && !file_existed) { + + /* Inherit the ACL if required */ + if (lp_inherit_perms(SNUM(conn))) { + inherit_access_acl(conn, fname, unx_mode); + } + + /* Change the owner if required. */ + if (lp_inherit_owner(SNUM(conn))) { + change_fd_owner_to_parent(conn, fsp); + } } } else { @@ -1702,10 +1708,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } } else { info = FILE_WAS_CREATED; - /* Change the owner if required. */ - if (lp_inherit_owner(SNUM(conn))) { - change_fd_owner_to_parent(conn, fsp); - } } if (pinfo) { @@ -1913,6 +1915,11 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, psbuf->st_mode | (mode & ~psbuf->st_mode)); } + /* Change the owner if required. */ + if (lp_inherit_owner(SNUM(conn))) { + change_owner_to_parent(conn, name, psbuf); + } + return NT_STATUS_OK; } @@ -2086,11 +2093,6 @@ NTSTATUS open_directory(connection_struct *conn, TALLOC_FREE(lck); - /* Change the owner if required. */ - if ((info == FILE_WAS_CREATED) && lp_inherit_owner(SNUM(conn))) { - change_owner_to_parent(conn, fsp->fsp_name, psbuf); - } - if (pinfo) { *pinfo = info; } -- cgit From 8cd9636458e175d2e1b63a5211423cec04a6ce91 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 27 Dec 2006 10:57:59 +0000 Subject: r20356: Consolidate the calls to parent_dirname() per open to one. This involved passing the dirname as argument to a few routines instead of calling parent_dirname() deep down. Volker (This used to be commit 7977fd78652897bb7d4db1c21c5749043428f911) --- source3/smbd/open.c | 86 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 51 insertions(+), 35 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 59cd8030af..28170e9cd8 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -84,18 +84,18 @@ int fd_close(struct connection_struct *conn, Do this by fd if possible. ****************************************************************************/ -static void change_fd_owner_to_parent(connection_struct *conn, - files_struct *fsp) +static void change_file_owner_to_parent(connection_struct *conn, + const char *inherit_from_dir, + files_struct *fsp) { - const char *parent_path = parent_dirname(fsp->fsp_name); SMB_STRUCT_STAT parent_st; int ret; - ret = SMB_VFS_STAT(conn, parent_path, &parent_st); + ret = SMB_VFS_STAT(conn, inherit_from_dir, &parent_st); if (ret == -1) { - DEBUG(0,("change_fd_owner_to_parent: failed to stat parent " + DEBUG(0,("change_file_owner_to_parent: failed to stat parent " "directory %s. Error was %s\n", - parent_path, strerror(errno) )); + inherit_from_dir, strerror(errno) )); return; } @@ -103,33 +103,33 @@ static void change_fd_owner_to_parent(connection_struct *conn, ret = SMB_VFS_FCHOWN(fsp, fsp->fh->fd, parent_st.st_uid, (gid_t)-1); unbecome_root(); if (ret == -1) { - DEBUG(0,("change_fd_owner_to_parent: failed to fchown " + DEBUG(0,("change_file_owner_to_parent: failed to fchown " "file %s to parent directory uid %u. Error " "was %s\n", fsp->fsp_name, (unsigned int)parent_st.st_uid, strerror(errno) )); } - DEBUG(10,("change_fd_owner_to_parent: changed new file %s to " + DEBUG(10,("change_file_owner_to_parent: changed new file %s to " "parent directory uid %u.\n", fsp->fsp_name, (unsigned int)parent_st.st_uid )); } -static void change_owner_to_parent(connection_struct *conn, - const char *fname, - SMB_STRUCT_STAT *psbuf) +static void change_dir_owner_to_parent(connection_struct *conn, + const char *inherit_from_dir, + const char *fname, + SMB_STRUCT_STAT *psbuf) { pstring saved_dir; SMB_STRUCT_STAT sbuf; - const char *parent_path = parent_dirname(fname); SMB_STRUCT_STAT parent_st; int ret; - ret = SMB_VFS_STAT(conn, parent_path, &parent_st); + ret = SMB_VFS_STAT(conn, inherit_from_dir, &parent_st); if (ret == -1) { - DEBUG(0,("change_owner_to_parent: failed to stat parent " + DEBUG(0,("change_dir_owner_to_parent: failed to stat parent " "directory %s. Error was %s\n", - parent_path, strerror(errno) )); + inherit_from_dir, strerror(errno) )); return; } @@ -141,21 +141,21 @@ static void change_owner_to_parent(connection_struct *conn, */ if (!vfs_GetWd(conn,saved_dir)) { - DEBUG(0,("change_owner_to_parent: failed to get " + DEBUG(0,("change_dir_owner_to_parent: failed to get " "current working directory\n")); return; } /* Chdir into the new path. */ if (vfs_ChDir(conn, fname) == -1) { - DEBUG(0,("change_owner_to_parent: failed to change " + DEBUG(0,("change_dir_owner_to_parent: failed to change " "current working directory to %s. Error " "was %s\n", fname, strerror(errno) )); goto out; } if (SMB_VFS_STAT(conn,".",&sbuf) == -1) { - DEBUG(0,("change_owner_to_parent: failed to stat " + DEBUG(0,("change_dir_owner_to_parent: failed to stat " "directory '.' (%s) Error was %s\n", fname, strerror(errno))); goto out; @@ -165,7 +165,7 @@ static void change_owner_to_parent(connection_struct *conn, if (sbuf.st_dev != psbuf->st_dev || sbuf.st_ino != psbuf->st_ino || sbuf.st_mode != psbuf->st_mode ) { - DEBUG(0,("change_owner_to_parent: " + DEBUG(0,("change_dir_owner_to_parent: " "device/inode/mode on directory %s changed. " "Refusing to chown !\n", fname )); goto out; @@ -175,14 +175,14 @@ static void change_owner_to_parent(connection_struct *conn, ret = SMB_VFS_CHOWN(conn, ".", parent_st.st_uid, (gid_t)-1); unbecome_root(); if (ret == -1) { - DEBUG(10,("change_owner_to_parent: failed to chown " + DEBUG(10,("change_dir_owner_to_parent: failed to chown " "directory %s to parent directory uid %u. " "Error was %s\n", fname, (unsigned int)parent_st.st_uid, strerror(errno) )); goto out; } - DEBUG(10,("change_owner_to_parent: changed ownership of new " + DEBUG(10,("change_dir_owner_to_parent: changed ownership of new " "directory %s to parent directory uid %u.\n", fname, (unsigned int)parent_st.st_uid )); @@ -197,6 +197,7 @@ static void change_owner_to_parent(connection_struct *conn, static NTSTATUS open_file(files_struct *fsp, connection_struct *conn, + const char *parent_dir, const char *fname, SMB_STRUCT_STAT *psbuf, int flags, @@ -297,12 +298,14 @@ static NTSTATUS open_file(files_struct *fsp, /* Inherit the ACL if required */ if (lp_inherit_perms(SNUM(conn))) { - inherit_access_acl(conn, fname, unx_mode); + inherit_access_acl(conn, parent_dir, fname, + unx_mode); } /* Change the owner if required. */ if (lp_inherit_owner(SNUM(conn))) { - change_fd_owner_to_parent(conn, fsp); + change_file_owner_to_parent(conn, parent_dir, + fsp); } } @@ -1124,6 +1127,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, uint32 open_access_mask = access_mask; NTSTATUS status; int ret_flock; + const char *parent_dir; if (conn->printer) { /* @@ -1140,9 +1144,15 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return print_fsp_open(conn, fname, result); } + if (!(parent_dir = talloc_strdup(tmp_talloc_ctx(), + parent_dirname(fname)))) { + return NT_STATUS_NO_MEMORY; + } + /* We add aARCH to this as this mode is only used if the file is * created new. */ - unx_mode = unix_mode(conn, new_dos_attributes | aARCH,fname, True); + unx_mode = unix_mode(conn, new_dos_attributes | aARCH, fname, + parent_dir); DEBUG(10, ("open_file_ntcreate: fname=%s, dos_attrs=0x%x " "access_mask=0x%x share_access=0x%x " @@ -1194,7 +1204,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, /* this is for OS/2 long file names - say we don't support them */ if (!lp_posix_pathnames() && strstr(fname,".+,;=[].")) { /* OS/2 Workplace shell fix may be main code stream in a later - * release. */ + * release. */ DEBUG(5,("open_file_ntcreate: OS/2 long filenames are not " "supported.\n")); if (use_nt_status()) { @@ -1554,8 +1564,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, */ 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, parent_dir))) { unx_mode = 0777; } @@ -1569,8 +1578,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, * open_file strips any O_TRUNC flags itself. */ - fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode, - access_mask, open_access_mask); + fsp_open = open_file(fsp, conn, parent_dir, fname, psbuf, flags|flags2, + unx_mode, access_mask, open_access_mask); if (!NT_STATUS_IS_OK(fsp_open)) { if (lck != NULL) { @@ -1658,7 +1667,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, ret_flock = SMB_VFS_KERNEL_FLOCK(fsp, fsp->fh->fd, share_access); if(ret_flock == -1 ){ - talloc_free(lck); + TALLOC_FREE(lck); fd_close(conn, fsp); file_free(fsp); @@ -1755,7 +1764,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, lp_store_dos_attributes(SNUM(conn))) { file_set_dosmode(conn, fname, new_dos_attributes | aARCH, NULL, - True); + parent_dir); } } @@ -1835,7 +1844,8 @@ NTSTATUS open_file_fchmod(connection_struct *conn, const char *fname, /* note! we must use a non-zero desired access or we don't get a real file descriptor. Oh what a twisted web we weave. */ - status = open_file(fsp,conn,fname,psbuf,O_WRONLY,0,FILE_WRITE_DATA,FILE_WRITE_DATA); + status = open_file(fsp, conn, NULL, fname, psbuf, O_WRONLY, 0, + FILE_WRITE_DATA, FILE_WRITE_DATA); /* * This is not a user visible file open. @@ -1868,6 +1878,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, { int ret= -1; mode_t mode; + const char *parent_dir; if(!CAN_WRITE(conn)) { DEBUG(5,("mkdir_internal: failing create on read-only share " @@ -1879,7 +1890,12 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, return map_nt_error_from_unix(errno); } - mode = unix_mode(conn, aDIR, name, True); + if (!(parent_dir = talloc_strdup(tmp_talloc_ctx(), + parent_dirname(name)))) { + return NT_STATUS_NO_MEMORY; + } + + mode = unix_mode(conn, aDIR, name, parent_dir); if ((ret=SMB_VFS_MKDIR(conn, name, mode)) != 0) { return map_nt_error_from_unix(errno); @@ -1901,7 +1917,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, } if (lp_inherit_perms(SNUM(conn))) { - inherit_access_acl(conn, name, mode); + inherit_access_acl(conn, parent_dir, name, mode); } /* @@ -1917,7 +1933,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, /* Change the owner if required. */ if (lp_inherit_owner(SNUM(conn))) { - change_owner_to_parent(conn, name, psbuf); + change_dir_owner_to_parent(conn, parent_dir, name, psbuf); } return NT_STATUS_OK; -- cgit From 98c082489bec0a0ce4db1daf4390e785381f229a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 28 Dec 2006 21:50:31 +0000 Subject: r20394: This is a *VERY* early start of my work on notify. Checking in because Jeremy was bugging me. Potentially this becomes quite intrusive, I'm not sure if I should open a temporary branch for this. Jeremy, Jerry, do you think 3_0 is the right place for this? Volker (This used to be commit bcf5c751cbe203c00814642e26440cf88f300bce) --- source3/smbd/open.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 28170e9cd8..040b0543aa 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1127,7 +1127,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, uint32 open_access_mask = access_mask; NTSTATUS status; int ret_flock; - const char *parent_dir; + char *parent_dir; + const char *newname; if (conn->printer) { /* @@ -1144,8 +1145,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return print_fsp_open(conn, fname, result); } - if (!(parent_dir = talloc_strdup(tmp_talloc_ctx(), - parent_dirname(fname)))) { + if (!parent_dirname_talloc(tmp_talloc_ctx(), fname, &parent_dir, + &newname)) { return NT_STATUS_NO_MEMORY; } @@ -1878,7 +1879,8 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, { int ret= -1; mode_t mode; - const char *parent_dir; + char *parent_dir; + const char *dirname; if(!CAN_WRITE(conn)) { DEBUG(5,("mkdir_internal: failing create on read-only share " @@ -1890,8 +1892,8 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, return map_nt_error_from_unix(errno); } - if (!(parent_dir = talloc_strdup(tmp_talloc_ctx(), - parent_dirname(name)))) { + if (!parent_dirname_talloc(tmp_talloc_ctx(), name, &parent_dir, + &dirname)) { return NT_STATUS_NO_MEMORY; } @@ -1936,6 +1938,8 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, change_dir_owner_to_parent(conn, parent_dir, name, psbuf); } + notify_action(conn, parent_dir, dirname, NOTIFY_ACTION_ADDED); + return NT_STATUS_OK; } -- cgit From 165f5f3f40317c1e75d60a977270f903f7475f69 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 31 Dec 2006 10:16:03 +0000 Subject: r20433: Work in progress: Survive more of RAW-NOTIFY. call_nt_transact_notify_change() is now sync if there are changes around. A notify_message does a direct reply from within the message, so process_pending_change_notify_queue is not needed anymore for samba-generated events. Next step is to restructure the kernel-mechanisms to generate messages. Volker (This used to be commit c813f71d0036ec52c99a97e60fe33ee47d0635fa) --- source3/smbd/open.c | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 040b0543aa..895dd48221 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -198,7 +198,8 @@ static void change_dir_owner_to_parent(connection_struct *conn, static NTSTATUS open_file(files_struct *fsp, connection_struct *conn, const char *parent_dir, - const char *fname, + const char *name, + const char *path, SMB_STRUCT_STAT *psbuf, int flags, mode_t unx_mode, @@ -227,7 +228,7 @@ static NTSTATUS open_file(files_struct *fsp, 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)); + DEBUG(3,("Permission denied opening %s\n", path)); return NT_STATUS_ACCESS_DENIED; } else if(flags & O_CREAT) { /* We don't want to write - but we must make sure that @@ -253,7 +254,7 @@ static NTSTATUS open_file(files_struct *fsp, if ((accmode == O_RDONLY) && ((flags & O_TRUNC) == O_TRUNC)) { DEBUG(10,("open_file: truncate requested on read-only open " - "for file %s\n",fname )); + "for file %s\n", path)); local_flags = (flags & ~O_ACCMODE)|O_RDWR; } @@ -282,15 +283,15 @@ static NTSTATUS open_file(files_struct *fsp, /* Don't create files with Microsoft wildcard characters. */ if ((local_flags & O_CREAT) && !file_existed && - ms_has_wild(fname)) { + ms_has_wild(path)) { return NT_STATUS_OBJECT_NAME_INVALID; } /* Actually do the open */ - if (!fd_open(conn, fname, fsp, local_flags, unx_mode)) { + if (!fd_open(conn, path, fsp, local_flags, unx_mode)) { DEBUG(3,("Error opening file %s (%s) (local_flags=%d) " "(flags=%d)\n", - fname,strerror(errno),local_flags,flags)); + path,strerror(errno),local_flags,flags)); return map_nt_error_from_unix(errno); } @@ -298,7 +299,7 @@ static NTSTATUS open_file(files_struct *fsp, /* Inherit the ACL if required */ if (lp_inherit_perms(SNUM(conn))) { - inherit_access_acl(conn, parent_dir, fname, + inherit_access_acl(conn, parent_dir, path, unx_mode); } @@ -307,6 +308,9 @@ static NTSTATUS open_file(files_struct *fsp, change_file_owner_to_parent(conn, parent_dir, fsp); } + + notify_action(conn, parent_dir, name, + NOTIFY_ACTION_ADDED); } } else { @@ -317,13 +321,13 @@ static NTSTATUS open_file(files_struct *fsp, int ret; if (fsp->fh->fd == -1) { - ret = SMB_VFS_STAT(conn, fname, psbuf); + ret = SMB_VFS_STAT(conn, path, psbuf); } else { ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf); /* If we have an fd, this stat should succeed. */ if (ret == -1) { DEBUG(0,("Error doing fstat on open file %s " - "(%s)\n", fname,strerror(errno) )); + "(%s)\n", path,strerror(errno) )); } } @@ -365,12 +369,13 @@ static NTSTATUS open_file(files_struct *fsp, fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = False; fsp->is_stat = False; - if (conn->aio_write_behind_list && - is_in_path(fname, conn->aio_write_behind_list, conn->case_sensitive)) { + if (conn->aio_write_behind_list + && is_in_path(path, conn->aio_write_behind_list, + conn->case_sensitive)) { fsp->aio_write_behind = True; } - string_set(&fsp->fsp_name,fname); + string_set(&fsp->fsp_name, path); fsp->wcp = NULL; /* Write cache pointer. */ DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n", @@ -1579,8 +1584,9 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, * open_file strips any O_TRUNC flags itself. */ - fsp_open = open_file(fsp, conn, parent_dir, fname, psbuf, flags|flags2, - unx_mode, access_mask, open_access_mask); + fsp_open = open_file(fsp, conn, parent_dir, newname, fname, psbuf, + flags|flags2, unx_mode, access_mask, + open_access_mask); if (!NT_STATUS_IS_OK(fsp_open)) { if (lck != NULL) { @@ -1845,7 +1851,7 @@ NTSTATUS open_file_fchmod(connection_struct *conn, const char *fname, /* note! we must use a non-zero desired access or we don't get a real file descriptor. Oh what a twisted web we weave. */ - status = open_file(fsp, conn, NULL, fname, psbuf, O_WRONLY, 0, + status = open_file(fsp, conn, NULL, NULL, fname, psbuf, O_WRONLY, 0, FILE_WRITE_DATA, FILE_WRITE_DATA); /* -- cgit From 92d02f7afe439a51f5a2eab3e1db8d628c170a6c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 1 Jan 2007 18:11:32 +0000 Subject: r20451: Survive the first of the filter-tests (mkdir). Add lots of TODOs :-) Volker (This used to be commit 0e953884a15873b0962ab1ab064d6b3a436726c0) --- source3/smbd/open.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 895dd48221..81537e0be3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -309,7 +309,7 @@ static NTSTATUS open_file(files_struct *fsp, fsp); } - notify_action(conn, parent_dir, name, + notify_action(conn, parent_dir, name, -1, NOTIFY_ACTION_ADDED); } @@ -1944,7 +1944,8 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, change_dir_owner_to_parent(conn, parent_dir, name, psbuf); } - notify_action(conn, parent_dir, dirname, NOTIFY_ACTION_ADDED); + notify_action(conn, parent_dir, dirname, FILE_NOTIFY_CHANGE_DIR_NAME, + NOTIFY_ACTION_ADDED); return NT_STATUS_OK; } -- cgit From 46fdae1b6b1b8e3285447193cb10e5a2a444d431 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 9 Jan 2007 16:12:54 +0000 Subject: r20634: A *LOT* more work is necessary before touching notify remotely starts to make sense. Until then, remove it from the tree to keep the diff between 3_0_24 and 3_0 small. Volker (This used to be commit f146a85e74c84e78a11e616a1cbeaeef4693a0e0) --- source3/smbd/open.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 81537e0be3..bccc91bbd3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -309,8 +309,6 @@ static NTSTATUS open_file(files_struct *fsp, fsp); } - notify_action(conn, parent_dir, name, -1, - NOTIFY_ACTION_ADDED); } } else { @@ -1944,9 +1942,6 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, change_dir_owner_to_parent(conn, parent_dir, name, psbuf); } - notify_action(conn, parent_dir, dirname, FILE_NOTIFY_CHANGE_DIR_NAME, - NOTIFY_ACTION_ADDED); - return NT_STATUS_OK; } -- cgit From 60c1a8e5a8f905a5ae703dac05ed2f440875ad5d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 17 Jan 2007 02:44:27 +0000 Subject: r20845: Somehow I missed this one - should have been part of the previous commit :-(. Jeremy. (This used to be commit 8fe3829e8a884ce2ddb91121d46b7a3a385874c1) --- source3/smbd/open.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index bccc91bbd3..49dfad3bc0 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1189,8 +1189,9 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, remove_deferred_open_smb_message(mid); } - if (!check_name(fname,conn)) { - return map_nt_error_from_unix(errno); + status = check_name(conn, fname); + if (!NT_STATUS_IS_OK(status)) { + return status; } new_dos_attributes &= SAMBA_ATTRIBUTES_MASK; @@ -1885,6 +1886,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, mode_t mode; char *parent_dir; const char *dirname; + NTSTATUS status; if(!CAN_WRITE(conn)) { DEBUG(5,("mkdir_internal: failing create on read-only share " @@ -1892,8 +1894,9 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, return NT_STATUS_ACCESS_DENIED; } - if (!check_name(name, conn)) { - return map_nt_error_from_unix(errno); + status = check_name(conn, name); + if (!NT_STATUS_IS_OK(status)) { + return status; } if (!parent_dirname_talloc(tmp_talloc_ctx(), name, &parent_dir, -- cgit From 940192ddcc9d23e3bec806b4419d5845eeac0fd0 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 17 Jan 2007 16:23:45 +0000 Subject: r20854: Ok, now I think we're at a point where looking at notify starts to make sense again :-) Volker (This used to be commit 5533cdeec1b0cdee39b1d89e2320587dc9281ee6) --- source3/smbd/open.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 49dfad3bc0..4249c6e85b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -309,6 +309,8 @@ static NTSTATUS open_file(files_struct *fsp, fsp); } + notify_action(conn, parent_dir, name, -1, + NOTIFY_ACTION_ADDED); } } else { @@ -1945,6 +1947,9 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, change_dir_owner_to_parent(conn, parent_dir, name, psbuf); } + notify_action(conn, parent_dir, dirname, FILE_NOTIFY_CHANGE_DIR_NAME, + NOTIFY_ACTION_ADDED); + return NT_STATUS_OK; } -- cgit From fd37f98158161406229b728a7c767121a30e254f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 18 Jan 2007 06:19:24 +0000 Subject: r20873: Some correctness fixes w.r.t. Samba4 torture BASE-DELETE. Allow us to correctly refuse to set delete on close on a non-empty directory. There are still some delete-on-close wrinkles to be fixed, but I understand how to do that better now. I'll fix this tomorrow. Jeremy. (This used to be commit 029635885825a5562e7974a6f5675cce3bf1b5dc) --- source3/smbd/open.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 4249c6e85b..c0638c0039 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2110,15 +2110,17 @@ NTSTATUS open_directory(connection_struct *conn, always to be honored on close... See test 19 in Samba4 BASE-DELETE. */ if (create_options & FILE_DELETE_ON_CLOSE) { status = can_set_delete_on_close(fsp, True, 0); - if (!NT_STATUS_IS_OK(status)) { + if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, NT_STATUS_DIRECTORY_NOT_EMPTY)) { TALLOC_FREE(lck); file_free(fsp); return status; } - set_delete_on_close_token(lck, ¤t_user.ut); - lck->initial_delete_on_close = True; - lck->modified = True; + if (NT_STATUS_IS_OK(status)) { + set_delete_on_close_token(lck, ¤t_user.ut); + lck->initial_delete_on_close = True; + lck->modified = True; + } } TALLOC_FREE(lck); -- cgit From c9a14ea19f812d86266bfa9e6ce8b32f7b4ff19f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 18 Jan 2007 21:51:52 +0000 Subject: r20883: W00t! I now understand how "delete on close" really works - even with the strange "initial delete on close" semantics. The "initial delete on close" flag isn't committed to the share mode db until the handle is closed, and is discarded if any real "delete on close" was set. This allows me to remove the "initial_delete_on_close" flag from the share db, and move it into a BOOL in files_struct. Warning ! You must do a make clean after this. Cope with the wrinkle in directory delete on close which is done differently from files. We now pass all Samba4 smbtortute BASE-DELETE tests except for the one checking that files can't be created in a directory which has the delete on close set (possibly expensive to fix). Jeremy. (This used to be commit f2df77a1497958c1ea791f1d2f4446b5fc3389b3) --- source3/smbd/open.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index c0638c0039..a5a8eacda0 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1761,10 +1761,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return status; } /* Note that here we set the *inital* delete on close flag, - not the regular one. */ - set_delete_on_close_token(lck, ¤t_user.ut); - lck->initial_delete_on_close = True; - lck->modified = True; + not the regular one. The magic gets handled in close. */ + fsp->initial_delete_on_close = True; } /* Files should be initially set as archive */ @@ -2117,9 +2115,9 @@ NTSTATUS open_directory(connection_struct *conn, } if (NT_STATUS_IS_OK(status)) { - set_delete_on_close_token(lck, ¤t_user.ut); - lck->initial_delete_on_close = True; - lck->modified = True; + /* Note that here we set the *inital* delete on close flag, + not the regular one. The magic gets handled in close. */ + fsp->initial_delete_on_close = True; } } -- cgit From caf8c6a76be051559ffcfe97084edca43e0a3cee Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 30 Jan 2007 22:22:06 +0000 Subject: r21064: The core of this patch is void message_register(int msg_type, void (*fn)(int msg_type, struct process_id pid, - void *buf, size_t len)) + void *buf, size_t len, + void *private_data), + void *private_data) { struct dispatch_fns *dfn; So this adds a (so far unused) private pointer that is passed from message_register to the message handler. A prerequisite to implement a tiny samba4-API compatible wrapper around our messaging system. That itself is necessary for the Samba4 notify system. Yes, I know, I could import the whole Samba4 messaging system, but I want to do it step by step and I think getting notify in is more important in this step. Volker (This used to be commit c8ae60ed65dcce9660ee39c75488f2838cf9a28b) --- source3/smbd/open.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index a5a8eacda0..529677a5f3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2210,7 +2210,8 @@ NTSTATUS open_file_stat(connection_struct *conn, const char *fname, smbd process. ****************************************************************************/ -void msg_file_was_renamed(int msg_type, struct process_id src, void *buf, size_t len) +void msg_file_was_renamed(int msg_type, struct process_id src, + void *buf, size_t len, void *private_data) { files_struct *fsp; char *frm = (char *)buf; -- cgit From 547f77778abc45bf329dcb53182127d72596c812 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 31 Jan 2007 14:14:57 +0000 Subject: r21087: Make the param list of notify_fname match notify_trigger (This used to be commit defa28f9c3eda85a072b972fffd2d5de8bcf01f7) --- source3/smbd/open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 529677a5f3..8dd4ed1925 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -309,8 +309,8 @@ static NTSTATUS open_file(files_struct *fsp, fsp); } - notify_action(conn, parent_dir, name, -1, - NOTIFY_ACTION_ADDED); + notify_fname(conn, NOTIFY_ACTION_ADDED, + FILE_NOTIFY_CHANGE_FILE_NAME, path); } } else { -- cgit From 9974656d3be3fb01af59bfefe592475e92bdceb0 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 31 Jan 2007 16:56:27 +0000 Subject: r21093: Remove the hash and dnotify backends. Disabling FAM for this checkin, I'm working on that right now. Volker (This used to be commit 01c9fb17281e99300b339d2cfc0acac7ca94843c) --- source3/smbd/open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 8dd4ed1925..6de620e488 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1945,8 +1945,8 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, change_dir_owner_to_parent(conn, parent_dir, name, psbuf); } - notify_action(conn, parent_dir, dirname, FILE_NOTIFY_CHANGE_DIR_NAME, - NOTIFY_ACTION_ADDED); + notify_fname(conn, NOTIFY_ACTION_ADDED, FILE_NOTIFY_CHANGE_DIR_NAME, + name); return NT_STATUS_OK; } -- cgit From 69d8c5ae5f1319e3c9430aa7d6d09ca2a62ba10a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 1 Feb 2007 19:29:07 +0000 Subject: r21115: notify_internal.c needs to remove the table entry if a process has crashed. So it needs the specific error message. Make messages.c return NTSTATUS and specificially NT_STATUS_INVALID_HANDLE if sending to a non-existent process. Volker (This used to be commit 3f620d181da0c356c8ffbdb5b380ccab3645a972) --- source3/smbd/open.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 6de620e488..2415433fe9 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -652,7 +652,7 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, BOOL valid_entry = False; BOOL delay_it = False; BOOL have_level2 = False; - BOOL ret; + NTSTATUS status; char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE]; if (oplock_request & INTERNAL_OPEN_ONLY) { @@ -740,10 +740,11 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, SSVAL(msg,6,exclusive->op_type | FORCE_OPLOCK_BREAK_TO_NONE); } - ret = message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST, - msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); - if (!ret) { - DEBUG(3, ("Could not send oplock break message\n")); + status = message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST, + msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("Could not send oplock break message: %s\n", + nt_errstr(status))); } return True; -- cgit From 7a5fa7f12ec439ef5a4af29aa86498f799b6b9a5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 6 Feb 2007 21:05:34 +0000 Subject: r21191: Add in the POSIX open/mkdir/unlink calls. Move more error code returns to NTSTATUS. Client test code to follow... See if this passes the build-farm before I add it into 3.0.25. Jeremy. (This used to be commit 83dbbdff345fa9e427c9579183f4380004bf3dd7) --- source3/smbd/open.c | 109 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 74 insertions(+), 35 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 2415433fe9..c9e29cf0e5 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -67,14 +67,13 @@ static BOOL fd_open(struct connection_struct *conn, Close the file associated with a fsp. ****************************************************************************/ -int fd_close(struct connection_struct *conn, - files_struct *fsp) +NTSTATUS fd_close(struct connection_struct *conn, files_struct *fsp) { if (fsp->fh->fd == -1) { - return 0; /* What we used to call a stat open. */ + return NT_STATUS_OK; /* What we used to call a stat open. */ } if (fsp->fh->ref_count > 1) { - return 0; /* Shared handle. Only close last reference. */ + return NT_STATUS_OK; /* Shared handle. Only close last reference. */ } return fd_close_posix(conn, fsp); } @@ -1118,6 +1117,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, int flags2=0; BOOL file_existed = VALID_STAT(*psbuf); BOOL def_acl = False; + BOOL posix_open = False; SMB_DEV_T dev = 0; SMB_INO_T inode = 0; NTSTATUS fsp_open = NT_STATUS_ACCESS_DENIED; @@ -1156,10 +1156,16 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return NT_STATUS_NO_MEMORY; } - /* We add aARCH to this as this mode is only used if the file is - * created new. */ - unx_mode = unix_mode(conn, new_dos_attributes | aARCH, fname, - parent_dir); + if (new_dos_attributes & FILE_FLAG_POSIX_SEMANTICS) { + posix_open = True; + unx_mode = (mode_t)(new_dos_attributes & ~FILE_FLAG_POSIX_SEMANTICS); + new_dos_attributes = 0; + } else { + /* We add aARCH to this as this mode is only used if the file is + * created new. */ + unx_mode = unix_mode(conn, new_dos_attributes | aARCH, fname, + parent_dir); + } DEBUG(10, ("open_file_ntcreate: fname=%s, dos_attrs=0x%x " "access_mask=0x%x share_access=0x%x " @@ -1197,9 +1203,11 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return status; } - new_dos_attributes &= SAMBA_ATTRIBUTES_MASK; - if (file_existed) { - existing_dos_attributes = dos_mode(conn, fname, psbuf); + if (!posix_open) { + new_dos_attributes &= SAMBA_ATTRIBUTES_MASK; + if (file_existed) { + existing_dos_attributes = dos_mode(conn, fname, psbuf); + } } /* ignore any oplock requests if oplocks are disabled */ @@ -1294,7 +1302,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, /* We only care about matching attributes on file exists and * overwrite. */ - if (file_existed && ((create_disposition == FILE_OVERWRITE) || + if (!posix_open && file_existed && ((create_disposition == FILE_OVERWRITE) || (create_disposition == FILE_OVERWRITE_IF))) { if (!open_match_attributes(conn, fname, existing_dos_attributes, @@ -1359,7 +1367,11 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } #endif /* O_SYNC */ - if (!CAN_WRITE(conn)) { + if (posix_open & (access_mask & FILE_APPEND_DATA)) { + flags2 |= O_APPEND; + } + + if (!posix_open && !CAN_WRITE(conn)) { /* * We should really return a permission denied error if either * O_CREAT or O_TRUNC are set, but for compatibility with @@ -1393,6 +1405,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, fsp->access_mask = open_access_mask; /* We change this to the * requested access_mask after * the open is done. */ + fsp->posix_open = posix_open; + /* Ensure no SAMBA_PRIVATE bits can be set. */ fsp->oplock_type = (oplock_request & ~SAMBA_PRIVATE_OPLOCK_MASK); @@ -1769,9 +1783,11 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, /* Files should be initially set as archive */ if (lp_map_archive(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) { - file_set_dosmode(conn, fname, + if (!posix_open) { + file_set_dosmode(conn, fname, new_dos_attributes | aARCH, NULL, parent_dir); + } } } @@ -1780,7 +1796,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, * selected. */ - if (!file_existed && !def_acl) { + if (!posix_open && !file_existed && !def_acl) { int saved_errno = errno; /* We might get ENOSYS in the next * call.. */ @@ -1873,15 +1889,17 @@ NTSTATUS open_file_fchmod(connection_struct *conn, const char *fname, Close the fchmod file fd - ensure no locks are lost. ****************************************************************************/ -int close_file_fchmod(files_struct *fsp) +NTSTATUS close_file_fchmod(files_struct *fsp) { - int ret = fd_close(fsp->conn, fsp); + NTSTATUS status = fd_close(fsp->conn, fsp); file_free(fsp); - return ret; + return status; } -static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, - SMB_STRUCT_STAT *psbuf) +static NTSTATUS mkdir_internal(connection_struct *conn, + const char *name, + uint32 file_attributes, + SMB_STRUCT_STAT *psbuf) { int ret= -1; mode_t mode; @@ -1905,7 +1923,11 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, return NT_STATUS_NO_MEMORY; } - mode = unix_mode(conn, aDIR, name, parent_dir); + if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) { + mode = (mode_t)(file_attributes & ~FILE_FLAG_POSIX_SEMANTICS); + } else { + mode = unix_mode(conn, aDIR, name, parent_dir); + } if ((ret=SMB_VFS_MKDIR(conn, name, mode)) != 0) { return map_nt_error_from_unix(errno); @@ -1930,15 +1952,17 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, inherit_access_acl(conn, parent_dir, name, mode); } - /* - * Check if high bits should have been set, - * then (if bits are missing): add them. - * Consider bits automagically set by UNIX, i.e. SGID bit from parent - * dir. - */ - if (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) && (mode & ~psbuf->st_mode)) { - SMB_VFS_CHMOD(conn, name, - psbuf->st_mode | (mode & ~psbuf->st_mode)); + if (!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) { + /* + * Check if high bits should have been set, + * then (if bits are missing): add them. + * Consider bits automagically set by UNIX, i.e. SGID bit from parent + * dir. + */ + if (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) && (mode & ~psbuf->st_mode)) { + SMB_VFS_CHMOD(conn, name, + psbuf->st_mode | (mode & ~psbuf->st_mode)); + } } /* Change the owner if required. */ @@ -1963,6 +1987,7 @@ NTSTATUS open_directory(connection_struct *conn, uint32 share_access, uint32 create_disposition, uint32 create_options, + uint32 file_attributes, int *pinfo, files_struct **result) { @@ -1974,12 +1999,13 @@ NTSTATUS open_directory(connection_struct *conn, DEBUG(5,("open_directory: opening directory %s, access_mask = 0x%x, " "share_access = 0x%x create_options = 0x%x, " - "create_disposition = 0x%x\n", + "create_disposition = 0x%x, file_attributes = 0x%x\n", fname, (unsigned int)access_mask, (unsigned int)share_access, (unsigned int)create_options, - (unsigned int)create_disposition)); + (unsigned int)create_disposition, + (unsigned int)file_attributes)); if (is_ntfs_stream_name(fname)) { DEBUG(0,("open_directory: %s is a stream name!\n", fname )); @@ -2006,7 +2032,11 @@ NTSTATUS open_directory(connection_struct *conn, /* If directory exists error. If directory doesn't * exist create. */ - status = mkdir_internal(conn, fname, psbuf); + status = mkdir_internal(conn, + fname, + file_attributes, + psbuf); + if (!NT_STATUS_IS_OK(status)) { DEBUG(2, ("open_directory: unable to create " "%s. Error was %s\n", fname, @@ -2023,7 +2053,10 @@ NTSTATUS open_directory(connection_struct *conn, * exist create. */ - status = mkdir_internal(conn, fname, psbuf); + status = mkdir_internal(conn, + fname, + file_attributes, + psbuf); if (NT_STATUS_IS_OK(status)) { info = FILE_WAS_CREATED; @@ -2081,6 +2114,8 @@ NTSTATUS open_directory(connection_struct *conn, fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = True; fsp->is_stat = False; + fsp->posix_open = (file_attributes & FILE_FLAG_POSIX_SEMANTICS) ? True : False; + string_set(&fsp->fsp_name,fname); lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, @@ -2145,7 +2180,11 @@ NTSTATUS create_directory(connection_struct *conn, const char *directory) status = open_directory(conn, directory, &sbuf, FILE_READ_ATTRIBUTES, /* Just a stat open */ FILE_SHARE_NONE, /* Ignored for stat opens */ - FILE_CREATE, 0, NULL, &fsp); + FILE_CREATE, + 0, + FILE_ATTRIBUTE_DIRECTORY, + NULL, + &fsp); if (NT_STATUS_IS_OK(status)) { close_file(fsp, NORMAL_CLOSE); -- cgit From d9a29aade0f01df1fa00ccdb8691b02b39bc1d14 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 11 Feb 2007 14:39:21 +0000 Subject: r21279: Get rid of 'aio write behind', this is broken. It should probably better be integrated with our write cache. Volker (This used to be commit 58bfd168b046a97a895aaa3384fd7af8d077a1d5) --- source3/smbd/open.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index c9e29cf0e5..32f70eb0af 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -368,11 +368,6 @@ static NTSTATUS open_file(files_struct *fsp, fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = False; fsp->is_stat = False; - if (conn->aio_write_behind_list - && is_in_path(path, conn->aio_write_behind_list, - conn->case_sensitive)) { - fsp->aio_write_behind = True; - } string_set(&fsp->fsp_name, path); fsp->wcp = NULL; /* Write cache pointer. */ -- cgit From a9dbdf937c4901c4e791bff0753bafe709bc0fa5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 21 Feb 2007 01:55:08 +0000 Subject: r21480: Make fd_open match fd_close be translating errno into an NTSTATUS immediately. Jeremy. (This used to be commit 71dd02cc164197152e76d8141f906390c4bd1526) --- source3/smbd/open.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 32f70eb0af..f03c8216d4 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -38,13 +38,13 @@ struct deferred_open_record { fd support routines - attempt to do a dos_open. ****************************************************************************/ -static BOOL fd_open(struct connection_struct *conn, +static NTSTATUS fd_open(struct connection_struct *conn, const char *fname, files_struct *fsp, int flags, mode_t mode) { - int sav; + NTSTATUS status = NT_STATUS_OK; #ifdef O_NOFOLLOW if (!lp_symlinks(SNUM(conn))) { @@ -53,14 +53,15 @@ static BOOL fd_open(struct connection_struct *conn, #endif fsp->fh->fd = SMB_VFS_OPEN(conn,fname,fsp,flags,mode); - sav = errno; + if (fsp->fh->fd == -1) { + status = map_nt_error_from_unix(errno); + } DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n", fname, flags, (int)mode, fsp->fh->fd, (fsp->fh->fd == -1) ? strerror(errno) : "" )); - errno = sav; - return fsp->fh->fd != -1; + return status; } /**************************************************************************** @@ -205,6 +206,7 @@ static NTSTATUS open_file(files_struct *fsp, uint32 access_mask, /* client requested access mask. */ uint32 open_access_mask) /* what we're actually using in the open. */ { + NTSTATUS status = NT_STATUS_OK; int accmode = (flags & O_ACCMODE); int local_flags = flags; BOOL file_existed = VALID_STAT(*psbuf); @@ -287,11 +289,12 @@ static NTSTATUS open_file(files_struct *fsp, } /* Actually do the open */ - if (!fd_open(conn, path, fsp, local_flags, unx_mode)) { + status = fd_open(conn, path, fsp, local_flags, unx_mode); + if (!NT_STATUS_IS_OK(status)) { DEBUG(3,("Error opening file %s (%s) (local_flags=%d) " "(flags=%d)\n", - path,strerror(errno),local_flags,flags)); - return map_nt_error_from_unix(errno); + path,nt_errstr(status),local_flags,flags)); + return status; } if ((local_flags & O_CREAT) && !file_existed) { @@ -332,7 +335,7 @@ static NTSTATUS open_file(files_struct *fsp, /* For a non-io open, this stat failing means file not found. JRA */ if (ret == -1) { - NTSTATUS status = map_nt_error_from_unix(errno); + status = map_nt_error_from_unix(errno); fd_close(conn, fsp); return status; } -- cgit From 1f56aabf903c13b170d36e12e50c804f2cbeb79c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 2 Mar 2007 22:19:53 +0000 Subject: r21665: Fix bug #4428 reported by Jason Mader . Jeremy. (This used to be commit fe00771df517071c5e654e0b2b9cfde2d88bd701) --- source3/smbd/open.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index f03c8216d4..f959f00b10 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1899,7 +1899,6 @@ static NTSTATUS mkdir_internal(connection_struct *conn, uint32 file_attributes, SMB_STRUCT_STAT *psbuf) { - int ret= -1; mode_t mode; char *parent_dir; const char *dirname; @@ -1927,7 +1926,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, mode = unix_mode(conn, aDIR, name, parent_dir); } - if ((ret=SMB_VFS_MKDIR(conn, name, mode)) != 0) { + if (SMB_VFS_MKDIR(conn, name, mode) != 0) { return map_nt_error_from_unix(errno); } -- cgit From e6383f47629368d9dd4e803f17566a24e9d7359e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 7 May 2007 09:35:35 +0000 Subject: r22736: Start to merge the low-hanging fruit from the now 7000-line cluster patch. This changes "struct process_id" to "struct server_id", keeping both is just too much hassle. No functional change (I hope ;-)) Volker (This used to be commit 0ad4b1226c9d91b72136310d3bbb640d2c5d67b8) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index f959f00b10..e891209d2b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2247,7 +2247,7 @@ NTSTATUS open_file_stat(connection_struct *conn, const char *fname, smbd process. ****************************************************************************/ -void msg_file_was_renamed(int msg_type, struct process_id src, +void msg_file_was_renamed(int msg_type, struct server_id src, void *buf, size_t len, void *private_data) { files_struct *fsp; -- cgit From fad7dd8a60e6637598b17fa89ec92d98db51fffe Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 14 May 2007 20:31:28 +0000 Subject: r22868: Replace some message_send_pid calls with messaging_send_pid calls. More tomorrow. (This used to be commit 74fa57ca5d7fa8eace72bbe948a08a0bca3cc4ca) --- source3/smbd/open.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index e891209d2b..35dc13d86c 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -737,8 +737,10 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, SSVAL(msg,6,exclusive->op_type | FORCE_OPLOCK_BREAK_TO_NONE); } - status = message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST, - msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True); + status = messaging_send_buf(smbd_messaging_context(), exclusive->pid, + MSG_SMB_BREAK_REQUEST, + (uint8 *)msg, + MSG_SMB_SHARE_MODE_ENTRY_SIZE); if (!NT_STATUS_IS_OK(status)) { DEBUG(3, ("Could not send oplock break message: %s\n", nt_errstr(status))); -- cgit From 81acb2d8051544f3ca9cfdfb964a7560dfad6105 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 16 May 2007 14:24:06 +0000 Subject: r22942: Some message_register -> messaging_register conversions (This used to be commit 65335a420645202fc79c599a1177838ec19a4075) --- source3/smbd/open.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 35dc13d86c..1a8a087bb7 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2249,19 +2249,24 @@ NTSTATUS open_file_stat(connection_struct *conn, const char *fname, smbd process. ****************************************************************************/ -void msg_file_was_renamed(int msg_type, struct server_id src, - void *buf, size_t len, void *private_data) +void msg_file_was_renamed(struct messaging_context *msg, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) { files_struct *fsp; - char *frm = (char *)buf; + char *frm = (char *)data->data; SMB_DEV_T dev; SMB_INO_T inode; const char *sharepath; const char *newname; size_t sp_len; - if (buf == NULL || len < MSG_FILE_RENAMED_MIN_SIZE + 2) { - DEBUG(0, ("msg_file_was_renamed: Got invalid msg len %d\n", (int)len)); + if (data->data == NULL + || data->length < MSG_FILE_RENAMED_MIN_SIZE + 2) { + DEBUG(0, ("msg_file_was_renamed: Got invalid msg len %d\n", + data->length)); return; } -- cgit From 828cb240047506afd292a613742ff88ee994896e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 22 May 2007 22:35:13 +0000 Subject: r23087: Fix POSIX setfilepathinfo to use lstat, not stat. Still missing lchown (will add this for 3.0.26). Don't merge for 3.0.25a - possibly 3.0.25b (if it exists). Jeremy. (This used to be commit f546750176a22cdd7298a73afc81587923baaff9) --- source3/smbd/open.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 1a8a087bb7..7784740063 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -47,7 +47,12 @@ static NTSTATUS fd_open(struct connection_struct *conn, NTSTATUS status = NT_STATUS_OK; #ifdef O_NOFOLLOW - if (!lp_symlinks(SNUM(conn))) { + /* + * Never follow symlinks on a POSIX client. The + * client should be doing this. + */ + + if (fsp->posix_open || !lp_symlinks(SNUM(conn))) { flags |= O_NOFOLLOW; } #endif -- cgit From dbfd6bf8c8cc9945c4ba7e22ac44b1f33f9c7ce6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 23 May 2007 21:32:10 +0000 Subject: r23100: Implement the delete on close semantics I've just tested for in Samba4 smbtorture. Fix rename on an open file handle. Needed for 3.0.25a. Jeremy. (This used to be commit a301467d5f645dada27093ddfd74890b88bb4ce8) --- source3/smbd/open.c | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 7784740063..89ff9ae809 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1123,6 +1123,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, BOOL file_existed = VALID_STAT(*psbuf); BOOL def_acl = False; BOOL posix_open = False; + BOOL new_file_created = False; SMB_DEV_T dev = 0; SMB_INO_T inode = 0; NTSTATUS fsp_open = NT_STATUS_ACCESS_DENIED; @@ -1763,28 +1764,31 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, fsp->oplock_type = NO_OPLOCK; } } - set_share_mode(lck, fsp, current_user.ut.uid, 0, fsp->oplock_type); - if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || - info == FILE_WAS_SUPERSEDED) { + if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || info == FILE_WAS_SUPERSEDED) { + new_file_created = True; + } - /* Handle strange delete on close create semantics. */ - if (create_options & FILE_DELETE_ON_CLOSE) { - status = can_set_delete_on_close(fsp, True, new_dos_attributes); + set_share_mode(lck, fsp, current_user.ut.uid, 0, fsp->oplock_type, new_file_created); - if (!NT_STATUS_IS_OK(status)) { - /* Remember to delete the mode we just added. */ - del_share_mode(lck, fsp); - TALLOC_FREE(lck); - fd_close(conn,fsp); - file_free(fsp); - return status; - } - /* Note that here we set the *inital* delete on close flag, - not the regular one. The magic gets handled in close. */ - fsp->initial_delete_on_close = True; + /* Handle strange delete on close create semantics. */ + if ((create_options & FILE_DELETE_ON_CLOSE) && can_set_initial_delete_on_close(lck)) { + status = can_set_delete_on_close(fsp, True, new_dos_attributes); + + if (!NT_STATUS_IS_OK(status)) { + /* Remember to delete the mode we just added. */ + del_share_mode(lck, fsp); + TALLOC_FREE(lck); + fd_close(conn,fsp); + file_free(fsp); + return status; } + /* Note that here we set the *inital* delete on close flag, + not the regular one. The magic gets handled in close. */ + fsp->initial_delete_on_close = True; + } + if (new_file_created) { /* Files should be initially set as archive */ if (lp_map_archive(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) { @@ -2142,7 +2146,7 @@ NTSTATUS open_directory(connection_struct *conn, return status; } - set_share_mode(lck, fsp, current_user.ut.uid, 0, NO_OPLOCK); + set_share_mode(lck, fsp, current_user.ut.uid, 0, NO_OPLOCK, True); /* For directories the delete on close bit at open time seems always to be honored on close... See test 19 in Samba4 BASE-DELETE. */ -- cgit From 4c795b293d34db5fa334c7627fa86d0ed197adcb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 26 May 2007 01:19:51 +0000 Subject: r23150: Fix Samba3 in the build farm again. In the case where the file was being created and we go into the race condition check, we were testing for compatible open modes, but were not breaking oplocks in the same way as if the file existed. This meant that we weren't going into the code path that sets fsp->oplock = FAKE_LEVEL_II_OPLOCK if the client didn't ask for an oplock on file create. We need to do this as internally it's what Windows does. Jeremy. (This used to be commit 9b9513856e9e9f84d5acd94e3e3d6e73358ee7dc) --- source3/smbd/open.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 89ff9ae809..ccd12c6946 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1650,6 +1650,15 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return NT_STATUS_SHARING_VIOLATION; } + /* First pass - send break only on batch oplocks. */ + if (delay_for_oplocks(lck, fsp, 1, oplock_request)) { + schedule_defer_open(lck, request_time); + TALLOC_FREE(lck); + fd_close(conn, fsp); + file_free(fsp); + return NT_STATUS_SHARING_VIOLATION; + } + status = open_mode_check(conn, fname, lck, access_mask, share_access, create_options, &file_existed); @@ -1677,6 +1686,14 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return status; } + if (delay_for_oplocks(lck, fsp, 2, oplock_request)) { + schedule_defer_open(lck, request_time); + TALLOC_FREE(lck); + fd_close(conn, fsp); + file_free(fsp); + return NT_STATUS_SHARING_VIOLATION; + } + /* * We exit this block with the share entry *locked*..... */ -- cgit From f3de07503af29e5593255324fb1f901e878dc776 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 26 May 2007 01:26:09 +0000 Subject: r23151: Re-arrange the logic so it looks identical to the "file existed" case above. This has no functional change but is easier to see that it's doing the same thing. Jeremy. (This used to be commit 0a7d8362be8379b77e6afb803ab88d726ae7877d) --- source3/smbd/open.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index ccd12c6946..987da7a94d 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1663,6 +1663,20 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, access_mask, share_access, create_options, &file_existed); + if (NT_STATUS_IS_OK(status)) { + /* We might be going to allow this open. Check oplock + * status again. */ + /* Second pass - send break for both batch or + * exclusive oplocks. */ + if (delay_for_oplocks(lck, fsp, 2, oplock_request)) { + schedule_defer_open(lck, request_time); + TALLOC_FREE(lck); + fd_close(conn, fsp); + file_free(fsp); + return NT_STATUS_SHARING_VIOLATION; + } + } + if (!NT_STATUS_IS_OK(status)) { struct deferred_open_record state; @@ -1686,14 +1700,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return status; } - if (delay_for_oplocks(lck, fsp, 2, oplock_request)) { - schedule_defer_open(lck, request_time); - TALLOC_FREE(lck); - fd_close(conn, fsp); - file_free(fsp); - return NT_STATUS_SHARING_VIOLATION; - } - /* * We exit this block with the share entry *locked*..... */ -- cgit From e8156439f24137b5418baad20a7f00f6949cfe29 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 29 May 2007 09:30:34 +0000 Subject: r23183: Check in a change made by Tridge: This replaces the internal explicit dev/ino file id representation by a "struct file_id". This is necessary as cluster file systems and NFS don't necessarily assign the same device number to the shared file system. With this structure in place we can now easily add different schemes to map a file to a unique 64-bit device node. Jeremy, you might note that I did not change the external interface of smb_share_modes.c. Volker (This used to be commit 9b10dbbd5de8813fc15ebbb6be9b18010ffe8139) --- source3/smbd/open.c | 69 ++++++++++++++++++++++------------------------------- 1 file changed, 29 insertions(+), 40 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 987da7a94d..30576f1e08 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -30,8 +30,7 @@ extern BOOL global_client_failed_oplock_break; struct deferred_open_record { BOOL delayed_for_oplocks; - SMB_DEV_T dev; - SMB_INO_T inode; + struct file_id id; }; /**************************************************************************** @@ -359,8 +358,7 @@ static NTSTATUS open_file(files_struct *fsp, } fsp->mode = psbuf->st_mode; - fsp->inode = psbuf->st_ino; - fsp->dev = psbuf->st_dev; + fsp->file_id = file_id_sbuf(psbuf); fsp->vuid = current_user.vuid; fsp->file_pid = global_smbpid; fsp->can_lock = True; @@ -513,7 +511,7 @@ static void validate_my_share_entries(int num, return; } - fsp = file_find_dif(share_entry->dev, share_entry->inode, + fsp = file_find_dif(share_entry->id, share_entry->share_file_id); if (!fsp) { DEBUG(0,("validate_my_share_entries: PANIC : %s\n", @@ -803,7 +801,7 @@ static void defer_open(struct share_mode_lock *lck, (char *)state, sizeof(*state))) { exit_server("push_deferred_smb_message failed"); } - add_deferred_open(lck, mid, request_time, state->dev, state->inode); + add_deferred_open(lck, mid, request_time, state->id); /* * Push the MID of this packet on the signing queue. @@ -871,8 +869,8 @@ static BOOL open_match_attributes(connection_struct *conn, ****************************************************************************/ static files_struct *fcb_or_dos_open(connection_struct *conn, - const char *fname, SMB_DEV_T dev, - SMB_INO_T inode, + const char *fname, + struct file_id id, uint32 access_mask, uint32 share_access, uint32 create_options) @@ -883,7 +881,7 @@ static files_struct *fcb_or_dos_open(connection_struct *conn, DEBUG(5,("fcb_or_dos_open: attempting old open semantics for " "file %s.\n", fname )); - for(fsp = file_find_di_first(dev, inode); fsp; + for(fsp = file_find_di_first(id); fsp; fsp = file_find_di_next(fsp)) { DEBUG(10,("fcb_or_dos_open: checking file %s, fd = %d, " @@ -1093,8 +1091,7 @@ static void schedule_defer_open(struct share_mode_lock *lck, struct timeval requ a 1 second delay for share mode conflicts. */ state.delayed_for_oplocks = True; - state.dev = lck->dev; - state.inode = lck->ino; + state.id = lck->id; if (!request_timed_out(request_time, timeout)) { defer_open(lck, request_time, timeout, &state); @@ -1124,8 +1121,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, BOOL def_acl = False; BOOL posix_open = False; BOOL new_file_created = False; - SMB_DEV_T dev = 0; - SMB_INO_T inode = 0; + struct file_id id; NTSTATUS fsp_open = NT_STATUS_ACCESS_DENIED; files_struct *fsp = NULL; mode_t new_unx_mode = (mode_t)0; @@ -1142,6 +1138,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, char *parent_dir; const char *newname; + ZERO_STRUCT(id); + if (conn->printer) { /* * Printers are handled completely differently. @@ -1192,7 +1190,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, request_time = pml->request_time; /* Remove the deferred open entry under lock. */ - lck = get_share_mode_lock(NULL, state->dev, state->inode, NULL, NULL); + lck = get_share_mode_lock(NULL, state->id, NULL, NULL); if (lck == NULL) { DEBUG(0, ("could not get share mode lock\n")); } else { @@ -1404,8 +1402,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return status; } - fsp->dev = psbuf->st_dev; - fsp->inode = psbuf->st_ino; + fsp->file_id = file_id_sbuf(psbuf); fsp->share_access = share_access; fsp->fh->private_options = create_options; fsp->access_mask = open_access_mask; /* We change this to the @@ -1421,10 +1418,9 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } if (file_existed) { - dev = psbuf->st_dev; - inode = psbuf->st_ino; + id = file_id_sbuf(psbuf); - lck = get_share_mode_lock(NULL, dev, inode, + lck = get_share_mode_lock(NULL, id, conn->connectpath, fname); @@ -1483,8 +1479,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, /* Use the client requested access mask here, * not the one we open with. */ - fsp_dup = fcb_or_dos_open(conn, fname, dev, - inode, access_mask, + fsp_dup = fcb_or_dos_open(conn, fname, id, + access_mask, share_access, create_options); @@ -1556,8 +1552,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, a 1 second delay for share mode conflicts. */ state.delayed_for_oplocks = False; - state.dev = dev; - state.inode = inode; + state.id = id; if (!request_timed_out(request_time, timeout)) { @@ -1635,10 +1630,9 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, * Nadav Danieli . JRA. */ - dev = fsp->dev; - inode = fsp->inode; + id = fsp->file_id; - lck = get_share_mode_lock(NULL, dev, inode, + lck = get_share_mode_lock(NULL, id, conn->connectpath, fname); @@ -1684,8 +1678,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, file_free(fsp); state.delayed_for_oplocks = False; - state.dev = dev; - state.inode = inode; + state.id = id; /* Do it all over again immediately. In the second * round we will find that the file existed and handle @@ -2127,8 +2120,7 @@ NTSTATUS open_directory(connection_struct *conn, */ fsp->mode = psbuf->st_mode; - fsp->inode = psbuf->st_ino; - fsp->dev = psbuf->st_dev; + fsp->file_id = file_id_sbuf(psbuf); fsp->vuid = current_user.vuid; fsp->file_pid = global_smbpid; fsp->can_lock = False; @@ -2149,7 +2141,7 @@ NTSTATUS open_directory(connection_struct *conn, string_set(&fsp->fsp_name,fname); - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, + lck = get_share_mode_lock(NULL, fsp->file_id, conn->connectpath, fname); @@ -2255,8 +2247,7 @@ NTSTATUS open_file_stat(connection_struct *conn, const char *fname, */ fsp->mode = psbuf->st_mode; - fsp->inode = psbuf->st_ino; - fsp->dev = psbuf->st_dev; + fsp->file_id = file_id_sbuf(psbuf); fsp->vuid = current_user.vuid; fsp->file_pid = global_smbpid; fsp->can_lock = False; @@ -2289,8 +2280,7 @@ void msg_file_was_renamed(struct messaging_context *msg, { files_struct *fsp; char *frm = (char *)data->data; - SMB_DEV_T dev; - SMB_INO_T inode; + struct file_id id; const char *sharepath; const char *newname; size_t sp_len; @@ -2303,17 +2293,16 @@ void msg_file_was_renamed(struct messaging_context *msg, } /* Unpack the message. */ - dev = DEV_T_VAL(frm,0); - inode = INO_T_VAL(frm,8); + pull_file_id_16(frm, &id); sharepath = &frm[16]; newname = sharepath + strlen(sharepath) + 1; sp_len = strlen(sharepath); DEBUG(10,("msg_file_was_renamed: Got rename message for sharepath %s, new name %s, " - "dev %x, inode %.0f\n", - sharepath, newname, (unsigned int)dev, (double)inode )); + "file_id %s\n", + sharepath, newname, file_id_static_string(&id))); - for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) { + for(fsp = file_find_di_first(id); fsp; fsp = file_find_di_next(fsp)) { if (memcmp(fsp->conn->connectpath, sharepath, sp_len) == 0) { DEBUG(10,("msg_file_was_renamed: renaming file fnum %d from %s -> %s\n", fsp->fnum, fsp->fsp_name, newname )); -- cgit From 075a5dfdc43303734122160e1a82c7685e616002 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 7 Jun 2007 07:49:43 +0000 Subject: r23375: Fix a 64-bit warning (This used to be commit c592b562fa793c9fb3bd0d84074d4ffaa8f63b64) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 30576f1e08..41fbce9889 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2288,7 +2288,7 @@ void msg_file_was_renamed(struct messaging_context *msg, if (data->data == NULL || data->length < MSG_FILE_RENAMED_MIN_SIZE + 2) { DEBUG(0, ("msg_file_was_renamed: Got invalid msg len %d\n", - data->length)); + (int)data->length)); return; } -- cgit From 0bc56a2e5ffd0e65e4770e10c80d9fec02950b36 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 5 Jul 2007 16:26:27 +0000 Subject: r23724: Reduce access to the global inbuf a tiny bit. Add a struct smb_request that contains some of the fields from the SMB header, removing the need to access inbuf directly. This right now is used only in the open file code & friends, and creating that header is only done when needed. This needs more work, but it is a start. Jeremy, I'm only checking this into 3_0, please review before I merge it to _26. Volker (This used to be commit ca988f4e79e977160d82e86486972afd15d4acf5) --- source3/smbd/open.c | 66 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 20 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 41fbce9889..62a4fe0807 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -25,7 +25,6 @@ extern struct generic_mapping file_generic_mapping; extern struct current_user current_user; extern userdom_struct current_user_info; -extern uint16 global_smbpid; extern BOOL global_client_failed_oplock_break; struct deferred_open_record { @@ -201,6 +200,7 @@ static void change_dir_owner_to_parent(connection_struct *conn, static NTSTATUS open_file(files_struct *fsp, connection_struct *conn, + struct smb_request *req, const char *parent_dir, const char *name, const char *path, @@ -359,8 +359,8 @@ static NTSTATUS open_file(files_struct *fsp, fsp->mode = psbuf->st_mode; fsp->file_id = file_id_sbuf(psbuf); - fsp->vuid = current_user.vuid; - fsp->file_pid = global_smbpid; + fsp->vuid = req ? req->vuid : UID_FIELD_INVALID; + fsp->file_pid = req ? req->smbpid : 0; fsp->can_lock = True; fsp->can_read = (access_mask & (FILE_READ_DATA)) ? True : False; if (!CAN_WRITE(conn)) { @@ -871,6 +871,8 @@ static BOOL open_match_attributes(connection_struct *conn, static files_struct *fcb_or_dos_open(connection_struct *conn, const char *fname, struct file_id id, + uint16 file_pid, + uint16 vuid, uint32 access_mask, uint32 share_access, uint32 create_options) @@ -893,8 +895,8 @@ static files_struct *fcb_or_dos_open(connection_struct *conn, (unsigned int)fsp->access_mask )); if (fsp->fh->fd != -1 && - fsp->vuid == current_user.vuid && - fsp->file_pid == global_smbpid && + fsp->vuid == vuid && + fsp->file_pid == file_pid && (fsp->fh->private_options & (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS | NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) && (fsp->access_mask & FILE_WRITE_DATA) && @@ -1103,6 +1105,7 @@ static void schedule_defer_open(struct share_mode_lock *lck, struct timeval requ ****************************************************************************/ NTSTATUS open_file_ntcreate(connection_struct *conn, + struct smb_request *req, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask, /* access bits (FILE_READ_DATA etc.) */ @@ -1129,7 +1132,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, int info; uint32 existing_dos_attributes = 0; struct pending_message_list *pml = NULL; - uint16 mid = get_current_mid(); struct timeval request_time = timeval_zero(); struct share_mode_lock *lck = NULL; uint32 open_access_mask = access_mask; @@ -1179,7 +1181,17 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, create_disposition, create_options, unx_mode, oplock_request)); - if ((pml = get_open_deferred_message(mid)) != NULL) { + if ((req == NULL) && ((oplock_request & INTERNAL_OPEN_ONLY) == 0)) { + DEBUG(0, ("No smb request but not an internal only open!\n")); + return NT_STATUS_INTERNAL_ERROR; + } + + /* + * Only non-internal opens can be deferred at all + */ + + if ((req != NULL) + && ((pml = get_open_deferred_message(req->mid)) != NULL)) { struct deferred_open_record *state = (struct deferred_open_record *)pml->private_data.data; @@ -1194,12 +1206,12 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if (lck == NULL) { DEBUG(0, ("could not get share mode lock\n")); } else { - del_deferred_open_entry(lck, mid); + del_deferred_open_entry(lck, req->mid); TALLOC_FREE(lck); } /* Ensure we don't reprocess this message. */ - remove_deferred_open_smb_message(mid); + remove_deferred_open_smb_message(req->mid); } status = check_name(conn, fname); @@ -1477,9 +1489,19 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) { files_struct *fsp_dup; + if (req == NULL) { + DEBUG(0, ("DOS open without an SMB " + "request!\n")); + TALLOC_FREE(lck); + file_free(fsp); + return NT_STATUS_INTERNAL_ERROR; + } + /* Use the client requested access mask here, * not the one we open with. */ fsp_dup = fcb_or_dos_open(conn, fname, id, + req->smbpid, + req->vuid, access_mask, share_access, create_options); @@ -1601,7 +1623,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, * open_file strips any O_TRUNC flags itself. */ - fsp_open = open_file(fsp, conn, parent_dir, newname, fname, psbuf, + fsp_open = open_file(fsp, conn, req, parent_dir, newname, fname, psbuf, flags|flags2, unx_mode, access_mask, open_access_mask); @@ -1862,7 +1884,9 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, /* If this is a successful open, we must remove any deferred open * records. */ - del_deferred_open_entry(lck, mid); + if (req != NULL) { + del_deferred_open_entry(lck, req->mid); + } TALLOC_FREE(lck); conn->num_files_open++; @@ -1892,8 +1916,8 @@ NTSTATUS open_file_fchmod(connection_struct *conn, const char *fname, /* note! we must use a non-zero desired access or we don't get a real file descriptor. Oh what a twisted web we weave. */ - status = open_file(fsp, conn, NULL, NULL, fname, psbuf, O_WRONLY, 0, - FILE_WRITE_DATA, FILE_WRITE_DATA); + status = open_file(fsp, conn, NULL, NULL, NULL, fname, psbuf, O_WRONLY, + 0, FILE_WRITE_DATA, FILE_WRITE_DATA); /* * This is not a user visible file open. @@ -2005,6 +2029,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, ****************************************************************************/ NTSTATUS open_directory(connection_struct *conn, + struct smb_request *req, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask, @@ -2121,8 +2146,8 @@ NTSTATUS open_directory(connection_struct *conn, fsp->mode = psbuf->st_mode; fsp->file_id = file_id_sbuf(psbuf); - fsp->vuid = current_user.vuid; - fsp->file_pid = global_smbpid; + fsp->vuid = req ? req->vuid : UID_FIELD_INVALID; + fsp->file_pid = req ? req->smbpid : 0; fsp->can_lock = False; fsp->can_read = False; fsp->can_write = False; @@ -2200,7 +2225,7 @@ NTSTATUS create_directory(connection_struct *conn, const char *directory) SET_STAT_INVALID(sbuf); - status = open_directory(conn, directory, &sbuf, + status = open_directory(conn, NULL, directory, &sbuf, FILE_READ_ATTRIBUTES, /* Just a stat open */ FILE_SHARE_NONE, /* Ignored for stat opens */ FILE_CREATE, @@ -2220,8 +2245,9 @@ NTSTATUS create_directory(connection_struct *conn, const char *directory) Open a pseudo-file (no locking checks - a 'stat' open). ****************************************************************************/ -NTSTATUS open_file_stat(connection_struct *conn, const char *fname, - SMB_STRUCT_STAT *psbuf, files_struct **result) +NTSTATUS open_file_stat(connection_struct *conn, struct smb_request *req, + const char *fname, SMB_STRUCT_STAT *psbuf, + files_struct **result) { files_struct *fsp = NULL; NTSTATUS status; @@ -2248,8 +2274,8 @@ NTSTATUS open_file_stat(connection_struct *conn, const char *fname, fsp->mode = psbuf->st_mode; fsp->file_id = file_id_sbuf(psbuf); - fsp->vuid = current_user.vuid; - fsp->file_pid = global_smbpid; + fsp->vuid = req ? req->vuid : UID_FIELD_INVALID; + fsp->file_pid = req ? req->smbpid : 0; fsp->can_lock = False; fsp->can_read = False; fsp->can_write = False; -- cgit From 5391750ce6db47678a03db4d67a016acff4fc8e2 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 5 Jul 2007 16:27:47 +0000 Subject: r23725: Remove get_current_mid() Jeremy, next one to review :-) (This used to be commit a50555dda7db5e848e337185ed91c41c2557f7be) --- source3/smbd/open.c | 50 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 17 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 62a4fe0807..5cb8340e0e 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -644,6 +644,7 @@ static BOOL is_delete_request(files_struct *fsp) { static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp, + uint16 mid, int pass_number, int oplock_request) { @@ -728,7 +729,7 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, DEBUG(10, ("Sending break request to PID %s\n", procid_str_static(&exclusive->pid))); - exclusive->op_mid = get_current_mid(); + exclusive->op_mid = mid; /* Create the message. */ share_mode_entry_to_message(msg, exclusive); @@ -768,9 +769,9 @@ static BOOL request_timed_out(struct timeval request_time, static void defer_open(struct share_mode_lock *lck, struct timeval request_time, struct timeval timeout, + uint16 mid, struct deferred_open_record *state) { - uint16 mid = get_current_mid(); int i; /* Paranoia check */ @@ -1065,7 +1066,9 @@ BOOL map_open_params_to_ntcreate(const char *fname, int deny_mode, int open_func } -static void schedule_defer_open(struct share_mode_lock *lck, struct timeval request_time) +static void schedule_defer_open(struct share_mode_lock *lck, + struct timeval request_time, + uint16 mid) { struct deferred_open_record state; @@ -1096,7 +1099,7 @@ static void schedule_defer_open(struct share_mode_lock *lck, struct timeval requ state.id = lck->id; if (!request_timed_out(request_time, timeout)) { - defer_open(lck, request_time, timeout, &state); + defer_open(lck, request_time, timeout, mid, &state); } } @@ -1443,8 +1446,10 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } /* First pass - send break only on batch oplocks. */ - if (delay_for_oplocks(lck, fsp, 1, oplock_request)) { - schedule_defer_open(lck, request_time); + if ((req != NULL) + && delay_for_oplocks(lck, fsp, req->mid, 1, + oplock_request)) { + schedule_defer_open(lck, request_time, req->mid); TALLOC_FREE(lck); file_free(fsp); return NT_STATUS_SHARING_VIOLATION; @@ -1461,8 +1466,11 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, * status again. */ /* Second pass - send break for both batch or * exclusive oplocks. */ - if (delay_for_oplocks(lck, fsp, 2, oplock_request)) { - schedule_defer_open(lck, request_time); + if ((req != NULL) + && delay_for_oplocks(lck, fsp, req->mid, 2, + oplock_request)) { + schedule_defer_open(lck, request_time, + req->mid); TALLOC_FREE(lck); file_free(fsp); return NT_STATUS_SHARING_VIOLATION; @@ -1576,10 +1584,11 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, state.delayed_for_oplocks = False; state.id = id; - if (!request_timed_out(request_time, - timeout)) { + if ((req != NULL) + && !request_timed_out(request_time, + timeout)) { defer_open(lck, request_time, timeout, - &state); + req->mid, &state); } } @@ -1667,8 +1676,10 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } /* First pass - send break only on batch oplocks. */ - if (delay_for_oplocks(lck, fsp, 1, oplock_request)) { - schedule_defer_open(lck, request_time); + if ((req != NULL) + && delay_for_oplocks(lck, fsp, req->mid, 1, + oplock_request)) { + schedule_defer_open(lck, request_time, req->mid); TALLOC_FREE(lck); fd_close(conn, fsp); file_free(fsp); @@ -1684,8 +1695,11 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, * status again. */ /* Second pass - send break for both batch or * exclusive oplocks. */ - if (delay_for_oplocks(lck, fsp, 2, oplock_request)) { - schedule_defer_open(lck, request_time); + if ((req != NULL) + && delay_for_oplocks(lck, fsp, req->mid, 2, + oplock_request)) { + schedule_defer_open(lck, request_time, + req->mid); TALLOC_FREE(lck); fd_close(conn, fsp); file_free(fsp); @@ -1709,8 +1723,10 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, * "goto top of this function", but don't tell * anybody... */ - defer_open(lck, request_time, timeval_zero(), - &state); + if (req != NULL) { + defer_open(lck, request_time, timeval_zero(), + req->mid, &state); + } TALLOC_FREE(lck); return status; } -- cgit From d824b98f80ba186030cbb70b3a1e5daf80469ecd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 9 Jul 2007 19:25:36 +0000 Subject: r23779: Change from v2 or later to v3 or later. Jeremy. (This used to be commit 407e6e695b8366369b7c76af1ff76869b45347b3) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 5cb8340e0e..948f475fda 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -7,7 +7,7 @@ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, -- cgit From 5e54558c6dea67b56bbfaba5698f3a434d3dffb6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Jul 2007 00:52:41 +0000 Subject: r23784: use the GPLv3 boilerplate as recommended by the FSF and the license text (This used to be commit b0132e94fc5fef936aa766fb99a306b3628e9f07) --- source3/smbd/open.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 948f475fda..432f6b808a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -16,8 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + along with this program. If not, see . */ #include "includes.h" -- cgit From 4b15f31f106f1dd69fdda721b5c3b787f5245a80 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 2 Aug 2007 08:53:24 +0000 Subject: r24120: add a file_id_create() hook into the VFS layer it's needed for some cluster filesystems to overload this function. metze (This used to be commit cdaa24e8047399002e4b287a31a8340a665e580f) --- source3/smbd/open.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 432f6b808a..bff445bf61 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -357,7 +357,7 @@ static NTSTATUS open_file(files_struct *fsp, } fsp->mode = psbuf->st_mode; - fsp->file_id = file_id_sbuf(psbuf); + fsp->file_id = vfs_file_id_from_sbuf(conn, psbuf); fsp->vuid = req ? req->vuid : UID_FIELD_INVALID; fsp->file_pid = req ? req->smbpid : 0; fsp->can_lock = True; @@ -1416,7 +1416,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return status; } - fsp->file_id = file_id_sbuf(psbuf); + fsp->file_id = vfs_file_id_from_sbuf(conn, psbuf); fsp->share_access = share_access; fsp->fh->private_options = create_options; fsp->access_mask = open_access_mask; /* We change this to the @@ -1432,7 +1432,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } if (file_existed) { - id = file_id_sbuf(psbuf); + id = vfs_file_id_from_sbuf(conn, psbuf); lck = get_share_mode_lock(NULL, id, conn->connectpath, @@ -2160,7 +2160,7 @@ NTSTATUS open_directory(connection_struct *conn, */ fsp->mode = psbuf->st_mode; - fsp->file_id = file_id_sbuf(psbuf); + fsp->file_id = vfs_file_id_from_sbuf(conn, psbuf); fsp->vuid = req ? req->vuid : UID_FIELD_INVALID; fsp->file_pid = req ? req->smbpid : 0; fsp->can_lock = False; @@ -2288,7 +2288,7 @@ NTSTATUS open_file_stat(connection_struct *conn, struct smb_request *req, */ fsp->mode = psbuf->st_mode; - fsp->file_id = file_id_sbuf(psbuf); + fsp->file_id = vfs_file_id_from_sbuf(conn, psbuf); fsp->vuid = req ? req->vuid : UID_FIELD_INVALID; fsp->file_pid = req ? req->smbpid : 0; fsp->can_lock = False; -- cgit From b578db69e91a088f158c1cd78a71d00045fc1da6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 27 Aug 2007 12:04:09 +0000 Subject: r24702: Remove the old API pointers (This used to be commit 17df313db42199e26d7d2044f6a1d845aacd1a90) --- source3/smbd/open.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index bff445bf61..725d72b284 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -768,7 +768,7 @@ static BOOL request_timed_out(struct timeval request_time, static void defer_open(struct share_mode_lock *lck, struct timeval request_time, struct timeval timeout, - uint16 mid, + struct smb_request *req, struct deferred_open_record *state) { int i; @@ -782,9 +782,9 @@ static void defer_open(struct share_mode_lock *lck, continue; } - if (procid_is_me(&e->pid) && (e->op_mid == mid)) { + if (procid_is_me(&e->pid) && (e->op_mid == req->mid)) { DEBUG(0, ("Trying to defer an already deferred " - "request: mid=%d, exiting\n", mid)); + "request: mid=%d, exiting\n", req->mid)); exit_server("attempt to defer a deferred request"); } } @@ -795,13 +795,13 @@ static void defer_open(struct share_mode_lock *lck, "open entry for mid %u\n", (unsigned int)request_time.tv_sec, (unsigned int)request_time.tv_usec, - (unsigned int)mid)); + (unsigned int)req->mid)); - if (!push_deferred_smb_message(mid, request_time, timeout, + if (!push_deferred_smb_message(req, request_time, timeout, (char *)state, sizeof(*state))) { exit_server("push_deferred_smb_message failed"); } - add_deferred_open(lck, mid, request_time, state->id); + add_deferred_open(lck, req->mid, request_time, state->id); /* * Push the MID of this packet on the signing queue. @@ -810,7 +810,7 @@ static void defer_open(struct share_mode_lock *lck, * of incrementing the response sequence number. */ - srv_defer_sign_response(mid); + srv_defer_sign_response(req->mid); } @@ -1067,7 +1067,7 @@ BOOL map_open_params_to_ntcreate(const char *fname, int deny_mode, int open_func static void schedule_defer_open(struct share_mode_lock *lck, struct timeval request_time, - uint16 mid) + struct smb_request *req) { struct deferred_open_record state; @@ -1098,7 +1098,7 @@ static void schedule_defer_open(struct share_mode_lock *lck, state.id = lck->id; if (!request_timed_out(request_time, timeout)) { - defer_open(lck, request_time, timeout, mid, &state); + defer_open(lck, request_time, timeout, req, &state); } } @@ -1448,7 +1448,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if ((req != NULL) && delay_for_oplocks(lck, fsp, req->mid, 1, oplock_request)) { - schedule_defer_open(lck, request_time, req->mid); + schedule_defer_open(lck, request_time, req); TALLOC_FREE(lck); file_free(fsp); return NT_STATUS_SHARING_VIOLATION; @@ -1468,8 +1468,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if ((req != NULL) && delay_for_oplocks(lck, fsp, req->mid, 2, oplock_request)) { - schedule_defer_open(lck, request_time, - req->mid); + schedule_defer_open(lck, request_time, req); TALLOC_FREE(lck); file_free(fsp); return NT_STATUS_SHARING_VIOLATION; @@ -1587,7 +1586,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, && !request_timed_out(request_time, timeout)) { defer_open(lck, request_time, timeout, - req->mid, &state); + req, &state); } } @@ -1678,7 +1677,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if ((req != NULL) && delay_for_oplocks(lck, fsp, req->mid, 1, oplock_request)) { - schedule_defer_open(lck, request_time, req->mid); + schedule_defer_open(lck, request_time, req); TALLOC_FREE(lck); fd_close(conn, fsp); file_free(fsp); @@ -1697,8 +1696,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if ((req != NULL) && delay_for_oplocks(lck, fsp, req->mid, 2, oplock_request)) { - schedule_defer_open(lck, request_time, - req->mid); + schedule_defer_open(lck, request_time, req); TALLOC_FREE(lck); fd_close(conn, fsp); file_free(fsp); @@ -1724,7 +1722,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if (req != NULL) { defer_open(lck, request_time, timeval_zero(), - req->mid, &state); + req, &state); } TALLOC_FREE(lck); return status; -- cgit From 929e1d99209e20a9c2c95c8bdfc8eaa37b2c2291 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 30 Aug 2007 19:48:31 +0000 Subject: r24809: Consolidate the use of temporary talloc contexts. This adds the two functions talloc_stackframe() and talloc_tos(). * When a new talloc stackframe is allocated with talloc_stackframe(), then * the TALLOC_CTX returned with talloc_tos() is reset to that new * frame. Whenever that stack frame is TALLOC_FREE()'ed, then the reverse * happens: The previous talloc_tos() is restored. * * This API is designed to be robust in the sense that if someone forgets to * TALLOC_FREE() a stackframe, then the next outer one correctly cleans up and * resets the talloc_tos(). The original motivation for this patch was to get rid of the sid_string_static & friends buffers. Explicitly passing talloc context everywhere clutters code too much for my taste, so an implicit talloc_tos() is introduced here. Many of these static buffers are replaced by a single static pointer. The intended use would thus be that low-level functions can rather freely push stuff to talloc_tos, the upper layers clean up by freeing the stackframe. The more of these stackframes are used and correctly freed the more exact the memory cleanup happens. This patch removes the main_loop_talloc_ctx, tmp_talloc_ctx and lp_talloc_ctx (did I forget any?) So, never do a tmp_ctx = talloc_init("foo"); anymore, instead, use tmp_ctx = talloc_stackframe() :-) Volker (This used to be commit 6585ea2cb7f417e14540495b9c7380fe9c8c717b) --- source3/smbd/open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 725d72b284..6efef2f912 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1159,7 +1159,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return print_fsp_open(conn, fname, result); } - if (!parent_dirname_talloc(tmp_talloc_ctx(), fname, &parent_dir, + if (!parent_dirname_talloc(talloc_tos(), fname, &parent_dir, &newname)) { return NT_STATUS_NO_MEMORY; } @@ -1979,7 +1979,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, return status; } - if (!parent_dirname_talloc(tmp_talloc_ctx(), name, &parent_dir, + if (!parent_dirname_talloc(talloc_tos(), name, &parent_dir, &dirname)) { return NT_STATUS_NO_MEMORY; } -- cgit From 4ee8b2937d48308c6089fb539fdbd8625dfde360 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 10 Sep 2007 10:56:07 +0000 Subject: r25055: Add file_id_string_tos This removes file_id_string_static and file_id_string_static2 (This used to be commit 638c848c9afe374feb30e34c494f89b2a6c64f7b) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 6efef2f912..691599ca97 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2339,7 +2339,7 @@ void msg_file_was_renamed(struct messaging_context *msg, DEBUG(10,("msg_file_was_renamed: Got rename message for sharepath %s, new name %s, " "file_id %s\n", - sharepath, newname, file_id_static_string(&id))); + sharepath, newname, file_id_string_tos(&id))); for(fsp = file_find_di_first(id); fsp; fsp = file_find_di_next(fsp)) { if (memcmp(fsp->conn->connectpath, sharepath, sp_len) == 0) { -- cgit From 12f61e09d943ea7fc4149166077507b5b0b3b4e7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Sep 2007 21:48:20 +0000 Subject: r25117: The mega-patch Jerry was waiting for. Remove all pstrings from the main server code paths. We should now be able to cope with paths up to PATH_MAX length now. Final job will be to add the TALLOC_CTX * parameter to unix_convert to make it explicit (for Volker). Jeremy. (This used to be commit 7f0db75fb0f24873577dcb758a2ecee74fdc4297) --- source3/smbd/open.c | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 691599ca97..8e1068e708 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -117,22 +117,26 @@ static void change_file_owner_to_parent(connection_struct *conn, (unsigned int)parent_st.st_uid )); } -static void change_dir_owner_to_parent(connection_struct *conn, +static NTSTATUS change_dir_owner_to_parent(connection_struct *conn, const char *inherit_from_dir, const char *fname, SMB_STRUCT_STAT *psbuf) { - pstring saved_dir; + char *saved_dir = NULL; SMB_STRUCT_STAT sbuf; SMB_STRUCT_STAT parent_st; + TALLOC_CTX *ctx = talloc_stackframe(); + NTSTATUS status = NT_STATUS_OK; int ret; ret = SMB_VFS_STAT(conn, inherit_from_dir, &parent_st); if (ret == -1) { + status = map_nt_error_from_unix(errno); DEBUG(0,("change_dir_owner_to_parent: failed to stat parent " "directory %s. Error was %s\n", inherit_from_dir, strerror(errno) )); - return; + TALLOC_FREE(ctx); + return status; } /* We've already done an lstat into psbuf, and we know it's a @@ -142,14 +146,19 @@ static void change_dir_owner_to_parent(connection_struct *conn, should work on any UNIX (thanks tridge :-). JRA. */ - if (!vfs_GetWd(conn,saved_dir)) { + saved_dir = vfs_GetWd(ctx,conn); + if (!saved_dir) { + status = map_nt_error_from_unix(errno); DEBUG(0,("change_dir_owner_to_parent: failed to get " - "current working directory\n")); - return; + "current working directory. Error was %s\n", + strerror(errno))); + TALLOC_FREE(ctx); + return status; } /* Chdir into the new path. */ if (vfs_ChDir(conn, fname) == -1) { + status = map_nt_error_from_unix(errno); DEBUG(0,("change_dir_owner_to_parent: failed to change " "current working directory to %s. Error " "was %s\n", fname, strerror(errno) )); @@ -157,6 +166,7 @@ static void change_dir_owner_to_parent(connection_struct *conn, } if (SMB_VFS_STAT(conn,".",&sbuf) == -1) { + status = map_nt_error_from_unix(errno); DEBUG(0,("change_dir_owner_to_parent: failed to stat " "directory '.' (%s) Error was %s\n", fname, strerror(errno))); @@ -170,6 +180,7 @@ static void change_dir_owner_to_parent(connection_struct *conn, DEBUG(0,("change_dir_owner_to_parent: " "device/inode/mode on directory %s changed. " "Refusing to chown !\n", fname )); + status = NT_STATUS_ACCESS_DENIED; goto out; } @@ -177,6 +188,7 @@ static void change_dir_owner_to_parent(connection_struct *conn, ret = SMB_VFS_CHOWN(conn, ".", parent_st.st_uid, (gid_t)-1); unbecome_root(); if (ret == -1) { + status = map_nt_error_from_unix(errno); DEBUG(10,("change_dir_owner_to_parent: failed to chown " "directory %s to parent directory uid %u. " "Error was %s\n", fname, @@ -190,7 +202,9 @@ static void change_dir_owner_to_parent(connection_struct *conn, out: + TALLOC_FREE(ctx); vfs_ChDir(conn,saved_dir); + return status; } /**************************************************************************** @@ -500,9 +514,10 @@ static void validate_my_share_entries(int num, if (is_deferred_open_entry(share_entry) && !open_was_deferred(share_entry->op_mid)) { - pstring str; - pstr_sprintf(str, "Got a deferred entry without a request: " - "PANIC: %s\n", share_mode_str(num, share_entry)); + char *str = talloc_asprintf(talloc_tos(), + "Got a deferred entry without a request: " + "PANIC: %s\n", + share_mode_str(num, share_entry)); smb_panic(str); } @@ -539,11 +554,12 @@ static void validate_my_share_entries(int num, panic: { - pstring str; + char *str; DEBUG(0,("validate_my_share_entries: PANIC : %s\n", share_mode_str(num, share_entry) )); - slprintf(str, sizeof(str)-1, "validate_my_share_entries: " - "file %s, oplock_type = 0x%x, op_type = 0x%x\n", + str = talloc_asprintf(talloc_tos(), + "validate_my_share_entries: " + "file %s, oplock_type = 0x%x, op_type = 0x%x\n", fsp->fsp_name, (unsigned int)fsp->oplock_type, (unsigned int)share_entry->op_type ); smb_panic(str); -- cgit From 152a1f4a7d462ca118169cb99a407c245f5c2504 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Sep 2007 23:28:35 +0000 Subject: r25391: Fix bug #4978 : Store DOS Attributes fails when copying folders. Jeremy. (This used to be commit 713277391ae7f81f8545723c919865ff8c07ed86) --- source3/smbd/open.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 8e1068e708..6c2b5a4907 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1983,6 +1983,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, char *parent_dir; const char *dirname; NTSTATUS status; + bool posix_open = false; if(!CAN_WRITE(conn)) { DEBUG(5,("mkdir_internal: failing create on read-only share " @@ -2001,6 +2002,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, } if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) { + posix_open = true; mode = (mode_t)(file_attributes & ~FILE_FLAG_POSIX_SEMANTICS); } else { mode = unix_mode(conn, aDIR, name, parent_dir); @@ -2025,6 +2027,14 @@ static NTSTATUS mkdir_internal(connection_struct *conn, return NT_STATUS_ACCESS_DENIED; } + if (lp_store_dos_attributes(SNUM(conn))) { + if (!posix_open) { + file_set_dosmode(conn, name, + file_attributes | aDIR, NULL, + parent_dir); + } + } + if (lp_inherit_perms(SNUM(conn))) { inherit_access_acl(conn, parent_dir, name, mode); } -- cgit From 0ebab65706e7e2ef82d8af81225db05a5f78b5c4 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 5 Oct 2007 21:41:17 +0000 Subject: r25534: Apply some const Why? It moves these structs from the data into the text segment, so they will never been copy-on-write copied. Not much, but as in German you say "Kleinvieh macht auch Mist...." (This used to be commit 0141e64ad4972232de867137064d0dae62da22ee) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 6c2b5a4907..c2d7807158 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -21,7 +21,7 @@ #include "includes.h" -extern struct generic_mapping file_generic_mapping; +extern const struct generic_mapping file_generic_mapping; extern struct current_user current_user; extern userdom_struct current_user_info; extern BOOL global_client_failed_oplock_break; -- cgit From e5a951325a6cac8567af3a66de6d2df577508ae4 Mon Sep 17 00:00:00 2001 From: "Gerald (Jerry) Carter" Date: Wed, 10 Oct 2007 15:34:30 -0500 Subject: [GLUE] Rsync SAMBA_3_2_0 SVN r25598 in order to create the v3-2-test branch. (This used to be commit 5c6c8e1fe93f340005110a7833946191659d88ab) --- source3/smbd/open.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index c2d7807158..fbc6f9ab64 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -387,6 +387,10 @@ static NTSTATUS open_file(files_struct *fsp, fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = False; fsp->is_stat = False; + if (conn->aio_write_behind_list && + is_in_path(path, conn->aio_write_behind_list, conn->case_sensitive)) { + fsp->aio_write_behind = True; + } string_set(&fsp->fsp_name, path); fsp->wcp = NULL; /* Write cache pointer. */ -- cgit From 30191d1a5704ad2b158386b511558972d539ce47 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 18 Oct 2007 17:40:25 -0700 Subject: RIP BOOL. Convert BOOL -> bool. I found a few interesting bugs in various places whilst doing this (places that assumed BOOL == int). I also need to fix the Samba4 pidl generation (next checkin). Jeremy. (This used to be commit f35a266b3cbb3e5fa6a86be60f34fe340a3ca71f) --- source3/smbd/open.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index fbc6f9ab64..4ed3a70411 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -24,10 +24,10 @@ extern const struct generic_mapping file_generic_mapping; extern struct current_user current_user; extern userdom_struct current_user_info; -extern BOOL global_client_failed_oplock_break; +extern bool global_client_failed_oplock_break; struct deferred_open_record { - BOOL delayed_for_oplocks; + bool delayed_for_oplocks; struct file_id id; }; @@ -226,7 +226,7 @@ static NTSTATUS open_file(files_struct *fsp, NTSTATUS status = NT_STATUS_OK; int accmode = (flags & O_ACCMODE); int local_flags = flags; - BOOL file_existed = VALID_STAT(*psbuf); + bool file_existed = VALID_STAT(*psbuf); fsp->fh->fd = -1; errno = EPERM; @@ -409,7 +409,7 @@ static NTSTATUS open_file(files_struct *fsp, Return True if the filename is one of the special executable types. ********************************************************************/ -static BOOL is_executable(const char *fname) +static bool is_executable(const char *fname) { if ((fname = strrchr_m(fname,'.'))) { if (strequal(fname,".com") || @@ -427,7 +427,7 @@ static BOOL is_executable(const char *fname) Returns True if conflict, False if not. ****************************************************************************/ -static BOOL share_conflict(struct share_mode_entry *entry, +static bool share_conflict(struct share_mode_entry *entry, uint32 access_mask, uint32 share_access) { @@ -571,7 +571,7 @@ static void validate_my_share_entries(int num, } #endif -static BOOL is_stat_open(uint32 access_mask) +static bool is_stat_open(uint32 access_mask) { return (access_mask && ((access_mask & ~(SYNCHRONIZE_ACCESS| FILE_READ_ATTRIBUTES| @@ -592,7 +592,7 @@ static NTSTATUS open_mode_check(connection_struct *conn, uint32 access_mask, uint32 share_access, uint32 create_options, - BOOL *file_existed) + bool *file_existed) { int i; @@ -646,7 +646,7 @@ static NTSTATUS open_mode_check(connection_struct *conn, return NT_STATUS_OK; } -static BOOL is_delete_request(files_struct *fsp) { +static bool is_delete_request(files_struct *fsp) { return ((fsp->access_mask == DELETE_ACCESS) && (fsp->oplock_type == NO_OPLOCK)); } @@ -661,7 +661,7 @@ static BOOL is_delete_request(files_struct *fsp) { * 3) Only level2 around: Grant level2 and do nothing else. */ -static BOOL delay_for_oplocks(struct share_mode_lock *lck, +static bool delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp, uint16 mid, int pass_number, @@ -669,9 +669,9 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, { int i; struct share_mode_entry *exclusive = NULL; - BOOL valid_entry = False; - BOOL delay_it = False; - BOOL have_level2 = False; + bool valid_entry = False; + bool delay_it = False; + bool have_level2 = False; NTSTATUS status; char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE]; @@ -772,7 +772,7 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, return True; } -static BOOL request_timed_out(struct timeval request_time, +static bool request_timed_out(struct timeval request_time, struct timeval timeout) { struct timeval now, end_time; @@ -838,7 +838,7 @@ static void defer_open(struct share_mode_lock *lck, On overwrite open ensure that the attributes match. ****************************************************************************/ -static BOOL open_match_attributes(connection_struct *conn, +static bool open_match_attributes(connection_struct *conn, const char *path, uint32 old_dos_attr, uint32 new_dos_attr, @@ -950,7 +950,7 @@ static files_struct *fcb_or_dos_open(connection_struct *conn, Open a file with a share mode - old openX method - map into NTCreate. ****************************************************************************/ -BOOL map_open_params_to_ntcreate(const char *fname, int deny_mode, int open_func, +bool map_open_params_to_ntcreate(const char *fname, int deny_mode, int open_func, uint32 *paccess_mask, uint32 *pshare_mode, uint32 *pcreate_disposition, @@ -1142,10 +1142,10 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, { int flags=0; int flags2=0; - BOOL file_existed = VALID_STAT(*psbuf); - BOOL def_acl = False; - BOOL posix_open = False; - BOOL new_file_created = False; + bool file_existed = VALID_STAT(*psbuf); + bool def_acl = False; + bool posix_open = False; + bool new_file_created = False; struct file_id id; NTSTATUS fsp_open = NT_STATUS_ACCESS_DENIED; files_struct *fsp = NULL; @@ -1504,7 +1504,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if (!NT_STATUS_IS_OK(status)) { uint32 can_access_mask; - BOOL can_access = True; + bool can_access = True; SMB_ASSERT(NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)); @@ -2084,7 +2084,7 @@ NTSTATUS open_directory(connection_struct *conn, files_struct **result) { files_struct *fsp = NULL; - BOOL dir_existed = VALID_STAT(*psbuf) ? True : False; + bool dir_existed = VALID_STAT(*psbuf) ? True : False; struct share_mode_lock *lck = NULL; NTSTATUS status; int info = 0; -- cgit From 8f1f2f04c796a8659d93bafadefca4a98fee00f0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 31 Oct 2007 15:45:45 -0700 Subject: Fix some cases where file_set_dosmode was being passed False instead of NULL. Fix more of the notifications to be correct for Samba4 RAW-NOTIFY torture (we had missed one when calling set_ea_dos_attribute(). Jeremy. (This used to be commit 39d265375cf55eedddef2c4faa65398df73d5ed2) --- source3/smbd/open.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 4ed3a70411..53fc1be586 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1866,7 +1866,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if (!posix_open) { file_set_dosmode(conn, fname, new_dos_attributes | aARCH, NULL, - parent_dir); + parent_dir, + true); } } } @@ -2035,7 +2036,8 @@ static NTSTATUS mkdir_internal(connection_struct *conn, if (!posix_open) { file_set_dosmode(conn, name, file_attributes | aDIR, NULL, - parent_dir); + parent_dir, + true); } } -- cgit From acb829ecc3b9af3f141425ecac032a7c722a1815 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 15 Nov 2007 18:27:26 -0800 Subject: Add MAX_DNS_NAME_LENGTH, remove more pstrings. Jeremy. (This used to be commit a1725f4ff7ed375808c78ac661b539557748d0a5) --- source3/smbd/open.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 53fc1be586..6dc979cf3b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -521,7 +521,7 @@ static void validate_my_share_entries(int num, char *str = talloc_asprintf(talloc_tos(), "Got a deferred entry without a request: " "PANIC: %s\n", - share_mode_str(num, share_entry)); + share_mode_str(talloc_tos(), num, share_entry)); smb_panic(str); } @@ -533,7 +533,7 @@ static void validate_my_share_entries(int num, share_entry->share_file_id); if (!fsp) { DEBUG(0,("validate_my_share_entries: PANIC : %s\n", - share_mode_str(num, share_entry) )); + share_mode_str(talloc_tos(), num, share_entry) )); smb_panic("validate_my_share_entries: Cannot match a " "share entry with an open file\n"); } @@ -560,7 +560,7 @@ static void validate_my_share_entries(int num, { char *str; DEBUG(0,("validate_my_share_entries: PANIC : %s\n", - share_mode_str(num, share_entry) )); + share_mode_str(talloc_tos(), num, share_entry) )); str = talloc_asprintf(talloc_tos(), "validate_my_share_entries: " "file %s, oplock_type = 0x%x, op_type = 0x%x\n", -- cgit From 188daba1a7eaa7201bc29bfa1a958fe7a20fc790 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 2 Dec 2007 15:35:22 +0100 Subject: Move create_file to open.c I'm checking in this long sequence of micro-checkins for review, the overall patch from 3b057022a5 to this is not too large. (This used to be commit 51db8d09a4652d626c093f7bacf075c1c168fc33) --- source3/smbd/open.c | 475 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 475 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 6dc979cf3b..0a142cd416 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2393,3 +2393,478 @@ void msg_file_was_renamed(struct messaging_context *msg, } } } + +struct case_semantics_state { + connection_struct *conn; + bool case_sensitive; + bool case_preserve; + bool short_case_preserve; +}; + +/**************************************************************************** + Restore case semantics. +****************************************************************************/ +static int restore_case_semantics(struct case_semantics_state *state) +{ + state->conn->case_sensitive = state->case_sensitive; + state->conn->case_preserve = state->case_preserve; + state->conn->short_case_preserve = state->short_case_preserve; + return 0; +} + +/**************************************************************************** + Save case semantics. +****************************************************************************/ +static struct case_semantics_state *set_posix_case_semantics(TALLOC_CTX *mem_ctx, + connection_struct *conn) +{ + struct case_semantics_state *result; + + if (!(result = talloc(mem_ctx, struct case_semantics_state))) { + DEBUG(0, ("talloc failed\n")); + return NULL; + } + + result->conn = conn; + result->case_sensitive = conn->case_sensitive; + result->case_preserve = conn->case_preserve; + result->short_case_preserve = conn->short_case_preserve; + + /* Set to POSIX. */ + conn->case_sensitive = True; + conn->case_preserve = True; + conn->short_case_preserve = True; + + talloc_set_destructor(result, restore_case_semantics); + + return result; +} + +/* + * Wrapper around open_file_ntcreate and open_directory + */ + +NTSTATUS create_file(connection_struct *conn, + struct smb_request *req, + uint16_t root_dir_fid, + char *fname, + uint32_t flags, + uint32_t access_mask, + uint32_t file_attributes, + uint32_t share_access, + uint32_t create_disposition, + uint32_t create_options, + int oplock_request, + SMB_BIG_UINT allocation_size, + struct security_descriptor *sd, + struct ea_list *ea_list, + + files_struct **result, + int *pinfo, + uint8_t *poplock_granted, + SMB_STRUCT_STAT *psbuf) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct case_semantics_state *case_state = NULL; + SMB_STRUCT_STAT sbuf; + int info = FILE_WAS_OPENED; + files_struct *fsp = NULL; + uint8_t oplock_granted = NO_OPLOCK_RETURN; + NTSTATUS status; + + DEBUG(10,("create_file: flags = 0x%x, access_mask = 0x%x " + "file_attributes = 0x%x, share_access = 0x%x, " + "create_disposition = 0x%x create_options = 0x%x " + "root_dir_fid = 0x%x, ea_list = 0x%p, sd = 0x%p, " + "fname = %s\n", + (unsigned int)flags, + (unsigned int)access_mask, + (unsigned int)file_attributes, + (unsigned int)share_access, + (unsigned int)create_disposition, + (unsigned int)create_options, + (unsigned int)root_dir_fid, + ea_list, sd, fname)); + + SET_STAT_INVALID(sbuf); + + if (create_options & FILE_OPEN_BY_FILE_ID) { + status = NT_STATUS_NOT_SUPPORTED; + goto fail; + } + + /* + * Get the file name. + */ + + if (root_dir_fid != 0) { + /* + * This filename is relative to a directory fid. + */ + char *parent_fname = NULL; + files_struct *dir_fsp = file_fsp(root_dir_fid); + + if (dir_fsp == NULL) { + status = NT_STATUS_INVALID_HANDLE; + goto fail; + } + + if (!dir_fsp->is_directory) { + + /* + * Check to see if this is a mac fork of some kind. + */ + + if (is_ntfs_stream_name(fname)) { + status = NT_STATUS_OBJECT_PATH_NOT_FOUND; + goto fail; + } + + /* + we need to handle the case when we get a + relative open relative to a file and the + pathname is blank - this is a reopen! + (hint from demyn plantenberg) + */ + + status = NT_STATUS_INVALID_HANDLE; + goto fail; + } + + if (ISDOT(dir_fsp->fsp_name)) { + /* + * We're at the toplevel dir, the final file name + * must not contain ./, as this is filtered out + * normally by srvstr_get_path and unix_convert + * explicitly rejects paths containing ./. + */ + parent_fname = talloc_strdup(talloc_tos(), ""); + if (parent_fname == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + } else { + size_t dir_name_len = strlen(dir_fsp->fsp_name); + + /* + * Copy in the base directory name. + */ + + parent_fname = TALLOC_ARRAY(talloc_tos(), char, + dir_name_len+2); + if (parent_fname == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + memcpy(parent_fname, dir_fsp->fsp_name, + dir_name_len+1); + + /* + * Ensure it ends in a '/'. + * We used TALLOC_SIZE +2 to add space for the '/'. + */ + + if(dir_name_len + && (parent_fname[dir_name_len-1] != '\\') + && (parent_fname[dir_name_len-1] != '/')) { + parent_fname[dir_name_len] = '/'; + parent_fname[dir_name_len+1] = '\0'; + } + } + + fname = talloc_asprintf(talloc_tos(), "%s%s", parent_fname, + fname); + if (fname == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + } else { + /* + * Check to see if this is a mac fork of some kind. + */ + + if (is_ntfs_stream_name(fname)) { + enum FAKE_FILE_TYPE fake_file_type; + + fake_file_type = is_fake_file(fname); + + if (fake_file_type == FAKE_FILE_TYPE_NONE) { + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + + /* + * Here we go! support for changing the disk quotas + * --metze + * + * We need to fake up to open this MAGIC QUOTA file + * and return a valid FID. + * + * w2k close this file directly after openening xp + * also tries a QUERY_FILE_INFO on the file and then + * close it + */ + status = open_fake_file(conn, fake_file_type, fname, + access_mask, &fsp); + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } + + goto done; + } + } + + oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; + if (oplock_request) { + oplock_request |= (flags & REQUEST_BATCH_OPLOCK) + ? BATCH_OPLOCK : 0; + } + + status = resolve_dfspath( + talloc_tos(), conn, req->flags2 & FLAGS2_DFS_PATHNAMES, + fname, &fname); + + if (!NT_STATUS_IS_OK(status)) { + /* + * For PATH_NOT_COVERED we had + * reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, + * ERRSRV, ERRbadpath); + * Need to fix in callers + */ + goto fail; + } + + /* + * Check if POSIX semantics are wanted. + */ + + if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) { + case_state = set_posix_case_semantics(talloc_tos(), conn); + file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS; + } + + status = unix_convert(talloc_tos(), conn, fname, False, &fname, NULL, + &sbuf); + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } + + /* All file access must go through check_name() */ + + status = check_name(conn, fname); + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } + + /* This is the correct thing to do (check every time) but can_delete + * is expensive (it may have to read the parent directory + * permissions). So for now we're not doing it unless we have a strong + * hint the client is really going to delete this file. If the client + * is forcing FILE_CREATE let the filesystem take care of the + * permissions. */ + + /* Setting FILE_SHARE_DELETE is the hint. */ + + if (lp_acl_check_permissions(SNUM(conn)) + && (create_disposition != FILE_CREATE) + && (share_access & FILE_SHARE_DELETE) + && (access_mask & DELETE_ACCESS) + && (((dos_mode(conn, fname, &sbuf) & FILE_ATTRIBUTE_READONLY) + && !lp_delete_readonly(SNUM(conn))) + || !can_delete_file_in_directory(conn, fname))) { + status = NT_STATUS_ACCESS_DENIED; + goto fail; + } + +#if 0 + /* We need to support SeSecurityPrivilege for this. */ + if ((access_mask & SEC_RIGHT_SYSTEM_SECURITY) && + !user_has_privileges(current_user.nt_user_token, + &se_security)) { + status = NT_STATUS_PRIVILEGE_NOT_HELD; + goto fail; + } +#endif + + /* + * If it's a request for a directory open, deal with it separately. + */ + + if (create_options & FILE_DIRECTORY_FILE) { + + /* Can't open a temp directory. IFS kit test. */ + if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) { + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + + /* + * We will get a create directory here if the Win32 + * app specified a security descriptor in the + * CreateDirectory() call. + */ + + oplock_request = 0; + status = open_directory( + conn, req, fname, &sbuf, access_mask, share_access, + create_disposition, create_options, file_attributes, + &info, &fsp); + } else { + + /* + * Ordinary file case. + */ + + status = open_file_ntcreate( + conn, req, fname, &sbuf, access_mask, share_access, + create_disposition, create_options, file_attributes, + oplock_request, &info, &fsp); + + if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) { + + /* + * Fail the open if it was explicitly a non-directory + * file. + */ + + if (create_options & FILE_NON_DIRECTORY_FILE) { + status = NT_STATUS_FILE_IS_A_DIRECTORY; + goto fail; + } + + oplock_request = 0; + status = open_directory( + conn, req, fname, &sbuf, access_mask, + share_access, create_disposition, + create_options, file_attributes, + &info, &fsp); + } + } + + TALLOC_FREE(case_state); + + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } + + /* + * According to the MS documentation, the only time the security + * descriptor is applied to the opened file is iff we *created* the + * file; an existing file stays the same. + * + * Also, it seems (from observation) that you can open the file with + * any access mask but you can still write the sd. We need to override + * the granted access before we call set_sd + * Patch for bug #2242 from Tom Lackemann . + */ + + if ((sd != NULL) && (info == FILE_WAS_CREATED) + && lp_nt_acl_support(SNUM(conn))) { + + uint32_t sec_info_sent = ALL_SECURITY_INFORMATION; + uint32_t saved_access_mask = fsp->access_mask; + + if (sd->owner_sid==0) { + sec_info_sent &= ~OWNER_SECURITY_INFORMATION; + } + if (sd->group_sid==0) { + sec_info_sent &= ~GROUP_SECURITY_INFORMATION; + } + if (sd->sacl==0) { + sec_info_sent &= ~SACL_SECURITY_INFORMATION; + } + if (sd->dacl==0) { + sec_info_sent &= ~DACL_SECURITY_INFORMATION; + } + + fsp->access_mask = FILE_GENERIC_ALL; + + status = SMB_VFS_FSET_NT_ACL( + fsp, fsp->fh->fd, sec_info_sent, sd); + + fsp->access_mask = saved_access_mask; + + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } + } + + if ((ea_list != NULL) && (info == FILE_WAS_CREATED)) { + status = set_ea(conn, fsp, fname, ea_list); + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } + } + + if (!fsp->is_directory && S_ISDIR(sbuf.st_mode)) { + status = NT_STATUS_ACCESS_DENIED; + goto fail; + } + + /* Save the requested allocation size. */ + if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) { + if (allocation_size + && (allocation_size > sbuf.st_size)) { + fsp->initial_allocation_size = smb_roundup( + fsp->conn, allocation_size); + if (fsp->is_directory) { + /* Can't set allocation size on a directory. */ + status = NT_STATUS_ACCESS_DENIED; + goto fail; + } + if (vfs_allocate_file_space( + fsp, fsp->initial_allocation_size) == -1) { + status = NT_STATUS_DISK_FULL; + goto fail; + } + } else { + fsp->initial_allocation_size = smb_roundup( + fsp->conn, (SMB_BIG_UINT)sbuf.st_size); + } + } + + /* + * If the caller set the extended oplock request bit + * and we granted one (by whatever means) - set the + * correct bit for extended oplock reply. + */ + + if (oplock_request && + (lp_fake_oplocks(SNUM(conn)) + || EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))) { + + /* + * Exclusive oplock granted + */ + + if (flags & REQUEST_BATCH_OPLOCK) { + oplock_granted = BATCH_OPLOCK_RETURN; + } else { + oplock_granted = EXCLUSIVE_OPLOCK_RETURN; + } + } else if (fsp->oplock_type == LEVEL_II_OPLOCK) { + oplock_granted = LEVEL_II_OPLOCK_RETURN; + } else { + oplock_granted = NO_OPLOCK_RETURN; + } + + done: + DEBUG(10, ("create_file: info=%d, oplock_granted=%d\n", + info, (int)oplock_granted)); + + *result = fsp; + *pinfo = info; + *poplock_granted = oplock_granted; + *psbuf = sbuf; + TALLOC_FREE(frame); + return NT_STATUS_OK; + + fail: + DEBUG(10, ("create_file: %s\n", nt_errstr(status))); + + if (fsp != NULL) { + close_file(fsp, ERROR_CLOSE); + fsp = NULL; + } + TALLOC_FREE(frame); + return status; +} -- cgit From b2ca9253e9a1e394a5fc1c550d1b30e4853dc43b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 5 Dec 2007 15:34:07 +0100 Subject: There's no point in passing down a 0 (This used to be commit 525a6887afcae8d8e740cf194a412c21da899649) --- source3/smbd/open.c | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 0a142cd416..66ceb8dac7 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2454,7 +2454,6 @@ NTSTATUS create_file(connection_struct *conn, uint32_t share_access, uint32_t create_disposition, uint32_t create_options, - int oplock_request, SMB_BIG_UINT allocation_size, struct security_descriptor *sd, struct ea_list *ea_list, @@ -2470,6 +2469,7 @@ NTSTATUS create_file(connection_struct *conn, int info = FILE_WAS_OPENED; files_struct *fsp = NULL; uint8_t oplock_granted = NO_OPLOCK_RETURN; + int oplock_request; NTSTATUS status; DEBUG(10,("create_file: flags = 0x%x, access_mask = 0x%x " @@ -2619,18 +2619,22 @@ NTSTATUS create_file(connection_struct *conn, ? BATCH_OPLOCK : 0; } - status = resolve_dfspath( - talloc_tos(), conn, req->flags2 & FLAGS2_DFS_PATHNAMES, - fname, &fname); + if (req == NULL) { + oplock_request |= INTERNAL_OPEN_ONLY; + } - if (!NT_STATUS_IS_OK(status)) { - /* - * For PATH_NOT_COVERED we had - * reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, - * ERRSRV, ERRbadpath); - * Need to fix in callers - */ - goto fail; + if ((req != NULL) && (req->flags2 & FLAGS2_DFS_PATHNAMES)) { + status = resolve_dfspath(talloc_tos(), conn, true, fname, &fname); + + if (!NT_STATUS_IS_OK(status)) { + /* + * For PATH_NOT_COVERED we had + * reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, + * ERRSRV, ERRbadpath); + * Need to fix in callers + */ + goto fail; + } } /* @@ -2852,9 +2856,15 @@ NTSTATUS create_file(connection_struct *conn, info, (int)oplock_granted)); *result = fsp; - *pinfo = info; - *poplock_granted = oplock_granted; - *psbuf = sbuf; + if (pinfo != NULL) { + *pinfo = info; + } + if (poplock_granted != NULL) { + *poplock_granted = oplock_granted; + } + if (psbuf != NULL) { + *psbuf = sbuf; + } TALLOC_FREE(frame); return NT_STATUS_OK; -- cgit From 30d31a3f85399042cd7f337c85a261352dd31b09 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 7 Dec 2007 10:46:11 +0100 Subject: Make fname arg to create_file a "const char *" (This used to be commit da94b5f9e37f38880e8ca4c2c7f8de6838864321) --- source3/smbd/open.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 66ceb8dac7..f4c3791b43 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2447,7 +2447,7 @@ static struct case_semantics_state *set_posix_case_semantics(TALLOC_CTX *mem_ctx NTSTATUS create_file(connection_struct *conn, struct smb_request *req, uint16_t root_dir_fid, - char *fname, + const char *fname, uint32_t flags, uint32_t access_mask, uint32_t file_attributes, @@ -2624,7 +2624,10 @@ NTSTATUS create_file(connection_struct *conn, } if ((req != NULL) && (req->flags2 & FLAGS2_DFS_PATHNAMES)) { - status = resolve_dfspath(talloc_tos(), conn, true, fname, &fname); + char *resolved_fname; + + status = resolve_dfspath(talloc_tos(), conn, true, fname, + &resolved_fname); if (!NT_STATUS_IS_OK(status)) { /* @@ -2635,6 +2638,7 @@ NTSTATUS create_file(connection_struct *conn, */ goto fail; } + fname = resolved_fname; } /* @@ -2646,10 +2650,15 @@ NTSTATUS create_file(connection_struct *conn, file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS; } - status = unix_convert(talloc_tos(), conn, fname, False, &fname, NULL, - &sbuf); - if (!NT_STATUS_IS_OK(status)) { - goto fail; + { + char *converted_fname; + + status = unix_convert(talloc_tos(), conn, fname, False, + &converted_fname, NULL, &sbuf); + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } + fname = converted_fname; } /* All file access must go through check_name() */ -- cgit From c55e44b6a7c8ca569010ddd7596ba05239c4d673 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 7 Dec 2007 11:58:40 +0100 Subject: Re-arrange create_file() parameters This changes them to be a bit closer to open_file_ntcreate and thus provides less surprises to developers (This used to be commit d000258b96b9bb714efdfe982947370a6dfb5d55) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index f4c3791b43..f555aeccb3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2450,10 +2450,10 @@ NTSTATUS create_file(connection_struct *conn, const char *fname, uint32_t flags, uint32_t access_mask, - uint32_t file_attributes, uint32_t share_access, uint32_t create_disposition, uint32_t create_options, + uint32_t file_attributes, SMB_BIG_UINT allocation_size, struct security_descriptor *sd, struct ea_list *ea_list, -- cgit From ce535b4dd8c410d91f9c0fa2d1d973b4326af64d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 7 Dec 2007 12:39:30 +0100 Subject: More parameter shuffling (This used to be commit 8f70f691ffa3e171a73d04a1c867aa6fca4d4583) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index f555aeccb3..11dff4dfe5 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2448,12 +2448,12 @@ NTSTATUS create_file(connection_struct *conn, struct smb_request *req, uint16_t root_dir_fid, const char *fname, - uint32_t flags, uint32_t access_mask, uint32_t share_access, uint32_t create_disposition, uint32_t create_options, uint32_t file_attributes, + uint32_t flags, SMB_BIG_UINT allocation_size, struct security_descriptor *sd, struct ea_list *ea_list, -- cgit From ca4eee5bbe477af2abcdbed542c5e8f7ef5eb610 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 7 Dec 2007 12:57:11 +0100 Subject: Pass only internal oplock request values to create_file Other callers (e.g. reply_open_and_X) might have other ideas of the bit shuffling (This used to be commit 6a58d823e51ccc8efd6682005e367c9096abc993) --- source3/smbd/open.c | 47 +++++------------------------------------------ 1 file changed, 5 insertions(+), 42 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 11dff4dfe5..b156dbbce1 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2453,14 +2453,13 @@ NTSTATUS create_file(connection_struct *conn, uint32_t create_disposition, uint32_t create_options, uint32_t file_attributes, - uint32_t flags, + uint32_t oplock_request, SMB_BIG_UINT allocation_size, struct security_descriptor *sd, struct ea_list *ea_list, files_struct **result, int *pinfo, - uint8_t *poplock_granted, SMB_STRUCT_STAT *psbuf) { TALLOC_CTX *frame = talloc_stackframe(); @@ -2468,21 +2467,20 @@ NTSTATUS create_file(connection_struct *conn, SMB_STRUCT_STAT sbuf; int info = FILE_WAS_OPENED; files_struct *fsp = NULL; - uint8_t oplock_granted = NO_OPLOCK_RETURN; - int oplock_request; NTSTATUS status; - DEBUG(10,("create_file: flags = 0x%x, access_mask = 0x%x " + DEBUG(10,("create_file: access_mask = 0x%x " "file_attributes = 0x%x, share_access = 0x%x, " "create_disposition = 0x%x create_options = 0x%x " + "oplock_request = 0x%x " "root_dir_fid = 0x%x, ea_list = 0x%p, sd = 0x%p, " "fname = %s\n", - (unsigned int)flags, (unsigned int)access_mask, (unsigned int)file_attributes, (unsigned int)share_access, (unsigned int)create_disposition, (unsigned int)create_options, + (unsigned int)oplock_request, (unsigned int)root_dir_fid, ea_list, sd, fname)); @@ -2613,12 +2611,6 @@ NTSTATUS create_file(connection_struct *conn, } } - oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; - if (oplock_request) { - oplock_request |= (flags & REQUEST_BATCH_OPLOCK) - ? BATCH_OPLOCK : 0; - } - if (req == NULL) { oplock_request |= INTERNAL_OPEN_ONLY; } @@ -2835,42 +2827,13 @@ NTSTATUS create_file(connection_struct *conn, } } - /* - * If the caller set the extended oplock request bit - * and we granted one (by whatever means) - set the - * correct bit for extended oplock reply. - */ - - if (oplock_request && - (lp_fake_oplocks(SNUM(conn)) - || EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))) { - - /* - * Exclusive oplock granted - */ - - if (flags & REQUEST_BATCH_OPLOCK) { - oplock_granted = BATCH_OPLOCK_RETURN; - } else { - oplock_granted = EXCLUSIVE_OPLOCK_RETURN; - } - } else if (fsp->oplock_type == LEVEL_II_OPLOCK) { - oplock_granted = LEVEL_II_OPLOCK_RETURN; - } else { - oplock_granted = NO_OPLOCK_RETURN; - } - done: - DEBUG(10, ("create_file: info=%d, oplock_granted=%d\n", - info, (int)oplock_granted)); + DEBUG(10, ("create_file: info=%d\n", info)); *result = fsp; if (pinfo != NULL) { *pinfo = info; } - if (poplock_granted != NULL) { - *poplock_granted = oplock_granted; - } if (psbuf != NULL) { *psbuf = sbuf; } -- cgit From 3a9576c724460381782f6e39126f353c054699af Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 7 Dec 2007 10:45:33 +0100 Subject: Increase debug level (This used to be commit 4e6df5547167fc235971498cb296a5f74dec8b8b) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index b156dbbce1..0e73ba964e 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2102,7 +2102,7 @@ NTSTATUS open_directory(connection_struct *conn, (unsigned int)file_attributes)); if (is_ntfs_stream_name(fname)) { - DEBUG(0,("open_directory: %s is a stream name!\n", fname )); + DEBUG(2, ("open_directory: %s is a stream name!\n", fname)); return NT_STATUS_NOT_A_DIRECTORY; } -- cgit From 0ac113e5a2c1de27a9a33f75821c4fac94ff8731 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 11 Dec 2007 10:36:59 +0100 Subject: Move INTERNAL_OPEN_ONLY calculation out of the way (This used to be commit 0e96549b56e288c596ed8772197f97ffa5ade300) --- source3/smbd/open.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 0e73ba964e..4798563721 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2611,10 +2611,6 @@ NTSTATUS create_file(connection_struct *conn, } } - if (req == NULL) { - oplock_request |= INTERNAL_OPEN_ONLY; - } - if ((req != NULL) && (req->flags2 & FLAGS2_DFS_PATHNAMES)) { char *resolved_fname; @@ -2660,6 +2656,10 @@ NTSTATUS create_file(connection_struct *conn, goto fail; } + if (req == NULL) { + oplock_request |= INTERNAL_OPEN_ONLY; + } + /* This is the correct thing to do (check every time) but can_delete * is expensive (it may have to read the parent directory * permissions). So for now we're not doing it unless we have a strong -- cgit From 3063f85a72e77d0b7dab66882cf08a45e1db539d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 11 Dec 2007 10:49:26 +0100 Subject: Move more stuff out of the way (This used to be commit ae422fce01cd7520d6dd72e08719a5cd003cb640) --- source3/smbd/open.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 4798563721..007b64abf2 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2484,13 +2484,6 @@ NTSTATUS create_file(connection_struct *conn, (unsigned int)root_dir_fid, ea_list, sd, fname)); - SET_STAT_INVALID(sbuf); - - if (create_options & FILE_OPEN_BY_FILE_ID) { - status = NT_STATUS_NOT_SUPPORTED; - goto fail; - } - /* * Get the file name. */ @@ -2641,6 +2634,8 @@ NTSTATUS create_file(connection_struct *conn, { char *converted_fname; + SET_STAT_INVALID(sbuf); + status = unix_convert(talloc_tos(), conn, fname, False, &converted_fname, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { @@ -2656,6 +2651,11 @@ NTSTATUS create_file(connection_struct *conn, goto fail; } + if (create_options & FILE_OPEN_BY_FILE_ID) { + status = NT_STATUS_NOT_SUPPORTED; + goto fail; + } + if (req == NULL) { oplock_request |= INTERNAL_OPEN_ONLY; } -- cgit From 39ea0edbbede873986a4dd333c3ec70ab1b5410c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 11 Dec 2007 11:14:30 +0100 Subject: separate out create_file_unixpath() (This used to be commit deaacf971e0fbffd0e5fe24f225ebf645a77e133) --- source3/smbd/open.c | 413 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 242 insertions(+), 171 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 007b64abf2..b83d6844d6 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2444,6 +2444,243 @@ static struct case_semantics_state *set_posix_case_semantics(TALLOC_CTX *mem_ctx * Wrapper around open_file_ntcreate and open_directory */ +NTSTATUS create_file_unixpath(connection_struct *conn, + struct smb_request *req, + const char *fname, + uint32_t access_mask, + uint32_t share_access, + uint32_t create_disposition, + uint32_t create_options, + uint32_t file_attributes, + uint32_t oplock_request, + SMB_BIG_UINT allocation_size, + struct security_descriptor *sd, + struct ea_list *ea_list, + + files_struct **result, + int *pinfo, + SMB_STRUCT_STAT *psbuf) +{ + SMB_STRUCT_STAT sbuf; + int info = FILE_WAS_OPENED; + files_struct *fsp = NULL; + NTSTATUS status; + + DEBUG(10,("create_file_unixpath: access_mask = 0x%x " + "file_attributes = 0x%x, share_access = 0x%x, " + "create_disposition = 0x%x create_options = 0x%x " + "oplock_request = 0x%x ea_list = 0x%p, sd = 0x%p, " + "fname = %s\n", + (unsigned int)access_mask, + (unsigned int)file_attributes, + (unsigned int)share_access, + (unsigned int)create_disposition, + (unsigned int)create_options, + (unsigned int)oplock_request, + ea_list, sd, fname)); + + if (create_options & FILE_OPEN_BY_FILE_ID) { + status = NT_STATUS_NOT_SUPPORTED; + goto fail; + } + + if (req == NULL) { + oplock_request |= INTERNAL_OPEN_ONLY; + } + + if (psbuf != NULL) { + sbuf = *psbuf; + } + else { + SET_STAT_INVALID(sbuf); + } + + /* This is the correct thing to do (check every time) but can_delete + * is expensive (it may have to read the parent directory + * permissions). So for now we're not doing it unless we have a strong + * hint the client is really going to delete this file. If the client + * is forcing FILE_CREATE let the filesystem take care of the + * permissions. */ + + /* Setting FILE_SHARE_DELETE is the hint. */ + + if (lp_acl_check_permissions(SNUM(conn)) + && (create_disposition != FILE_CREATE) + && (share_access & FILE_SHARE_DELETE) + && (access_mask & DELETE_ACCESS) + && (((dos_mode(conn, fname, &sbuf) & FILE_ATTRIBUTE_READONLY) + && !lp_delete_readonly(SNUM(conn))) + || !can_delete_file_in_directory(conn, fname))) { + status = NT_STATUS_ACCESS_DENIED; + goto fail; + } + +#if 0 + /* We need to support SeSecurityPrivilege for this. */ + if ((access_mask & SEC_RIGHT_SYSTEM_SECURITY) && + !user_has_privileges(current_user.nt_user_token, + &se_security)) { + status = NT_STATUS_PRIVILEGE_NOT_HELD; + goto fail; + } +#endif + + /* + * If it's a request for a directory open, deal with it separately. + */ + + if (create_options & FILE_DIRECTORY_FILE) { + + /* Can't open a temp directory. IFS kit test. */ + if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) { + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + + /* + * We will get a create directory here if the Win32 + * app specified a security descriptor in the + * CreateDirectory() call. + */ + + oplock_request = 0; + status = open_directory( + conn, req, fname, &sbuf, access_mask, share_access, + create_disposition, create_options, file_attributes, + &info, &fsp); + } else { + + /* + * Ordinary file case. + */ + + status = open_file_ntcreate( + conn, req, fname, &sbuf, access_mask, share_access, + create_disposition, create_options, file_attributes, + oplock_request, &info, &fsp); + + if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) { + + /* + * Fail the open if it was explicitly a non-directory + * file. + */ + + if (create_options & FILE_NON_DIRECTORY_FILE) { + status = NT_STATUS_FILE_IS_A_DIRECTORY; + goto fail; + } + + oplock_request = 0; + status = open_directory( + conn, req, fname, &sbuf, access_mask, + share_access, create_disposition, + create_options, file_attributes, + &info, &fsp); + } + } + + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } + + /* + * According to the MS documentation, the only time the security + * descriptor is applied to the opened file is iff we *created* the + * file; an existing file stays the same. + * + * Also, it seems (from observation) that you can open the file with + * any access mask but you can still write the sd. We need to override + * the granted access before we call set_sd + * Patch for bug #2242 from Tom Lackemann . + */ + + if ((sd != NULL) && (info == FILE_WAS_CREATED) + && lp_nt_acl_support(SNUM(conn))) { + + uint32_t sec_info_sent = ALL_SECURITY_INFORMATION; + uint32_t saved_access_mask = fsp->access_mask; + + if (sd->owner_sid==0) { + sec_info_sent &= ~OWNER_SECURITY_INFORMATION; + } + if (sd->group_sid==0) { + sec_info_sent &= ~GROUP_SECURITY_INFORMATION; + } + if (sd->sacl==0) { + sec_info_sent &= ~SACL_SECURITY_INFORMATION; + } + if (sd->dacl==0) { + sec_info_sent &= ~DACL_SECURITY_INFORMATION; + } + + fsp->access_mask = FILE_GENERIC_ALL; + + status = SMB_VFS_FSET_NT_ACL( + fsp, fsp->fh->fd, sec_info_sent, sd); + + fsp->access_mask = saved_access_mask; + + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } + } + + if ((ea_list != NULL) && (info == FILE_WAS_CREATED)) { + status = set_ea(conn, fsp, fname, ea_list); + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } + } + + if (!fsp->is_directory && S_ISDIR(sbuf.st_mode)) { + status = NT_STATUS_ACCESS_DENIED; + goto fail; + } + + /* Save the requested allocation size. */ + if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) { + if (allocation_size + && (allocation_size > sbuf.st_size)) { + fsp->initial_allocation_size = smb_roundup( + fsp->conn, allocation_size); + if (fsp->is_directory) { + /* Can't set allocation size on a directory. */ + status = NT_STATUS_ACCESS_DENIED; + goto fail; + } + if (vfs_allocate_file_space( + fsp, fsp->initial_allocation_size) == -1) { + status = NT_STATUS_DISK_FULL; + goto fail; + } + } else { + fsp->initial_allocation_size = smb_roundup( + fsp->conn, (SMB_BIG_UINT)sbuf.st_size); + } + } + + DEBUG(10, ("create_file: info=%d\n", info)); + + *result = fsp; + if (pinfo != NULL) { + *pinfo = info; + } + if (psbuf != NULL) { + *psbuf = sbuf; + } + return NT_STATUS_OK; + + fail: + DEBUG(10, ("create_file: %s\n", nt_errstr(status))); + + if (fsp != NULL) { + close_file(fsp, ERROR_CLOSE); + fsp = NULL; + } + return status; +} + NTSTATUS create_file(connection_struct *conn, struct smb_request *req, uint16_t root_dir_fid, @@ -2651,182 +2888,16 @@ NTSTATUS create_file(connection_struct *conn, goto fail; } - if (create_options & FILE_OPEN_BY_FILE_ID) { - status = NT_STATUS_NOT_SUPPORTED; - goto fail; - } - - if (req == NULL) { - oplock_request |= INTERNAL_OPEN_ONLY; - } - - /* This is the correct thing to do (check every time) but can_delete - * is expensive (it may have to read the parent directory - * permissions). So for now we're not doing it unless we have a strong - * hint the client is really going to delete this file. If the client - * is forcing FILE_CREATE let the filesystem take care of the - * permissions. */ - - /* Setting FILE_SHARE_DELETE is the hint. */ - - if (lp_acl_check_permissions(SNUM(conn)) - && (create_disposition != FILE_CREATE) - && (share_access & FILE_SHARE_DELETE) - && (access_mask & DELETE_ACCESS) - && (((dos_mode(conn, fname, &sbuf) & FILE_ATTRIBUTE_READONLY) - && !lp_delete_readonly(SNUM(conn))) - || !can_delete_file_in_directory(conn, fname))) { - status = NT_STATUS_ACCESS_DENIED; - goto fail; - } - -#if 0 - /* We need to support SeSecurityPrivilege for this. */ - if ((access_mask & SEC_RIGHT_SYSTEM_SECURITY) && - !user_has_privileges(current_user.nt_user_token, - &se_security)) { - status = NT_STATUS_PRIVILEGE_NOT_HELD; - goto fail; - } -#endif - - /* - * If it's a request for a directory open, deal with it separately. - */ - - if (create_options & FILE_DIRECTORY_FILE) { - - /* Can't open a temp directory. IFS kit test. */ - if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) { - status = NT_STATUS_INVALID_PARAMETER; - goto fail; - } - - /* - * We will get a create directory here if the Win32 - * app specified a security descriptor in the - * CreateDirectory() call. - */ - - oplock_request = 0; - status = open_directory( - conn, req, fname, &sbuf, access_mask, share_access, - create_disposition, create_options, file_attributes, - &info, &fsp); - } else { - - /* - * Ordinary file case. - */ - - status = open_file_ntcreate( - conn, req, fname, &sbuf, access_mask, share_access, - create_disposition, create_options, file_attributes, - oplock_request, &info, &fsp); - - if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) { - - /* - * Fail the open if it was explicitly a non-directory - * file. - */ - - if (create_options & FILE_NON_DIRECTORY_FILE) { - status = NT_STATUS_FILE_IS_A_DIRECTORY; - goto fail; - } - - oplock_request = 0; - status = open_directory( - conn, req, fname, &sbuf, access_mask, - share_access, create_disposition, - create_options, file_attributes, - &info, &fsp); - } - } - - TALLOC_FREE(case_state); + status = create_file_unixpath( + conn, req, fname, access_mask, share_access, + create_disposition, create_options, file_attributes, + oplock_request, allocation_size, sd, ea_list, + &fsp, &info, &sbuf); if (!NT_STATUS_IS_OK(status)) { goto fail; } - /* - * According to the MS documentation, the only time the security - * descriptor is applied to the opened file is iff we *created* the - * file; an existing file stays the same. - * - * Also, it seems (from observation) that you can open the file with - * any access mask but you can still write the sd. We need to override - * the granted access before we call set_sd - * Patch for bug #2242 from Tom Lackemann . - */ - - if ((sd != NULL) && (info == FILE_WAS_CREATED) - && lp_nt_acl_support(SNUM(conn))) { - - uint32_t sec_info_sent = ALL_SECURITY_INFORMATION; - uint32_t saved_access_mask = fsp->access_mask; - - if (sd->owner_sid==0) { - sec_info_sent &= ~OWNER_SECURITY_INFORMATION; - } - if (sd->group_sid==0) { - sec_info_sent &= ~GROUP_SECURITY_INFORMATION; - } - if (sd->sacl==0) { - sec_info_sent &= ~SACL_SECURITY_INFORMATION; - } - if (sd->dacl==0) { - sec_info_sent &= ~DACL_SECURITY_INFORMATION; - } - - fsp->access_mask = FILE_GENERIC_ALL; - - status = SMB_VFS_FSET_NT_ACL( - fsp, fsp->fh->fd, sec_info_sent, sd); - - fsp->access_mask = saved_access_mask; - - if (!NT_STATUS_IS_OK(status)) { - goto fail; - } - } - - if ((ea_list != NULL) && (info == FILE_WAS_CREATED)) { - status = set_ea(conn, fsp, fname, ea_list); - if (!NT_STATUS_IS_OK(status)) { - goto fail; - } - } - - if (!fsp->is_directory && S_ISDIR(sbuf.st_mode)) { - status = NT_STATUS_ACCESS_DENIED; - goto fail; - } - - /* Save the requested allocation size. */ - if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) { - if (allocation_size - && (allocation_size > sbuf.st_size)) { - fsp->initial_allocation_size = smb_roundup( - fsp->conn, allocation_size); - if (fsp->is_directory) { - /* Can't set allocation size on a directory. */ - status = NT_STATUS_ACCESS_DENIED; - goto fail; - } - if (vfs_allocate_file_space( - fsp, fsp->initial_allocation_size) == -1) { - status = NT_STATUS_DISK_FULL; - goto fail; - } - } else { - fsp->initial_allocation_size = smb_roundup( - fsp->conn, (SMB_BIG_UINT)sbuf.st_size); - } - } - done: DEBUG(10, ("create_file: info=%d\n", info)); -- cgit From 4773973300d9b4c6d46bdeefd57d200378f6cec3 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Sat, 22 Dec 2007 01:49:29 +0100 Subject: Remove redundant connection_struct from fd_close_posix() parameter list. Michael (This used to be commit f3365b74ac016eaee1e82eef769dd618af5df201) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index b83d6844d6..743f040911 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -78,7 +78,7 @@ NTSTATUS fd_close(struct connection_struct *conn, files_struct *fsp) if (fsp->fh->ref_count > 1) { return NT_STATUS_OK; /* Shared handle. Only close last reference. */ } - return fd_close_posix(conn, fsp); + return fd_close_posix(fsp); } /**************************************************************************** -- cgit From e47520f2221ea34a2264a3cc03fe1c5fcc5bf5c5 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Sat, 22 Dec 2007 02:01:26 +0100 Subject: Remove redundant connection_struct from fd_close() parameter list. Michael (This used to be commit 3611cc8561cf837adea83fc7c16ca7535f188466) --- source3/smbd/open.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 743f040911..9428b47b6a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -70,7 +70,7 @@ static NTSTATUS fd_open(struct connection_struct *conn, Close the file associated with a fsp. ****************************************************************************/ -NTSTATUS fd_close(struct connection_struct *conn, files_struct *fsp) +NTSTATUS fd_close(files_struct *fsp) { if (fsp->fh->fd == -1) { return NT_STATUS_OK; /* What we used to call a stat open. */ @@ -353,7 +353,7 @@ static NTSTATUS open_file(files_struct *fsp, /* For a non-io open, this stat failing means file not found. JRA */ if (ret == -1) { status = map_nt_error_from_unix(errno); - fd_close(conn, fsp); + fd_close(fsp); return status; } } @@ -365,7 +365,7 @@ static NTSTATUS open_file(files_struct *fsp, */ if(S_ISDIR(psbuf->st_mode)) { - fd_close(conn, fsp); + fd_close(fsp); errno = EISDIR; return NT_STATUS_FILE_IS_A_DIRECTORY; } @@ -1688,7 +1688,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if (lck == NULL) { DEBUG(0, ("open_file_ntcreate: Could not get share " "mode lock for %s\n", fname)); - fd_close(conn, fsp); + fd_close(fsp); file_free(fsp); return NT_STATUS_SHARING_VIOLATION; } @@ -1699,7 +1699,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, oplock_request)) { schedule_defer_open(lck, request_time, req); TALLOC_FREE(lck); - fd_close(conn, fsp); + fd_close(fsp); file_free(fsp); return NT_STATUS_SHARING_VIOLATION; } @@ -1718,7 +1718,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, oplock_request)) { schedule_defer_open(lck, request_time, req); TALLOC_FREE(lck); - fd_close(conn, fsp); + fd_close(fsp); file_free(fsp); return NT_STATUS_SHARING_VIOLATION; } @@ -1727,7 +1727,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if (!NT_STATUS_IS_OK(status)) { struct deferred_open_record state; - fd_close(conn, fsp); + fd_close(fsp); file_free(fsp); state.delayed_for_oplocks = False; @@ -1768,7 +1768,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if(ret_flock == -1 ){ TALLOC_FREE(lck); - fd_close(conn, fsp); + fd_close(fsp); file_free(fsp); return NT_STATUS_SHARING_VIOLATION; @@ -1793,7 +1793,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, (SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf)==-1)) { status = map_nt_error_from_unix(errno); TALLOC_FREE(lck); - fd_close(conn,fsp); + fd_close(fsp); file_free(fsp); return status; } @@ -1850,7 +1850,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, /* Remember to delete the mode we just added. */ del_share_mode(lck, fsp); TALLOC_FREE(lck); - fd_close(conn,fsp); + fd_close(fsp); file_free(fsp); return status; } @@ -1974,7 +1974,7 @@ NTSTATUS open_file_fchmod(connection_struct *conn, const char *fname, NTSTATUS close_file_fchmod(files_struct *fsp) { - NTSTATUS status = fd_close(fsp->conn, fsp); + NTSTATUS status = fd_close(fsp); file_free(fsp); return status; } -- cgit From 250c57ccfbae343e8d713c768d0288f73a0a5013 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 26 Dec 2007 14:18:11 +0100 Subject: We need to return the correct atime On systems with nanosecond atime we need to re-stat after messing with the fd, at least Solaris 10 updates atime after we stat(2)ed the file. (This used to be commit 6e6ec0a563f8b7e3d4618ce60e776bcce53f40c4) --- source3/smbd/open.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 9428b47b6a..f30808b30a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2667,7 +2667,12 @@ NTSTATUS create_file_unixpath(connection_struct *conn, *pinfo = info; } if (psbuf != NULL) { - *psbuf = sbuf; + if ((fsp->fh == NULL) || (fsp->fh->fd == -1)) { + *psbuf = sbuf; + } + else { + SMB_VFS_FSTAT(fsp, fsp->fh->fd, psbuf); + } } return NT_STATUS_OK; -- cgit From 33f01360e0a40f6d1fa03035979d816ff9198d85 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 27 Dec 2007 21:31:08 +0100 Subject: Fix setting the initial permission bits This fixes a make test failure on Solaris. When creating a new file, file_set_dosmode() called from open_file_ntcreate calculates a new permission mask, very likely different from what had been calculated in open_file_ntcreate. Further down we overwrote the newly calculated value with SMB_FCHMOD_ACL, ignoring what file_set_dosmode had calculated. Why did Linux not see this? fchmod_acl on a newly created file without acls would not retrieve an acl at all, whereas under Solaris acl(2) returns something even for files with just posix permissions returns something. Jeremy, given that we have very similar code in 3.0.28 this might also explain some of the bug reports that people have concerning ACLs on new files. Volker P.S: This one took a while to find... (This used to be commit 2135dfe91bf1ae114a18c15286b535662200677d) --- source3/smbd/open.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index f30808b30a..d3ba9e076c 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1864,10 +1864,15 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if (lp_map_archive(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) { if (!posix_open) { - file_set_dosmode(conn, fname, - new_dos_attributes | aARCH, NULL, - parent_dir, - true); + SMB_STRUCT_STAT tmp_sbuf; + SET_STAT_INVALID(tmp_sbuf); + if (file_set_dosmode( + conn, fname, + new_dos_attributes | aARCH, + &tmp_sbuf, parent_dir, + true) == 0) { + unx_mode = tmp_sbuf.st_mode; + } } } } -- cgit From 31d3f5726a0f4ae23243c82645506cb257d57b53 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 1 Jan 2008 12:55:29 +0100 Subject: Use NULL instead of 0 "struct security_descriptor" has pointers, not integers inside (This used to be commit 13158014e3b05e44eea897fbcf470957301c5c97) --- source3/smbd/open.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index d3ba9e076c..b6e6adde8a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2606,16 +2606,16 @@ NTSTATUS create_file_unixpath(connection_struct *conn, uint32_t sec_info_sent = ALL_SECURITY_INFORMATION; uint32_t saved_access_mask = fsp->access_mask; - if (sd->owner_sid==0) { + if (sd->owner_sid == NULL) { sec_info_sent &= ~OWNER_SECURITY_INFORMATION; } - if (sd->group_sid==0) { + if (sd->group_sid == NULL) { sec_info_sent &= ~GROUP_SECURITY_INFORMATION; } - if (sd->sacl==0) { + if (sd->sacl == NULL) { sec_info_sent &= ~SACL_SECURITY_INFORMATION; } - if (sd->dacl==0) { + if (sd->dacl == NULL) { sec_info_sent &= ~DACL_SECURITY_INFORMATION; } -- cgit From 9254bb4ef1c3c3a52ea8e935edb0e7a86ec3ea7a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 4 Jan 2008 12:56:23 -0800 Subject: Refactor the crypto code after a very helpful conversation with Volker. Mostly making sure we have data on the incoming packet type, not stored in the smb header. Jeremy. (This used to be commit c4e5a505043965eec77b5bb9bc60957e8f3b97c8) --- source3/smbd/open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index b6e6adde8a..e3fae02b83 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2267,7 +2267,7 @@ NTSTATUS open_directory(connection_struct *conn, return NT_STATUS_OK; } -NTSTATUS create_directory(connection_struct *conn, const char *directory) +NTSTATUS create_directory(connection_struct *conn, struct smb_request *req, const char *directory) { NTSTATUS status; SMB_STRUCT_STAT sbuf; @@ -2275,7 +2275,7 @@ NTSTATUS create_directory(connection_struct *conn, const char *directory) SET_STAT_INVALID(sbuf); - status = open_directory(conn, NULL, directory, &sbuf, + status = open_directory(conn, req, directory, &sbuf, FILE_READ_ATTRIBUTES, /* Just a stat open */ FILE_SHARE_NONE, /* Ignored for stat opens */ FILE_CREATE, -- cgit From c6a2292724036340f766d774e64d6738d702478d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 4 Jan 2008 23:17:38 -0800 Subject: Using a bool with a logical operation. IBM checker caught. Jeremy. (This used to be commit 7f9fe7da1e25bcc730f4c4226bf77f6d39b5ace4) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index e3fae02b83..f178102fdd 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1405,7 +1405,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } #endif /* O_SYNC */ - if (posix_open & (access_mask & FILE_APPEND_DATA)) { + if (posix_open && (access_mask & FILE_APPEND_DATA)) { flags2 |= O_APPEND; } -- cgit From 05352cf2cb7f9710444d340f3f14ac6917fb0416 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Sun, 6 Jan 2008 18:48:02 +0100 Subject: Remove superfluous parameter fd from SMB_VFS_FSET_NT_ACL(). Michael (This used to be commit 4f2d139a186048f08180378a877b69d2f80ad51f) --- source3/smbd/open.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index f178102fdd..23d0223446 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2621,8 +2621,7 @@ NTSTATUS create_file_unixpath(connection_struct *conn, fsp->access_mask = FILE_GENERIC_ALL; - status = SMB_VFS_FSET_NT_ACL( - fsp, fsp->fh->fd, sec_info_sent, sd); + status = SMB_VFS_FSET_NT_ACL(fsp, sec_info_sent, sd); fsp->access_mask = saved_access_mask; -- cgit From 87a684f7fcfa8d9fabc42e33981299d0b33eeeb7 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 7 Jan 2008 13:21:26 +0100 Subject: Remove redundant parameter fd from SMB_VFS_FSTAT(). Michael (This used to be commit 0b86c420be94d295f6917a220b5d699f65b46711) --- source3/smbd/open.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 23d0223446..d870374835 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -342,7 +342,7 @@ static NTSTATUS open_file(files_struct *fsp, if (fsp->fh->fd == -1) { ret = SMB_VFS_STAT(conn, path, psbuf); } else { - ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf); + ret = SMB_VFS_FSTAT(fsp, psbuf); /* If we have an fd, this stat should succeed. */ if (ret == -1) { DEBUG(0,("Error doing fstat on open file %s " @@ -1790,7 +1790,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, * struct.. */ if ((SMB_VFS_FTRUNCATE(fsp,fsp->fh->fd,0) == -1) || - (SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf)==-1)) { + (SMB_VFS_FSTAT(fsp, psbuf)==-1)) { status = map_nt_error_from_unix(errno); TALLOC_FREE(lck); fd_close(fsp); @@ -2675,7 +2675,7 @@ NTSTATUS create_file_unixpath(connection_struct *conn, *psbuf = sbuf; } else { - SMB_VFS_FSTAT(fsp, fsp->fh->fd, psbuf); + SMB_VFS_FSTAT(fsp, psbuf); } } return NT_STATUS_OK; -- cgit From e614dec27f33c932c6c29c806d567fd6015cd5e6 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 7 Jan 2008 13:44:37 +0100 Subject: Remove redundant parameter fd from SMB_VFS_FCHMOD(). Michael (This used to be commit a54d5604da556d1250ca9948d4acc4a187a9fede) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index d870374835..c7b053d531 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1915,7 +1915,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } if ((ret == -1) && - (SMB_VFS_FCHMOD(fsp, fsp->fh->fd, new_unx_mode) == -1)) + (SMB_VFS_FCHMOD(fsp, new_unx_mode) == -1)) DEBUG(5, ("open_file_ntcreate: failed to reset " "attributes of file %s to 0%o\n", fname, (unsigned int)new_unx_mode)); -- cgit From 670909cb07e38a06bf5db12342b3b1189f0e1ab7 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 7 Jan 2008 14:26:00 +0100 Subject: Remove redundant parameter fd from SMB_VFS_FCHOWN(). Michael (This used to be commit fbb193db3e0dc51cb000ae406a68bc547f31d9ab) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index c7b053d531..036e3e12a2 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -102,7 +102,7 @@ static void change_file_owner_to_parent(connection_struct *conn, } become_root(); - ret = SMB_VFS_FCHOWN(fsp, fsp->fh->fd, parent_st.st_uid, (gid_t)-1); + ret = SMB_VFS_FCHOWN(fsp, parent_st.st_uid, (gid_t)-1); unbecome_root(); if (ret == -1) { DEBUG(0,("change_file_owner_to_parent: failed to fchown " -- cgit From b457b94bb86897b7020c6f300cd19a3d8e192610 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 7 Jan 2008 15:55:09 +0100 Subject: Remove redundant parameter fd from SMB_VFS_FTRUNCATE(). Michael (This used to be commit 2ad66050a0452b8e7e08b1e7a01efa00c72fd451) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 036e3e12a2..cc62e020da 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1789,7 +1789,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, * We are modifing the file after open - update the stat * struct.. */ - if ((SMB_VFS_FTRUNCATE(fsp,fsp->fh->fd,0) == -1) || + if ((SMB_VFS_FTRUNCATE(fsp, 0) == -1) || (SMB_VFS_FSTAT(fsp, psbuf)==-1)) { status = map_nt_error_from_unix(errno); TALLOC_FREE(lck); -- cgit From 327cc04da587fa54f28dafb00267fde79b858349 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 7 Jan 2008 17:14:20 +0100 Subject: Remove redundant parameter fd from SMB_VFS_KERNEL_FLOCK(). Michael (This used to be commit 195c519377c2fdc655e25760b52bc0694b8dda81) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index cc62e020da..b618092a32 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1764,7 +1764,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, the kernel refuses the operations then the kernel is wrong. note that GPFS supports it as well - jmcd */ - ret_flock = SMB_VFS_KERNEL_FLOCK(fsp, fsp->fh->fd, share_access); + ret_flock = SMB_VFS_KERNEL_FLOCK(fsp, share_access); if(ret_flock == -1 ){ TALLOC_FREE(lck); -- cgit From b2182c11eab0e1b2f0acb5d82aec86d4598573eb Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 8 Jan 2008 01:14:24 +0100 Subject: Remove redundant parameter fd from SMB_VFS_FCHMOD_ACL(). Michael (This used to be commit 7b201c177b3668f54751ba17d6a0b53ed913e7f7) --- source3/smbd/open.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index b618092a32..4abe017380 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1887,7 +1887,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, int saved_errno = errno; /* We might get ENOSYS in the next * call.. */ - if (SMB_VFS_FCHMOD_ACL(fsp, fsp->fh->fd, unx_mode) == -1 && + if (SMB_VFS_FCHMOD_ACL(fsp, unx_mode) == -1 && errno == ENOSYS) { errno = saved_errno; /* Ignore ENOSYS */ } @@ -1901,8 +1901,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, { int saved_errno = errno; /* We might get ENOSYS in the * next call.. */ - ret = SMB_VFS_FCHMOD_ACL(fsp, fsp->fh->fd, - new_unx_mode); + ret = SMB_VFS_FCHMOD_ACL(fsp, new_unx_mode); if (ret == -1 && errno == ENOSYS) { errno = saved_errno; /* Ignore ENOSYS */ -- cgit From c16a00b0af1fe1268dd798254ffd2a9501cf0e17 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 9 Jan 2008 10:29:34 +0100 Subject: Replace an uninitialized variable Reported by the IBM checker (This used to be commit 48f61e4b9fce5ea4f4bc3cf55530bb757c0def07) --- source3/smbd/open.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 4abe017380..6aef99ff0e 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2845,6 +2845,8 @@ NTSTATUS create_file(connection_struct *conn, goto fail; } + SET_STAT_INVALID(sbuf); + goto done; } } -- cgit From 253fbf1a6ece5c8dc9759e3535b7f9fa46883c1b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 9 Jan 2008 17:11:04 -0800 Subject: Make use of talloc_pool in the main codepaths. Remove the sub-contexts. Jeremy. (This used to be commit bc932b8ad4396f76b71c43efe9a6346f89c3632c) --- source3/smbd/open.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 6aef99ff0e..037ab633e3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -125,7 +125,7 @@ static NTSTATUS change_dir_owner_to_parent(connection_struct *conn, char *saved_dir = NULL; SMB_STRUCT_STAT sbuf; SMB_STRUCT_STAT parent_st; - TALLOC_CTX *ctx = talloc_stackframe(); + TALLOC_CTX *ctx = talloc_tos(); NTSTATUS status = NT_STATUS_OK; int ret; @@ -135,7 +135,6 @@ static NTSTATUS change_dir_owner_to_parent(connection_struct *conn, DEBUG(0,("change_dir_owner_to_parent: failed to stat parent " "directory %s. Error was %s\n", inherit_from_dir, strerror(errno) )); - TALLOC_FREE(ctx); return status; } @@ -152,7 +151,6 @@ static NTSTATUS change_dir_owner_to_parent(connection_struct *conn, DEBUG(0,("change_dir_owner_to_parent: failed to get " "current working directory. Error was %s\n", strerror(errno))); - TALLOC_FREE(ctx); return status; } @@ -202,7 +200,6 @@ static NTSTATUS change_dir_owner_to_parent(connection_struct *conn, out: - TALLOC_FREE(ctx); vfs_ChDir(conn,saved_dir); return status; } @@ -2707,7 +2704,6 @@ NTSTATUS create_file(connection_struct *conn, int *pinfo, SMB_STRUCT_STAT *psbuf) { - TALLOC_CTX *frame = talloc_stackframe(); struct case_semantics_state *case_state = NULL; SMB_STRUCT_STAT sbuf; int info = FILE_WAS_OPENED; @@ -2918,7 +2914,6 @@ NTSTATUS create_file(connection_struct *conn, if (psbuf != NULL) { *psbuf = sbuf; } - TALLOC_FREE(frame); return NT_STATUS_OK; fail: @@ -2928,6 +2923,5 @@ NTSTATUS create_file(connection_struct *conn, close_file(fsp, ERROR_CLOSE); fsp = NULL; } - TALLOC_FREE(frame); return status; } -- cgit From 3cc3b9e1879d3d9714ac2914364418a140e8389c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 6 Jan 2008 14:21:25 +0100 Subject: use talloc_tos in a few more places (This used to be commit 65dd869bea351010c67f02046ae4134bdada1a4c) --- source3/smbd/open.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 037ab633e3..59699dfbd0 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1221,7 +1221,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, request_time = pml->request_time; /* Remove the deferred open entry under lock. */ - lck = get_share_mode_lock(NULL, state->id, NULL, NULL); + lck = get_share_mode_lock(talloc_tos(), state->id, NULL, NULL); if (lck == NULL) { DEBUG(0, ("could not get share mode lock\n")); } else { @@ -1451,7 +1451,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if (file_existed) { id = vfs_file_id_from_sbuf(conn, psbuf); - lck = get_share_mode_lock(NULL, id, + lck = get_share_mode_lock(talloc_tos(), id, conn->connectpath, fname); @@ -1678,7 +1678,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, id = fsp->file_id; - lck = get_share_mode_lock(NULL, id, + lck = get_share_mode_lock(talloc_tos(), id, conn->connectpath, fname); @@ -2212,7 +2212,7 @@ NTSTATUS open_directory(connection_struct *conn, string_set(&fsp->fsp_name,fname); - lck = get_share_mode_lock(NULL, fsp->file_id, + lck = get_share_mode_lock(talloc_tos(), fsp->file_id, conn->connectpath, fname); -- cgit From 4c0ca860515a799ddcda3804fe4c2080d1df9b80 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 11 Jan 2008 21:53:29 +0100 Subject: There's no point in calling FLOCK on a non-existing fd (This used to be commit 9ff79f231f1206631662b5c521ecddf5df9141c0) --- source3/smbd/open.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 59699dfbd0..d1679209bb 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1761,14 +1761,16 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, the kernel refuses the operations then the kernel is wrong. note that GPFS supports it as well - jmcd */ - ret_flock = SMB_VFS_KERNEL_FLOCK(fsp, share_access); - if(ret_flock == -1 ){ + if (fsp->fh->fd != -1) { + ret_flock = SMB_VFS_KERNEL_FLOCK(fsp, share_access); + if(ret_flock == -1 ){ - TALLOC_FREE(lck); - fd_close(fsp); - file_free(fsp); - - return NT_STATUS_SHARING_VIOLATION; + TALLOC_FREE(lck); + fd_close(fsp); + file_free(fsp); + + return NT_STATUS_SHARING_VIOLATION; + } } /* -- cgit From b36a78837f2bb16725c39e42296015c61f1c5910 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 11 Jan 2008 12:35:04 +0100 Subject: delete on close even prevents stat opens (This used to be commit 85fe7f3f6ed4aae76e5cf31ab689b2dfacfd74de) --- source3/smbd/open.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index d1679209bb..9d48bcc98b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -598,12 +598,6 @@ static NTSTATUS open_mode_check(connection_struct *conn, } *file_existed = True; - - if (is_stat_open(access_mask)) { - /* Stat open that doesn't trigger oplock breaks or share mode - * checks... ! JRA. */ - return NT_STATUS_OK; - } /* A delete on close prohibits everything */ @@ -611,6 +605,12 @@ static NTSTATUS open_mode_check(connection_struct *conn, return NT_STATUS_DELETE_PENDING; } + if (is_stat_open(access_mask)) { + /* Stat open that doesn't trigger oplock breaks or share mode + * checks... ! JRA. */ + return NT_STATUS_OK; + } + /* * Check if the share modes will give us access. */ -- cgit From 1069cfe4ade88a032164c1242c9480a544584655 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 19 Jan 2008 23:25:36 +0100 Subject: Add streams support This is the core of the streams support. The main change is that in files_struct there is now a base_fsp pointer that holds the main file open while a stream is open. This is necessary to get the rather strange delete semantics right: You can't delete the main file while a stream is open without FILE_SHARE_DELETE, and while a stream is open a successful unlink of the main file leads to DELETE_PENDING for all further access on the main file or any stream. (This used to be commit 6022873cc155bdbbd3fb620689715f07a24d6ed1) --- source3/smbd/open.c | 214 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 202 insertions(+), 12 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 9d48bcc98b..0d6e07a032 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1842,7 +1842,9 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, set_share_mode(lck, fsp, current_user.ut.uid, 0, fsp->oplock_type, new_file_created); /* Handle strange delete on close create semantics. */ - if ((create_options & FILE_DELETE_ON_CLOSE) && can_set_initial_delete_on_close(lck)) { + if ((create_options & FILE_DELETE_ON_CLOSE) + && (is_ntfs_stream_name(fname) + || can_set_initial_delete_on_close(lck))) { status = can_set_delete_on_close(fsp, True, new_dos_attributes); if (!NT_STATUS_IS_OK(status)) { @@ -2443,6 +2445,115 @@ static struct case_semantics_state *set_posix_case_semantics(TALLOC_CTX *mem_ctx return result; } +/* + * If a main file is opened for delete, all streams need to be checked for + * !FILE_SHARE_DELETE. Do this by opening with DELETE_ACCESS. + * If that works, delete them all by setting the delete on close and close. + */ + +static NTSTATUS open_streams_for_delete(connection_struct *conn, + const char *fname) +{ + struct stream_struct *stream_info; + files_struct **streams; + int i; + unsigned int num_streams; + TALLOC_CTX *frame = talloc_stackframe(); + NTSTATUS status; + + status = SMB_VFS_STREAMINFO(conn, NULL, fname, talloc_tos(), + &num_streams, &stream_info); + + if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) { + DEBUG(10, ("no streams around\n")); + TALLOC_FREE(frame); + return NT_STATUS_OK; + } + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("SMB_VFS_STREAMINFO failed: %s\n", + nt_errstr(status))); + goto fail; + } + + DEBUG(10, ("open_streams_for_delete found %d streams\n", + num_streams)); + + if (num_streams == 0) { + TALLOC_FREE(frame); + return NT_STATUS_OK; + } + + streams = TALLOC_ARRAY(talloc_tos(), files_struct *, num_streams); + if (streams == NULL) { + DEBUG(0, ("talloc failed\n")); + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + for (i=0; i= 0; i--) { + if (streams[i] == NULL) { + continue; + } + + DEBUG(10, ("Closing stream # %d, %s\n", i, + streams[i]->fsp_name)); + close_file(streams[i], NORMAL_CLOSE); + } + + fail: + TALLOC_FREE(frame); + return status; +} + /* * Wrapper around open_file_ntcreate and open_directory */ @@ -2466,6 +2577,7 @@ NTSTATUS create_file_unixpath(connection_struct *conn, { SMB_STRUCT_STAT sbuf; int info = FILE_WAS_OPENED; + files_struct *base_fsp = NULL; files_struct *fsp = NULL; NTSTATUS status; @@ -2495,7 +2607,23 @@ NTSTATUS create_file_unixpath(connection_struct *conn, sbuf = *psbuf; } else { - SET_STAT_INVALID(sbuf); + if (SMB_VFS_STAT(conn, fname, &sbuf) == -1) { + SET_STAT_INVALID(sbuf); + } + } + + if ((conn->fs_capabilities & FILE_NAMED_STREAMS) + && (access_mask & DELETE_ACCESS) + && !is_ntfs_stream_name(fname)) { + /* + * We can't open a file with DELETE access if any of the + * streams is open without FILE_SHARE_DELETE + */ + status = open_streams_for_delete(conn, fname); + + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } } /* This is the correct thing to do (check every time) but can_delete @@ -2528,12 +2656,61 @@ NTSTATUS create_file_unixpath(connection_struct *conn, } #endif + if ((conn->fs_capabilities & FILE_NAMED_STREAMS) + && is_ntfs_stream_name(fname) + && (!(create_options & NTCREATEX_OPTIONS_PRIVATE_STREAM_DELETE))) { + char *base; + uint32 base_create_disposition; + + if (create_options & FILE_DIRECTORY_FILE) { + status = NT_STATUS_NOT_A_DIRECTORY; + goto fail; + } + + status = split_ntfs_stream_name(talloc_tos(), fname, + &base, NULL); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("split_ntfs_stream_name failed: %s\n", + nt_errstr(status))); + goto fail; + } + + SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */ + + switch (create_disposition) { + case FILE_OPEN: + base_create_disposition = FILE_OPEN; + break; + default: + base_create_disposition = FILE_OPEN_IF; + break; + } + + status = create_file_unixpath(conn, NULL, base, 0, + FILE_SHARE_READ + | FILE_SHARE_WRITE + | FILE_SHARE_DELETE, + base_create_disposition, + 0, 0, 0, 0, NULL, NULL, + &base_fsp, NULL, NULL); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("create_file_unixpath for base %s failed: " + "%s\n", base, nt_errstr(status))); + goto fail; + } + } + /* * If it's a request for a directory open, deal with it separately. */ if (create_options & FILE_DIRECTORY_FILE) { + if (create_options & FILE_NON_DIRECTORY_FILE) { + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + /* Can't open a temp directory. IFS kit test. */ if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) { status = NT_STATUS_INVALID_PARAMETER; @@ -2664,6 +2841,16 @@ NTSTATUS create_file_unixpath(connection_struct *conn, DEBUG(10, ("create_file: info=%d\n", info)); + /* + * Set fsp->base_fsp late enough that we can't "goto fail" anymore. In + * the fail: branch we call close_file(fsp, ERROR_CLOSE) which would + * also close fsp->base_fsp which we have to also do explicitly in + * this routine here, as not in all "goto fail:" we have the fsp set + * up already to be initialized with the base_fsp. + */ + + fsp->base_fsp = base_fsp; + *result = fsp; if (pinfo != NULL) { *pinfo = info; @@ -2685,6 +2872,10 @@ NTSTATUS create_file_unixpath(connection_struct *conn, close_file(fsp, ERROR_CLOSE); fsp = NULL; } + if (base_fsp != NULL) { + close_file(base_fsp, ERROR_CLOSE); + base_fsp = NULL; + } return status; } @@ -2812,19 +3003,18 @@ NTSTATUS create_file(connection_struct *conn, status = NT_STATUS_NO_MEMORY; goto fail; } - } else { - /* - * Check to see if this is a mac fork of some kind. - */ + } + + /* + * Check to see if this is a mac fork of some kind. + */ - if (is_ntfs_stream_name(fname)) { - enum FAKE_FILE_TYPE fake_file_type; + if (is_ntfs_stream_name(fname)) { + enum FAKE_FILE_TYPE fake_file_type; - fake_file_type = is_fake_file(fname); + fake_file_type = is_fake_file(fname); - if (fake_file_type == FAKE_FILE_TYPE_NONE) { - return NT_STATUS_OBJECT_PATH_NOT_FOUND; - } + if (fake_file_type != FAKE_FILE_TYPE_NONE) { /* * Here we go! support for changing the disk quotas -- cgit From 0bb6fb7b6f8ea1c039e710f55bba779363716f2d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 19 Jan 2008 21:53:49 -0800 Subject: Couple of minor fixes for POSIX pathname processing in the new stream code. (1) In smbd/filename, don't split the name at ':' if we know it's a posix path (this should be parameterized....). (2). When calling posix_mkdir, we get the flag FILE_FLAG_POSIX_SEMANTICS passed to open_directory(). I know for a posix client lp_posix_pathnames should be true (which is checked for in is_ntfs_stream_name() but we have an explicit flag here, so let's use it. Jeremy. (This used to be commit 7bb7a0def6518784befa75e5303289d2b4d36dd4) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 0d6e07a032..ad221c3227 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2106,7 +2106,7 @@ NTSTATUS open_directory(connection_struct *conn, (unsigned int)create_disposition, (unsigned int)file_attributes)); - if (is_ntfs_stream_name(fname)) { + if (!(file_attributes & FILE_FLAG_POSIX_SEMANTICS) && is_ntfs_stream_name(fname)) { DEBUG(2, ("open_directory: %s is a stream name!\n", fname)); return NT_STATUS_NOT_A_DIRECTORY; } -- cgit From 896ec681816b38d85e3dfbb45e9df8993de42899 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 20 Jan 2008 14:44:07 +0100 Subject: NT_STATUS_OBJECT_NAME_NOT_FOUND also means "no streams around :-)" (This used to be commit 96b9a7b3eb92c9f133a3f43ffc4d57d0212e4ebd) --- source3/smbd/open.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index ad221c3227..f55728665f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2464,7 +2464,8 @@ static NTSTATUS open_streams_for_delete(connection_struct *conn, status = SMB_VFS_STREAMINFO(conn, NULL, fname, talloc_tos(), &num_streams, &stream_info); - if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) { + if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED) + || NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { DEBUG(10, ("no streams around\n")); TALLOC_FREE(frame); return NT_STATUS_OK; -- cgit From b1017bb551fd28d2f9562acb1ff7f0dde933417a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 20 Jan 2008 17:32:19 +0100 Subject: Free case_state earlier Found by a "set but never used" warning. Thanks to talloc_tos() this was not really a bug, but this way the code becomes much clearer. (This used to be commit b326f11dc39a8ce20d957aac976be0cf7108ba9d) --- source3/smbd/open.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index f55728665f..9fca38e3ed 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -3080,6 +3080,8 @@ NTSTATUS create_file(connection_struct *conn, fname = converted_fname; } + TALLOC_FREE(case_state); + /* All file access must go through check_name() */ status = check_name(conn, fname); -- cgit From 2a78eb9c0d5f82b9d893509dff3932bde9799adf Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 22 Jan 2008 09:22:14 +0100 Subject: Fix a ton of IBM checker uninitialized variable warnings SET_STAT_INVALID only sets nlink, not the other fields We might consider to change SET_STAT_INVALID to always do ZERO_STRUCT (This used to be commit 8cf8c5b2034fe093b5db7f069bc6be8d328399bf) --- source3/smbd/open.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 9fca38e3ed..aa4bc48f3d 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -3034,8 +3034,7 @@ NTSTATUS create_file(connection_struct *conn, goto fail; } - SET_STAT_INVALID(sbuf); - + ZERO_STRUCT(sbuf); goto done; } } -- cgit From 6cdd527fed86476f9fc86b11cd5d2e7f1067d2e7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 22 Feb 2008 16:12:57 -0800 Subject: Fix debug messages. Jeremy. (This used to be commit d265cedb55b07c6b8a13b9632fbdf8a05fbba886) --- source3/smbd/open.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index aa4bc48f3d..cc78503379 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2671,8 +2671,9 @@ NTSTATUS create_file_unixpath(connection_struct *conn, status = split_ntfs_stream_name(talloc_tos(), fname, &base, NULL); if (!NT_STATUS_IS_OK(status)) { - DEBUG(10, ("split_ntfs_stream_name failed: %s\n", - nt_errstr(status))); + DEBUG(10, ("create_file_unixpath: " + "split_ntfs_stream_name failed: %s\n", + nt_errstr(status))); goto fail; } @@ -2840,7 +2841,7 @@ NTSTATUS create_file_unixpath(connection_struct *conn, } } - DEBUG(10, ("create_file: info=%d\n", info)); + DEBUG(10, ("create_file_unixpath: info=%d\n", info)); /* * Set fsp->base_fsp late enough that we can't "goto fail" anymore. In @@ -2867,7 +2868,7 @@ NTSTATUS create_file_unixpath(connection_struct *conn, return NT_STATUS_OK; fail: - DEBUG(10, ("create_file: %s\n", nt_errstr(status))); + DEBUG(10, ("create_file_unixpath: %s\n", nt_errstr(status))); if (fsp != NULL) { close_file(fsp, ERROR_CLOSE); -- cgit From 380fcfa60047e0f886ce9fdf35f304427891a7d8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Mar 2008 12:37:01 -0700 Subject: Fix S3 to pass the test_raw_oplock_exclusive3 test. Jeremy. (This used to be commit 028302fac53083d66c969b876db1d831e53b8e35) --- source3/smbd/open.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index cc78503379..0cc48c4f1c 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1366,7 +1366,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, se_map_generic(&access_mask, &file_generic_mapping); open_access_mask = access_mask; - if (flags2 & O_TRUNC) { + if ((flags2 & O_TRUNC) || (oplock_request & FORCE_OPLOCK_BREAK_TO_NONE)) { open_access_mask |= FILE_WRITE_DATA; /* This will cause oplock breaks. */ } @@ -1378,7 +1378,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, * mean the same thing under DOS and Unix. */ - if (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) { + if ((access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) || + (oplock_request & FORCE_OPLOCK_BREAK_TO_NONE)) { /* DENY_DOS opens are always underlying read-write on the file handle, no matter what the requested access mask says. */ -- cgit From 2ccf50256e31bd7b9da0f7a7c223bebca5bca062 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 12 Mar 2008 15:32:47 +0100 Subject: locking: store the write time in the locking.tdb This is needed to implement the strange write time update logic later. We need to store 2 time timestamps to distinguish between the time the file system had before the first client opened the file and a forced timestamp update. metze (This used to be commit 6aaa2ce0eeb46f6735ec984a2e7aadde7a7f456d) --- source3/smbd/open.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 0cc48c4f1c..f3ed234c87 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1221,7 +1221,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, request_time = pml->request_time; /* Remove the deferred open entry under lock. */ - lck = get_share_mode_lock(talloc_tos(), state->id, NULL, NULL); + lck = get_share_mode_lock(talloc_tos(), state->id, NULL, NULL, + NULL); if (lck == NULL) { DEBUG(0, ("could not get share mode lock\n")); } else { @@ -1450,11 +1451,12 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } if (file_existed) { + struct timespec old_write_time = get_mtimespec(psbuf); id = vfs_file_id_from_sbuf(conn, psbuf); lck = get_share_mode_lock(talloc_tos(), id, conn->connectpath, - fname); + fname, &old_write_time); if (lck == NULL) { file_free(fsp); @@ -1661,7 +1663,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } if (!file_existed) { - + struct timespec old_write_time = get_mtimespec(psbuf); /* * Deal with the race condition where two smbd's detect the * file doesn't exist and do the create at the same time. One @@ -1681,7 +1683,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, lck = get_share_mode_lock(talloc_tos(), id, conn->connectpath, - fname); + fname, &old_write_time); if (lck == NULL) { DEBUG(0, ("open_file_ntcreate: Could not get share " @@ -2095,6 +2097,7 @@ NTSTATUS open_directory(connection_struct *conn, bool dir_existed = VALID_STAT(*psbuf) ? True : False; struct share_mode_lock *lck = NULL; NTSTATUS status; + struct timespec mtimespec; int info = 0; DEBUG(5,("open_directory: opening directory %s, access_mask = 0x%x, " @@ -2217,9 +2220,11 @@ NTSTATUS open_directory(connection_struct *conn, string_set(&fsp->fsp_name,fname); + mtimespec = get_mtimespec(psbuf); + lck = get_share_mode_lock(talloc_tos(), fsp->file_id, conn->connectpath, - fname); + fname, &mtimespec); if (lck == NULL) { DEBUG(0, ("open_directory: Could not get share mode lock for %s\n", fname)); -- cgit From 3756467db6a661be91f4aeb484000e993e4a9a4c Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 11 Jan 2008 12:18:33 +0100 Subject: Move the posix pending close functionality down into the VFS layer. This hides the pending close fds from the outside. Call order of SMB_VFS_CLOSE is reversed. Originally, it was: fd_close -> fd_close_posix -> SMB_VFS_CLOSE -> close And now it is: fd_close -> SMB_VFS_CLOSE -> fd_close_posix -> close This is in preparation of removing the fd parameter from the SMB_VFS_CLOSE function. But it is also the right place for the pending close calls anyways. Michael (This used to be commit 3cf56b124a2886c6260455bba4bf77d08e9a4f77) --- source3/smbd/open.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index f3ed234c87..7a13b3ae38 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -72,13 +72,21 @@ static NTSTATUS fd_open(struct connection_struct *conn, NTSTATUS fd_close(files_struct *fsp) { + int ret; + if (fsp->fh->fd == -1) { return NT_STATUS_OK; /* What we used to call a stat open. */ } if (fsp->fh->ref_count > 1) { return NT_STATUS_OK; /* Shared handle. Only close last reference. */ } - return fd_close_posix(fsp); + + ret = SMB_VFS_CLOSE(fsp, fsp->fh->fd); + fsp->fh->fd = -1; + if (ret == -1) { + return map_nt_error_from_unix(errno); + } + return NT_STATUS_OK; } /**************************************************************************** -- cgit From 0db7aba8af80a01150d1061a4192ab814e4234b7 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 11 Jan 2008 14:19:28 +0100 Subject: Remove redundant parameter fd from SMB_VFS_CLOSE(). Now all those redundant fd's have vanished from the VFS API. Michael (This used to be commit 14294535512a7f191c5008e622b6708e417854ae) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 7a13b3ae38..0d1dd31cd6 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -81,7 +81,7 @@ NTSTATUS fd_close(files_struct *fsp) return NT_STATUS_OK; /* Shared handle. Only close last reference. */ } - ret = SMB_VFS_CLOSE(fsp, fsp->fh->fd); + ret = SMB_VFS_CLOSE(fsp); fsp->fh->fd = -1; if (ret == -1) { return map_nt_error_from_unix(errno); -- cgit From 85dc0ad7beb50dbab6d98a22b114f20537425268 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 2 May 2008 12:54:53 -0700 Subject: Rename inherit_access_acl() -> inherit_access_posix_acl() to make use clear. Jeremy. (This used to be commit b739c7f1cdb2b19a380b06681b00dcf490d788a9) --- source3/smbd/open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 0d1dd31cd6..dd518b90de 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -323,7 +323,7 @@ static NTSTATUS open_file(files_struct *fsp, /* Inherit the ACL if required */ if (lp_inherit_perms(SNUM(conn))) { - inherit_access_acl(conn, parent_dir, path, + inherit_access_posix_acl(conn, parent_dir, path, unx_mode); } @@ -2058,7 +2058,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, } if (lp_inherit_perms(SNUM(conn))) { - inherit_access_acl(conn, parent_dir, name, mode); + inherit_access_posix_acl(conn, parent_dir, name, mode); } if (!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) { -- cgit From b430b382202858a6c52c1cacbb91910b2dd7e16c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 2 May 2008 17:22:10 -0700 Subject: Remove the "stat_open()" function, flag, and all associated code. It was only being (correctly) used in the can_read/can_write checks for hide unreadable/unwritable and this is more properly done using the functions in smbd/file_access.c. Preparing to do NT access checks on all file access. Jeremy. (This used to be commit 6bfb06ad95963ae2acb67c4694a98282d3b29faa) --- source3/smbd/open.c | 56 +---------------------------------------------------- 1 file changed, 1 insertion(+), 55 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index dd518b90de..5c860f891d 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -391,7 +391,6 @@ static NTSTATUS open_file(files_struct *fsp, fsp->modified = False; fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = False; - fsp->is_stat = False; if (conn->aio_write_behind_list && is_in_path(path, conn->aio_write_behind_list, conn->case_sensitive)) { fsp->aio_write_behind = True; @@ -1571,7 +1570,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } if (((can_access_mask & FILE_WRITE_DATA) && !CAN_WRITE(conn)) || - !can_access_file(conn,fname,psbuf,can_access_mask)) { + !can_access_file_data(conn,fname,psbuf,can_access_mask)) { can_access = False; } @@ -2223,7 +2222,6 @@ NTSTATUS open_directory(connection_struct *conn, fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = True; - fsp->is_stat = False; fsp->posix_open = (file_attributes & FILE_FLAG_POSIX_SEMANTICS) ? True : False; string_set(&fsp->fsp_name,fname); @@ -2305,58 +2303,6 @@ NTSTATUS create_directory(connection_struct *conn, struct smb_request *req, cons return status; } -/**************************************************************************** - Open a pseudo-file (no locking checks - a 'stat' open). -****************************************************************************/ - -NTSTATUS open_file_stat(connection_struct *conn, struct smb_request *req, - const char *fname, SMB_STRUCT_STAT *psbuf, - files_struct **result) -{ - files_struct *fsp = NULL; - NTSTATUS status; - - if (!VALID_STAT(*psbuf)) { - return NT_STATUS_INVALID_PARAMETER; - } - - /* Can't 'stat' open directories. */ - if(S_ISDIR(psbuf->st_mode)) { - return NT_STATUS_FILE_IS_A_DIRECTORY; - } - - status = file_new(conn, &fsp); - if(!NT_STATUS_IS_OK(status)) { - return status; - } - - DEBUG(5,("open_file_stat: 'opening' file %s\n", fname)); - - /* - * Setup the files_struct for it. - */ - - fsp->mode = psbuf->st_mode; - fsp->file_id = vfs_file_id_from_sbuf(conn, psbuf); - fsp->vuid = req ? req->vuid : UID_FIELD_INVALID; - fsp->file_pid = req ? req->smbpid : 0; - fsp->can_lock = False; - fsp->can_read = False; - fsp->can_write = False; - fsp->print_file = False; - fsp->modified = False; - fsp->oplock_type = NO_OPLOCK; - fsp->sent_oplock_break = NO_BREAK_SENT; - fsp->is_directory = False; - fsp->is_stat = True; - string_set(&fsp->fsp_name,fname); - - conn->num_files_open++; - - *result = fsp; - return NT_STATUS_OK; -} - /**************************************************************************** Receive notification that one of our open files has been renamed by another smbd process. -- cgit From 5bda9a8af02c7889e15e580a5620689aa312a16a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 8 May 2008 16:06:42 +0200 Subject: Remove "user" from connection_struct (This used to be commit 368454a27cb53a408ec416cbf37235b304592fb5) --- source3/smbd/open.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 5c860f891d..546128c0e5 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -400,8 +400,9 @@ static NTSTATUS open_file(files_struct *fsp, fsp->wcp = NULL; /* Write cache pointer. */ DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n", - *current_user_info.smb_name ? - current_user_info.smb_name : conn->user,fsp->fsp_name, + *current_user_info.smb_name + ? current_user_info.smb_name : conn->server_info->unix_name, + fsp->fsp_name, BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write), conn->num_files_open + 1)); -- cgit From d49de28f1154140f63670cfbf5093cdee6f16eb0 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 15 Jun 2008 13:37:53 +0200 Subject: Remove the current_user reference from fake_file.c The current vuid is not only available there, it is also in the current smb_request structure. (This used to be commit c8fd5eef32a86888c7a28317f0fdf717a26b7d4c) --- source3/smbd/open.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 546128c0e5..9b847ec877 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2990,7 +2990,8 @@ NTSTATUS create_file(connection_struct *conn, * also tries a QUERY_FILE_INFO on the file and then * close it */ - status = open_fake_file(conn, fake_file_type, fname, + status = open_fake_file(conn, req->vuid, + fake_file_type, fname, access_mask, &fsp); if (!NT_STATUS_IS_OK(status)) { goto fail; -- cgit From b6c125e4e0201498e67405fe9065415d6f45abef Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 15 Jun 2008 13:41:16 +0200 Subject: Remove the current_user references from open.c current_user_info was "only" used in a debug msg, and current_user.ut.uid is also available via conn->server_info (This used to be commit d0386914ff0f7b0f1edc3302fdc6a25f211712fa) --- source3/smbd/open.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 9b847ec877..5a1af42638 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -22,8 +22,6 @@ #include "includes.h" extern const struct generic_mapping file_generic_mapping; -extern struct current_user current_user; -extern userdom_struct current_user_info; extern bool global_client_failed_oplock_break; struct deferred_open_record { @@ -400,8 +398,7 @@ static NTSTATUS open_file(files_struct *fsp, fsp->wcp = NULL; /* Write cache pointer. */ DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n", - *current_user_info.smb_name - ? current_user_info.smb_name : conn->server_info->unix_name, + conn->server_info->unix_name, fsp->fsp_name, BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write), conn->num_files_open + 1)); @@ -1850,7 +1847,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, new_file_created = True; } - set_share_mode(lck, fsp, current_user.ut.uid, 0, fsp->oplock_type, new_file_created); + set_share_mode(lck, fsp, conn->server_info->uid, 0, fsp->oplock_type, + new_file_created); /* Handle strange delete on close create semantics. */ if ((create_options & FILE_DELETE_ON_CLOSE) @@ -2249,7 +2247,7 @@ NTSTATUS open_directory(connection_struct *conn, return status; } - set_share_mode(lck, fsp, current_user.ut.uid, 0, NO_OPLOCK, True); + set_share_mode(lck, fsp, conn->server_info->uid, 0, NO_OPLOCK, True); /* For directories the delete on close bit at open time seems always to be honored on close... See test 19 in Samba4 BASE-DELETE. */ -- cgit From 40f5eab5eb515937e1b23cf6762b77c194d29b9d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 19 Jun 2008 16:54:12 +0200 Subject: Wrap the unix token info in a unix_user_token in auth_serversupplied_info No functional change, this is a preparation for more current_user ref removal (This used to be commit dcaedf345e62ab74ea87f0a3fa1e3199c75c5445) --- source3/smbd/open.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 5a1af42638..3cec80c6df 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1847,8 +1847,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, new_file_created = True; } - set_share_mode(lck, fsp, conn->server_info->uid, 0, fsp->oplock_type, - new_file_created); + set_share_mode(lck, fsp, conn->server_info->utok.uid, 0, + fsp->oplock_type, new_file_created); /* Handle strange delete on close create semantics. */ if ((create_options & FILE_DELETE_ON_CLOSE) @@ -2247,7 +2247,8 @@ NTSTATUS open_directory(connection_struct *conn, return status; } - set_share_mode(lck, fsp, conn->server_info->uid, 0, NO_OPLOCK, True); + set_share_mode(lck, fsp, conn->server_info->utok.uid, 0, NO_OPLOCK, + True); /* For directories the delete on close bit at open time seems always to be honored on close... See test 19 in Samba4 BASE-DELETE. */ -- cgit From c885ae01ebbf2b2f5c75799c4e8b1b0c68b2d34e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 24 Jun 2008 16:58:29 +0200 Subject: Remove current_user reference from printfsp.c (This used to be commit 510f45d01a19ce1c226755ac42a328241098b2e0) --- source3/smbd/open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 3cec80c6df..aa3bbdf685 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1178,7 +1178,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, DEBUG(10, ("open_file_ntcreate: printer open fname=%s\n", fname)); - return print_fsp_open(conn, fname, result); + return print_fsp_open(conn, fname, req->vuid, result); } if (!parent_dirname_talloc(talloc_tos(), fname, &parent_dir, -- cgit From f9223a7139e7cc43cb3337a5c66d0262b9e03d54 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 Jul 2008 18:12:12 -0700 Subject: If we're not allowing streams on this conn ptr, then don't allow create_file() to call down to create_file_unixpath() with a stream name. Jeremy. (This used to be commit 167d611b525db6d103a7f83fd5a19792be4e7745) --- source3/smbd/open.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index aa3bbdf685..03efd09f06 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2999,6 +2999,11 @@ NTSTATUS create_file(connection_struct *conn, ZERO_STRUCT(sbuf); goto done; } + + if (!(conn->fs_capabilities & FILE_NAMED_STREAMS)) { + status = NT_STATUS_OBJECT_PATH_NOT_FOUND; + goto fail; + } } if ((req != NULL) && (req->flags2 & FLAGS2_DFS_PATHNAMES)) { -- cgit From eb8dd6a81181c3dab9cbe6b934ceb4f3ba1ba2af Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 19 Aug 2008 16:34:50 +0200 Subject: smbd: fix the handling of create_options to pass RAW-OPEN Some of the bits generate INVALID_PARAMETER and some bits are ignored when they come from a client, that's why we need to use bits from the ignored range for our internal usage. metze (This used to be commit 7b4c8a4e39f310eb450918fa841b0ea1b4af19f7) --- source3/smbd/open.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd/open.c') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 03efd09f06..8b32907a4b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2560,6 +2560,11 @@ NTSTATUS create_file_unixpath(connection_struct *conn, goto fail; } + if (create_options & NTCREATEX_OPTIONS_INVALID_PARAM_MASK) { + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + if (req == NULL) { oplock_request |= INTERNAL_OPEN_ONLY; } -- cgit