"Fossies" - the Fresh Open Source Software Archive

Member "s-nail-14.9.7/dotlock.h" (16 Feb 2018, 5304 Bytes) of package /linux/misc/s-nail-14.9.7.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 "dotlock.h" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 14.9.6_vs_14.9.7.

    1 /*@ S-nail - a mail user agent derived from Berkeley Mail.
    2  *@ Creation of an exclusive "dotlock" file.  This is (potentially) shared
    3  *@ in between n_dotlock() and the privilege-separated "dotlocker"..
    4  *@ (Which is why it doesn't use NYD or other utilities.)
    5  *@ The code assumes it has been chdir(2)d into the target directory and
    6  *@ that SIGPIPE is ignored (we react upon ERR_PIPE).
    7  *@ It furtherly assumes that it can create a file name that is at least one
    8  *@ byte longer than the dotlock file's name!
    9  *
   10  * Copyright (c) 2012 - 2018 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
   11  */
   12 /*
   13  * Copyright (c) 1996 Christos Zoulas.  All rights reserved.
   14  *
   15  * Redistribution and use in source and binary forms, with or without
   16  * modification, are permitted provided that the following conditions
   17  * are met:
   18  * 1. Redistributions of source code must retain the above copyright
   19  *    notice, this list of conditions and the following disclaimer.
   20  * 2. Redistributions in binary form must reproduce the above copyright
   21  *    notice, this list of conditions and the following disclaimer in the
   22  *    documentation and/or other materials provided with the distribution.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   26  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   27  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   29  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   30  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   31  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   32  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   33  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   34  */
   35 
   36 /* Jump in */
   37 static enum n_dotlock_state a_dotlock_create(struct n_dotlock_info *dip);
   38 
   39 /* Create a unique file. O_EXCL does not really work over NFS so we follow
   40  * the following trick (inspired by S.R. van den Berg):
   41  * - make a mostly unique filename and try to create it
   42  * - link the unique filename to our target
   43  * - get the link count of the target
   44  * - unlink the mostly unique filename
   45  * - if the link count was 2, then we are ok; else we've failed */
   46 static enum n_dotlock_state a_dotlock__create_excl(struct n_dotlock_info *dip,
   47                               char const *lname);
   48 
   49 static enum n_dotlock_state
   50 a_dotlock_create(struct n_dotlock_info *dip){
   51    /* Use PATH_MAX not NAME_MAX to catch those "we proclaim the minimum value"
   52     * problems (SunOS), since the pathconf(3) value came too late! */
   53    char lname[PATH_MAX +1];
   54    sigset_t nset, oset;
   55    size_t tries;
   56    ssize_t w;
   57    enum n_dotlock_state rv, xrv;
   58 
   59    /* (Callee ensured this doesn't end up as plain "di_lock_name") */
   60    snprintf(lname, sizeof lname, "%s.%s.%s",
   61       dip->di_lock_name, dip->di_hostname, dip->di_randstr);
   62 
   63    sigfillset(&nset);
   64 
   65    for(tries = 0;; ++tries){
   66       sigprocmask(SIG_BLOCK, &nset, &oset);
   67       rv = a_dotlock__create_excl(dip, lname);
   68       sigprocmask(SIG_SETMASK, &oset, NULL);
   69 
   70       if(rv == n_DLS_NONE || (rv & n_DLS_ABANDON))
   71          break;
   72       if(dip->di_pollmsecs == 0 || tries >= DOTLOCK_TRIES){
   73          rv |= n_DLS_ABANDON;
   74          break;
   75       }
   76 
   77       xrv = n_DLS_PING;
   78       w = write(STDOUT_FILENO, &xrv, sizeof xrv);
   79       if(w == -1 && n_err_no == n_ERR_PIPE){
   80          rv = n_DLS_DUNNO | n_DLS_ABANDON;
   81          break;
   82       }
   83       n_msleep(dip->di_pollmsecs, FAL0);
   84    }
   85    return rv;
   86 }
   87 
   88 static enum n_dotlock_state
   89 a_dotlock__create_excl(struct n_dotlock_info *dip, char const *lname){
   90    struct stat stb;
   91    int fd, e;
   92    size_t tries;
   93    enum n_dotlock_state rv = n_DLS_NONE;
   94 
   95    /* We try to create the unique filename */
   96    for(tries = 0;; ++tries){
   97       fd = open(lname,
   98 #ifdef O_SYNC
   99                (O_WRONLY | O_CREAT | O_EXCL | O_SYNC),
  100 #else
  101                (O_WRONLY | O_CREAT | O_EXCL),
  102 #endif
  103             S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
  104       if(fd != -1){
  105 #ifdef n_PRIVSEP_SOURCE
  106          if(dip->di_stb != NULL &&
  107                fchown(fd, dip->di_stb->st_uid, dip->di_stb->st_gid)){
  108             int x = n_err_no;
  109             close(fd);
  110             n_err_no = x;
  111             goto jbados;
  112          }
  113 #endif
  114          close(fd);
  115          break;
  116       }else if((e = n_err_no) != n_ERR_EXIST){
  117          rv = (e == n_ERR_ROFS) ? n_DLS_ROFS | n_DLS_ABANDON : n_DLS_NOPERM;
  118          goto jleave;
  119       }else if(tries >= DOTLOCK_TRIES){
  120          rv = n_DLS_EXIST;
  121          goto jleave;
  122       }
  123    }
  124 
  125    /* We link the name to the fname */
  126    if(link(lname, dip->di_lock_name) == -1)
  127       goto jbados;
  128 
  129    /* Note that we stat our own exclusively created name, not the
  130     * destination, since the destination can be affected by others */
  131    if(stat(lname, &stb) == -1)
  132       goto jbados;
  133 
  134    unlink(lname);
  135 
  136    /* If the number of links was two (one for the unique file and one for
  137     * the lock), we've won the race */
  138    if(stb.st_nlink != 2)
  139       rv = n_DLS_EXIST;
  140 jleave:
  141    return rv;
  142 jbados:
  143    rv = (n_err_no == n_ERR_EXIST) ? n_DLS_EXIST : n_DLS_NOPERM | n_DLS_ABANDON;
  144    unlink(lname);
  145    goto jleave;
  146 }
  147 
  148 /* s-it-mode */