home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / samba-1.9.18p7.tar.gz / samba-1.9.18p7.tar / samba-1.9.18p7 / source / locking_slow.c < prev    next >
C/C++ Source or Header  |  1998-05-12  |  29KB  |  1,096 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.9.
  4.    slow (lockfile) locking implementation
  5.    Copyright (C) Andrew Tridgell 1992-1998
  6.    
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 2 of the License, or
  10.    (at your option) any later version.
  11.    
  12.    This program is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.    
  17.    You should have received a copy of the GNU General Public License
  18.    along with this program; if not, write to the Free Software
  19.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  
  21.    Revision History:
  22.  
  23.    12 aug 96: Erik.Devriendt@te6.siemens.be
  24.    added support for shared memory implementation of share mode locking
  25.  
  26.    May 1997. Jeremy Allison (jallison@whistle.com). Modified share mode
  27.    locking to deal with multiple share modes per open file.
  28.  
  29.    September 1997. Jeremy Allison (jallison@whistle.com). Added oplock
  30.    support.
  31.  
  32.    October 1997 - split into separate file (tridge)
  33. */
  34.  
  35. #include "includes.h"
  36. extern int DEBUGLEVEL;
  37. extern connection_struct Connections[];
  38. extern files_struct Files[];
  39.  
  40. /* 
  41.  * Locking file header lengths & offsets. 
  42.  */
  43. #define SMF_VERSION_OFFSET 0
  44. #define SMF_NUM_ENTRIES_OFFSET 4
  45. #define SMF_FILENAME_LEN_OFFSET 8
  46. #define SMF_HEADER_LENGTH 10
  47.  
  48. #define SMF_ENTRY_LENGTH 20
  49.  
  50. /*
  51.  * Share mode record offsets.
  52.  */
  53.  
  54. #define SME_SEC_OFFSET 0
  55. #define SME_USEC_OFFSET 4
  56. #define SME_SHAREMODE_OFFSET 8
  57. #define SME_PID_OFFSET 12
  58. #define SME_PORT_OFFSET 16
  59. #define SME_OPLOCK_TYPE_OFFSET 18
  60.  
  61. /* we need world read for smbstatus to function correctly */
  62. #ifdef SECURE_SHARE_MODES
  63. #define SHARE_FILE_MODE 0600
  64. #else
  65. #define SHARE_FILE_MODE 0644
  66. #endif
  67.  
  68. static int read_only;
  69.  
  70. /*******************************************************************
  71.   deinitialize share_mode management 
  72.   ******************************************************************/
  73. static BOOL slow_stop_share_mode_mgmt(void)
  74. {
  75.    return True;
  76. }
  77.  
  78.  
  79. /*******************************************************************
  80.   name a share file
  81.   ******************************************************************/
  82. static BOOL share_name(int cnum, uint32 dev, uint32 inode, char *name)
  83. {
  84.   int len;
  85.   pstrcpy(name,lp_lockdir());
  86.   trim_string(name,"","/");
  87.   if (!*name) return(False);
  88.   len = strlen(name);
  89.   name += len;
  90.   
  91.   slprintf(name,sizeof(pstring) - len - 1,"/share.%u.%u",dev,inode);
  92.   return(True);
  93. }
  94.  
  95. /*******************************************************************
  96. Force a share file to be deleted.
  97. ********************************************************************/
  98. static int delete_share_file( int cnum, char *fname )
  99. {
  100.   if (read_only) return -1;
  101.  
  102.   /* the share file could be owned by anyone, so do this as root */
  103.   become_root(False);
  104.  
  105.   if(unlink(fname) != 0)
  106.   {
  107.     DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n",
  108.             fname, strerror(errno)));
  109.   } 
  110.   else 
  111.   {
  112.     DEBUG(5,("delete_share_file: Deleted share file %s\n", fname));
  113.   }
  114.  
  115.   /* return to our previous privilage level */
  116.   unbecome_root(False);
  117.  
  118.   return 0;
  119. }
  120.  
  121. /*******************************************************************
  122.   lock a share mode file.
  123.   ******************************************************************/
  124. static BOOL slow_lock_share_entry(int cnum, uint32 dev, uint32 inode, int *ptok)
  125. {
  126.   pstring fname;
  127.   int fd;
  128.   int ret = True;
  129.  
  130.   *ptok = (int)-1;
  131.  
  132.   if(!share_name(cnum, dev, inode, fname))
  133.     return False;
  134.  
  135.   if (read_only) return True;
  136.  
  137.   /* we need to do this as root */
  138.   become_root(False);
  139.  
  140.   {
  141.     BOOL gotlock = False;
  142.     /*
  143.      * There was a race condition in the original slow share mode code.
  144.      * A smbd could open a share mode file, and before getting
  145.      * the lock, another smbd could delete the last entry for
  146.      * the share mode file and delete the file entry from the
  147.      * directory. Thus this smbd would be left with a locked
  148.      * share mode fd attached to a file that no longer had a
  149.      * directory entry. Thus another smbd would think that
  150.      * there were no outstanding opens on the file. To fix
  151.      * this we now check we can do a stat() call on the filename
  152.      * before allowing the lock to proceed, and back out completely
  153.      * and try the open again if we cannot.
  154.      * Jeremy Allison (jallison@whistle.com).
  155.      */
  156.  
  157.     do
  158.     {
  159.       struct stat dummy_stat;
  160.  
  161.       fd = (int)open(fname,read_only?O_RDONLY:(O_RDWR|O_CREAT),
  162.              SHARE_FILE_MODE);
  163.  
  164.       if(fd < 0)
  165.       {
  166.         DEBUG(0,("ERROR lock_share_entry: failed to open share file %s. Error was %s\n",
  167.                   fname, strerror(errno)));
  168.         ret = False;
  169.         break;
  170.       }
  171.  
  172.        /* At this point we have an open fd to the share mode file. 
  173.          Lock the first byte exclusively to signify a lock. */
  174.       if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False)
  175.       {
  176.         DEBUG(0,("ERROR lock_share_entry: fcntl_lock on file %s failed with %s\n",
  177.                   fname, strerror(errno)));   
  178.         close(fd);
  179.         ret = False;
  180.         break;
  181.       }
  182.  
  183.       /* 
  184.        * If we cannot stat the filename, the file was deleted between
  185.        * the open and the lock call. Back out and try again.
  186.        */
  187.  
  188.       if(stat(fname, &dummy_stat)!=0)
  189.       {
  190.         DEBUG(2,("lock_share_entry: Re-issuing open on %s to fix race. Error was %s\n",
  191.                 fname, strerror(errno)));
  192.         close(fd);
  193.       }
  194.       else
  195.         gotlock = True;
  196.     } while(!gotlock);
  197.  
  198.     /*
  199.      * We have to come here if any of the above calls fail
  200.      * as we don't want to return and leave ourselves running
  201.      * as root !
  202.      */
  203.   }
  204.  
  205.   *ptok = (int)fd;
  206.  
  207.   /* return to our previous privilage level */
  208.   unbecome_root(False);
  209.  
  210.   return ret;
  211. }
  212.  
  213. /*******************************************************************
  214.   unlock a share mode file.
  215.   ******************************************************************/
  216. static BOOL slow_unlock_share_entry(int cnum, uint32 dev, uint32 inode, int token)
  217. {
  218.   int fd = (int)token;
  219.   int ret = True;
  220.   struct stat sb;
  221.   pstring fname;
  222.  
  223.   if (read_only) return True;
  224.  
  225.   /* Fix for zero length share files from
  226.      Gerald Werner <wernerg@mfldclin.edu> */
  227.     
  228.   share_name(cnum, dev, inode, fname);
  229.  
  230.   /* get the share mode file size */
  231.   if(fstat((int)token, &sb) != 0)
  232.   {
  233.     DEBUG(0,("ERROR: unlock_share_entry: Failed to do stat on share file %s (%s)\n",
  234.               fname, strerror(errno)));
  235.     sb.st_size = 1;
  236.     ret = False;
  237.   }
  238.  
  239.   /* If the file was zero length, we must delete before
  240.      doing the unlock to avoid a race condition (see
  241.      the code in lock_share_mode_entry for details.
  242.    */
  243.  
  244.   /* remove the share file if zero length */    
  245.   if(sb.st_size == 0)  
  246.     delete_share_file(cnum, fname);
  247.  
  248.   /* token is the fd of the open share mode file. */
  249.   /* Unlock the first byte. */
  250.   if(fcntl_lock(fd, F_SETLKW, 0, 1, F_UNLCK) == False)
  251.    { 
  252.       DEBUG(0,("ERROR unlock_share_entry: fcntl_lock failed with %s\n",
  253.                       strerror(errno)));   
  254.       ret = False;
  255.    }
  256.  
  257.   close(fd);
  258.   return ret;
  259. }
  260.  
  261. /*******************************************************************
  262. Read a share file into a buffer.
  263. ********************************************************************/
  264. static int read_share_file(int cnum, int fd, char *fname, char **out, BOOL *p_new_file)
  265. {
  266.   struct stat sb;
  267.   char *buf;
  268.   int size;
  269.  
  270.   *out = 0;
  271.   *p_new_file = False;
  272.  
  273.   if(fstat(fd, &sb) != 0)
  274.   {
  275.     DEBUG(0,("ERROR: read_share_file: Failed to do stat on share file %s (%s)\n",
  276.                   fname, strerror(errno)));
  277.     return -1;
  278.   }
  279.  
  280.   if(sb.st_size == 0)
  281.   {
  282.      *p_new_file = True;
  283.      return 0;
  284.   }
  285.  
  286.   /* Allocate space for the file */
  287.   if((buf = (char *)malloc(sb.st_size)) == NULL)
  288.   {
  289.     DEBUG(0,("read_share_file: malloc for file size %d fail !\n", sb.st_size));
  290.     return -1;
  291.   }
  292.   
  293.   if(lseek(fd, 0, SEEK_SET) != 0)
  294.   {
  295.     DEBUG(0,("ERROR: read_share_file: Failed to reset position to 0 \
  296. for share file %s (%s)\n", fname, strerror(errno)));
  297.     if(buf)
  298.       free(buf);
  299.     return -1;
  300.   }
  301.   
  302.   if (read(fd,buf,sb.st_size) != sb.st_size)
  303.   {
  304.     DEBUG(0,("ERROR: read_share_file: Failed to read share file %s (%s)\n",
  305.                fname, strerror(errno)));
  306.     if(buf)
  307.       free(buf);
  308.     return -1;
  309.   }
  310.   
  311.   if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION) {
  312.     DEBUG(0,("ERROR: read_share_file: share file %s has incorrect \
  313. locking version (was %d, should be %d).\n",fname, 
  314.                     IVAL(buf,SMF_VERSION_OFFSET), LOCKING_VERSION));
  315.    if(buf)
  316.       free(buf);
  317.     delete_share_file(cnum, fname);
  318.     return -1;
  319.   }
  320.  
  321.   /* Sanity check for file contents */
  322.   size = sb.st_size;
  323.   size -= SMF_HEADER_LENGTH; /* Remove the header */
  324.  
  325.   /* Remove the filename component. */
  326.   size -= SVAL(buf, SMF_FILENAME_LEN_OFFSET);
  327.  
  328.   /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */
  329.   if((size % SMF_ENTRY_LENGTH) != 0)
  330.   {
  331.     DEBUG(0,("ERROR: read_share_file: share file %s is an incorrect length - \
  332. deleting it.\n", fname));
  333.     if(buf)
  334.       free(buf);
  335.     delete_share_file(cnum, fname);
  336.     return -1;
  337.   }
  338.  
  339.   *out = buf;
  340.   return 0;
  341. }
  342.  
  343. /*******************************************************************
  344. get all share mode entries in a share file for a dev/inode pair.
  345. ********************************************************************/
  346. static int slow_get_share_modes(int cnum, int token, uint32 dev, uint32 inode, 
  347.                 share_mode_entry **old_shares)
  348. {
  349.   int fd = (int)token;
  350.   pstring fname;
  351.   int i;
  352.   int num_entries;
  353.   int num_entries_copied;
  354.   int newsize;
  355.   share_mode_entry *share_array;
  356.   char *buf = 0;
  357.   char *base = 0;
  358.   BOOL new_file;
  359.  
  360.   *old_shares = 0;
  361.  
  362.   /* Read the share file header - this is of the form:
  363.      0   -  locking version.
  364.      4   -  number of share mode entries.
  365.      8   -  2 byte name length
  366.      [n bytes] file name (zero terminated).
  367.  
  368.    Followed by <n> share mode entries of the form :
  369.  
  370.      0   -  tv_sec
  371.      4   -  tv_usec
  372.      8   -  share_mode
  373.     12   -  pid
  374.     16   -  oplock port (if oplocks in use) - 2 bytes.
  375.   */
  376.  
  377.   share_name(cnum, dev, inode, fname);
  378.  
  379.   if(read_share_file( cnum, fd, fname, &buf, &new_file) != 0)
  380.   {
  381.     DEBUG(0,("ERROR: get_share_modes: Failed to read share file %s\n",
  382.                   fname));
  383.     return 0;
  384.   }
  385.  
  386.   if(new_file == True)
  387.     return 0;
  388.  
  389.   num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
  390.  
  391.   DEBUG(5,("get_share_modes: share file %s has %d share mode entries.\n",
  392.             fname, num_entries));
  393.  
  394.   /* PARANOIA TEST */
  395.   if(num_entries < 0)
  396.   {
  397.     DEBUG(0,("PANIC ERROR:get_share_mode: num_share_mode_entries < 0 (%d) \
  398. for share file %d\n", num_entries, fname));
  399.     return 0;
  400.   }
  401.  
  402.   if(num_entries)
  403.   {
  404.     *old_shares = share_array = (share_mode_entry *)
  405.                  malloc(num_entries * sizeof(share_mode_entry));
  406.     if(*old_shares == 0)
  407.     {
  408.       DEBUG(0,("get_share_modes: malloc fail !\n"));
  409.       return 0;
  410.     }
  411.   } 
  412.   else
  413.   {
  414.     /* No entries - just delete the file. */
  415.     DEBUG(0,("get_share_modes: share file %s has no share mode entries - deleting.\n",
  416.               fname));
  417.     if(buf)
  418.       free(buf);
  419.     delete_share_file(cnum, fname);
  420.     return 0;
  421.   }
  422.  
  423.   num_entries_copied = 0;
  424.   base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
  425.  
  426.   for( i = 0; i < num_entries; i++)
  427.   {
  428.     int pid;
  429.     char *p = base + (i*SMF_ENTRY_LENGTH);
  430.  
  431.     pid = IVAL(p,SME_PID_OFFSET);
  432.  
  433.     if(!process_exists(pid))
  434.     {
  435.       DEBUG(0,("get_share_modes: process %d no longer exists and \
  436. it left a share mode entry with mode 0x%X in share file %s\n",
  437.             pid, IVAL(p,SME_SHAREMODE_OFFSET), fname));
  438.       continue;
  439.     }
  440.     share_array[num_entries_copied].time.tv_sec = IVAL(p,SME_SEC_OFFSET);
  441.     share_array[num_entries_copied].time.tv_usec = IVAL(p,SME_USEC_OFFSET);
  442.     share_array[num_entries_copied].share_mode = IVAL(p,SME_SHAREMODE_OFFSET);
  443.     share_array[num_entries_copied].pid = pid;
  444.     share_array[num_entries_copied].op_port = SVAL(p,SME_PORT_OFFSET);
  445.     share_array[num_entries_copied].op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET);
  446.  
  447.     num_entries_copied++;
  448.   }
  449.  
  450.   if(num_entries_copied == 0)
  451.   {
  452.     /* Delete the whole file. */
  453.     DEBUG(0,("get_share_modes: share file %s had no valid entries - deleting it !\n",
  454.              fname));
  455.     if(*old_shares)
  456.       free((char *)*old_shares);
  457.     *old_shares = 0;
  458.     if(buf)
  459.       free(buf);
  460.     delete_share_file(cnum, fname);
  461.     return 0;
  462.   }
  463.  
  464.   /* If we deleted some entries we need to re-write the whole number of
  465.      share mode entries back into the file. */
  466.  
  467.   if(num_entries_copied != num_entries)
  468.   {
  469.     if(lseek(fd, 0, SEEK_SET) != 0)
  470.     {
  471.       DEBUG(0,("ERROR: get_share_modes: lseek failed to reset to \
  472. position 0 for share mode file %s (%s)\n", fname, strerror(errno)));
  473.       if(*old_shares)
  474.         free((char *)*old_shares);
  475.       *old_shares = 0;
  476.       if(buf)
  477.         free(buf);
  478.       return 0;
  479.     }
  480.  
  481.     SIVAL(buf, SMF_NUM_ENTRIES_OFFSET, num_entries_copied);
  482.     for( i = 0; i < num_entries_copied; i++)
  483.     {
  484.       char *p = base + (i*SMF_ENTRY_LENGTH);
  485.  
  486.       SIVAL(p,SME_PID_OFFSET,share_array[i].pid);
  487.       SIVAL(p,SME_SHAREMODE_OFFSET,share_array[i].share_mode);
  488.       SIVAL(p,SME_SEC_OFFSET,share_array[i].time.tv_sec);
  489.       SIVAL(p,SME_USEC_OFFSET,share_array[i].time.tv_usec);
  490.       SSVAL(p,SME_PORT_OFFSET,share_array[i].op_port);
  491.       SSVAL(p,SME_OPLOCK_TYPE_OFFSET,share_array[i].op_type);
  492.     }
  493.  
  494.     newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries_copied);
  495.     if(write(fd, buf, newsize) != newsize)
  496.     {
  497.       DEBUG(0,("ERROR: get_share_modes: failed to re-write share \
  498. mode file %s (%s)\n", fname, strerror(errno)));
  499.       if(*old_shares)
  500.         free((char *)*old_shares);
  501.       *old_shares = 0;
  502.       if(buf)
  503.         free(buf);
  504.       return 0;
  505.     }
  506.     /* Now truncate the file at this point. */
  507. #ifdef FTRUNCATE_NEEDS_ROOT
  508.     become_root(False);
  509. #endif /* FTRUNCATE_NEEDS_ROOT */
  510.  
  511.     if(ftruncate(fd, newsize)!= 0)
  512.     {
  513.  
  514. #ifdef FTRUNCATE_NEEDS_ROOT
  515.       unbecome_root(False);
  516. #endif /* FTRUNCATE_NEEDS_ROOT */
  517.  
  518.       DEBUG(0,("ERROR: get_share_modes: failed to ftruncate share \
  519. mode file %s to size %d (%s)\n", fname, newsize, strerror(errno)));
  520.       if(*old_shares)
  521.         free((char *)*old_shares);
  522.       *old_shares = 0;
  523.       if(buf)
  524.         free(buf);
  525.       return 0;
  526.     }
  527.   }
  528.  
  529. #ifdef FTRUNCATE_NEEDS_ROOT
  530.       unbecome_root(False);
  531. #endif /* FTRUNCATE_NEEDS_ROOT */
  532.  
  533.   if(buf)
  534.     free(buf);
  535.  
  536.   DEBUG(5,("get_share_modes: Read share file %s returning %d entries\n",fname,
  537.             num_entries_copied));
  538.  
  539.   return num_entries_copied;
  540. }
  541.  
  542. /*******************************************************************
  543. del a share mode from a share mode file.
  544. ********************************************************************/
  545. static void slow_del_share_mode(int token, int fnum)
  546. {
  547.   pstring fname;
  548.   int fd = (int)token;
  549.   char *buf = 0;
  550.   char *base = 0;
  551.   int num_entries;
  552.   int newsize;
  553.   int i;
  554.   files_struct *fs_p = &Files[fnum];
  555.   int pid;
  556.   BOOL deleted = False;
  557.   BOOL new_file;
  558.  
  559.   share_name(fs_p->cnum, fs_p->fd_ptr->dev, 
  560.                        fs_p->fd_ptr->inode, fname);
  561.  
  562.   if(read_share_file( fs_p->cnum, fd, fname, &buf, &new_file) != 0)
  563.   {
  564.     DEBUG(0,("ERROR: del_share_mode: Failed to read share file %s\n",
  565.                   fname));
  566.     return;
  567.   }
  568.  
  569.   if(new_file == True)
  570.   {
  571.     DEBUG(0,("ERROR:del_share_mode: share file %s is new (size zero), deleting it.\n",
  572.               fname));
  573.     delete_share_file(fs_p->cnum, fname);
  574.     return;
  575.   }
  576.  
  577.   num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
  578.  
  579.   DEBUG(5,("del_share_mode: share file %s has %d share mode entries.\n",
  580.             fname, num_entries));
  581.  
  582.   /* PARANOIA TEST */
  583.   if(num_entries < 0)
  584.   {
  585.     DEBUG(0,("PANIC ERROR:del_share_mode: num_share_mode_entries < 0 (%d) \
  586. for share file %d\n", num_entries, fname));
  587.     return;
  588.   }
  589.  
  590.   if(num_entries == 0)
  591.   {
  592.     /* No entries - just delete the file. */
  593.     DEBUG(0,("del_share_mode: share file %s has no share mode entries - deleting.\n",
  594.               fname));
  595.     if(buf)
  596.       free(buf);
  597.     delete_share_file(fs_p->cnum, fname);
  598.     return;
  599.   }
  600.  
  601.   pid = getpid();
  602.  
  603.   /* Go through the entries looking for the particular one
  604.      we have set - delete it.
  605.   */
  606.  
  607.   base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
  608.  
  609.   for(i = 0; i < num_entries; i++)
  610.   {
  611.     char *p = base + (i*SMF_ENTRY_LENGTH);
  612.  
  613.     if((IVAL(p,SME_SEC_OFFSET) != fs_p->open_time.tv_sec) || 
  614.        (IVAL(p,SME_USEC_OFFSET) != fs_p->open_time.tv_usec) ||
  615.        (IVAL(p,SME_SHAREMODE_OFFSET) != fs_p->share_mode) || 
  616.        (IVAL(p,SME_PID_OFFSET) != pid))
  617.       continue;
  618.  
  619.     DEBUG(5,("del_share_mode: deleting entry number %d (of %d) from the share file %s\n",
  620.              i, num_entries, fname));
  621.  
  622.     /* Remove this entry. */
  623.     if(i != num_entries - 1)
  624.       memcpy(p, p + SMF_ENTRY_LENGTH, (num_entries - i - 1)*SMF_ENTRY_LENGTH);
  625.  
  626.     deleted = True;
  627.     break;
  628.   }
  629.  
  630.   if(!deleted)
  631.   {
  632.     DEBUG(0,("del_share_mode: entry not found in share file %s\n", fname));
  633.     if(buf)
  634.       free(buf);
  635.     return;
  636.   }
  637.  
  638.   num_entries--;
  639.   SIVAL(buf,SMF_NUM_ENTRIES_OFFSET, num_entries);
  640.  
  641.   if(num_entries == 0)
  642.   {
  643.     /* Deleted the last entry - remove the file. */
  644.     DEBUG(5,("del_share_mode: removed last entry in share file - deleting share file %s\n",
  645.              fname));
  646.     if(buf)
  647.       free(buf);
  648.     delete_share_file(fs_p->cnum,fname);
  649.     return;
  650.   }
  651.  
  652.   /* Re-write the file - and truncate it at the correct point. */
  653.   if(lseek(fd, 0, SEEK_SET) != 0)
  654.   {
  655.     DEBUG(0,("ERROR: del_share_mode: lseek failed to reset to \
  656. position 0 for share mode file %s (%s)\n", fname, strerror(errno)));
  657.     if(buf)
  658.       free(buf);
  659.     return;
  660.   }
  661.  
  662.   newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries);
  663.   if(write(fd, buf, newsize) != newsize)
  664.   {
  665.     DEBUG(0,("ERROR: del_share_mode: failed to re-write share \
  666. mode file %s (%s)\n", fname, strerror(errno)));
  667.     if(buf)
  668.       free(buf);
  669.     return;
  670.   }
  671.  
  672.   /* Now truncate the file at this point. */
  673. #ifdef FTRUNCATE_NEEDS_ROOT
  674.   become_root(False);
  675. #endif /* FTRUNCATE_NEEDS_ROOT */
  676.  
  677.   if(ftruncate(fd, newsize) != 0)
  678.   {
  679.  
  680. #ifdef FTRUNCATE_NEEDS_ROOT
  681.     unbecome_root(False);
  682. #endif /* FTRUNCATE_NEEDS_ROOT */
  683.  
  684.     DEBUG(0,("ERROR: del_share_mode: failed to ftruncate share \
  685. mode file %s to size %d (%s)\n", fname, newsize, strerror(errno)));
  686.     if(buf)
  687.       free(buf);
  688.     return;
  689.   }
  690.  
  691. #ifdef FTRUNCATE_NEEDS_ROOT
  692.   unbecome_root(False);
  693. #endif /* FTRUNCATE_NEEDS_ROOT */
  694. }
  695.   
  696. /*******************************************************************
  697. set the share mode of a file
  698. ********************************************************************/
  699. static BOOL slow_set_share_mode(int token,int fnum, uint16 port, uint16 op_type)
  700. {
  701.   files_struct *fs_p = &Files[fnum];
  702.   pstring fname;
  703.   int fd = (int)token;
  704.   int pid = (int)getpid();
  705.   struct stat sb;
  706.   char *buf;
  707.   int num_entries;
  708.   int header_size;
  709.   char *p;
  710.  
  711.   share_name(fs_p->cnum, fs_p->fd_ptr->dev,
  712.                        fs_p->fd_ptr->inode, fname);
  713.  
  714.   if(fstat(fd, &sb) != 0)
  715.   {
  716.     DEBUG(0,("ERROR: set_share_mode: Failed to do stat on share file %s\n",
  717.                   fname));
  718.     return False;
  719.   }
  720.  
  721.   /* Sanity check for file contents (if it's not a new share file). */
  722.   if(sb.st_size != 0)
  723.   {
  724.     int size = sb.st_size;
  725.  
  726.     /* Allocate space for the file plus one extra entry */
  727.     if((buf = (char *)malloc(sb.st_size + SMF_ENTRY_LENGTH)) == NULL)
  728.     {
  729.       DEBUG(0,("set_share_mode: malloc for file size %d fail !\n", 
  730.                   sb.st_size + SMF_ENTRY_LENGTH));
  731.       return False;
  732.     }
  733.  
  734.     if(lseek(fd, 0, SEEK_SET) != 0)
  735.     {
  736.       DEBUG(0,("ERROR: set_share_mode: Failed to reset position \
  737. to 0 for share file %s (%s)\n", fname, strerror(errno)));
  738.       if(buf)
  739.         free(buf);
  740.       return False;
  741.     }
  742.  
  743.     if (read(fd,buf,sb.st_size) != sb.st_size)
  744.     {
  745.       DEBUG(0,("ERROR: set_share_mode: Failed to read share file %s (%s)\n",
  746.                   fname, strerror(errno)));
  747.       if(buf)
  748.         free(buf);
  749.       return False;
  750.     }   
  751.   
  752.     if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION) 
  753.     {
  754.       DEBUG(0,("ERROR: set_share_mode: share file %s has incorrect \
  755. locking version (was %d, should be %d).\n",fname, IVAL(buf,SMF_VERSION_OFFSET), 
  756.                     LOCKING_VERSION));
  757.       if(buf)
  758.         free(buf);
  759.       delete_share_file(fs_p->cnum, fname);
  760.       return False;
  761.     }   
  762.  
  763.     size -= (SMF_HEADER_LENGTH + SVAL(buf, SMF_FILENAME_LEN_OFFSET)); /* Remove the header */
  764.  
  765.     /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */
  766.     if((size % SMF_ENTRY_LENGTH) != 0)
  767.     {
  768.       DEBUG(0,("ERROR: set_share_mode: share file %s is an incorrect length - \
  769. deleting it.\n", fname));
  770.       if(buf)
  771.         free(buf);
  772.       delete_share_file(fs_p->cnum, fname);
  773.       return False;
  774.     }
  775.  
  776.   }
  777.   else
  778.   {
  779.     /* New file - just use a single_entry. */
  780.     if((buf = (char *)malloc(SMF_HEADER_LENGTH + 
  781.                   strlen(fs_p->name) + 1 + SMF_ENTRY_LENGTH)) == NULL)
  782.     {
  783.       DEBUG(0,("ERROR: set_share_mode: malloc failed for single entry.\n"));
  784.       return False;
  785.     }
  786.     SIVAL(buf,SMF_VERSION_OFFSET,LOCKING_VERSION);
  787.     SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,0);
  788.     SSVAL(buf,SMF_FILENAME_LEN_OFFSET,strlen(fs_p->name) + 1);
  789.     pstrcpy(buf + SMF_HEADER_LENGTH, fs_p->name);
  790.   }
  791.  
  792.   num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
  793.   header_size = SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
  794.   p = buf + header_size + (num_entries * SMF_ENTRY_LENGTH);
  795.   SIVAL(p,SME_SEC_OFFSET,fs_p->open_time.tv_sec);
  796.   SIVAL(p,SME_USEC_OFFSET,fs_p->open_time.tv_usec);
  797.   SIVAL(p,SME_SHAREMODE_OFFSET,fs_p->share_mode);
  798.   SIVAL(p,SME_PID_OFFSET,pid);
  799.   SSVAL(p,SME_PORT_OFFSET,port);
  800.   SSVAL(p,SME_OPLOCK_TYPE_OFFSET,op_type);
  801.  
  802.   num_entries++;
  803.  
  804.   SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,num_entries);
  805.  
  806.   if(lseek(fd, 0, SEEK_SET) != 0)
  807.   {
  808.     DEBUG(0,("ERROR: set_share_mode: (1) Failed to reset position to \
  809. 0 for share file %s (%s)\n", fname, strerror(errno)));
  810.     if(buf)
  811.       free(buf);
  812.     return False;
  813.   }
  814.  
  815.   if (write(fd,buf,header_size + (num_entries*SMF_ENTRY_LENGTH)) != 
  816.                        (header_size + (num_entries*SMF_ENTRY_LENGTH))) 
  817.   {
  818.     DEBUG(2,("ERROR: set_share_mode: Failed to write share file %s - \
  819. deleting it (%s).\n",fname, strerror(errno)));
  820.     delete_share_file(fs_p->cnum, fname);
  821.     if(buf)
  822.       free(buf);
  823.     return False;
  824.   }
  825.  
  826.   /* Now truncate the file at this point - just for safety. */
  827.  
  828. #ifdef FTRUNCATE_NEEDS_ROOT
  829.   become_root(False);
  830. #endif /* FTRUNCATE_NEEDS_ROOT */
  831.  
  832.   if(ftruncate(fd, header_size + (SMF_ENTRY_LENGTH*num_entries))!= 0)
  833.   {
  834.  
  835. #ifdef FTRUNCATE_NEEDS_ROOT
  836.     unbecome_root(False);
  837. #endif /* FTRUNCATE_NEEDS_ROOT */
  838.  
  839.     DEBUG(0,("ERROR: set_share_mode: failed to ftruncate share \
  840. mode file %s to size %d (%s)\n", fname, header_size + (SMF_ENTRY_LENGTH*num_entries), 
  841.                 strerror(errno)));
  842.     if(buf)
  843.       free(buf);
  844.     return False;
  845.   }
  846.  
  847. #ifdef FTRUNCATE_NEEDS_ROOT
  848.   unbecome_root(False);
  849. #endif /* FTRUNCATE_NEEDS_ROOT */
  850.  
  851.   if(buf)
  852.     free(buf);
  853.  
  854.   DEBUG(3,("set_share_mode: Created share file %s with \
  855. mode 0x%X pid=%d\n",fname,fs_p->share_mode,pid));
  856.  
  857.   return True;
  858. }
  859.  
  860. /*******************************************************************
  861. Remove an oplock port and mode entry from a share mode.
  862. ********************************************************************/
  863. static BOOL slow_remove_share_oplock(int fnum, int token)
  864. {
  865.   pstring fname;
  866.   int fd = (int)token;
  867.   char *buf = 0;
  868.   char *base = 0;
  869.   int num_entries;
  870.   int fsize;
  871.   int i;
  872.   files_struct *fs_p = &Files[fnum];
  873.   int pid;
  874.   BOOL found = False;
  875.   BOOL new_file;
  876.  
  877.   share_name(fs_p->cnum, fs_p->fd_ptr->dev, 
  878.                        fs_p->fd_ptr->inode, fname);
  879.  
  880.   if(read_share_file( fs_p->cnum, fd, fname, &buf, &new_file) != 0)
  881.   {
  882.     DEBUG(0,("ERROR: remove_share_oplock: Failed to read share file %s\n",
  883.                   fname));
  884.     return False;
  885.   }
  886.  
  887.   if(new_file == True)
  888.   {
  889.     DEBUG(0,("ERROR: remove_share_oplock: share file %s is new (size zero), \
  890. deleting it.\n", fname));
  891.     delete_share_file(fs_p->cnum, fname);
  892.     return False;
  893.   }
  894.  
  895.   num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
  896.  
  897.   DEBUG(5,("remove_share_oplock: share file %s has %d share mode entries.\n",
  898.             fname, num_entries));
  899.  
  900.   /* PARANOIA TEST */
  901.   if(num_entries < 0)
  902.   {
  903.     DEBUG(0,("PANIC ERROR:remove_share_oplock: num_share_mode_entries < 0 (%d) \
  904. for share file %d\n", num_entries, fname));
  905.     return False;
  906.   }
  907.  
  908.   if(num_entries == 0)
  909.   {
  910.     /* No entries - just delete the file. */
  911.     DEBUG(0,("remove_share_oplock: share file %s has no share mode entries - deleting.\n",
  912.               fname));
  913.     if(buf)
  914.       free(buf);
  915.     delete_share_file(fs_p->cnum, fname);
  916.     return False;
  917.   }
  918.  
  919.   pid = getpid();
  920.  
  921.   /* Go through the entries looking for the particular one
  922.      we have set - remove the oplock settings on it.
  923.   */
  924.  
  925.   base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
  926.  
  927.   for(i = 0; i < num_entries; i++)
  928.   {
  929.     char *p = base + (i*SMF_ENTRY_LENGTH);
  930.  
  931.     if((IVAL(p,SME_SEC_OFFSET) != fs_p->open_time.tv_sec) || 
  932.        (IVAL(p,SME_USEC_OFFSET) != fs_p->open_time.tv_usec) ||
  933.        (IVAL(p,SME_SHAREMODE_OFFSET) != fs_p->share_mode) || 
  934.        (IVAL(p,SME_PID_OFFSET) != pid))
  935.       continue;
  936.  
  937.     DEBUG(5,("remove_share_oplock: clearing oplock on entry number %d (of %d) \
  938. from the share file %s\n", i, num_entries, fname));
  939.  
  940.     SSVAL(p,SME_PORT_OFFSET,0);
  941.     SSVAL(p,SME_OPLOCK_TYPE_OFFSET,0);
  942.     found = True;
  943.     break;
  944.   }
  945.  
  946.   if(!found)
  947.   {
  948.     DEBUG(0,("remove_share_oplock: entry not found in share file %s\n", fname));
  949.     if(buf)
  950.       free(buf);
  951.     return False;
  952.   }
  953.  
  954.   /* Re-write the file - and truncate it at the correct point. */
  955.   if(lseek(fd, 0, SEEK_SET) != 0)
  956.   {
  957.     DEBUG(0,("ERROR: remove_share_oplock: lseek failed to reset to \
  958. position 0 for share mode file %s (%s)\n", fname, strerror(errno)));
  959.     if(buf)
  960.       free(buf);
  961.     return False;
  962.   }
  963.  
  964.   fsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries);
  965.   if(write(fd, buf, fsize) != fsize)
  966.   {
  967.     DEBUG(0,("ERROR: remove_share_oplock: failed to re-write share \
  968. mode file %s (%s)\n", fname, strerror(errno)));
  969.     if(buf)
  970.       free(buf);
  971.     return False;
  972.   }
  973.  
  974.   return True;
  975. }
  976.  
  977.  
  978.  
  979. /*******************************************************************
  980. call the specified function on each entry under management by the
  981. share ode system
  982. ********************************************************************/
  983. static int slow_share_forall(void (*fn)(share_mode_entry *, char *))
  984. {
  985.     int i, count=0;
  986.     void *dir;
  987.     char *s;
  988.     share_mode_entry e;
  989.  
  990.     dir = opendir(lp_lockdir());
  991.     if (!dir) {
  992.         return(0);
  993.     }
  994.  
  995.     while ((s=readdirname(dir))) {
  996.         char *buf;
  997.         char *base;
  998.         int fd;
  999.         pstring lname;
  1000.         uint32 dev,inode;
  1001.         BOOL new_file;
  1002.         pstring fname;
  1003.  
  1004.         if (sscanf(s,"share.%u.%u",&dev,&inode)!=2) continue;
  1005.        
  1006.         pstrcpy(lname,lp_lockdir());
  1007.         trim_string(lname,NULL,"/");
  1008.         pstrcat(lname,"/");
  1009.         pstrcat(lname,s);
  1010.        
  1011.         fd = open(lname,read_only?O_RDONLY:O_RDWR,0);
  1012.         if (fd < 0) {
  1013.             continue;
  1014.         }
  1015.  
  1016.         /* Lock the share mode file while we read it. */
  1017.         if(!read_only &&
  1018.            fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False) {
  1019.             close(fd);
  1020.             continue;
  1021.         }
  1022.  
  1023.         if(read_share_file( 0, fd, lname, &buf, &new_file)) {
  1024.             close(fd);
  1025.             continue;
  1026.         } 
  1027.         pstrcpy( fname, &buf[10]);
  1028.         close(fd);
  1029.       
  1030.         base = buf + SMF_HEADER_LENGTH + 
  1031.             SVAL(buf,SMF_FILENAME_LEN_OFFSET); 
  1032.         for( i = 0; i < IVAL(buf, SMF_NUM_ENTRIES_OFFSET); i++) {
  1033.             char *p = base + (i*SMF_ENTRY_LENGTH);
  1034.             e.pid = IVAL(p,SME_PID_OFFSET);
  1035.             e.share_mode = IVAL(p,SME_SHAREMODE_OFFSET);
  1036.             e.time.tv_sec = IVAL(p,SME_SEC_OFFSET);
  1037.             e.time.tv_usec = IVAL(p,SME_USEC_OFFSET);
  1038.             e.op_port = SVAL(p,SME_PORT_OFFSET);
  1039.             e.pid = SVAL(p,SME_PID_OFFSET);
  1040.             e.op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET);
  1041.  
  1042.             if (process_exists(e.pid)) {
  1043.                 fn(&e, fname);
  1044.                 count++;
  1045.             }
  1046.         } /* end for i */
  1047.  
  1048.         if(buf)
  1049.             free(buf);
  1050.         base = 0;
  1051.     } /* end while */
  1052.     closedir(dir);
  1053.  
  1054.     return count;
  1055. }
  1056.  
  1057.  
  1058. /*******************************************************************
  1059. dump the state of the system
  1060. ********************************************************************/
  1061. static void slow_share_status(FILE *f)
  1062. {
  1063.     
  1064. }
  1065.  
  1066.  
  1067. static struct share_ops share_ops = {
  1068.     slow_stop_share_mode_mgmt,
  1069.     slow_lock_share_entry,
  1070.     slow_unlock_share_entry,
  1071.     slow_get_share_modes,
  1072.     slow_del_share_mode,
  1073.     slow_set_share_mode,
  1074.     slow_remove_share_oplock,
  1075.     slow_share_forall,
  1076.     slow_share_status,
  1077. };
  1078.  
  1079. /*******************************************************************
  1080.   initialize the slow share_mode management 
  1081.   ******************************************************************/
  1082. struct share_ops *locking_slow_init(int ronly)
  1083. {
  1084.  
  1085.     read_only = ronly;
  1086.  
  1087.     if (!directory_exist(lp_lockdir(),NULL)) {
  1088.         if (!read_only)
  1089.             mkdir(lp_lockdir(),0755);
  1090.         if (!directory_exist(lp_lockdir(),NULL))
  1091.             return NULL;
  1092.     }
  1093.  
  1094.     return &share_ops;
  1095. }
  1096.