LCOV - code coverage report
Current view: top level - src - lock.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 71 92 77.2 %
Date: 2021-05-02 03:18:47 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         470 :         if(!lock || !*lock) return;
      35         922 :         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         102 :         if((lock->fd=open(
      47         102 :                 lock->path,
      48             : #ifdef O_NOFOLLOW
      49             :                 O_NOFOLLOW|
      50             : #endif
      51             :                 O_WRONLY|O_CREAT,
      52             :                 0666
      53             :         ))<0)
      54             :         {
      55           0 :                 logp("Could not open lock file %s: %s\n",
      56           0 :                         lock->path, strerror(errno));
      57           0 :                 goto error;
      58             :         }
      59         102 :         if(lockf(lock->fd, F_TLOCK, 0))
      60             :         {
      61           2 :                 if(errno==EACCES || errno==EAGAIN)
      62             :                         goto notgot;
      63           0 :                 logp("Could not get lock %s: %s\n",
      64             :                         lock->path, strerror(errno));
      65           0 :                 goto error; // Some other error.
      66             :         }
      67         100 :         if(lock_write_pid(lock))
      68             :                 goto error;
      69             :         
      70         100 :         lock->status=GET_LOCK_GOT;
      71         100 :         return;
      72             : error:
      73           0 :         lock->status=GET_LOCK_ERROR;
      74           0 :         return;
      75             : notgot:
      76           2 :         lock->status=GET_LOCK_NOT_GOT;
      77           2 :         return;
      78             : #endif
      79             : }
      80             : 
      81         100 : int lock_write_pid(struct lock *lock)
      82             : {
      83         100 :         char text[64]="";
      84         100 :         if(ftruncate(lock->fd, 0))
      85             :         {
      86           0 :                 logp("Could not ftruncate lock %s: %s\n",
      87           0 :                         lock->path, strerror(errno));
      88           0 :                 return -1;
      89             :         }
      90         100 :         if(lseek(lock->fd, 0, SEEK_SET)<0)
      91             :         {
      92           0 :                 logp("Could not seek to start of lock %s: %s\n",
      93           0 :                         lock->path, strerror(errno));
      94           0 :                 return -1;
      95             :         }
      96         100 :         snprintf(text, sizeof(text), "%d\n", (int)getpid());
      97         100 :         if(write(lock->fd, text, strlen(text))!=(ssize_t)strlen(text))
      98             :         {
      99           0 :                 logp("Could not write pid/progname to %s: %s\n",
     100           0 :                         lock->path, strerror(errno));
     101           0 :                 return -1;
     102             :         }
     103             :         return 0;
     104             : }
     105             : 
     106             : // Return 0 for lock got, 1 for lock not got, -1 for error.
     107          81 : void lock_get(struct lock *lock)
     108             : {
     109             : #if defined(HAVE_WIN32) || !defined(HAVE_LOCKF)
     110             :         // Would somebody please tell me how to get a lock on Windows?!
     111             :         lock->status=GET_LOCK_GOT;
     112             :         return;
     113             : #else
     114          81 :         char *cp=NULL;
     115          81 :         char *copy=NULL;
     116             : 
     117             :         // Try to make sure the lock directory exists.
     118          81 :         if(!(copy=strdup_w(lock->path, __func__)))
     119             :         {
     120           0 :                 lock->status=GET_LOCK_ERROR;
     121           0 :                 return;
     122             :         }
     123          81 :         if((cp=strrchr(copy, '/')))
     124             :         {
     125          81 :                 *cp='\0';
     126          81 :                 if(*copy) mkdir(copy, 0777);
     127             :         }
     128          81 :         free_w(&copy);
     129             : 
     130          81 :         lock_get_quick(lock);
     131             : 
     132             :         // Try to make sure the pid gets onto the disk.
     133          81 :         if(lock->status==GET_LOCK_GOT) fsync(lock->fd);
     134             :         return;
     135             : #endif
     136             : }
     137             : 
     138          11 : int lock_test(const char *path)
     139             : {
     140             : #if defined(HAVE_WIN32) || !defined(HAVE_LOCKF)
     141             :         // Would somebody please tell me how to test a lock on Windows?!
     142             :         return 0;
     143             : #else
     144          11 :         int r=0;
     145             :         int fdlock;
     146             : 
     147          11 :         if((fdlock=open(path, O_WRONLY, 0666))<0)
     148             :                 return 0; // file does not exist - could have got the lock
     149           2 :         errno=0;
     150           2 :         if((r=lockf(fdlock, F_TLOCK, 0)) && (errno==EAGAIN || errno==EACCES))
     151             :         {
     152             :                 // could not have got the lock
     153           1 :                 close(fdlock);
     154           1 :                 return -1;
     155             :         }
     156           1 :         close(fdlock);
     157             :         // could have got the lock
     158           1 :         return 0;
     159             : #endif
     160             : }
     161             : 
     162         118 : int lock_release(struct lock *lock)
     163             : {
     164         118 :         int ret=0;
     165         118 :         if(!lock || lock->status!=GET_LOCK_GOT) return 0;
     166          99 :         if(lock->path) unlink(lock->path);
     167          99 :         if(lock->fd>=0)
     168             :         {
     169          99 :                 if((ret=close(lock->fd)))
     170           0 :                         logp("Could not close %s: %s\n",
     171           0 :                                 lock->path, strerror(errno));
     172          99 :                 lock->fd=-1;
     173             :         }
     174          99 :         lock->status=GET_LOCK_NOT_GOT;
     175          99 :         return ret;
     176             : }
     177             : 
     178           3 : void lock_add_to_list(struct lock **locklist, struct lock *lock)
     179             : {
     180           3 :         if(*locklist) lock->next=*locklist;
     181           3 :         *locklist=lock;
     182           3 : }
     183             : 
     184           4 : void locks_release_and_free(struct lock **locklist)
     185             : {
     186             :         struct lock *l;
     187             :         struct lock *head;
     188           7 :         if(!locklist) return;
     189           1 :         head=*locklist;
     190           5 :         while(head)
     191             :         {
     192           3 :                 l=head;
     193           3 :                 head=head->next;
     194           3 :                 lock_release(l);
     195           3 :                 lock_free(&l);
     196             :         }
     197           1 :         *locklist=NULL;
     198             : }

Generated by: LCOV version 1.13