"Fossies" - the Fresh Open Source Software Archive

Member "anacron-2.5.3/lock.c" (9 Dec 2007, 4518 Bytes) of package /linux/misc/old/anacron.2.5.3.tar.gz:


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.

    1 /*
    2     Anacron - run commands periodically
    3     Copyright (C) 1998  Itai Tzur <itzur@actcom.co.il>
    4     Copyright (C) 1999  Sean 'Shaleh' Perry <shaleh@debian.org>
    5  
    6     This program is free software; you can redistribute it and/or modify
    7     it under the terms of the GNU General Public License as published by
    8     the Free Software Foundation; either version 2 of the License, or
    9     (at your option) any later version.
   10  
   11     This program is distributed in the hope that it will be useful,
   12     but WITHOUT ANY WARRANTY; without even the implied warranty of
   13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14     GNU General Public License for more details.
   15  
   16     You should have received a copy of the GNU General Public License
   17     along with this program; if not, write to the Free Software
   18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   19  
   20     The GNU General Public License can also be found in the file
   21     `COPYING' that comes with the Anacron source distribution.
   22 */
   23 
   24 
   25 /* Lock and timestamp management
   26  */
   27 
   28 #include <stdio.h>
   29 #include <fcntl.h>
   30 #include <sys/stat.h>
   31 #include <sys/types.h>
   32 #include <unistd.h>
   33 #include <errno.h>
   34 #include <signal.h>
   35 #include "global.h"
   36 #include "gregor.h"
   37 
   38 static void
   39 open_tsfile(job_rec *jr)
   40 /* Open the timestamp file for job jr */
   41 {
   42     jr->timestamp_fd = open(jr->ident, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
   43     if (jr->timestamp_fd == -1)
   44     die_e("Can't open timestamp file for job %s", jr->ident);
   45     fcntl(jr->timestamp_fd, F_SETFD, 1);    /* set close-on-exec flag */
   46     /* We want to own this file, and set its mode to 0600. This is necessary
   47      * in order to prevent other users from putting locks on it. */
   48     if (fchown(jr->timestamp_fd, getuid(), getgid()))
   49     die_e("Can't chown timestamp file %s", jr->ident);
   50     if (fchmod(jr->timestamp_fd, S_IRUSR | S_IWUSR))
   51     die_e("Can't chmod timestamp file %s", jr->ident);
   52 }
   53 
   54 static int
   55 lock_file(int fd)
   56 /* Attempt to put an exclusive fcntl() lock on file "fd"
   57  * Return 1 on success, 0 on failure.
   58  */
   59 {
   60     int r;
   61     struct flock sfl;
   62 
   63     sfl.l_type = F_WRLCK;
   64     sfl.l_start = 0;
   65     sfl.l_whence = SEEK_SET;
   66     sfl.l_len = 0;   /* we lock all the file */
   67     errno = 0;
   68     r = fcntl(fd, F_SETLK, &sfl);
   69     if (r != -1) return 1;
   70     if (errno != EACCES && errno != EAGAIN)
   71     die_e("fcntl() error");
   72     return 0;
   73 }
   74 
   75 int
   76 consider_job(job_rec *jr)
   77 /* Check the timestamp of the job. If "its time has come", lock the job
   78  * and return 1, if it's too early, or we can't get the lock, return 0.
   79  */
   80 {
   81     char timestamp[9];
   82     int ts_year, ts_month, ts_day, dn;
   83     ssize_t b;
   84 
   85     open_tsfile(jr);
   86 
   87     /* read timestamp */
   88     b = read(jr->timestamp_fd, timestamp, 8);
   89     if (b == -1) die_e("Error reading timestamp file %s", jr->ident);
   90     timestamp[8] = 0;
   91 
   92     /* is it too early? */
   93     if (!force && b == 8)
   94     {
   95     int day_delta;
   96     if (sscanf(timestamp, "%4d%2d%2d", &ts_year, &ts_month, &ts_day) == 3)
   97         dn = day_num(ts_year, ts_month, ts_day);
   98     else
   99         dn = 0;
  100 
  101     day_delta = day_now - dn;
  102 
  103     /*
  104      * if day_delta is negative, we assume there was a clock skew 
  105      * and re-run any affected jobs
  106      * otherwise we check if the job's time has come
  107      */
  108     if (day_delta >= 0 && day_delta < jr->period)
  109     {
  110             /* yes, skip job */
  111         xclose(jr->timestamp_fd);
  112         return 0;
  113     }
  114     }
  115 
  116     /* no! try to grab the lock */
  117     if (lock_file(jr->timestamp_fd)) return 1;  /* success */
  118 
  119     /* didn't get lock */
  120     xclose(jr->timestamp_fd);
  121     explain("Job `%s' locked by another anacron - skipping", jr->ident);
  122     return 0;
  123 }
  124 
  125 void
  126 unlock(job_rec *jr)
  127 {
  128     xclose(jr->timestamp_fd);
  129 }
  130 
  131 void
  132 update_timestamp(job_rec *jr)
  133 /* We write the date "now".  "Now" can be either the time when anacron
  134  * started, or the time when the job finished.
  135  * I'm not quite sure which is more "right", but I've decided on the first
  136  * option.
  137  * Note that this is not the way it was with anacron 1.0.3 to 1.0.7.  
  138  */
  139 {
  140     char stamp[10];
  141 
  142     snprintf(stamp, 10, "%04d%02d%02d\n", year, month, day_of_month);
  143     if (lseek(jr->timestamp_fd, 0, SEEK_SET))
  144     die_e("Can't lseek timestamp file for job %s", jr->ident);
  145     if (write(jr->timestamp_fd, stamp, 9) != 9)
  146     die_e("Can't write timestamp file for job %s", jr->ident);
  147     if (ftruncate(jr->timestamp_fd, 9))
  148     die_e("ftruncate error");
  149 }
  150 
  151 void
  152 fake_job(job_rec *jr)
  153 /* We don't bother with any locking here.  There's no point. */
  154 {
  155     open_tsfile(jr);
  156     update_timestamp(jr);
  157     xclose(jr->timestamp_fd);
  158 }