This source file includes following definitions.
- vfs_get_local_username
- vfs_finduid
- vfs_findgid
- vfs_mkstemps
- vfs_url_split
- vfs_die
- vfs_get_password
- vfs_utime
- vfs_get_timespecs_from_timesbuf
- vfs_get_timesbuf_from_stat
- vfs_copy_stat_times
- vfs_zero_stat_times
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 #include <config.h>
33
34 #include <ctype.h>
35 #include <sys/types.h>
36 #include <pwd.h>
37 #include <grp.h>
38 #include <stdlib.h>
39 #include <string.h>
40
41 #if !defined (HAVE_UTIMENSAT) && defined (HAVE_UTIME_H)
42 #include <utime.h>
43 #endif
44
45 #include "lib/global.h"
46 #include "lib/unixcompat.h"
47 #include "lib/widget.h"
48 #include "lib/strutil.h"
49
50 #include "vfs.h"
51 #include "utilvfs.h"
52
53
54
55
56
57 #ifndef TUNMLEN
58 #define TUNMLEN 256
59 #endif
60 #ifndef TGNMLEN
61 #define TGNMLEN 256
62 #endif
63
64 #define MC_HISTORY_VFS_PASSWORD "mc.vfs.password"
65
66
67
68
69 #define GUID_DEFAULT_CONST -993
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90 char *
91 vfs_get_local_username (void)
92 {
93 struct passwd *p_i;
94
95 p_i = getpwuid (geteuid ());
96
97
98 return (p_i != NULL && p_i->pw_name != NULL) ? g_strdup (p_i->pw_name) : g_strdup ("anonymous");
99 }
100
101
102
103
104
105
106
107
108
109 int
110 vfs_finduid (const char *uname)
111 {
112 static int saveuid = GUID_DEFAULT_CONST;
113 static char saveuname[TUNMLEN] = "\0";
114
115 size_t uname_len;
116
117 uname_len = strlen (uname);
118
119 if (uname[0] != saveuname[0]
120 || strncmp (uname, saveuname, MIN (uname_len, TUNMLEN - 1)) != 0)
121 {
122 struct passwd *pw;
123
124 g_strlcpy (saveuname, uname, TUNMLEN);
125 pw = getpwnam (uname);
126 if (pw != NULL)
127 saveuid = pw->pw_uid;
128 else
129 {
130 static int my_uid = GUID_DEFAULT_CONST;
131
132 if (my_uid < 0)
133 my_uid = getuid ();
134
135 saveuid = my_uid;
136 }
137 }
138
139 return saveuid;
140 }
141
142
143
144 int
145 vfs_findgid (const char *gname)
146 {
147 static int savegid = GUID_DEFAULT_CONST;
148 static char savegname[TGNMLEN] = "\0";
149
150 size_t gname_len;
151
152 gname_len = strlen (gname);
153
154 if (gname[0] != savegname[0]
155 || strncmp (gname, savegname, MIN (gname_len, TGNMLEN - 1)) != 0)
156 {
157 struct group *gr;
158
159 g_strlcpy (savegname, gname, TGNMLEN);
160 gr = getgrnam (gname);
161 if (gr != NULL)
162 savegid = gr->gr_gid;
163 else
164 {
165 static int my_gid = GUID_DEFAULT_CONST;
166
167 if (my_gid < 0)
168 my_gid = getgid ();
169
170 savegid = my_gid;
171 }
172 }
173
174 return savegid;
175 }
176
177
178
179
180
181
182
183
184
185 int
186 vfs_mkstemps (vfs_path_t **pname_vpath, const char *prefix, const char *param_basename)
187 {
188 const char *p;
189 GString *suffix;
190 int shift;
191 int fd;
192
193
194 p = strrchr (param_basename, PATH_SEP);
195 if (p == NULL)
196 p = param_basename;
197 else
198 p++;
199
200
201 shift = strlen (p) - (MC_MAXPATHLEN - 16);
202 if (shift > 0)
203 p += shift;
204
205 suffix = g_string_sized_new (32);
206
207
208 for (; *p != '\0' && *p != '#'; p++)
209 if (strchr (".-_@", *p) != NULL || g_ascii_isalnum (*p))
210 g_string_append_c (suffix, *p);
211
212 fd = mc_mkstemps (pname_vpath, prefix, suffix->str);
213 g_string_free (suffix, TRUE);
214
215 return fd;
216 }
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240 vfs_path_element_t *
241 vfs_url_split (const char *path, int default_port, vfs_url_flags_t flags)
242 {
243 vfs_path_element_t *path_element;
244
245 char *pcopy;
246 size_t pcopy_len;
247 const char *pend;
248 char *colon, *at, *rest;
249
250 path_element = g_new0 (vfs_path_element_t, 1);
251 path_element->port = default_port;
252
253 pcopy_len = strlen (path);
254 pcopy = g_strndup (path, pcopy_len);
255 pend = pcopy + pcopy_len;
256
257 if ((flags & URL_NOSLASH) == 0)
258 {
259 char *dir;
260
261
262 dir = strchr (pcopy, PATH_SEP);
263
264 if (dir == NULL)
265 path_element->path = g_strdup (PATH_SEP_STR);
266 else
267 {
268 path_element->path = g_strndup (dir, pcopy_len - (size_t) (dir - pcopy));
269 *dir = '\0';
270 }
271 }
272
273
274 at = strrchr (pcopy, '@');
275
276
277 if (at == NULL)
278 rest = pcopy;
279 else
280 {
281 char *inner_colon;
282
283 *at = '\0';
284 inner_colon = strchr (pcopy, ':');
285 if (inner_colon != NULL)
286 {
287 *inner_colon = '\0';
288 inner_colon++;
289 path_element->password = g_strdup (inner_colon);
290 }
291
292 if (*pcopy != '\0')
293 path_element->user = g_strdup (pcopy);
294
295 if (pend == at + 1)
296 rest = at;
297 else
298 rest = at + 1;
299 }
300
301 if ((flags & URL_USE_ANONYMOUS) == 0)
302 {
303 g_free (path_element->user);
304 path_element->user = vfs_get_local_username ();
305 }
306
307 if (*rest != '[')
308 colon = strchr (rest, ':');
309 else
310 {
311 colon = strchr (++rest, ']');
312 if (colon != NULL)
313 {
314 colon[0] = '\0';
315 colon[1] = '\0';
316 colon++;
317 }
318 else
319 {
320 vfs_path_element_free (path_element);
321 g_free (pcopy);
322 return NULL;
323 }
324 }
325
326 if (colon != NULL)
327 {
328 *colon = '\0';
329
330 if (sscanf (colon + 1, "%d", &path_element->port) == 1)
331 {
332 if (path_element->port <= 0 || path_element->port >= 65536)
333 path_element->port = default_port;
334 }
335 else
336 while (*(++colon) != '\0')
337 {
338 switch (*colon)
339 {
340 case 'C':
341 path_element->port = 1;
342 break;
343 case 'r':
344 path_element->port = 2;
345 break;
346 default:
347 break;
348 }
349 }
350 }
351
352 path_element->host = g_strdup (rest);
353 g_free (pcopy);
354 #ifdef HAVE_CHARSET
355 path_element->dir.converter = INVALID_CONV;
356 #endif
357
358 return path_element;
359 }
360
361
362
363 void __attribute__((noreturn)) vfs_die (const char *m)
364 {
365 message (D_ERROR, _("Internal error:"), "%s", m);
366 exit (EXIT_FAILURE);
367 }
368
369
370
371 char *
372 vfs_get_password (const char *msg)
373 {
374 return input_dialog (msg, _("Password:"), MC_HISTORY_VFS_PASSWORD, INPUT_PASSWORD,
375 INPUT_COMPLETE_NONE);
376 }
377
378
379
380 int
381 vfs_utime (const char *path, mc_timesbuf_t *times)
382 {
383 #ifdef HAVE_UTIMENSAT
384 return utimensat (AT_FDCWD, path, *times, AT_SYMLINK_NOFOLLOW);
385 #else
386 return utime (path, times);
387 #endif
388 }
389
390
391
392 void
393 vfs_get_timespecs_from_timesbuf (mc_timesbuf_t *times, mc_timespec_t *atime, mc_timespec_t *mtime)
394 {
395 #ifdef HAVE_UTIMENSAT
396 atime->tv_sec = (*times)[0].tv_sec;
397 atime->tv_nsec = (*times)[0].tv_nsec;
398 mtime->tv_sec = (*times)[1].tv_sec;
399 mtime->tv_nsec = (*times)[1].tv_nsec;
400 #else
401 atime->tv_sec = times->actime;
402 atime->tv_nsec = 0;
403 mtime->tv_sec = times->modtime;
404 mtime->tv_nsec = 0;
405 #endif
406 }
407
408
409
410 void
411 vfs_get_timesbuf_from_stat (const struct stat *s, mc_timesbuf_t *times)
412 {
413 #ifdef HAVE_UTIMENSAT
414 #ifdef HAVE_STRUCT_STAT_ST_MTIM
415
416
417
418
419
420 (*times)[0].tv_sec = s->st_atim.tv_sec;
421 (*times)[0].tv_nsec = s->st_atim.tv_nsec;
422 (*times)[1].tv_sec = s->st_mtim.tv_sec;
423 (*times)[1].tv_nsec = s->st_mtim.tv_nsec;
424 #elif HAVE_STRUCT_STAT_ST_MTIMESPEC
425
426 (*times)[0] = s->st_atimespec;
427 (*times)[1] = s->st_mtimespec;
428 #elif HAVE_STRUCT_STAT_ST_MTIMENSEC
429
430 (*times)[0].tv_sec = s->st_atime;
431 (*times)[0].tv_nsec = s->st_atimensec;
432 (*times)[1].tv_sec = s->st_mtime;
433 (*times)[1].tv_nsec = s->st_mtimensec;
434 #else
435 #error "Found utimensat for nanosecond timestamps, but unsupported struct stat format!"
436 #endif
437 #else
438 times->actime = s->st_atime;
439 times->modtime = s->st_mtime;
440 #endif
441 }
442
443
444
445 void
446 vfs_copy_stat_times (const struct stat *src, struct stat *dst)
447 {
448 dst->st_atime = src->st_atime;
449 dst->st_mtime = src->st_mtime;
450 dst->st_ctime = src->st_ctime;
451
452 #ifdef HAVE_STRUCT_STAT_ST_MTIM
453 dst->st_atim.tv_nsec = src->st_atim.tv_nsec;
454 dst->st_mtim.tv_nsec = src->st_mtim.tv_nsec;
455 dst->st_ctim.tv_nsec = src->st_ctim.tv_nsec;
456 #elif HAVE_STRUCT_STAT_ST_MTIMESPEC
457 dst->st_atimespec.tv_nsec = src->st_atimespec.tv_nsec;
458 dst->st_mtimespec.tv_nsec = src->st_mtimespec.tv_nsec;
459 dst->st_ctimespec.tv_nsec = src->st_ctimespec.tv_nsec;
460 #elif HAVE_STRUCT_STAT_ST_MTIMENSEC
461 dst->st_atimensec = src->st_atimensec;
462 dst->st_mtimensec = src->st_mtimensec;
463 dst->st_ctimensec = src->st_ctimensec;
464 #endif
465 }
466
467
468
469 void
470 vfs_zero_stat_times (struct stat *s)
471 {
472 const struct stat empty = { 0 };
473
474 vfs_copy_stat_times (&empty, s);
475 }
476
477