"Fossies" - the Fresh Open Source Software Archive

Member "tin-2.6.2/src/lock.c" (9 Dec 2022, 6767 Bytes) of package /linux/misc/tin-2.6.2.tar.xz:


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 report: 2.6.1_vs_2.6.2.

    1 /*
    2  *  Project   : tin - a Usenet reader
    3  *  Module    : lock.c
    4  *  Author    : Urs Janssen <urs@tin.org>
    5  *  Created   : 1998-07-27
    6  *  Updated   : 2013-11-17
    7  *  Notes     :
    8  *
    9  * Copyright (c) 1998-2023 Urs Janssen <urs@tin.org>
   10  * All rights reserved.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  *
   16  * 1. Redistributions of source code must retain the above copyright notice,
   17  *    this list of conditions and the following disclaimer.
   18  *
   19  * 2. Redistributions in binary form must reproduce the above copyright
   20  *    notice, this list of conditions and the following disclaimer in the
   21  *    documentation and/or other materials provided with the distribution.
   22  *
   23  * 3. Neither the name of the copyright holder nor the names of its
   24  *    contributors may be used to endorse or promote products derived from
   25  *    this software without specific prior written permission.
   26  *
   27  * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   28  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   30  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   31  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   37  * POSSIBILITY OF SUCH DAMAGE.
   38  */
   39 
   40 #ifndef TIN_H
   41 #   include "tin.h"
   42 #endif /* !TIN_H */
   43 
   44 #if !defined(USE_FLOCK) && !defined(USE_LOCKF) && !defined(USE_FCNTL)
   45 #   ifdef HAVE_FCNTL
   46 #       define USE_FCNTL 1
   47 #   else
   48 #       ifdef HAVE_LOCKF
   49 #           define USE_LOCKF 1
   50 #       else
   51 #           ifdef HAVE_FLOCK
   52 #               define USE_FLOCK 1
   53 #           endif /* HAVE_FLOCK */
   54 #       endif /* HAVE_LOCKF */
   55 #   endif /* HAVE_FCNTL */
   56 #endif /* !USE_FLOCK && !USE_LOCKF && !USE_FCNTL */
   57 
   58 /*
   59  * TODO: add support for $LOCKEXT
   60  */
   61 #define LOCK_SUFFIX ".lock"
   62 
   63 /*
   64  * fd_lock(fd, block)
   65  *
   66  * try to lock a file descriptor with fcntl(), flock() or lockf()
   67  *
   68  * return codes:
   69  *  0 = file locked successfully
   70  * -1 = some error occurred
   71  */
   72 int
   73 fd_lock(
   74     int fd,
   75     t_bool block)
   76 {
   77     int rval = -1; /* assume an error */
   78 
   79 #ifdef USE_FCNTL
   80     struct flock flk;
   81 
   82     flk.l_type = F_WRLCK;
   83     flk.l_whence = SEEK_SET;
   84     flk.l_start = 0;
   85     flk.l_len = 0;
   86     if ((rval = fcntl(fd, block ? F_SETLKW : F_SETLK, &flk)))
   87         return rval; /* fcntl locking failed */
   88 #else
   89 #   ifdef USE_LOCKF
   90     if ((rval = lockf(fd, block ? F_LOCK : F_TLOCK, 0L)))
   91         return rval; /* lockf locking failed */
   92 #   else
   93 #       ifdef USE_FLOCK
   94     if ((rval = flock(fd, block ? LOCK_EX : (LOCK_EX | LOCK_NB))))
   95         return rval; /* flock locking failed */
   96 #       endif /* USE_FLOCK */
   97 #   endif /* USE_LOCKF */
   98 #endif /* USE_FCNTL */
   99 
  100     return rval;    /* available lock successfully applied or no locking available */
  101 }
  102 
  103 
  104 #if 0 /* unused */
  105 /*
  106  * test_fd_lock(fd)
  107  *
  108  * check for an existing lock on file descriptor with fcntl(), lockf()
  109  * or flock()
  110  *
  111  * return codes:
  112  *  0 = file is not locked
  113  *  1 = file is locked
  114  * -1 = some error occurred
  115  */
  116 int
  117 test_fd_lock(
  118     int fd)
  119 {
  120     int rval = -1; /* assume an error */
  121 
  122     errno = 0;
  123 #ifdef USE_FCNTL
  124     {
  125         struct flock flk;
  126 
  127         flk.l_type = F_WRLCK;
  128         flk.l_whence = SEEK_SET;
  129         flk.l_start = 0;
  130         flk.l_len = 0;
  131         if (fcntl(fd, F_GETLK, &flk) < 0)
  132             return -1; /* some error occurred */
  133         else {
  134             if (flk.l_type != F_UNLCK)
  135                 return 1;   /* file is locked */
  136             else
  137                 rval = 0; /* file is not fcntl locked */
  138         }
  139     }
  140 #else
  141 #   ifdef USE_LOCKF
  142     if (lockf(fd, F_TEST, 0L)) {
  143         if (errno == EACCES)
  144             return 1;   /* file is locked */
  145         else
  146             return -1;  /* some error occurred */
  147     } else
  148         rval = 0;   /* file is not lockf locked */
  149 #   else
  150 #       ifdef USE_FLOCK
  151     if (flock(fd, (LOCK_EX|LOCK_NB))) {
  152         if (errno == EWOULDBLOCK)
  153             return 1;   /* file is locked */
  154         else
  155             return -1;  /* some error occurred */
  156     } else
  157         rval = 0; /* file is not flock locked */
  158 
  159 #       endif /* USE_FLOCK */
  160 #   endif /* USE_LOCKF */
  161 #endif /* USE_FCNTL */
  162 
  163     return rval;    /* file wasn't locked or no locking available */
  164 }
  165 #endif /* 0 */
  166 
  167 
  168 /*
  169  * fd_unlock(fd)
  170  *
  171  * try to unlock a file descriptor with fcntl(), lockf() or flock()
  172  *
  173  * return codes:
  174  *  0 = file unlocked successfully
  175  * -1 = some error occurred
  176  */
  177 int
  178 fd_unlock(
  179     int fd)
  180 {
  181     int rval = -1; /* assume an error */
  182 
  183 #ifdef USE_FCNTL
  184     {
  185         struct flock flk;
  186 
  187         flk.l_type = F_UNLCK;
  188         flk.l_whence = SEEK_SET;
  189         flk.l_start = 0;
  190         flk.l_len = 0;
  191         if ((rval = fcntl(fd, F_SETLK, &flk)))
  192             return rval; /* couldn't release fcntl lock */
  193     }
  194 #else
  195 #   ifdef USE_LOCKF
  196     if ((rval = lockf(fd, F_ULOCK, 0L)))
  197         return rval; /* couldn't release lockf lock */
  198 #   else
  199 #       ifdef USE_FLOCK
  200     if ((rval = flock(fd, LOCK_UN)))
  201         return rval; /* couldn't release flock lock */
  202 #       endif /* USE_FLOCK */
  203 #   endif /* USE_LOCKF */
  204 #endif /* USE_FCNTL */
  205 
  206     return rval;    /* file successfully unlocked or no locking available */
  207 }
  208 
  209 
  210 /*
  211  * dot_lock(filename)
  212  *
  213  * try to lock filename via dotfile locking
  214  *
  215  * return codes:
  216  *  TRUE  = file locked successfully
  217  *  FALSE = some error occurred
  218  */
  219 t_bool
  220 dot_lock(
  221     const char *filename)
  222 {
  223     char tempfile[PATH_LEN];
  224     char lockfile[PATH_LEN];
  225     char base_dir[PATH_LEN];
  226     int dot_fd;
  227     struct stat statbuf;
  228     t_bool rval = FALSE;
  229 
  230     dir_name(filename, base_dir);
  231     if (!strcmp(filename, base_dir)) /* no filename portion */
  232         return rval;
  233     if ((dot_fd = my_tmpfile(tempfile, sizeof(tempfile) - 1, base_dir)) == -1)
  234         return rval;
  235     snprintf(lockfile, sizeof(lockfile), "%s%s", filename, LOCK_SUFFIX);
  236 
  237 #ifdef HAVE_LINK
  238     if (stat(lockfile, &statbuf)) { /* lockfile doesn't exist */
  239         if (!link(tempfile, lockfile)) {            /* link successful */
  240             if (!stat(tempfile, &statbuf)) {    /* tempfile exist */
  241                 if (statbuf.st_nlink == 2)          /* link count ok */
  242                     rval = TRUE;
  243             }
  244         }
  245     }
  246 #endif /* HAVE_LINK */
  247 
  248     close(dot_fd);
  249     (void) unlink(tempfile);
  250 
  251     if (!stat(lockfile, &statbuf)) {            /* lockfile still here */
  252         if (statbuf.st_nlink != 1)                  /* link count wrong? */
  253             rval = FALSE;                               /* shouldn't happen */
  254     }
  255     return rval;
  256 }
  257 
  258 
  259 /*
  260  * try to remove a dotlock for filename
  261  *
  262  * return codes:
  263  *  TRUE  = file unlocked successfully
  264  *  FALSE = some error occurred
  265  */
  266 t_bool
  267 dot_unlock(
  268     const char *filename)
  269 {
  270     char *lockfile;
  271     t_bool rval = FALSE;
  272 
  273     lockfile = my_malloc(strlen(filename) + strlen(LOCK_SUFFIX) + 2);
  274     strcpy(lockfile, filename);
  275     strcat(lockfile, LOCK_SUFFIX);
  276     if (!unlink(lockfile))
  277         rval = TRUE;
  278     free(lockfile);
  279     return rval;
  280 }