diff options
Diffstat (limited to 'source3/locking/locking_slow.c')
-rw-r--r-- | source3/locking/locking_slow.c | 1144 |
1 files changed, 0 insertions, 1144 deletions
diff --git a/source3/locking/locking_slow.c b/source3/locking/locking_slow.c deleted file mode 100644 index 58673d2707..0000000000 --- a/source3/locking/locking_slow.c +++ /dev/null @@ -1,1144 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - slow (lockfile) locking implementation - 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. - - Revision History: - - 12 aug 96: Erik.Devriendt@te6.siemens.be - added support for shared memory implementation of share mode locking - - May 1997. Jeremy Allison (jallison@whistle.com). Modified share mode - locking to deal with multiple share modes per open file. - - September 1997. Jeremy Allison (jallison@whistle.com). Added oplock - support. - - October 1997 - split into separate file (tridge) -*/ - -#include "includes.h" - -#ifndef FAST_SHARE_MODES - -extern int DEBUGLEVEL; - -/* - * Locking file header lengths & offsets. - */ -#define SMF_VERSION_OFFSET 0 -#define SMF_NUM_ENTRIES_OFFSET 4 -#define SMF_FILENAME_LEN_OFFSET 8 -#define SMF_HEADER_LENGTH 10 - -#define SMF_ENTRY_LENGTH 20 - -/* - * Share mode record offsets. - */ - -#define SME_SEC_OFFSET 0 -#define SME_USEC_OFFSET 4 -#define SME_SHAREMODE_OFFSET 8 -#define SME_PID_OFFSET 12 -#define SME_PORT_OFFSET 16 -#define SME_OPLOCK_TYPE_OFFSET 18 - -/* we need world read for smbstatus to function correctly */ -#ifdef SECURE_SHARE_MODES -#define SHARE_FILE_MODE 0600 -#else -#define SHARE_FILE_MODE 0644 -#endif - -static int read_only; - -/******************************************************************* - deinitialize share_mode management - ******************************************************************/ -static BOOL slow_stop_share_mode_mgmt(void) -{ - return True; -} - - -/******************************************************************* - name a share file - ******************************************************************/ -static BOOL share_name(connection_struct *conn, - SMB_DEV_T dev, SMB_INO_T inode, char *name) -{ - int len; - pstrcpy(name,lp_lockdir()); - trim_string(name,"","/"); - if (!*name) return(False); - len = strlen(name); - name += len; - -#ifdef LARGE_SMB_INO_T - slprintf(name, sizeof(pstring) - len - 1, "/share.%u.%.0f",(unsigned int)dev,(double)inode); -#else /* LARGE_SMB_INO_T */ - slprintf(name, sizeof(pstring) - len - 1, "/share.%u.%lu",(unsigned int)dev,(unsigned long)inode); -#endif /* LARGE_SMB_INO_T */ - return(True); -} - -/******************************************************************* -Force a share file to be deleted. -********************************************************************/ -static int delete_share_file(connection_struct *conn, char *fname ) -{ - if (read_only) return -1; - - /* the share file could be owned by anyone, so do this as root */ - become_root(False); - - if(unlink(fname) != 0) - { - DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n", - fname, strerror(errno))); - } - else - { - DEBUG(5,("delete_share_file: Deleted share file %s\n", fname)); - } - - /* return to our previous privilege level */ - unbecome_root(False); - - return 0; -} - -/******************************************************************* - lock a share mode file. - ******************************************************************/ -static BOOL slow_lock_share_entry(connection_struct *conn, - SMB_DEV_T dev, SMB_INO_T inode, int *ptok) -{ - pstring fname; - int fd; - int ret = True; - - *ptok = (int)-1; - - if(!share_name(conn, dev, inode, fname)) - return False; - - if (read_only) return True; - - /* we need to do this as root */ - become_root(False); - - { - BOOL gotlock = False; - /* - * There was a race condition in the original slow share mode code. - * A smbd could open a share mode file, and before getting - * the lock, another smbd could delete the last entry for - * the share mode file and delete the file entry from the - * directory. Thus this smbd would be left with a locked - * share mode fd attached to a file that no longer had a - * directory entry. Thus another smbd would think that - * there were no outstanding opens on the file. To fix - * this we now check we can do a stat() call on the filename - * before allowing the lock to proceed, and back out completely - * and try the open again if we cannot. - * Jeremy Allison (jallison@whistle.com). - */ - - do - { - SMB_STRUCT_STAT dummy_stat; - - fd = sys_open(fname,read_only?O_RDONLY:(O_RDWR|O_CREAT), SHARE_FILE_MODE); - - if(fd < 0) - { - DEBUG(0,("ERROR lock_share_entry: failed to open share file %s. Error was %s\n", - fname, strerror(errno))); - ret = False; - break; - } - - /* At this point we have an open fd to the share mode file. - Lock the first byte exclusively to signify a lock. */ - if(fcntl_lock(fd, SMB_F_SETLKW, 0, 1, F_WRLCK) == False) - { - DEBUG(0,("ERROR lock_share_entry: fcntl_lock on file %s failed with %s\n", - fname, strerror(errno))); - close(fd); - ret = False; - break; - } - - /* - * If we cannot stat the filename, the file was deleted between - * the open and the lock call. Back out and try again. - */ - - if(sys_stat(fname, &dummy_stat)!=0) - { - DEBUG(2,("lock_share_entry: Re-issuing open on %s to fix race. Error was %s\n", - fname, strerror(errno))); - close(fd); - } - else - gotlock = True; - } while(!gotlock); - - /* - * We have to come here if any of the above calls fail - * as we don't want to return and leave ourselves running - * as root ! - */ - } - - *ptok = (int)fd; - - /* return to our previous privilege level */ - unbecome_root(False); - - return ret; -} - -/******************************************************************* - unlock a share mode file. - ******************************************************************/ -static BOOL slow_unlock_share_entry(connection_struct *conn, - SMB_DEV_T dev, SMB_INO_T inode, int token) -{ - int fd = token; - int ret = True; - SMB_STRUCT_STAT sb; - pstring fname; - - if (read_only) return True; - - /* Fix for zero length share files from - Gerald Werner <wernerg@mfldclin.edu> */ - - share_name(conn, dev, inode, fname); - - /* get the share mode file size */ - if(sys_fstat((int)token, &sb) != 0) - { - DEBUG(0,("ERROR: unlock_share_entry: Failed to do stat on share file %s (%s)\n", - fname, strerror(errno))); - sb.st_size = 1; - ret = False; - } - - /* If the file was zero length, we must delete before - doing the unlock to avoid a race condition (see - the code in lock_share_mode_entry for details. - */ - - /* remove the share file if zero length */ - if(sb.st_size == 0) - delete_share_file(conn, fname); - - /* token is the fd of the open share mode file. */ - /* Unlock the first byte. */ - if(fcntl_lock(fd, SMB_F_SETLKW, 0, 1, F_UNLCK) == False) - { - DEBUG(0,("ERROR unlock_share_entry: fcntl_lock failed with %s\n", - strerror(errno))); - ret = False; - } - - close(fd); - return ret; -} - -/******************************************************************* -Read a share file into a buffer. -********************************************************************/ -static int read_share_file(connection_struct *conn, int fd, char *fname, char **out, BOOL *p_new_file) -{ - SMB_STRUCT_STAT sb; - char *buf; - SMB_OFF_T size; - - *out = 0; - *p_new_file = False; - - if(sys_fstat(fd, &sb) != 0) - { - DEBUG(0,("ERROR: read_share_file: Failed to do stat on share file %s (%s)\n", - fname, strerror(errno))); - return -1; - } - - if(sb.st_size == 0) - { - *p_new_file = True; - return 0; - } - - /* Allocate space for the file */ - if((buf = (char *)malloc((size_t)sb.st_size)) == NULL) - { - DEBUG(0,("read_share_file: malloc for file size %d fail !\n", - (int)sb.st_size)); - return -1; - } - - if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: read_share_file: Failed to reset position to 0 \ -for share file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return -1; - } - - if (read(fd,buf,(size_t)sb.st_size) != (size_t)sb.st_size) - { - DEBUG(0,("ERROR: read_share_file: Failed to read share file %s (%s)\n", - fname, strerror(errno))); - if(buf) - free(buf); - return -1; - } - - if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION) { - DEBUG(0,("ERROR: read_share_file: share file %s has incorrect \ -locking version (was %d, should be %d).\n",fname, - IVAL(buf,SMF_VERSION_OFFSET), LOCKING_VERSION)); - if(buf) - free(buf); - delete_share_file(conn, fname); - return -1; - } - - /* Sanity check for file contents */ - size = sb.st_size; - size -= SMF_HEADER_LENGTH; /* Remove the header */ - - /* Remove the filename component. */ - size -= SVAL(buf, SMF_FILENAME_LEN_OFFSET); - - /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */ - if((size % SMF_ENTRY_LENGTH) != 0) - { - DEBUG(0,("ERROR: read_share_file: share file %s is an incorrect length - \ -deleting it.\n", fname)); - if(buf) - free(buf); - delete_share_file(conn, fname); - return -1; - } - - *out = buf; - return 0; -} - -/******************************************************************* -get all share mode entries in a share file for a dev/inode pair. -********************************************************************/ -static int slow_get_share_modes(connection_struct *conn, int token, - SMB_DEV_T dev, SMB_INO_T inode, - share_mode_entry **old_shares) -{ - int fd = token; - pstring fname; - int i; - int num_entries; - int num_entries_copied; - int newsize; - share_mode_entry *share_array; - char *buf = 0; - char *base = 0; - BOOL new_file; - - *old_shares = 0; - - /* Read the share file header - this is of the form: - 0 - locking version. - 4 - number of share mode entries. - 8 - 2 byte name length - [n bytes] file name (zero terminated). - - Followed by <n> share mode entries of the form : - - 0 - tv_sec - 4 - tv_usec - 8 - share_mode - 12 - pid - 16 - oplock port (if oplocks in use) - 2 bytes. - */ - - share_name(conn, dev, inode, fname); - - if(read_share_file( conn, fd, fname, &buf, &new_file) != 0) - { - DEBUG(0,("ERROR: get_share_modes: Failed to read share file %s\n", - fname)); - return 0; - } - - if(new_file == True) - return 0; - - num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); - - DEBUG(5,("get_share_modes: share file %s has %d share mode entries.\n", - fname, num_entries)); - - /* PARANOIA TEST */ - if(num_entries < 0) - { - DEBUG(0,("PANIC ERROR:get_share_mode: num_share_mode_entries < 0 (%d) \ -for share file %s\n", num_entries, fname)); - return 0; - } - - if(num_entries) - { - *old_shares = share_array = (share_mode_entry *) - malloc(num_entries * sizeof(share_mode_entry)); - if(*old_shares == 0) - { - DEBUG(0,("get_share_modes: malloc fail !\n")); - return 0; - } - } - else - { - /* No entries - just delete the file. */ - DEBUG(0,("get_share_modes: share file %s has no share mode entries - deleting.\n", - fname)); - if(buf) - free(buf); - delete_share_file(conn, fname); - return 0; - } - - num_entries_copied = 0; - base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); - - for( i = 0; i < num_entries; i++) - { - pid_t pid; - char *p = base + (i*SMF_ENTRY_LENGTH); - - pid = (pid_t)IVAL(p,SME_PID_OFFSET); - - if(!process_exists(pid)) - { - DEBUG(0,("get_share_modes: process %d no longer exists and \ -it left a share mode entry with mode 0x%X in share file %s\n", - (int)pid, IVAL(p,SME_SHAREMODE_OFFSET), fname)); - continue; - } - share_array[num_entries_copied].time.tv_sec = IVAL(p,SME_SEC_OFFSET); - share_array[num_entries_copied].time.tv_usec = IVAL(p,SME_USEC_OFFSET); - share_array[num_entries_copied].share_mode = IVAL(p,SME_SHAREMODE_OFFSET); - share_array[num_entries_copied].pid = pid; - share_array[num_entries_copied].op_port = SVAL(p,SME_PORT_OFFSET); - share_array[num_entries_copied].op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET); - - num_entries_copied++; - } - - if(num_entries_copied == 0) - { - /* Delete the whole file. */ - DEBUG(0,("get_share_modes: share file %s had no valid entries - deleting it !\n", - fname)); - if(*old_shares) - free((char *)*old_shares); - *old_shares = 0; - if(buf) - free(buf); - delete_share_file(conn, fname); - return 0; - } - - /* If we deleted some entries we need to re-write the whole number of - share mode entries back into the file. */ - - if(num_entries_copied != num_entries) - { - if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: get_share_modes: lseek failed to reset to \ -position 0 for share mode file %s (%s)\n", fname, strerror(errno))); - if(*old_shares) - free((char *)*old_shares); - *old_shares = 0; - if(buf) - free(buf); - return 0; - } - - SIVAL(buf, SMF_NUM_ENTRIES_OFFSET, num_entries_copied); - for( i = 0; i < num_entries_copied; i++) - { - char *p = base + (i*SMF_ENTRY_LENGTH); - - SIVAL(p,SME_PID_OFFSET,(uint32)share_array[i].pid); - SIVAL(p,SME_SHAREMODE_OFFSET,share_array[i].share_mode); - SIVAL(p,SME_SEC_OFFSET,share_array[i].time.tv_sec); - SIVAL(p,SME_USEC_OFFSET,share_array[i].time.tv_usec); - SSVAL(p,SME_PORT_OFFSET,share_array[i].op_port); - SSVAL(p,SME_OPLOCK_TYPE_OFFSET,share_array[i].op_type); - } - - newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries_copied); - if(write(fd, buf, newsize) != newsize) - { - DEBUG(0,("ERROR: get_share_modes: failed to re-write share \ -mode file %s (%s)\n", fname, strerror(errno))); - if(*old_shares) - free((char *)*old_shares); - *old_shares = 0; - if(buf) - free(buf); - return 0; - } - /* Now truncate the file at this point. */ -#ifdef FTRUNCATE_NEEDS_ROOT - become_root(False); -#endif /* FTRUNCATE_NEEDS_ROOT */ - - if(sys_ftruncate(fd, (SMB_OFF_T)newsize)!= 0) - { -#ifdef FTRUNCATE_NEEDS_ROOT - int saved_errno = errno; - unbecome_root(False); - errno = saved_errno; -#endif /* FTRUNCATE_NEEDS_ROOT */ - - DEBUG(0,("ERROR: get_share_modes: failed to ftruncate share \ -mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); - if(*old_shares) - free((char *)*old_shares); - *old_shares = 0; - if(buf) - free(buf); - return 0; - } - } - -#ifdef FTRUNCATE_NEEDS_ROOT - unbecome_root(False); -#endif /* FTRUNCATE_NEEDS_ROOT */ - - if(buf) - free(buf); - - DEBUG(5,("get_share_modes: Read share file %s returning %d entries\n",fname, - num_entries_copied)); - - return num_entries_copied; -} - -/******************************************************************* -del a share mode from a share mode file. -********************************************************************/ -static void slow_del_share_mode(int token, files_struct *fsp) -{ - pstring fname; - int fd = (int)token; - char *buf = 0; - char *base = 0; - int num_entries; - int newsize; - int i; - pid_t pid; - BOOL deleted = False; - BOOL new_file; - - share_name(fsp->conn, fsp->fd_ptr->dev, - fsp->fd_ptr->inode, fname); - - if(read_share_file( fsp->conn, fd, fname, &buf, &new_file) != 0) - { - DEBUG(0,("ERROR: del_share_mode: Failed to read share file %s\n", - fname)); - return; - } - - if(new_file == True) - { - DEBUG(0,("ERROR:del_share_mode: share file %s is new (size zero), deleting it.\n", - fname)); - delete_share_file(fsp->conn, fname); - return; - } - - num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); - - DEBUG(5,("del_share_mode: share file %s has %d share mode entries.\n", - fname, num_entries)); - - /* PARANOIA TEST */ - if(num_entries < 0) - { - DEBUG(0,("PANIC ERROR:del_share_mode: num_share_mode_entries < 0 (%d) \ -for share file %s\n", num_entries, fname)); - return; - } - - if(num_entries == 0) - { - /* No entries - just delete the file. */ - DEBUG(0,("del_share_mode: share file %s has no share mode entries - deleting.\n", - fname)); - if(buf) - free(buf); - delete_share_file(fsp->conn, fname); - return; - } - - pid = getpid(); - - /* Go through the entries looking for the particular one - we have set - delete it. - */ - - base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); - - for(i = 0; i < num_entries; i++) - { - char *p = base + (i*SMF_ENTRY_LENGTH); - - if((IVAL(p,SME_SEC_OFFSET) != fsp->open_time.tv_sec) || - (IVAL(p,SME_USEC_OFFSET) != fsp->open_time.tv_usec) || - (IVAL(p,SME_SHAREMODE_OFFSET) != fsp->share_mode) || - (((pid_t)IVAL(p,SME_PID_OFFSET)) != pid)) - continue; - - DEBUG(5,("del_share_mode: deleting entry number %d (of %d) from the share file %s\n", - i, num_entries, fname)); - - /* Remove this entry. */ - if(i != num_entries - 1) - memcpy(p, p + SMF_ENTRY_LENGTH, (num_entries - i - 1)*SMF_ENTRY_LENGTH); - - deleted = True; - break; - } - - if(!deleted) - { - DEBUG(0,("del_share_mode: entry not found in share file %s\n", fname)); - if(buf) - free(buf); - return; - } - - num_entries--; - SIVAL(buf,SMF_NUM_ENTRIES_OFFSET, num_entries); - - if(num_entries == 0) - { - /* Deleted the last entry - remove the file. */ - DEBUG(5,("del_share_mode: removed last entry in share file - deleting share file %s\n", - fname)); - if(buf) - free(buf); - delete_share_file(fsp->conn,fname); - return; - } - - /* Re-write the file - and truncate it at the correct point. */ - if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: del_share_mode: lseek failed to reset to \ -position 0 for share mode file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return; - } - - newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries); - if(write(fd, buf, newsize) != newsize) - { - DEBUG(0,("ERROR: del_share_mode: failed to re-write share \ -mode file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return; - } - - /* Now truncate the file at this point. */ -#ifdef FTRUNCATE_NEEDS_ROOT - become_root(False); -#endif /* FTRUNCATE_NEEDS_ROOT */ - - if(sys_ftruncate(fd, (SMB_OFF_T)newsize) != 0) - { -#ifdef FTRUNCATE_NEEDS_ROOT - int saved_errno = errno; - unbecome_root(False); - errno = saved_errno; -#endif /* FTRUNCATE_NEEDS_ROOT */ - - - DEBUG(0,("ERROR: del_share_mode: failed to ftruncate share \ -mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); - if(buf) - free(buf); - return; - } - -#ifdef FTRUNCATE_NEEDS_ROOT - unbecome_root(False); -#endif /* FTRUNCATE_NEEDS_ROOT */ - -} - -/******************************************************************* -set the share mode of a file -********************************************************************/ -static BOOL slow_set_share_mode(int token,files_struct *fsp, uint16 port, uint16 op_type) -{ - pstring fname; - int fd = (int)token; - pid_t pid = getpid(); - SMB_STRUCT_STAT sb; - char *buf; - int num_entries; - int header_size; - char *p; - - share_name(fsp->conn, fsp->fd_ptr->dev, - fsp->fd_ptr->inode, fname); - - if(sys_fstat(fd, &sb) != 0) - { - DEBUG(0,("ERROR: set_share_mode: Failed to do stat on share file %s\n", - fname)); - return False; - } - - /* Sanity check for file contents (if it's not a new share file). */ - if(sb.st_size != 0) - { - SMB_OFF_T size = sb.st_size; - - /* Allocate space for the file plus one extra entry */ - if((buf = (char *)malloc((size_t)(sb.st_size + SMF_ENTRY_LENGTH))) == NULL) - { - DEBUG(0,("set_share_mode: malloc for file size %d fail !\n", - (int)(sb.st_size + SMF_ENTRY_LENGTH))); - return False; - } - - if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: set_share_mode: Failed to reset position \ -to 0 for share file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return False; - } - - if (read(fd,buf,(size_t)sb.st_size) != (size_t)sb.st_size) - { - DEBUG(0,("ERROR: set_share_mode: Failed to read share file %s (%s)\n", - fname, strerror(errno))); - if(buf) - free(buf); - return False; - } - - if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION) - { - DEBUG(0,("ERROR: set_share_mode: share file %s has incorrect \ -locking version (was %d, should be %d).\n",fname, IVAL(buf,SMF_VERSION_OFFSET), - LOCKING_VERSION)); - if(buf) - free(buf); - delete_share_file(fsp->conn, fname); - return False; - } - - size -= (SMF_HEADER_LENGTH + SVAL(buf, SMF_FILENAME_LEN_OFFSET)); /* Remove the header */ - - /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */ - if((size % SMF_ENTRY_LENGTH) != 0) - { - DEBUG(0,("ERROR: set_share_mode: share file %s is an incorrect length - \ -deleting it.\n", fname)); - if(buf) - free(buf); - delete_share_file(fsp->conn, fname); - return False; - } - - } - else - { - /* New file - just use a single_entry. */ - if((buf = (char *)malloc(SMF_HEADER_LENGTH + - strlen(fsp->fsp_name) + strlen(fsp->conn->connectpath) + 2 + SMF_ENTRY_LENGTH)) == NULL) - { - DEBUG(0,("ERROR: set_share_mode: malloc failed for single entry.\n")); - return False; - } - SIVAL(buf,SMF_VERSION_OFFSET,LOCKING_VERSION); - SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,0); - SSVAL(buf,SMF_FILENAME_LEN_OFFSET,strlen(fsp->fsp_name) + strlen(fsp->conn->connectpath) + 2); - pstrcpy(buf + SMF_HEADER_LENGTH, fsp->conn->connectpath); - pstrcat(buf + SMF_HEADER_LENGTH, "/"); - pstrcat(buf + SMF_HEADER_LENGTH, fsp->fsp_name); - } - - num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); - header_size = SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); - p = buf + header_size + (num_entries * SMF_ENTRY_LENGTH); - SIVAL(p,SME_SEC_OFFSET,fsp->open_time.tv_sec); - SIVAL(p,SME_USEC_OFFSET,fsp->open_time.tv_usec); - SIVAL(p,SME_SHAREMODE_OFFSET,fsp->share_mode); - SIVAL(p,SME_PID_OFFSET,(uint32)pid); - SSVAL(p,SME_PORT_OFFSET,port); - SSVAL(p,SME_OPLOCK_TYPE_OFFSET,op_type); - - num_entries++; - - SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,num_entries); - - if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: set_share_mode: (1) Failed to reset position to \ -0 for share file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return False; - } - - if (write(fd,buf,header_size + (num_entries*SMF_ENTRY_LENGTH)) != - (header_size + (num_entries*SMF_ENTRY_LENGTH))) - { - DEBUG(2,("ERROR: set_share_mode: Failed to write share file %s - \ -deleting it (%s).\n",fname, strerror(errno))); - delete_share_file(fsp->conn, fname); - if(buf) - free(buf); - return False; - } - - /* Now truncate the file at this point - just for safety. */ - -#ifdef FTRUNCATE_NEEDS_ROOT - become_root(False); -#endif /* FTRUNCATE_NEEDS_ROOT */ - - if(sys_ftruncate(fd, (SMB_OFF_T)(header_size + (SMF_ENTRY_LENGTH*num_entries)))!= 0) - { - -#ifdef FTRUNCATE_NEEDS_ROOT - int saved_errno = errno; - unbecome_root(False); - errno = saved_errno; -#endif /* FTRUNCATE_NEEDS_ROOT */ - - DEBUG(0,("ERROR: set_share_mode: failed to ftruncate share \ -mode file %s to size %d (%s)\n", fname, header_size + (SMF_ENTRY_LENGTH*num_entries), - strerror(errno))); - if(buf) - free(buf); - return False; - } - -#ifdef FTRUNCATE_NEEDS_ROOT - unbecome_root(False); -#endif /* FTRUNCATE_NEEDS_ROOT */ - - if(buf) - free(buf); - - DEBUG(3,("set_share_mode: Created share file %s with \ -mode 0x%X pid=%d\n",fname,fsp->share_mode,(int)pid)); - - return True; -} - -/******************************************************************* - Call a generic modify function for a share mode entry. -********************************************************************/ - -static BOOL slow_mod_share_entry(int token, files_struct *fsp, - void (*mod_fn)(share_mode_entry *, SMB_DEV_T, SMB_INO_T, void *), - void *param) -{ - pstring fname; - int fd = (int)token; - char *buf = 0; - char *base = 0; - int num_entries; - int fsize; - int i; - pid_t pid; - BOOL found = False; - BOOL new_file; - share_mode_entry entry; - - share_name(fsp->conn, fsp->fd_ptr->dev, - fsp->fd_ptr->inode, fname); - - if(read_share_file( fsp->conn, fd, fname, &buf, &new_file) != 0) - { - DEBUG(0,("ERROR: slow_mod_share_entry: Failed to read share file %s\n", - fname)); - return False; - } - - if(new_file == True) - { - DEBUG(0,("ERROR: slow_mod_share_entry: share file %s is new (size zero), \ -deleting it.\n", fname)); - delete_share_file(fsp->conn, fname); - return False; - } - - num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); - - DEBUG(5,("slow_mod_share_entry: share file %s has %d share mode entries.\n", - fname, num_entries)); - - /* PARANOIA TEST */ - if(num_entries < 0) - { - DEBUG(0,("PANIC ERROR:slow_mod_share_entry: num_share_mode_entries < 0 (%d) \ -for share file %s\n", num_entries, fname)); - return False; - } - - if(num_entries == 0) - { - /* No entries - just delete the file. */ - DEBUG(0,("slow_mod_share_entry: share file %s has no share mode entries - deleting.\n", - fname)); - if(buf) - free(buf); - delete_share_file(fsp->conn, fname); - return False; - } - - pid = getpid(); - - base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); - - for(i = 0; i < num_entries; i++) - { - char *p = base + (i*SMF_ENTRY_LENGTH); - - if((IVAL(p,SME_SEC_OFFSET) != fsp->open_time.tv_sec) || - (IVAL(p,SME_USEC_OFFSET) != fsp->open_time.tv_usec) || - (IVAL(p,SME_SHAREMODE_OFFSET) != fsp->share_mode) || - (((pid_t)IVAL(p,SME_PID_OFFSET)) != pid)) - continue; - - DEBUG(5,("slow_mod_share_entry: Calling generic function to modify entry number %d (of %d) \ -from the share file %s\n", i, num_entries, fname)); - - /* - * Copy into the share_mode_entry structure and then call - * the generic function with the given parameter. - */ - - entry.pid = (pid_t)IVAL(p,SME_PID_OFFSET); - entry.op_port = SVAL(p,SME_PORT_OFFSET); - entry.op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET); - entry.share_mode = IVAL(p,SME_SHAREMODE_OFFSET); - entry.time.tv_sec = IVAL(p,SME_SEC_OFFSET); - entry.time.tv_usec = IVAL(p,SME_USEC_OFFSET); - - (*mod_fn)( &entry, fsp->fd_ptr->dev, fsp->fd_ptr->inode, param); - - /* - * Now copy any changes the function made back into the buffer. - */ - - SIVAL(p,SME_PID_OFFSET, (uint32)entry.pid); - SSVAL(p,SME_PORT_OFFSET,entry.op_port); - SSVAL(p,SME_OPLOCK_TYPE_OFFSET,entry.op_type); - SIVAL(p,SME_SHAREMODE_OFFSET,entry.share_mode); - SIVAL(p,SME_SEC_OFFSET,entry.time.tv_sec); - SIVAL(p,SME_USEC_OFFSET,entry.time.tv_usec); - - found = True; - break; - } - - if(!found) - { - DEBUG(0,("slow_mod_share_entry: entry not found in share file %s\n", fname)); - if(buf) - free(buf); - return False; - } - - /* Re-write the file - and truncate it at the correct point. */ - if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: slow_mod_share_entry: lseek failed to reset to \ -position 0 for share mode file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return False; - } - - fsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries); - if(write(fd, buf, fsize) != fsize) - { - DEBUG(0,("ERROR: slow_mod_share_entry: failed to re-write share \ -mode file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return False; - } - - return True; -} - - - -/******************************************************************* -call the specified function on each entry under management by the -share mode system -********************************************************************/ -static int slow_share_forall(void (*fn)(share_mode_entry *, char *)) -{ - int i, count=0; - DIR *dir; - char *s; - share_mode_entry e; - - dir = opendir(lp_lockdir()); - if (!dir) { - return(0); - } - - while ((s=readdirname(dir))) { - char *buf; - char *base; - int fd; - pstring lname; - SMB_DEV_T dev; - SMB_INO_T inode; - BOOL new_file; - pstring fname; - -#ifdef LARGE_SMB_INO_T - double inode_ascii; - if (sscanf(s,"share.%u.%lf",&dev,&inode_ascii)!=2) continue; - inode = (SMB_INO_T)inode_ascii; -#else /* LARGE_SMB_INO_T */ - unsigned long inode_long; - if (sscanf(s,"share.%u.%lu",&dev,&inode_long)!=2) continue; - inode = (SMB_INO_T)inode_long; -#endif /* LARGE_SMB_INO_T */ - - pstrcpy(lname,lp_lockdir()); - trim_string(lname,NULL,"/"); - pstrcat(lname,"/"); - pstrcat(lname,s); - - fd = sys_open(lname,read_only?O_RDONLY:O_RDWR,0); - if (fd < 0) { - continue; - } - - /* Lock the share mode file while we read it. */ - if(!read_only && - fcntl_lock(fd, SMB_F_SETLKW, 0, 1, F_WRLCK) == False) { - close(fd); - continue; - } - - if(read_share_file( 0, fd, lname, &buf, &new_file)) { - close(fd); - continue; - } - pstrcpy( fname, &buf[10]); - close(fd); - - base = buf + SMF_HEADER_LENGTH + - SVAL(buf,SMF_FILENAME_LEN_OFFSET); - for( i = 0; i < IVAL(buf, SMF_NUM_ENTRIES_OFFSET); i++) { - char *p = base + (i*SMF_ENTRY_LENGTH); - e.pid = (pid_t)IVAL(p,SME_PID_OFFSET); - e.share_mode = IVAL(p,SME_SHAREMODE_OFFSET); - e.time.tv_sec = IVAL(p,SME_SEC_OFFSET); - e.time.tv_usec = IVAL(p,SME_USEC_OFFSET); - e.op_port = SVAL(p,SME_PORT_OFFSET); - e.op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET); - - if (process_exists(e.pid)) { - fn(&e, fname); - count++; - } - } /* end for i */ - - if(buf) - free(buf); - base = 0; - } /* end while */ - closedir(dir); - - return count; -} - - -/******************************************************************* -dump the state of the system -********************************************************************/ -static void slow_share_status(FILE *f) -{ - -} - - -static struct share_ops share_ops = { - slow_stop_share_mode_mgmt, - slow_lock_share_entry, - slow_unlock_share_entry, - slow_get_share_modes, - slow_del_share_mode, - slow_set_share_mode, - slow_mod_share_entry, - slow_share_forall, - slow_share_status, -}; - -/******************************************************************* - initialize the slow share_mode management - ******************************************************************/ -struct share_ops *locking_slow_init(int ronly) -{ - - read_only = ronly; - - if (!directory_exist(lp_lockdir(),NULL)) { - if (!read_only) - mkdir(lp_lockdir(),0755); - if (!directory_exist(lp_lockdir(),NULL)) - return NULL; - } - - return &share_ops; -} -#else - int locking_slow_dummy_procedure(void); - int locking_slow_dummy_procedure(void) {return 0;} -#endif /* !FAST_SHARE_MODES */ |