"Fossies" - the Fresh Open Source Software Archive

Member "schily-2021-09-18/sunpro/Make/lib/makestate/src/lock.c" (14 Aug 2021, 5919 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.c" 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.c 1.5 06/12/12
   29  */
   30 
   31 /*
   32  * Copyright 2017-2021 J. Schilling
   33  *
   34  * @(#)lock.c   1.11 21/08/15 2017-2021 J. Schilling
   35  */
   36 #include <schily/mconfig.h>
   37 #ifndef lint
   38 static  UConst char sccsid[] =
   39     "@(#)lock.c 1.11 21/08/15 2017-2021 J. Schilling";
   40 #endif
   41 
   42 #if defined(SCHILY_BUILD) || defined(SCHILY_INCLUDES)
   43 #include <schily/stdio.h>
   44 #include <schily/stdlib.h>
   45 #include <schily/unistd.h>
   46 #include <schily/string.h>
   47 #include <schily/fcntl.h>
   48 #include <schily/types.h>
   49 #include <schily/param.h>
   50 #include <schily/stat.h>
   51 #include <schily/maxpath.h>
   52 #include <schily/errno.h>   /* errno */
   53 #else
   54 #include <stdio.h>
   55 #include <stdlib.h>
   56 #include <unistd.h>
   57 #include <string.h>
   58 #include <fcntl.h>
   59 #include <sys/types.h>
   60 #include <sys/param.h>
   61 #include <sys/stat.h>
   62 #include <errno.h>      /* errno */
   63 #endif
   64 
   65 #ifdef  HAVE_STRERROR
   66 /*
   67  * The symbols _sys_errlist and _sys_nerr are not visible in the
   68  * LP64 libc.  Use strerror(3C) instead.
   69  */
   70 #else  /* #_LP64 */
   71 extern  char    *sys_errlist[];
   72 extern  int sys_nerr;
   73 #endif /* #_LP64 */
   74 
   75     char    *file_lock      __PR((char *name, char *lockname,
   76                         int timeout));
   77 static  void    file_lock_error     __PR((char *msg, char *file,
   78                         const char *str,
   79                         char *arg1, char *arg2));
   80 
   81 /*
   82  * This code stolen from the NSE library and changed to not depend
   83  * upon any NSE routines or header files.
   84  *
   85  * Simple file locking.
   86  * Create a symlink to a file.  The "test and set" will be
   87  * atomic as creating the symlink provides both functions.
   88  *
   89  * The timeout value specifies how long to wait for stale locks
   90  * to disappear.  If the lock is more than 'timeout' seconds old
   91  * then it is ok to blow it away.  This part has a small window
   92  * of vunerability as the operations of testing the time,
   93  * removing the lock and creating a new one are not atomic.
   94  * It would be possible for two processes to both decide to blow
   95  * away the lock and then have process A remove the lock and establish
   96  * its own, and then then have process B remove the lock which accidentily
   97  * removes A's lock rather than the stale one.
   98  *
   99  * A further complication is with the NFS.  If the file in question is
  100  * being served by an NFS server, then its time is set by that server.
  101  * We can not use the time on the client machine to check for a stale
  102  * lock.  Therefore, a temp file on the server is created to get
  103  * the servers current time.
  104  *
  105  * Returns an error message.  NULL return means the lock was obtained.
  106  *
  107  */
  108 char *
  109 file_lock(name, lockname, timeout)
  110     char    *name;
  111     char    *lockname;
  112     int timeout;
  113 {
  114     int     r;
  115     int     fd;
  116     struct  stat    statb;
  117     struct  stat    fs_statb;
  118     char        tmpname[MAXPATHLEN];
  119     static  char    msg[MAXPATHLEN];
  120 
  121     if (timeout <= 0) {
  122         timeout = 15;
  123     }
  124     for (;;) {
  125         r = symlink(name, lockname);
  126         if (r == 0) {
  127             return (NULL);
  128         }
  129         if (errno != EEXIST) {
  130             file_lock_error(msg, name,
  131                 (const char *)"symlink(%s, %s)", name, lockname);
  132             return (msg);
  133         }
  134         for (;;) {
  135             (void) sleep(1);
  136             r = lstat(lockname, &statb);
  137             if (r == -1) {
  138                 /*
  139                  * The lock must have just gone away - try
  140                  * again.
  141                  */
  142                 break;
  143             }
  144 
  145             /*
  146              * With the NFS the time given a file is the time on
  147              * the file server.  This time may vary from the
  148              * client's time.  Therefore, we create a tmpfile in
  149              * the same directory to establish the time on the
  150              * server and use this time to see if the lock has
  151              * expired.
  152              */
  153             (void) sprintf(tmpname, "%s.XXXXXX", lockname);
  154 #ifdef  HAVE_MKSTEMP
  155             fd = mkstemp(tmpname);
  156 #else
  157             (void) mktemp(tmpname);
  158             fd = creat(tmpname, 0666);
  159 #endif
  160             if (fd != -1) {
  161                 (void) close(fd);
  162             } else {
  163                 file_lock_error(msg, name,
  164                     (const char *)"creat(%s)", tmpname, 0);
  165                 return (msg);
  166             }
  167             if (stat(tmpname, &fs_statb) == -1) {
  168                 file_lock_error(msg, name,
  169                     (const char *)"stat(%s)", tmpname, 0);
  170                 return (msg);
  171             }
  172             (void) unlink(tmpname);
  173             if (statb.st_mtime + timeout < fs_statb.st_mtime) {
  174                 /*
  175                  * The lock has expired - blow it away.
  176                  */
  177                 (void) unlink(lockname);
  178                 break;
  179             }
  180         }
  181     }
  182     /* NOTREACHED */
  183 }
  184 
  185 /*
  186  * Format a message telling why the lock could not be created.
  187  */
  188 /* VARARGS4 */
  189 static  void
  190 file_lock_error(msg, file, str, arg1, arg2)
  191     char        *msg;
  192     char        *file;
  193     const char  *str;
  194     char        *arg1;
  195     char        *arg2;
  196 {
  197     int len;
  198 #ifdef  HAVE_STRERROR
  199     char    *emsg;
  200 #endif
  201 
  202     (void) sprintf(msg, "Could not lock file `%s'; ", file);
  203     len = strlen(msg);
  204     (void) sprintf(&msg[len], str, arg1, arg2);
  205     (void) strcat(msg, " failed - ");
  206 #ifdef  HAVE_STRERROR
  207     /* Needs to be changed to use strerror(3C) instead. */
  208     emsg = strerror(errno);
  209     if (emsg) {
  210         (void) strcat(msg, emsg);
  211     } else {
  212         len = strlen(msg);
  213         (void) sprintf(&msg[len], "errno %d", errno);
  214     }
  215 #else  /* #_LP64 */
  216     if (errno < sys_nerr) {
  217         (void) strcat(msg, sys_errlist[errno]);
  218     } else {
  219         len = strlen(msg);
  220         (void) sprintf(&msg[len], "errno %d", errno);
  221     }
  222 #endif /* #_LP64 */
  223 }