LCOV - code coverage report
Current view: top level - src - lock.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 69 87 79.3 %
Date: 2017-10-31 Functions: 11 11 100.0 %

          Line data    Source code
       1             : #include "burp.h"
       2             : #include "alloc.h"
       3             : #include "lock.h"
       4             : #include "log.h"
       5             : 
       6          17 : struct lock *lock_alloc(void)
       7             : {
       8         425 :         return (struct lock *)calloc_w(1, sizeof(struct lock), __func__);
       9             : }
      10             : 
      11         426 : int lock_init(struct lock *lock, const char *path)
      12             : {
      13         426 :         free_w(&lock->path);
      14         426 :         if(!(lock->path=strdup_w(path, __func__)))
      15             :                 return -1;
      16         426 :         return 0;
      17             : }
      18             : 
      19         408 : struct lock *lock_alloc_and_init(const char *path)
      20             : {
      21             :         struct lock *lock;
      22         408 :         if(!(lock=lock_alloc()) || lock_init(lock, path))
      23           0 :                 lock_free(&lock);
      24         408 :         return lock;
      25             : }
      26             : 
      27             : static void lock_free_content(struct lock *lock)
      28             : {
      29         424 :         free_w(&lock->path);
      30             : }
      31             : 
      32         433 : void lock_free(struct lock **lock)
      33             : {
      34         866 :         if(!lock || !*lock) return;
      35         424 :         lock_free_content(*lock);
      36         424 :         free_v((void **)lock);
      37             : }
      38             : 
      39         102 : void lock_get_quick(struct lock *lock)
      40             : {
      41             : #if defined(HAVE_WIN32) || !defined(HAVE_LOCKF)
      42             :         // Would somebody please tell me how to get a lock on Windows?!
      43             :         lock->status=GET_LOCK_GOT;
      44             :         return;
      45             : #else
      46         204 :         if((lock->fd=open(lock->path, O_WRONLY|O_CREAT, 0666))<0)
      47             :         {
      48           0 :                 logp("Could not open lock file %s: %s\n",
      49           0 :                         lock->path, strerror(errno));
      50           0 :                 goto error;
      51             :         }
      52         102 :         if(lockf(lock->fd, F_TLOCK, 0))
      53             :         {
      54           2 :                 if(errno==EACCES || errno==EAGAIN)
      55             :                         goto notgot;
      56           0 :                 logp("Could not get lock %s: %s\n",
      57             :                         lock->path, strerror(errno));
      58           0 :                 goto error; // Some other error.
      59             :         }
      60         100 :         if(lock_write_pid_and_prog(lock))
      61             :                 goto error;
      62             :         
      63         100 :         lock->status=GET_LOCK_GOT;
      64         100 :         return;
      65             : error:
      66           0 :         lock->status=GET_LOCK_ERROR;
      67           0 :         return;
      68             : notgot:
      69           2 :         lock->status=GET_LOCK_NOT_GOT;
      70           2 :         return;
      71             : #endif
      72             : }
      73             : 
      74         100 : int lock_write_pid_and_prog(struct lock *lock)
      75             : {
      76         100 :         char text[64]="";
      77         100 :         if(ftruncate(lock->fd, 0))
      78             :         {
      79           0 :                 logp("Could not ftruncate lock %s: %s\n",
      80           0 :                         lock->path, strerror(errno));
      81           0 :                 return -1;
      82             :         }
      83         100 :         snprintf(text, sizeof(text), "%d\n%s\n", (int)getpid(), progname());
      84         100 :         if(write(lock->fd, text, strlen(text))!=(ssize_t)strlen(text))
      85             :         {
      86           0 :                 logp("Could not write pid/progname to %s: %s\n",
      87           0 :                         lock->path, strerror(errno));
      88           0 :                 return -1;
      89             :         }
      90             :         return 0;
      91             : }
      92             : 
      93             : // Return 0 for lock got, 1 for lock not got, -1 for error.
      94          81 : void lock_get(struct lock *lock)
      95             : {
      96             : #if defined(HAVE_WIN32) || !defined(HAVE_LOCKF)
      97             :         // Would somebody please tell me how to get a lock on Windows?!
      98             :         lock->status=GET_LOCK_GOT;
      99             :         return;
     100             : #else
     101          81 :         char *cp=NULL;
     102          81 :         char *copy=NULL;
     103             : 
     104             :         // Try to make sure the lock directory exists.
     105          81 :         if(!(copy=strdup_w(lock->path, __func__)))
     106             :         {
     107           0 :                 lock->status=GET_LOCK_ERROR;
     108           0 :                 return;
     109             :         }
     110          81 :         if((cp=strrchr(copy, '/')))
     111             :         {
     112          81 :                 *cp='\0';
     113          81 :                 if(*copy) mkdir(copy, 0777);
     114             :         }
     115          81 :         free_w(&copy);
     116             : 
     117          81 :         lock_get_quick(lock);
     118             : 
     119             :         // Try to make sure the pid gets onto the disk.
     120          81 :         if(lock->status==GET_LOCK_GOT) fsync(lock->fd);
     121             :         return;
     122             : #endif
     123             : }
     124             : 
     125          11 : int lock_test(const char *path)
     126             : {
     127             : #if defined(HAVE_WIN32) || !defined(HAVE_LOCKF)
     128             :         // Would somebody please tell me how to test a lock on Windows?!
     129             :         return 0;
     130             : #else
     131          11 :         int r=0;
     132             :         int fdlock;
     133             : 
     134          11 :         if((fdlock=open(path, O_WRONLY, 0666))<0)
     135             :                 return 0; // file does not exist - could have got the lock
     136           2 :         errno=0;
     137           2 :         if((r=lockf(fdlock, F_TLOCK, 0)) && (errno==EAGAIN || errno==EACCES))
     138             :         {
     139             :                 // could not have got the lock
     140           1 :                 close(fdlock);
     141           1 :                 return -1;
     142             :         }
     143           1 :         close(fdlock);
     144             :         // could have got the lock
     145           1 :         return 0;
     146             : #endif
     147             : }
     148             : 
     149         118 : int lock_release(struct lock *lock)
     150             : {
     151         118 :         int ret=0;
     152         118 :         if(!lock || lock->status!=GET_LOCK_GOT) return 0;
     153          99 :         if(lock->path) unlink(lock->path);
     154          99 :         if(lock->fd>=0)
     155             :         {
     156          99 :                 if((ret=close(lock->fd)))
     157           0 :                         logp("Could not close %s: %s\n",
     158           0 :                                 lock->path, strerror(errno));
     159          99 :                 lock->fd=-1;
     160             :         }
     161          99 :         lock->status=GET_LOCK_NOT_GOT;
     162          99 :         return ret;
     163             : }
     164             : 
     165           3 : void lock_add_to_list(struct lock **locklist, struct lock *lock)
     166             : {
     167           3 :         if(*locklist) lock->next=*locklist;
     168           3 :         *locklist=lock;
     169           3 : }
     170             : 
     171           4 : void locks_release_and_free(struct lock **locklist)
     172             : {
     173             :         struct lock *l;
     174             :         struct lock *head;
     175           7 :         if(!locklist) return;
     176           1 :         head=*locklist;
     177           5 :         while(head)
     178             :         {
     179           3 :                 l=head;
     180           3 :                 head=head->next;
     181           3 :                 lock_release(l);
     182           3 :                 lock_free(&l);
     183             :         }
     184           1 :         *locklist=NULL;
     185             : }

Generated by: LCOV version 1.10