LCOV - code coverage report
Current view: top level - src - lock.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 70 91 76.9 %
Date: 2018-01-01 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         462 :         return (struct lock *)calloc_w(1, sizeof(struct lock), __func__);
       9             : }
      10             : 
      11         463 : int lock_init(struct lock *lock, const char *path)
      12             : {
      13         463 :         free_w(&lock->path);
      14         463 :         if(!(lock->path=strdup_w(path, __func__)))
      15             :                 return -1;
      16         463 :         return 0;
      17             : }
      18             : 
      19         445 : struct lock *lock_alloc_and_init(const char *path)
      20             : {
      21             :         struct lock *lock;
      22         445 :         if(!(lock=lock_alloc()) || lock_init(lock, path))
      23           0 :                 lock_free(&lock);
      24         445 :         return lock;
      25             : }
      26             : 
      27             : static void lock_free_content(struct lock *lock)
      28             : {
      29         461 :         free_w(&lock->path);
      30             : }
      31             : 
      32         470 : void lock_free(struct lock **lock)
      33             : {
      34         940 :         if(!lock || !*lock) return;
      35         461 :         lock_free_content(*lock);
      36         461 :         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 :         if(lseek(lock->fd, 0, SEEK_SET)<0)
      84             :         {
      85           0 :                 logp("Could not seek to start of lock %s: %s\n",
      86           0 :                         lock->path, strerror(errno));
      87           0 :                 return -1;
      88             :         }
      89         100 :         snprintf(text, sizeof(text), "%d\n%s\n", (int)getpid(), progname());
      90         100 :         if(write(lock->fd, text, strlen(text))!=(ssize_t)strlen(text))
      91             :         {
      92           0 :                 logp("Could not write pid/progname to %s: %s\n",
      93           0 :                         lock->path, strerror(errno));
      94           0 :                 return -1;
      95             :         }
      96             :         return 0;
      97             : }
      98             : 
      99             : // Return 0 for lock got, 1 for lock not got, -1 for error.
     100          81 : void lock_get(struct lock *lock)
     101             : {
     102             : #if defined(HAVE_WIN32) || !defined(HAVE_LOCKF)
     103             :         // Would somebody please tell me how to get a lock on Windows?!
     104             :         lock->status=GET_LOCK_GOT;
     105             :         return;
     106             : #else
     107          81 :         char *cp=NULL;
     108          81 :         char *copy=NULL;
     109             : 
     110             :         // Try to make sure the lock directory exists.
     111          81 :         if(!(copy=strdup_w(lock->path, __func__)))
     112             :         {
     113           0 :                 lock->status=GET_LOCK_ERROR;
     114           0 :                 return;
     115             :         }
     116          81 :         if((cp=strrchr(copy, '/')))
     117             :         {
     118          81 :                 *cp='\0';
     119          81 :                 if(*copy) mkdir(copy, 0777);
     120             :         }
     121          81 :         free_w(&copy);
     122             : 
     123          81 :         lock_get_quick(lock);
     124             : 
     125             :         // Try to make sure the pid gets onto the disk.
     126          81 :         if(lock->status==GET_LOCK_GOT) fsync(lock->fd);
     127             :         return;
     128             : #endif
     129             : }
     130             : 
     131          11 : int lock_test(const char *path)
     132             : {
     133             : #if defined(HAVE_WIN32) || !defined(HAVE_LOCKF)
     134             :         // Would somebody please tell me how to test a lock on Windows?!
     135             :         return 0;
     136             : #else
     137          11 :         int r=0;
     138             :         int fdlock;
     139             : 
     140          11 :         if((fdlock=open(path, O_WRONLY, 0666))<0)
     141             :                 return 0; // file does not exist - could have got the lock
     142           2 :         errno=0;
     143           2 :         if((r=lockf(fdlock, F_TLOCK, 0)) && (errno==EAGAIN || errno==EACCES))
     144             :         {
     145             :                 // could not have got the lock
     146           1 :                 close(fdlock);
     147           1 :                 return -1;
     148             :         }
     149           1 :         close(fdlock);
     150             :         // could have got the lock
     151           1 :         return 0;
     152             : #endif
     153             : }
     154             : 
     155         118 : int lock_release(struct lock *lock)
     156             : {
     157         118 :         int ret=0;
     158         118 :         if(!lock || lock->status!=GET_LOCK_GOT) return 0;
     159          99 :         if(lock->path) unlink(lock->path);
     160          99 :         if(lock->fd>=0)
     161             :         {
     162          99 :                 if((ret=close(lock->fd)))
     163           0 :                         logp("Could not close %s: %s\n",
     164           0 :                                 lock->path, strerror(errno));
     165          99 :                 lock->fd=-1;
     166             :         }
     167          99 :         lock->status=GET_LOCK_NOT_GOT;
     168          99 :         return ret;
     169             : }
     170             : 
     171           3 : void lock_add_to_list(struct lock **locklist, struct lock *lock)
     172             : {
     173           3 :         if(*locklist) lock->next=*locklist;
     174           3 :         *locklist=lock;
     175           3 : }
     176             : 
     177           4 : void locks_release_and_free(struct lock **locklist)
     178             : {
     179             :         struct lock *l;
     180             :         struct lock *head;
     181           7 :         if(!locklist) return;
     182           1 :         head=*locklist;
     183           5 :         while(head)
     184             :         {
     185           3 :                 l=head;
     186           3 :                 head=head->next;
     187           3 :                 lock_release(l);
     188           3 :                 lock_free(&l);
     189             :         }
     190           1 :         *locklist=NULL;
     191             : }

Generated by: LCOV version 1.10