/[mailutils]/mailutils/mailbox/locker.c
ViewVC logotype

Diff of /mailutils/mailbox/locker.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.15 by gray, Mon Mar 25 09:52:33 2002 UTC revision 1.16 by gray, Mon Apr 8 13:39:51 2002 UTC
# Line 29  Line 29 
29  #include <string.h>  #include <string.h>
30  #include <time.h>  #include <time.h>
31  #include <unistd.h>  #include <unistd.h>
32    #include <fcntl.h>
33  #include <utime.h>  #include <utime.h>
34    
35  #include <sys/param.h>  #include <sys/param.h>
# Line 50  struct _locker Line 51  struct _locker
51    int refcnt;    int refcnt;
52    
53    char *file;    char *file;
   
   char *dotlock;  
   char *nfslock;  
   
54    int flags;    int flags;
   
55    int expire_time;    int expire_time;
56    int retries;    int retries;
57    int retry_sleep;    int retry_sleep;
58    char *external;  
59      union lock_data {
60        struct {
61          char *dotlock;
62          char *nfslock;
63        } dot;
64        
65        struct {
66          char *name;
67        } external;
68        
69        struct {
70          int fd;
71        } kernel;
72      } data;
73  };  };
74    
75  /* Assert that we're managing the refcnt and fd correctly, either  /* Assert that we're managing the refcnt and fd correctly, either
# Line 68  struct _locker Line 78  struct _locker
78   */   */
79  #define INVARIANT(l) assert((l)->refcnt >= 0);  #define INVARIANT(l) assert((l)->refcnt >= 0);
80    
81  static void expire_stale_lock (locker_t lock);  static void expire_stale_lock __P((locker_t lock));
82  static int  stat_check (const char *file, int fd, int links);  static int stat_check __P((const char *file, int fd, int links));
83  static int  check_file_permissions (const char *file);  static int check_file_permissions __P((const char *file));
84  static int  lock_external(locker_t l, int lock);  static int lock_external __P((locker_t l, int lock));
85    static int _locker_lock_dotlock __P((locker_t lock));
86    static int _locker_unlock_dotlock __P((locker_t lock));
87    static int _locker_lock_kernel __P((locker_t lock));
88    static int _locker_unlock_kernel __P((locker_t lock));
89    
90  int  int
91  locker_create (locker_t *plocker, const char *filename, int flags)  locker_create (locker_t *plocker, const char *filename, int flags)
# Line 81  locker_create (locker_t *plocker, const Line 95  locker_create (locker_t *plocker, const
95    if (plocker == NULL)    if (plocker == NULL)
96      return MU_ERR_OUT_PTR_NULL;      return MU_ERR_OUT_PTR_NULL;
97    
98    if(filename == NULL)    if (filename == NULL)
99      return EINVAL;      return EINVAL;
100    
101    l = calloc (1, sizeof (*l));    l = calloc (1, sizeof (*l));
# Line 89  locker_create (locker_t *plocker, const Line 103  locker_create (locker_t *plocker, const
103      return ENOMEM;      return ENOMEM;
104    
105    /* Should make l->file be the resulting of following the symlinks. */    /* Should make l->file be the resulting of following the symlinks. */
106    l->file = strdup(filename);    l->file = strdup (filename);
107    if (l->file == NULL)    if (l->file == NULL)
108      {      {
109        free (l);        free (l);
110        return ENOMEM;        return ENOMEM;
111      }      }
112    
   l->dotlock = malloc(strlen(l->file) + 5 /*strlen(".lock")*/ + 1);  
   
   if(!l->dotlock)  
     {  
       free (l->file);  
       free (l);  
       return ENOMEM;  
     }  
   
   sprintf(l->dotlock, "%s.lock", l->file);  
   
113    if (strcmp (filename, "/dev/null") == 0)    if (strcmp (filename, "/dev/null") == 0)
114      l->flags = MU_LOCKER_NULL;      l->flags = MU_LOCKER_NULL;
115    else if (flags)    else if (flags)
# Line 118  locker_create (locker_t *plocker, const Line 121  locker_create (locker_t *plocker, const
121    l->retries = MU_LOCKER_RETRIES;    l->retries = MU_LOCKER_RETRIES;
122    l->retry_sleep = MU_LOCKER_RETRY_SLEEP;    l->retry_sleep = MU_LOCKER_RETRY_SLEEP;
123    
124    if(flags & MU_LOCKER_EXTERNAL)    /* Initialize locker-type-specific data */
125    {    if (flags & MU_LOCKER_EXTERNAL)
     if(!(l->external = strdup(MU_LOCKER_EXTERNAL_PROGRAM)))  
126      {      {
127        locker_destroy(&l);        if (!(l->data.external.name = strdup (MU_LOCKER_EXTERNAL_PROGRAM)))
128        return ENOMEM;          {
129              locker_destroy (&l);
130              return ENOMEM;
131            }
132        }
133      else if (!(flags & MU_LOCKER_KERNEL))
134        {
135          l->data.dot.dotlock = malloc (strlen (l->file)
136                                        + 5 /*strlen(".lock")*/ + 1);
137    
138          if (!l->data.dot.dotlock)
139            {
140              free (l->file);
141              free (l);
142              return ENOMEM;
143            }
144    
145          sprintf (l->data.dot.dotlock, "%s.lock", l->file);
146      }      }
   }  
147    
148    INVARIANT(l);    INVARIANT(l);
149    
# Line 135  locker_create (locker_t *plocker, const Line 153  locker_create (locker_t *plocker, const
153  }  }
154    
155  void  void
156    _locker_destroy_private (locker_t locker)
157    {
158      if (locker)
159        {
160          if (locker->flags & MU_LOCKER_EXTERNAL)
161            free (locker->data.external.name);
162          else if (locker->flags & MU_LOCKER_KERNEL)
163            /* nothing */;
164          else
165            {
166              free (locker->data.dot.dotlock);
167              free (locker->data.dot.nfslock);
168            }
169        }
170    }
171    
172    void
173  locker_destroy (locker_t *plocker)  locker_destroy (locker_t *plocker)
174  {  {
175    if (plocker && *plocker)    if (plocker && *plocker)
176      {      {
177          _locker_destroy_private (*plocker);
178        free ((*plocker)->file);        free ((*plocker)->file);
       free ((*plocker)->dotlock);  
       free ((*plocker)->nfslock);  
       free ((*plocker)->external);  
179        free (*plocker);        free (*plocker);
180        *plocker = NULL;        *plocker = NULL;
181      }      }
# Line 164  locker_set_expire_time (locker_t locker, Line 197  locker_set_expire_time (locker_t locker,
197    if (!locker)    if (!locker)
198      return MU_ERR_LOCKER_NULL;      return MU_ERR_LOCKER_NULL;
199    
200    if(etime <= 0)    if (etime <= 0)
201      return EINVAL;      return EINVAL;
202    
203    locker->expire_time = etime;    locker->expire_time = etime;
# Line 178  locker_set_retries (locker_t locker, int Line 211  locker_set_retries (locker_t locker, int
211    if (!locker)    if (!locker)
212      return MU_ERR_LOCKER_NULL;      return MU_ERR_LOCKER_NULL;
213    
214    if(retries <= 0)    if (retries <= 0)
215      return EINVAL;      return EINVAL;
216    
217    locker->retries = retries;    locker->retries = retries;
# Line 192  locker_set_retry_sleep (locker_t locker, Line 225  locker_set_retry_sleep (locker_t locker,
225    if (!locker)    if (!locker)
226      return MU_ERR_LOCKER_NULL;      return MU_ERR_LOCKER_NULL;
227    
228    if(retry_sleep <= 0)    if (retry_sleep <= 0)
229      return EINVAL;      return EINVAL;
230    
231    locker->retry_sleep = retry_sleep;    locker->retry_sleep = retry_sleep;
# Line 207  locker_set_external (locker_t locker, co Line 240  locker_set_external (locker_t locker, co
240    
241    if (!locker)    if (!locker)
242      return MU_ERR_LOCKER_NULL;      return MU_ERR_LOCKER_NULL;
243      if (!(locker->flags & MU_LOCKER_EXTERNAL))
244        return EINVAL;
245        
246    /* program can be NULL */    /* program can be NULL */
247    if(program != 0)    if (program != 0)
248    {      {
249      p = strdup(program);        p = strdup (program);
250      if(!p)        if (!p)
251        return ENOMEM;          return ENOMEM;
252    }    }
253    
254    free(locker->external);    free (locker->data.external.name);
255    locker->external = p;    locker->data.external.name = p;
256    
257    return 0;    return 0;
258  }  }
259    
260  int locker_get_flags (locker_t locker, int *flags)  int
261    locker_get_flags (locker_t locker, int *flags)
262  {  {
263    if (!locker)    if (!locker)
264      return MU_ERR_LOCKER_NULL;      return MU_ERR_LOCKER_NULL;
# Line 241  locker_get_expire_time (locker_t locker, Line 277  locker_get_expire_time (locker_t locker,
277    if (!locker)    if (!locker)
278      return MU_ERR_LOCKER_NULL;      return MU_ERR_LOCKER_NULL;
279    
280    if(!ptime)    if (!ptime)
281      return EINVAL;      return EINVAL;
282    
283    *ptime = locker->expire_time;    *ptime = locker->expire_time;
# Line 255  locker_get_retries (locker_t locker, int Line 291  locker_get_retries (locker_t locker, int
291    if (!locker)    if (!locker)
292      return MU_ERR_LOCKER_NULL;      return MU_ERR_LOCKER_NULL;
293    
294    if(!retries)    if (!retries)
295      return EINVAL;      return EINVAL;
296    
297    *retries = locker->retries;    *retries = locker->retries;
# Line 269  locker_get_retry_sleep (locker_t locker, Line 305  locker_get_retry_sleep (locker_t locker,
305    if (!locker)    if (!locker)
306      return MU_ERR_LOCKER_NULL;      return MU_ERR_LOCKER_NULL;
307    
308    if(!retry_sleep)    if (!retry_sleep)
309      return EINVAL;      return EINVAL;
310    
311    *retry_sleep = locker->retry_sleep;    *retry_sleep = locker->retry_sleep;
# Line 280  locker_get_retry_sleep (locker_t locker, Line 316  locker_get_retry_sleep (locker_t locker,
316  int  int
317  locker_lock (locker_t lock)  locker_lock (locker_t lock)
318  {  {
319    int err = 0;    int rc;
   int fd = -1;  
320    int retries = 1;    int retries = 1;
321    
322    if (lock == NULL)    if (lock == NULL)
# Line 298  locker_lock (locker_t lock) Line 333  locker_lock (locker_t lock)
333        return 0;        return 0;
334      }      }
335    
336      if (access (lock->file, W_OK))
337        {
338          /* There is no use trying to lock the file if we are not
339             allowed to write to it */
340          _locker_destroy_private (lock);
341          lock->flags |= MU_LOCKER_NULL;
342          return 0;
343        }
344      
345      /* Check we are trying to lock a regular file, with a link count
346         of 1, that we have permission to read, etc., or don't lock it. */
347      if ((rc = check_file_permissions(lock->file)))
348          return rc;
349    
350    /* Do the lock with an external program, if requested. */    /* Do the lock with an external program, if requested. */
351    if (lock->flags & MU_LOCKER_EXTERNAL)    if (lock->flags & MU_LOCKER_EXTERNAL)
352    {      return lock_external (lock, 1);
353      return lock_external(lock, 1);    else if (!(lock->flags & MU_LOCKER_KERNEL))
354    }      {
355          char *tmp, *p;
356    
357    /* Check we are trying to lock a regular file, with a link count        tmp = strdup (lock->file);
358       of 1, that we have permission to read, etc., or don't lock it. */        if (!tmp)
359    if((err = check_file_permissions(lock->file)))          return ENOMEM;
360        return err;  
361          strcpy (tmp, lock->file);
362          p = strrchr (tmp, '/');
363          /* A '/' must be present, if not we'll coredump, and that's
364             correct! */
365          *p = 0;
366    
367          if (access (tmp, W_OK))
368            {
369              /* Fallback to kernel locking */
370              _locker_destroy_private (lock);
371              lock->flags |= MU_LOCKER_KERNEL;
372            }
373          free (tmp);
374        }
375    
376    if (lock->flags & MU_LOCKER_RETRY)    if (lock->flags & MU_LOCKER_RETRY)
377      {      {
# Line 316  locker_lock (locker_t lock) Line 380  locker_lock (locker_t lock)
380    
381    while (retries--)    while (retries--)
382      {      {
383        /* cleanup after last loop */        if (lock->flags & MU_LOCKER_KERNEL)
384        close (fd);          rc = _locker_lock_kernel (lock);
       fd = -1;  
       if (lock->nfslock)  
         {  
           unlink (lock->nfslock);  
           free (lock->nfslock);  
           lock->nfslock = 0;  
         }  
   
       expire_stale_lock (lock);  
   
       /* build the NFS hitching-post to the lock file */  
       {  
         char host[MAXHOSTNAMELEN + 1] = "localhost";  
         char pid[11];           /* 10 is strlen(2^32 = 4294967296) */  
         char now[11];  
         size_t sz = 0;  
   
         gethostname (host, sizeof (host));  
         host[MAXHOSTNAMELEN] = 0;  
   
         snprintf (pid, sizeof (pid), "%d", getpid ());  
         pid[sizeof (pid) - 1] = 0;  
   
         snprintf (now, sizeof (now), "%d", time (0));  
         now[sizeof (now) - 1] = 0;  
   
         sz = strlen (lock->file) + 1 /* "." */  +  
           strlen (pid) + 1 /* "." */  +  
           strlen (now) + 1 /* "." */  +  
           strlen (host) + 1;  
   
         lock->nfslock = malloc (sz);  
   
         if (!lock->nfslock)  
           return ENOMEM;  
   
         snprintf (lock->nfslock, sz, "%s.%s.%s.%s", lock->file, pid, now,  
                   host);  
         lock->nfslock[sz - 1] = 0;  
       }  
   
       fd = open (lock->nfslock, O_WRONLY | O_CREAT | O_EXCL, LOCKFILE_ATTR);  
   
       if (fd == -1)  
         {  
           if (errno == EEXIST)  
             continue;           /* Try with another lockfile name. */  
           else  
             return errno;  
         }  
       close (fd);  
   
       fd = -1;  
   
   
       /* Try to link to the lockfile. */  
       if (link (lock->nfslock, lock->dotlock) == -1)  
         {  
           err = errno;  
   
           if (err != EEXIST)  
             break;              /* fatal */  
         }  
385        else        else
386          {          rc = _locker_lock_dotlock (lock);
387            if ((fd = open (lock->dotlock, O_RDONLY)) == -1)        if (rc == EAGAIN && retries)
             {  
               err = errno;  
               break;            /* fatal, we just made it, we should be able to open! */  
             }  
           err = stat_check (lock->nfslock, fd, 2);  
           if (err == 0)  
             {  
               /* We got the lock! */  
               break;  
             }  
           else  
             {  
               unlink (lock->dotlock);  
               unlink (lock->nfslock);  
   
               /* If there was something invalid about the file/fd, return  
                  a more descriptive code. */  
               if (err == EINVAL)  
                 err = MU_ERR_LOCK_BAD_LOCK;  
   
               break;  
             }  
         }  
       if (retries)  
388          sleep (lock->retry_sleep);          sleep (lock->retry_sleep);
389          else if (rc)
390            return rc;
391          else /* rc == 0 */
392            break;
393      }      }
394    
   unlink (lock->nfslock);  
   
   /* EEXIST means somebody else has the lock, anything else is an  
      error. */  
   if (err == EEXIST)  
     err = MU_ERR_LOCK_CONFLICT;  
   
   if (err)  
     return err;  
   
   /* If no errors, we have the lock. */  
   assert (lock->refcnt == 0);  
   
   if (lock->flags & MU_LOCKER_PID)  
     {  
       char buf[16];  
       sprintf (buf, "%ld", (long) getpid ());  
       write (fd, buf, strlen (buf));  
     }  
   
   close(fd);  
   
395    lock->refcnt = 1;    lock->refcnt = 1;
396    
397    return 0;    return 0;
# Line 447  locker_touchlock (locker_t lock) Line 406  locker_touchlock (locker_t lock)
406    if (lock->flags == MU_LOCKER_NULL)    if (lock->flags == MU_LOCKER_NULL)
407      return 0;      return 0;
408        
409    if(lock->refcnt > 0)    if (lock->refcnt > 0)
410      return utime (lock->dotlock, NULL);      return utime (lock->data.dot.dotlock, NULL);
411    
412    return MU_ERR_LOCK_NOT_HELD;    return MU_ERR_LOCK_NOT_HELD;
413  }  }
# Line 456  locker_touchlock (locker_t lock) Line 415  locker_touchlock (locker_t lock)
415  int  int
416  locker_unlock (locker_t lock)  locker_unlock (locker_t lock)
417  {  {
418    int err = 0;    int rc = 0;
419    
420    if (!lock)    if (!lock)
421      return MU_ERR_LOCKER_NULL;      return MU_ERR_LOCKER_NULL;
# Line 469  locker_unlock (locker_t lock) Line 428  locker_unlock (locker_t lock)
428    
429    /* Do the lock with an external program, if requested. */    /* Do the lock with an external program, if requested. */
430    if (lock->flags & MU_LOCKER_EXTERNAL)    if (lock->flags & MU_LOCKER_EXTERNAL)
431      {      return lock_external (lock, 0);
432        return lock_external (lock, 0);    
     }  
   
433    if (lock->refcnt > 1)    if (lock->refcnt > 1)
434      {      {
435        lock->refcnt--;        lock->refcnt--;
436        return 0;        return 0;
437      }      }
438    
439    if ((err = check_file_permissions (lock->file)))    if ((rc = check_file_permissions (lock->file)))
440      return err;      return rc;
   
   if (unlink (lock->dotlock) == -1)  
     {  
       err = errno;  
       if (err == ENOENT)  
         {  
           lock->refcnt = 0;  
           err = MU_ERR_LOCK_NOT_HELD;  
           return err;  
         }  
441    
442        return err;    if (lock->flags & MU_LOCKER_KERNEL)
443      }      rc = _locker_unlock_kernel (lock);
444      else
445        rc = _locker_unlock_dotlock (lock);
446    
447    lock->refcnt = 0;    if (rc == 0)
448        lock->refcnt = 0;
449    
450    return 0;    return rc;
451  }  }
452    
453  int  int
# Line 513  locker_remove_lock (locker_t lock) Line 463  locker_remove_lock (locker_t lock)
463    
464    /* Force the reference count to 1 to unlock the file. */    /* Force the reference count to 1 to unlock the file. */
465    lock->refcnt = 1;    lock->refcnt = 1;
466    err = locker_unlock(lock);    err = locker_unlock (lock);
467    
468    return err;    return err;
469  }  }
# Line 523  static void Line 473  static void
473  expire_stale_lock (locker_t lock)  expire_stale_lock (locker_t lock)
474  {  {
475    int stale = 0;    int stale = 0;
476    int fd = open (lock->dotlock, O_RDONLY);    int fd = open (lock->data.dot.dotlock, O_RDONLY);
477    if (fd == -1)    if (fd == -1)
478      return;      return;
479    
# Line 547  expire_stale_lock (locker_t lock) Line 497  expire_stale_lock (locker_t lock)
497              stale = 1;          /* Corrupted file, remove the lock. */              stale = 1;          /* Corrupted file, remove the lock. */
498          }          }
499      }      }
500      
501    /* Check to see if the lock expired.  */    /* Check to see if the lock expired.  */
502    if (lock->flags & MU_LOCKER_TIME)    if (lock->flags & MU_LOCKER_TIME)
503      {      {
# Line 560  expire_stale_lock (locker_t lock) Line 511  expire_stale_lock (locker_t lock)
511    
512    close (fd);    close (fd);
513    if (stale)    if (stale)
514      unlink (lock->dotlock);      unlink (lock->data.dot.dotlock);
515  }  }
516    
517  static int  static int
# Line 571  stat_check (const char *file, int fd, in Line 522  stat_check (const char *file, int fd, in
522    int err = 0;    int err = 0;
523    int localfd = -1;    int localfd = -1;
524    
525    if(fd == -1)    if (fd == -1)
526    {      {
527      localfd = open(file, O_RDONLY);        localfd = open(file, O_RDONLY);
528          
529      if(localfd == -1)        if (localfd == -1)
530        return errno;          return errno;
531      fd = localfd;        fd = localfd;
532    }      }
533    
534    /* We should always be able to stat a valid fd, so this    /* We should always be able to stat a valid fd, so this
535       is an error condition. */       is an error condition. */
# Line 603  stat_check (const char *file, int fd, in Line 554  stat_check (const char *file, int fd, in
554    
555  #undef CHK  #undef CHK
556      }      }
557    if(localfd != -1)    if (localfd != -1)
558      close(localfd);      close (localfd);
559    
560    return err;    return err;
561  }  }
# Line 616  check_file_permissions (const char *file Line 567  check_file_permissions (const char *file
567    int err = 0;    int err = 0;
568    
569    if ((fd = open (file, O_RDONLY)) == -1)    if ((fd = open (file, O_RDONLY)) == -1)
570      return errno;      return errno == ENOENT ? 0 : errno;
571    
572    err = stat_check (file, fd, 1);    err = stat_check (file, fd, 1);
573    close (fd);    close (fd);
# Line 631  check_file_permissions (const char *file Line 582  check_file_permissions (const char *file
582    return 0;    return 0;
583  }  }
584    
585    /* Locker-specific lock/unlock functions */
586    int
587    _locker_lock_dotlock (locker_t lock)
588    {
589      char host[MAXHOSTNAMELEN + 1] = "localhost";
590      char pid[11];         /* 10 is strlen(2^32 = 4294967296) */
591      char now[11];
592      size_t sz = 0;
593      int err = 0;
594      int fd;
595        
596      if (lock->data.dot.nfslock)
597        {
598          unlink (lock->data.dot.nfslock);
599          free (lock->data.dot.nfslock);
600          lock->data.dot.nfslock = 0;
601        }
602    
603      expire_stale_lock (lock);
604    
605      /* build the NFS hitching-post to the lock file */
606    
607      gethostname (host, sizeof (host));
608      host[MAXHOSTNAMELEN] = 0;
609    
610      snprintf (now, sizeof (now), "%d", time (0));
611      now[sizeof (now) - 1] = 0;
612    
613      snprintf (pid, sizeof (pid), "%d", getpid ());
614      pid[sizeof (pid) - 1] = 0;
615                      
616      sz = strlen (lock->file) + 1 /* "." */
617        + strlen (pid) + 1 /* "." */
618        + strlen (now) + 1 /* "." */
619        + strlen (host) + 1;
620      
621      lock->data.dot.nfslock = malloc (sz);
622      
623      if (!lock->data.dot.nfslock)
624        return ENOMEM;
625      
626      snprintf (lock->data.dot.nfslock, sz, "%s.%s.%s.%s", lock->file, pid, now,
627                host);
628      
629      fd = open (lock->data.dot.nfslock,
630                 O_WRONLY | O_CREAT | O_EXCL, LOCKFILE_ATTR);
631      if (fd == -1)
632        {
633          if (errno == EEXIST)
634            return EAGAIN;
635          else
636            return errno;
637        }
638      close (fd);
639      
640      /* Try to link to the lockfile. */
641      if (link (lock->data.dot.nfslock, lock->data.dot.dotlock) == -1)
642        {
643          if (errno == EEXIST)
644            return MU_ERR_LOCK_CONFLICT;
645          return errno;
646        }
647    
648      if ((fd = open (lock->data.dot.dotlock, O_RDONLY)) == -1)
649        return errno;
650      err = stat_check (lock->data.dot.nfslock, fd, 2);
651      if (err)
652        {
653          if (err == EINVAL)
654            return MU_ERR_LOCK_BAD_LOCK;
655          return errno;
656        }
657    
658      unlink (lock->data.dot.nfslock);
659    
660      /* If no errors, we have the lock. */
661      assert (lock->refcnt == 0);
662    
663      if (lock->flags & MU_LOCKER_PID)
664        {
665          char buf[16];
666          sprintf (buf, "%ld", (long) getpid ());
667          write (fd, buf, strlen (buf));
668        }
669      close(fd);
670      return 0;
671    }  
672    
673    int
674    _locker_unlock_dotlock (locker_t lock)
675    {
676      if (unlink (lock->data.dot.dotlock) == -1)
677        {
678          int err = errno;
679          if (err == ENOENT)
680            {
681              lock->refcnt = 0;
682              err = MU_ERR_LOCK_NOT_HELD;
683              return err;
684            }
685          return err;
686        }
687      return 0;
688    }
689    
690    int
691    _locker_lock_kernel (locker_t lock)
692    {
693      int fd;
694      struct flock fl;
695    
696      fd = open (lock->file, O_RDWR);
697      if (fd == -1)
698        return errno;
699      lock->data.kernel.fd = fd;
700      fl.l_type = F_WRLCK;
701      fl.l_whence = SEEK_SET;
702      fl.l_start = 0;
703      fl.l_len = 0; /* Lock entire file */
704      if (fcntl (fd, F_SETLK, &fl))
705        {
706    #ifdef EACCESS      
707          if (errno == EACCESS)
708            return EAGAIN;
709    #endif
710          if (errno == EAGAIN)
711            return EAGAIN;
712          return errno;
713        }
714      return 0;
715    }
716    
717    int
718    _locker_unlock_kernel (locker_t lock)
719    {
720      struct flock fl;
721    
722      fl.l_type = F_UNLCK;
723      fl.l_whence = SEEK_SET;
724      fl.l_start = 0;
725      fl.l_len = 0; /* Unlock entire file */
726      if (fcntl (lock->data.kernel.fd, F_SETLK, &fl))
727        {
728    #ifdef EACCESS
729          if (errno == EACCESS)
730            return EAGAIN;
731    #endif
732          if (errno == EAGAIN)
733            return EAGAIN;
734          return errno;
735        }
736      close (lock->data.kernel.fd);
737      return 0;
738    }
739    
740  /*  /*
741    Estimate 1 decimal digit per 3 bits, + 1 for round off.    Estimate 1 decimal digit per 3 bits, + 1 for round off.
742  */  */
# Line 651  lock_external (locker_t l, int lock) Line 757  lock_external (locker_t l, int lock)
757    assert (lock == !l->refcnt);    assert (lock == !l->refcnt);
758    /* lock is true, refcnt is 0 or lock is false and refcnt is 1 */    /* lock is true, refcnt is 0 or lock is false and refcnt is 1 */
759    
760    av[ac++] = l->external ? l->external : MU_LOCKER_EXTERNAL_PROGRAM;    av[ac++] = l->data.external.name ?
761                       l->data.external.name : MU_LOCKER_EXTERNAL_PROGRAM;
762    
763    if (l->flags & MU_LOCKER_TIME)    if (l->flags & MU_LOCKER_TIME)
764      {      {
# Line 659  lock_external (locker_t l, int lock) Line 766  lock_external (locker_t l, int lock)
766        aforce[sizeof (aforce) - 1] = 0;        aforce[sizeof (aforce) - 1] = 0;
767        av[ac++] = aforce;        av[ac++] = aforce;
768      }      }
769      
770    if (l->flags & MU_LOCKER_RETRY)    if (l->flags & MU_LOCKER_RETRY)
771      {      {
772        snprintf (aretry, sizeof (aretry), "-r%d", l->retries);        snprintf (aretry, sizeof (aretry), "-r%d", l->retries);
773        aretry[sizeof (aretry) - 1] = 0;        aretry[sizeof (aretry) - 1] = 0;
774        av[ac++] = aretry;        av[ac++] = aretry;
775      }      }
776    
777    if (lock == 0)    if (lock == 0)
778      {      {
779        av[ac++] = "-u";        av[ac++] = "-u";

Legend:
Removed from v.1.15  
changed lines
  Added in v.1.16

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26