-
Notifications
You must be signed in to change notification settings - Fork 7
/
pklock.c
147 lines (125 loc) · 3.08 KB
/
pklock.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/* pklock.c -- implements pklock.h */
#include "pklock.h"
/* PKLOCK.C
*
* locking routines as modified by Petri Kutvonen
*/
#if (FILOCK && BSD) || SVR4
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include "util.h"
/* Maximum file length name 255 */
#define MAXLOCK 256
#define MAXNAME 128
#if defined(SVR4) && ! defined(__linux__)
#include <sys/systeminfo.h>
int gethostname(char *name, int namelen)
{
return sysinfo(SI_HOSTNAME, name, namelen);
}
#endif
char *cuserid( char *retbuf) ; /* should have been declared in stdio.h */
/**********************
*
* if successful, returns NULL
* if file locked, returns username of person locking the file
* if other error, returns "LOCK ERROR: explanation"
*
*********************/
char *dolock( const char *fname)
{
int fd, n;
char lname[ MAXLOCK] ;
static char locker[ MAXNAME + 1] ;
int mask;
struct stat sbuf;
mystrscpy( lname, fname, sizeof lname - 6) ;
strcat( lname, ".lock~") ;
/* check that we are not being cheated, qname must point to */
/* a regular file - even this code leaves a small window of */
/* vulnerability but it is rather hard to exploit it */
#if defined(S_IFLNK)
if (lstat(lname, &sbuf) == 0)
#else
if (stat(lname, &sbuf) == 0)
#endif
#if defined(S_ISREG)
if (!S_ISREG(sbuf.st_mode))
#else
if (!(((sbuf.st_mode) & 070000) == 0)) /* SysV R2 */
#endif
return "LOCK ERROR: not a regular file";
mask = umask(0);
fd = open(lname, O_RDWR | O_CREAT, 0666);
umask(mask);
if (fd < 0) {
if (errno == EACCES)
return NULL;
#ifdef EROFS
if (errno == EROFS)
return NULL;
#endif
return "LOCK ERROR: cannot access lock file";
}
if ((n = read(fd, locker, MAXNAME)) < 1) {
lseek(fd, 0, SEEK_SET);
/*
** Since Ubuntu 17.04, cuserid prototype seems missing. Replacing it by
** getlogin does the trick on 64 bits but fails on 32 bits.
** So let's work around with cuserid for a while.
** logname = getlogin() ;
** strcpy( locker, logname ? logname : cuserid( NULL)) ;
*/
#if BSD
strcpy( locker, getlogin()) ;
#else
strcpy( locker, cuserid( NULL)) ;
#endif
strcat(locker + strlen(locker), "@");
gethostname(locker + strlen(locker), 64);
{
int ret, locker_size ;
locker_size = strlen( locker) ;
ret = write( fd, locker, locker_size) ;
if( ret != locker_size) {
/* some error handling here */
}
}
close(fd);
return NULL;
}
locker[n > MAXNAME ? MAXNAME : n] = 0;
return locker;
}
/*********************
*
* undolock -- unlock the file fname
*
* if successful, returns NULL
* if other error, returns "LOCK ERROR: explanation"
*
*********************/
char *undolock( const char *fname) {
char lname[ MAXLOCK] ;
mystrscpy( lname, fname, sizeof lname - 6) ;
strcat( lname, ".lock~") ;
if (unlink(lname) != 0) {
if (errno == EACCES || errno == ENOENT)
return NULL;
#ifdef EROFS
if (errno == EROFS)
return NULL;
#endif
return "LOCK ERROR: cannot remove lock file";
}
return NULL;
}
#else
typedef void _pedantic_empty_translation_unit ;
#endif
/* end of pklock.c */