"Fossies" - the Fresh Open Source Software Archive

Member "s-nail-14.9.11/dotlock.h" (8 Aug 2018, 5345 Bytes) of package /linux/misc/s-nail-14.9.11.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.10_vs_14.9.11.

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