This source file includes following definitions.
- lock_build_name
- lock_build_symlink_name
- lock_extract_info
- lock_get_info
- lock_file
- unlock_file
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 #include <config.h>
44
45 #include <signal.h>
46 #include <stdio.h>
47 #include <stdarg.h>
48 #include <sys/types.h>
49 #include <unistd.h>
50 #include <string.h>
51 #include <ctype.h>
52 #include <errno.h>
53 #include <sys/stat.h>
54 #include <pwd.h>
55 #include <stdlib.h>
56
57 #include "lib/global.h"
58 #include "lib/vfs/vfs.h"
59 #include "lib/util.h"
60 #include "lib/lock.h"
61 #include "lib/widget.h"
62
63
64
65
66
67 #define BUF_SIZE 255
68 #define PID_BUF_SIZE 10
69
70
71
72 typedef struct
73 {
74 char *who;
75 pid_t pid;
76 } lock_s;
77
78
79
80
81
82
83
84
85
86
87 static char *
88 lock_build_name (void)
89 {
90 char host[BUF_SIZE];
91 const char *user = NULL;
92 struct passwd *pw;
93
94 pw = getpwuid (getuid ());
95 if (pw)
96 user = pw->pw_name;
97 if (!user)
98 user = getenv ("USER");
99 if (!user)
100 user = getenv ("USERNAME");
101 if (!user)
102 user = getenv ("LOGNAME");
103 if (!user)
104 user = "";
105
106
107 if (gethostname (host, BUF_SIZE - 1) == -1)
108 *host = '\0';
109
110 return g_strdup_printf ("%s@%s.%d", user, host, (int) getpid ());
111 }
112
113
114
115 static char *
116 lock_build_symlink_name (const vfs_path_t * fname_vpath)
117 {
118 const char *elpath;
119 char *str_filename, *str_dirname, *symlink_name;
120
121
122 elpath = vfs_path_get_by_index (fname_vpath, 0)->path;
123
124 str_filename = g_path_get_basename (elpath);
125 str_dirname = g_path_get_dirname (elpath);
126 symlink_name = g_strconcat (str_dirname, PATH_SEP_STR ".#", str_filename, (char *) NULL);
127 g_free (str_dirname);
128 g_free (str_filename);
129
130 return symlink_name;
131 }
132
133
134
135
136
137
138 static lock_s *
139 lock_extract_info (const char *str)
140 {
141 size_t i, len;
142 const char *p, *s;
143 static char pid[PID_BUF_SIZE], who[BUF_SIZE];
144 static lock_s lock;
145
146 len = strlen (str);
147
148 for (p = str + len - 1; p >= str; p--)
149 if (*p == '.')
150 break;
151
152
153 i = 0;
154 for (s = str; i < BUF_SIZE && s < p; s++)
155 who[i++] = *s;
156 if (i == BUF_SIZE)
157 i--;
158 who[i] = '\0';
159
160
161 i = 0;
162 for (p = p + 1; i < PID_BUF_SIZE && p < str + len && *p != ':'; p++)
163 pid[i++] = *p;
164 if (i == PID_BUF_SIZE)
165 i--;
166 pid[i] = '\0';
167
168 lock.pid = (pid_t) atol (pid);
169 lock.who = who;
170 return &lock;
171 }
172
173
174
175
176
177
178 static const char *
179 lock_get_info (const char *lockfname)
180 {
181 ssize_t cnt;
182 static char buf[BUF_SIZE];
183
184 cnt = readlink (lockfname, buf, BUF_SIZE - 1);
185 if (cnt == -1 || *buf == '\0')
186 return NULL;
187 buf[cnt] = '\0';
188 return buf;
189 }
190
191
192
193
194
195
196
197
198
199 int
200 lock_file (const vfs_path_t * fname_vpath)
201 {
202 char *lockfname = NULL, *newlock, *msg;
203 struct stat statbuf;
204 lock_s *lockinfo;
205 gboolean is_local;
206 gboolean symlink_ok = FALSE;
207 const char *elpath;
208
209 if (fname_vpath == NULL)
210 return 0;
211
212 elpath = vfs_path_get_by_index (fname_vpath, 0)->path;
213
214 if (*elpath == '\0')
215 return 0;
216
217
218 is_local = vfs_file_is_local (fname_vpath);
219 if (is_local)
220 {
221
222 lockfname = lock_build_symlink_name (fname_vpath);
223 }
224
225 if (!is_local || lockfname == NULL)
226 return 0;
227
228 if (lstat (lockfname, &statbuf) == 0)
229 {
230 const char *lock;
231
232 lock = lock_get_info (lockfname);
233 if (lock == NULL)
234 goto ret;
235 lockinfo = lock_extract_info (lock);
236
237
238 if (lockinfo->pid == 0 || !(kill (lockinfo->pid, 0) == -1 && errno == ESRCH))
239 {
240 msg =
241 g_strdup_printf (_
242 ("File \"%s\" is already being edited.\n"
243 "User: %s\nProcess ID: %d"), x_basename (lockfname) + 2,
244 lockinfo->who, (int) lockinfo->pid);
245
246 switch (query_dialog
247 (_("File locked"), msg, D_NORMAL, 2, _("&Grab lock"), _("&Ignore lock")))
248 {
249 case 0:
250 break;
251 case 1:
252 case -1:
253 default:
254 g_free (msg);
255 goto ret;
256 }
257 g_free (msg);
258 }
259 unlink (lockfname);
260 }
261
262
263 newlock = lock_build_name ();
264 symlink_ok = (symlink (newlock, lockfname) != -1);
265 g_free (newlock);
266
267 ret:
268 g_free (lockfname);
269 return symlink_ok ? 1 : 0;
270 }
271
272
273
274
275
276
277
278 int
279 unlock_file (const vfs_path_t * fname_vpath)
280 {
281 char *lockfname;
282 struct stat statbuf;
283 const char *elpath, *lock;
284
285 if (fname_vpath == NULL)
286 return 0;
287
288 elpath = vfs_path_get_by_index (fname_vpath, 0)->path;
289
290 if (*elpath == '\0')
291 return 0;
292
293 lockfname = lock_build_symlink_name (fname_vpath);
294
295 if (lockfname == NULL)
296 return 0;
297
298
299 if (lstat (lockfname, &statbuf) == -1)
300 goto ret;
301
302 lock = lock_get_info (lockfname);
303 if (lock != NULL)
304 {
305
306 if (lock_extract_info (lock)->pid != getpid ())
307 goto ret;
308 }
309
310
311 unlink (lockfname);
312
313 ret:
314 g_free (lockfname);
315 return 0;
316 }
317
318