"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.

    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 }