"Fossies" - the Fresh Open Source Software Archive

Member "schily-2021-09-18/sunpro/Make/lib/vroot/src/lock.cc" (14 Aug 2021, 6192 Bytes) of package /linux/privat/schily-2021-09-18.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "lock.cc" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes reports: 2021-08-14_vs_2021-09-18 or 2021-07-29_vs_2021-09-18.

    1 /*
    2  * CDDL HEADER START
    3  *
    4  * This file and its contents are supplied under the terms of the
    5  * Common Development and Distribution License ("CDDL"), version 1.0.
    6  * You may use this file only in accordance with the terms of version
    7  * 1.0 of the CDDL.
    8  *
    9  * A full copy of the text of the CDDL should have accompanied this
   10  * source.  A copy of the CDDL is also available via the Internet at
   11  * http://www.opensource.org/licenses/cddl1.txt
   12  * See the License for the specific language governing permissions
   13  * and limitations under the License.
   14  *
   15  * When distributing Covered Code, include this CDDL HEADER in each
   16  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
   17  * If applicable, add the following below this CDDL HEADER, with the
   18  * fields enclosed by brackets "[]" replaced with your own identifying
   19  * information: Portions Copyright [yyyy] [name of copyright owner]
   20  *
   21  * CDDL HEADER END
   22  */
   23 /*
   24  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
   25  * Use is subject to license terms.
   26  */
   27 /*
   28  * @(#)lock.cc 1.17 06/12/12
   29  */
   30 
   31 #pragma ident   "@(#)lock.cc    1.17    06/12/12"
   32 
   33 /*
   34  * Copyright 2017-2021 J. Schilling
   35  *
   36  * @(#)lock.cc  1.10 21/08/15 2017-2021 J. Schilling
   37  */
   38 #include <schily/mconfig.h>
   39 #ifndef lint
   40 static  UConst char sccsid[] =
   41     "@(#)lock.cc    1.10 21/08/15 2017-2021 J. Schilling";
   42 #endif
   43 
   44 #include <avo/intl.h>   /* for NOCATGETS */
   45 
   46 #if defined(SCHILY_BUILD) || defined(SCHILY_INCLUDES)
   47 #include <schily/stdio.h>
   48 #include <schily/stdlib.h>
   49 #include <schily/string.h>
   50 #include <schily/param.h>
   51 #include <schily/stat.h>
   52 #include <schily/types.h>
   53 #include <schily/unistd.h>
   54 #else
   55 #include <stdio.h>
   56 #include <stdlib.h>
   57 #include <string.h>
   58 #include <sys/param.h>
   59 #include <sys/stat.h>
   60 #include <sys/types.h>
   61 #include <unistd.h>
   62 #endif
   63 
   64 #include <vroot/vroot.h>
   65 #include <mksh/defs.h>  /* for libintl */
   66 
   67 #if defined(SCHILY_BUILD) || defined(SCHILY_INCLUDES)
   68 #include <schily/signal.h>
   69 #include <schily/errno.h>       /* errno */
   70 #else
   71 #include <signal.h>
   72 #include <errno.h>          /* errno */
   73 #endif
   74 
   75 #if !defined(HAVE_STRERROR)
   76 extern  char        *sys_errlist[];
   77 extern  int     sys_nerr;
   78 #endif
   79 
   80 static  void        file_lock_error(char *msg, char *file, const char *str, const char *arg1, const char *arg2);
   81 
   82 #define BLOCK_INTERUPTS sigfillset(&newset) ; \
   83     sigprocmask(SIG_SETMASK, &newset, &oldset)
   84 
   85 #define UNBLOCK_INTERUPTS \
   86     sigprocmask(SIG_SETMASK, &oldset, &newset)
   87 
   88 /*
   89  * This code stolen from the NSE library and changed to not depend
   90  * upon any NSE routines or header files.
   91  *
   92  * Simple file locking.
   93  * Create a symlink to a file.  The "test and set" will be
   94  * atomic as creating the symlink provides both functions.
   95  *
   96  * The timeout value specifies how long to wait for stale locks
   97  * to disappear.  If the lock is more than 'timeout' seconds old
   98  * then it is ok to blow it away.  This part has a small window
   99  * of vunerability as the operations of testing the time,
  100  * removing the lock and creating a new one are not atomic.
  101  * It would be possible for two processes to both decide to blow
  102  * away the lock and then have process A remove the lock and establish
  103  * its own, and then then have process B remove the lock which accidentily
  104  * removes A's lock rather than the stale one.
  105  *
  106  * A further complication is with the NFS.  If the file in question is
  107  * being served by an NFS server, then its time is set by that server.
  108  * We can not use the time on the client machine to check for a stale
  109  * lock.  Therefore, a temp file on the server is created to get
  110  * the servers current time.
  111  *
  112  * Returns an error message.  NULL return means the lock was obtained.
  113  *
  114  * 12/6/91 Added the parameter "file_locked".  Before this parameter 
  115  * was added, the calling procedure would have to wait for file_lock() 
  116  * to return before it sets the flag. If the user interrupted "make"
  117  * between the time the lock was acquired and the time file_lock()
  118  * returns, make wouldn't know that the file has been locked, and therefore
  119  * it wouldn' remove the lock. Setting the flag right after locking the file
  120  * makes this window much smaller.
  121  */
  122 
  123 int
  124 file_lock(char *name, char *lockname, int *file_locked, int timeout)
  125 {
  126     int     counter = 0;
  127     static char msg[MAXPATHLEN+1];
  128     int     printed_warning = 0;
  129     int     r;
  130     struct stat statb;
  131     sigset_t newset;
  132     sigset_t oldset;
  133 
  134     *file_locked = 0;   
  135     if (timeout <= 0) {
  136         timeout = 120;
  137     }
  138     for (;;) {
  139         BLOCK_INTERUPTS;
  140         r = symlink(name, lockname);
  141         if (r == 0) {
  142             *file_locked = 1;
  143             UNBLOCK_INTERUPTS;
  144             return 0; /* success */
  145         }
  146         UNBLOCK_INTERUPTS;
  147 
  148         if (errno != EEXIST) {
  149             file_lock_error(msg, name, NOCATGETS("symlink(%s, %s)"),
  150                 name, lockname);
  151             fprintf(stderr, "%s", msg);
  152             return errno;
  153         }
  154 
  155         counter = 0;
  156         for (;;) {
  157             sleep(1); 
  158             r = lstat(lockname, &statb);
  159             if (r == -1) {
  160                 /*
  161                  * The lock must have just gone away - try 
  162                  * again.
  163                  */
  164                 break;
  165             }
  166 
  167             if ((counter > 5) && (!printed_warning)) {
  168                 /* Print waiting message after 5 secs */
  169                 if (getcwd(msg, MAXPATHLEN) == NULL)
  170                     msg[0] = nul_char;
  171                 fprintf(stderr,
  172                     gettext("file_lock: file %s is already locked.\n"),
  173                     name);
  174                 fprintf(stderr,
  175                     gettext("file_lock: will periodically check the lockfile %s for two minutes.\n"),
  176                     lockname);
  177                 fprintf(stderr,
  178                     gettext("Current working directory %s\n"),
  179                     msg);
  180 
  181                 printed_warning = 1;
  182             }
  183 
  184             if (++counter > timeout ) {
  185                 /*
  186                  * Waited enough - return an error..
  187                  */
  188                 return EEXIST;
  189             }
  190         }
  191     }
  192     /* NOTREACHED */
  193 }
  194 
  195 /*
  196  * Format a message telling why the lock could not be created.
  197  */
  198 static  void
  199 file_lock_error(char *msg, char *file, const char *str, const char *arg1, const char *arg2)
  200 {
  201     int     len;
  202 
  203     sprintf(msg, gettext("Could not lock file `%s'; "), file);
  204     len = strlen(msg);
  205     sprintf(&msg[len], str, arg1, arg2);
  206     strcat(msg, gettext(" failed - "));
  207 #ifdef  HAVE_STRERROR
  208     char    *emsg;
  209 
  210     emsg = strerror(errno);
  211     if (emsg) {
  212         strcat(msg, strerror(errno));
  213     } else {
  214         len = strlen(msg);
  215         sprintf(&msg[len], NOCATGETS("errno %d"), errno);
  216     }
  217 #else
  218     if (errno < sys_nerr) {
  219         strcat(msg, sys_errlist[errno]);
  220     } else {
  221         len = strlen(msg);
  222         sprintf(&msg[len], NOCATGETS("errno %d"), errno);
  223     }
  224 #endif
  225 }