forked from vandry/mairix
-
Notifications
You must be signed in to change notification settings - Fork 1
/
dotlock.c
116 lines (107 loc) · 2.96 KB
/
dotlock.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
/*
mairix - message index builder and finder for maildir folders.
**********************************************************************
* Copyright (C) Richard P. Curnow 2005
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
**********************************************************************
*/
#include "mairix.h"
#include <sys/utsname.h>
#include <sys/types.h>
#include <pwd.h>
#include <unistd.h>
static char *lock_file_name = NULL;
/* This locking code was originally written for tdl */
void lock_database(char *path, int forced_unlock)/*{{{*/
{
struct utsname uu;
struct passwd *pw;
int pid;
int len;
char *tname;
struct stat sb;
FILE *out;
if (uname(&uu) < 0) {
perror("uname");
exit(1);
}
pw = getpwuid(getuid());
if (!pw) {
perror("getpwuid");
exit(1);
}
pid = getpid();
len = 1 + strlen(path) + 5;
lock_file_name = new_array(char, len);
sprintf(lock_file_name, "%s.lock", path);
if (forced_unlock) {
unlock_database();
forced_unlock = 0;
}
len += strlen(uu.nodename);
/* add on max width of pid field (allow up to 32 bit pid_t) + 2 '.' chars */
len += (10 + 2);
tname = new_array(char, len);
sprintf(tname, "%s.%d.%s", lock_file_name, pid, uu.nodename);
out = fopen(tname, "w");
if (!out) {
fprintf(stderr, "Cannot open lock file %s for writing\n", tname);
exit(1);
}
fprintf(out, "%d,%s,%s\n", pid, uu.nodename, pw->pw_name);
fclose(out);
if (link(tname, lock_file_name) < 0) {
/* check if link count==2 */
if (stat(tname, &sb) < 0) {
fprintf(stderr, "Could not stat the lock file\n");
unlink(tname);
exit(1);
} else {
if (sb.st_nlink != 2) {
FILE *in;
in = fopen(lock_file_name, "r");
if (in) {
char line[2048];
fgets(line, sizeof(line), in);
line[strlen(line)-1] = 0; /* strip trailing newline */
fprintf(stderr, "Database %s appears to be locked by (pid,node,user)=(%s)\n", path, line);
unlink(tname);
exit(1);
}
} else {
/* lock succeeded apparently */
}
}
} else {
/* lock succeeded apparently */
}
unlink(tname);
free(tname);
return;
}
/*}}}*/
void unlock_database(void)/*{{{*/
{
if (lock_file_name) unlink(lock_file_name);
return;
}
/*}}}*/
void unlock_and_exit(int code)/*{{{*/
{
unlock_database();
exit(code);
}
/*}}}*/