1 /* filesystem.c
2 * Filesystem utility routines
3 *
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11 #include <config.h>
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <errno.h>
17
18 #include <glib.h>
19
20 #ifdef _WIN32
21 #include <windows.h>
22 #include <tchar.h>
23 #include <shlobj.h>
24 #include <wsutil/unicode-utils.h>
25 #else /* _WIN32 */
26 #ifdef __APPLE__
27 #include <mach-o/dyld.h>
28 #endif
29 #ifdef __linux__
30 #include <sys/utsname.h>
31 #endif
32 #ifdef __FreeBSD__
33 #include <sys/types.h>
34 #include <sys/sysctl.h>
35 #endif
36 #ifdef HAVE_DLGET
37 #include <dlfcn.h>
38 #endif
39 #include <pwd.h>
40 #endif /* _WIN32 */
41
42 #include "filesystem.h"
43 #include <wsutil/report_message.h>
44 #include <wsutil/privileges.h>
45 #include <wsutil/file_util.h>
46 #include <wsutil/utf8_entities.h>
47 #include <wsutil/ws_assert.h>
48
49 #include <wiretap/wtap.h> /* for WTAP_ERR_SHORT_WRITE */
50
51 #define PROFILES_DIR "profiles"
52 #define PLUGINS_DIR_NAME "plugins"
53 #define PROFILES_INFO_NAME "profile_files.txt"
54
55 #define ENV_CONFIG_PATH_VAR "WIRESHARK_CONFIG_DIR"
56
57 char *persconffile_dir = NULL;
58 char *datafile_dir = NULL;
59 char *persdatafile_dir = NULL;
60 char *persconfprofile = NULL;
61
62 static gboolean do_store_persconffiles = FALSE;
63 static GHashTable *profile_files = NULL;
64
65 /*
66 * Given a pathname, return a pointer to the last pathname separator
67 * character in the pathname, or NULL if the pathname contains no
68 * separators.
69 */
70 char *
find_last_pathname_separator(const char * path)71 find_last_pathname_separator(const char *path)
72 {
73 char *separator;
74
75 #ifdef _WIN32
76 char c;
77
78 /*
79 * We have to scan for '\' or '/'.
80 * Get to the end of the string.
81 */
82 separator = strchr(path, '\0'); /* points to ending '\0' */
83 while (separator > path) {
84 c = *--separator;
85 if (c == '\\' || c == '/')
86 return separator; /* found it */
87 }
88
89 /*
90 * OK, we didn't find any, so no directories - but there might
91 * be a drive letter....
92 */
93 return strchr(path, ':');
94 #else
95 separator = strrchr(path, '/');
96 return separator;
97 #endif
98 }
99
100 /*
101 * Given a pathname, return the last component.
102 */
103 const char *
get_basename(const char * path)104 get_basename(const char *path)
105 {
106 const char *filename;
107
108 ws_assert(path != NULL);
109 filename = find_last_pathname_separator(path);
110 if (filename == NULL) {
111 /*
112 * There're no directories, drive letters, etc. in the
113 * name; the pathname *is* the file name.
114 */
115 filename = path;
116 } else {
117 /*
118 * Skip past the pathname or drive letter separator.
119 */
120 filename++;
121 }
122 return filename;
123 }
124
125 /*
126 * Given a pathname, return a string containing everything but the
127 * last component. NOTE: this overwrites the pathname handed into
128 * it....
129 */
130 char *
get_dirname(char * path)131 get_dirname(char *path)
132 {
133 char *separator;
134
135 ws_assert(path != NULL);
136 separator = find_last_pathname_separator(path);
137 if (separator == NULL) {
138 /*
139 * There're no directories, drive letters, etc. in the
140 * name; there is no directory path to return.
141 */
142 return NULL;
143 }
144
145 /*
146 * Get rid of the last pathname separator and the final file
147 * name following it.
148 */
149 *separator = '\0';
150
151 /*
152 * "path" now contains the pathname of the directory containing
153 * the file/directory to which it referred.
154 */
155 return path;
156 }
157
158 /*
159 * Given a pathname, return:
160 *
161 * the errno, if an attempt to "stat()" the file fails;
162 *
163 * EISDIR, if the attempt succeeded and the file turned out
164 * to be a directory;
165 *
166 * 0, if the attempt succeeded and the file turned out not
167 * to be a directory.
168 */
169
170 int
test_for_directory(const char * path)171 test_for_directory(const char *path)
172 {
173 ws_statb64 statb;
174
175 if (ws_stat64(path, &statb) < 0)
176 return errno;
177
178 if (S_ISDIR(statb.st_mode))
179 return EISDIR;
180 else
181 return 0;
182 }
183
184 int
test_for_fifo(const char * path)185 test_for_fifo(const char *path)
186 {
187 ws_statb64 statb;
188
189 if (ws_stat64(path, &statb) < 0)
190 return errno;
191
192 if (S_ISFIFO(statb.st_mode))
193 return ESPIPE;
194 else
195 return 0;
196 }
197
198 /*
199 * Directory from which the executable came.
200 */
201 static char *progfile_dir;
202
203 #ifdef __APPLE__
204 /*
205 * Directory of the application bundle in which we're contained,
206 * if we're contained in an application bundle. Otherwise, NULL.
207 *
208 * Note: Table 2-5 "Subdirectories of the Contents directory" of
209 *
210 * https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/BundleTypes/BundleTypes.html#//apple_ref/doc/uid/10000123i-CH101-SW1
211 *
212 * says that the "Frameworks" directory
213 *
214 * Contains any private shared libraries and frameworks used by the
215 * executable. The frameworks in this directory are revision-locked
216 * to the application and cannot be superseded by any other, even
217 * newer, versions that may be available to the operating system. In
218 * other words, the frameworks included in this directory take precedence
219 * over any other similarly named frameworks found in other parts of
220 * the operating system. For information on how to add private
221 * frameworks to your application bundle, see Framework Programming Guide.
222 *
223 * so if we were to ship with any frameworks (e.g. Qt) we should
224 * perhaps put them in a Frameworks directory rather than under
225 * Resources.
226 *
227 * It also says that the "PlugIns" directory
228 *
229 * Contains loadable bundles that extend the basic features of your
230 * application. You use this directory to include code modules that
231 * must be loaded into your applicationbs process space in order to
232 * be used. You would not use this directory to store standalone
233 * executables.
234 *
235 * Our plugins are just raw .so/.dylib files; I don't know whether by
236 * "bundles" they mean application bundles (i.e., directory hierarchies)
237 * or just "bundles" in the Mach-O sense (which are an image type that
238 * can be loaded with dlopen() but not linked as libraries; our plugins
239 * are, I think, built as dylibs and can be loaded either way).
240 *
241 * And it says that the "SharedSupport" directory
242 *
243 * Contains additional non-critical resources that do not impact the
244 * ability of the application to run. You might use this directory to
245 * include things like document templates, clip art, and tutorials
246 * that your application expects to be present but that do not affect
247 * the ability of your application to run.
248 *
249 * I don't think I'd put the files that currently go under Resources/share
250 * into that category; they're not, for example, sample Lua scripts that
251 * don't actually get run by Wireshark, they're configuration/data files
252 * for Wireshark whose absence might not prevent Wireshark from running
253 * but that would affect how it behaves when run.
254 */
255 static char *appbundle_dir;
256 #endif
257
258 /*
259 * TRUE if we're running from the build directory and we aren't running
260 * with special privileges.
261 */
262 static gboolean running_in_build_directory_flag = FALSE;
263
264 #ifndef _WIN32
265 /*
266 * Get the pathname of the executable using various platform-
267 * dependent mechanisms for various UN*Xes.
268 *
269 * These calls all should return something independent of the argv[0]
270 * passed to the program, so it shouldn't be fooled by an argv[0]
271 * that doesn't match the executable path.
272 *
273 * We don't use dladdr() because:
274 *
275 * not all UN*Xes necessarily have dladdr();
276 *
277 * those that do have it don't necessarily have dladdr(main)
278 * return information about the executable image;
279 *
280 * those that do have a dladdr() where dladdr(main) returns
281 * information about the executable image don't necessarily
282 * have a mechanism by which the executable image can get
283 * its own path from the kernel (either by a call or by it
284 * being handed to it along with argv[] and the environment),
285 * so they just fall back on getting it from argv[0], which we
286 * already have code to do;
287 *
288 * those that do have such a mechanism don't necessarily use
289 * it in dladdr(), and, instead, just fall back on getting it
290 * from argv[0];
291 *
292 * so the only places where it's worth bothering to use dladdr()
293 * are platforms where dladdr(main) return information about the
294 * executable image by getting it from the kernel rather than
295 * by looking at argv[0], and where we can't get at that information
296 * ourselves, and we haven't seen any indication that there are any
297 * such platforms.
298 *
299 * In particular, some dynamic linkers supply a dladdr() such that
300 * dladdr(main) just returns something derived from argv[0], so
301 * just using dladdr(main) is the wrong thing to do if there's
302 * another mechanism that can get you a more reliable version of
303 * the executable path.
304 *
305 * So, on platforms where we know of a mechanism to get that path
306 * (where getting that path doesn't involve argv[0], which is not
307 * guaranteed to reflect the path to the binary), this routine
308 * attempsts to use that platform's mechanism. On other platforms,
309 * it just returns NULL.
310 *
311 * This is not guaranteed to return an absolute path; if it doesn't,
312 * our caller must prepend the current directory if it's a path.
313 *
314 * This is not guaranteed to return the "real path"; it might return
315 * something with symbolic links in the path. Our caller must
316 * use realpath() if they want the real thing, but that's also true of
317 * something obtained by looking at argv[0].
318 */
319 #define xx_free free /* hack so checkAPIs doesn't complain */
320 static const char *
get_executable_path(void)321 get_executable_path(void)
322 {
323 #if defined(__APPLE__)
324 static char *executable_path;
325 uint32_t path_buf_size;
326
327 if (executable_path) {
328 return executable_path;
329 }
330
331 path_buf_size = PATH_MAX;
332 executable_path = (char *)g_malloc(path_buf_size);
333 if (_NSGetExecutablePath(executable_path, &path_buf_size) == -1) {
334 executable_path = (char *)g_realloc(executable_path, path_buf_size);
335 if (_NSGetExecutablePath(executable_path, &path_buf_size) == -1)
336 return NULL;
337 }
338 /*
339 * Resolve our path so that it's possible to symlink the executables
340 * in our application bundle.
341 */
342 char *rp_execpath = realpath(executable_path, NULL);
343 if (rp_execpath) {
344 g_free(executable_path);
345 executable_path = g_strdup(rp_execpath);
346 xx_free(rp_execpath);
347 }
348 return executable_path;
349 #elif defined(__linux__)
350 /*
351 * In older versions of GNU libc's dynamic linker, as used on Linux,
352 * dladdr(main) supplies a path based on argv[0], so we use
353 * /proc/self/exe instead; there are Linux distributions with
354 * kernels that support /proc/self/exe and those older versions
355 * of the dynamic linker, and this will get a better answer on
356 * those versions.
357 *
358 * It only works on Linux 2.2 or later, so we just give up on
359 * earlier versions.
360 *
361 * XXX - are there OS versions that support "exe" but not "self"?
362 */
363 struct utsname name;
364 static char executable_path[PATH_MAX + 1];
365 ssize_t r;
366
367 if (uname(&name) == -1)
368 return NULL;
369 if (strncmp(name.release, "1.", 2) == 0)
370 return NULL; /* Linux 1.x */
371 if (strcmp(name.release, "2.0") == 0 ||
372 strncmp(name.release, "2.0.", 4) == 0 ||
373 strcmp(name.release, "2.1") == 0 ||
374 strncmp(name.release, "2.1.", 4) == 0)
375 return NULL; /* Linux 2.0.x or 2.1.x */
376 if ((r = readlink("/proc/self/exe", executable_path, PATH_MAX)) == -1)
377 return NULL;
378 executable_path[r] = '\0';
379 return executable_path;
380 #elif defined(__FreeBSD__) && defined(KERN_PROC_PATHNAME)
381 /*
382 * In older versions of FreeBSD's dynamic linker, dladdr(main)
383 * supplies a path based on argv[0], so we use the KERN_PROC_PATHNAME
384 * sysctl instead; there are, I think, versions of FreeBSD
385 * that support the sysctl that have and those older versions
386 * of the dynamic linker, and this will get a better answer on
387 * those versions.
388 */
389 int mib[4];
390 char *executable_path;
391 size_t path_buf_size;
392
393 mib[0] = CTL_KERN;
394 mib[1] = KERN_PROC;
395 mib[2] = KERN_PROC_PATHNAME;
396 mib[3] = -1;
397 path_buf_size = PATH_MAX;
398 executable_path = (char *)g_malloc(path_buf_size);
399 if (sysctl(mib, 4, executable_path, &path_buf_size, NULL, 0) == -1) {
400 if (errno != ENOMEM)
401 return NULL;
402 executable_path = (char *)g_realloc(executable_path, path_buf_size);
403 if (sysctl(mib, 4, executable_path, &path_buf_size, NULL, 0) == -1)
404 return NULL;
405 }
406 return executable_path;
407 #elif defined(__NetBSD__)
408 /*
409 * In all versions of NetBSD's dynamic linker as of 2013-08-12,
410 * dladdr(main) supplies a path based on argv[0], so we use
411 * /proc/curproc/exe instead.
412 *
413 * XXX - are there OS versions that support "exe" but not "curproc"
414 * or "self"? Are there any that support "self" but not "curproc"?
415 */
416 static char executable_path[PATH_MAX + 1];
417 ssize_t r;
418
419 if ((r = readlink("/proc/curproc/exe", executable_path, PATH_MAX)) == -1)
420 return NULL;
421 executable_path[r] = '\0';
422 return executable_path;
423 #elif defined(__DragonFly__)
424 /*
425 * In older versions of DragonFly BSD's dynamic linker, dladdr(main)
426 * supplies a path based on argv[0], so we use /proc/curproc/file
427 * instead; it appears to be supported by all versions of DragonFly
428 * BSD.
429 */
430 static char executable_path[PATH_MAX + 1];
431 ssize_t r;
432
433 if ((r = readlink("/proc/curproc/file", executable_path, PATH_MAX)) == -1)
434 return NULL;
435 executable_path[r] = '\0';
436 return executable_path;
437 #elif defined(HAVE_GETEXECNAME)
438 /*
439 * Solaris, with getexecname().
440 * It appears that getexecname() dates back to at least Solaris 8,
441 * but /proc/{pid}/path is first documented in the Solaris 10 documentation,
442 * so we use getexecname() if available, rather than /proc/self/path/a.out
443 * (which isn't documented, but appears to be a symlink to the
444 * executable image file).
445 */
446 return getexecname();
447 #elif defined(HAVE_DLGET)
448 /*
449 * HP-UX 11, with dlget(); use dlget() and dlgetname().
450 * See
451 *
452 * https://web.archive.org/web/20081025174755/http://h21007.www2.hp.com/portal/site/dspp/menuitem.863c3e4cbcdc3f3515b49c108973a801?ciid=88086d6e1de021106d6e1de02110275d6e10RCRD#two
453 */
454 struct load_module_desc desc;
455
456 if (dlget(-2, &desc, sizeof(desc)) != NULL)
457 return dlgetname(&desc, sizeof(desc), NULL, NULL, NULL);
458 else
459 return NULL;
460 #else
461 /* Fill in your favorite UN*X's code here, if there is something */
462 return NULL;
463 #endif
464 }
465 #endif /* _WIN32 */
466
467 /*
468 * Get the pathname of the directory from which the executable came,
469 * and save it for future use. Returns NULL on success, and a
470 * g_mallocated string containing an error on failure.
471 */
472 char *
init_progfile_dir(const char * arg0 _U_)473 init_progfile_dir(
474 #ifdef _WIN32
475 const char* arg0 _U_
476 #else
477 const char* arg0
478 #endif
479 )
480 {
481 #ifdef _WIN32
482 TCHAR prog_pathname_w[_MAX_PATH+2];
483 char *prog_pathname;
484 DWORD error;
485 TCHAR *msg_w;
486 guchar *msg;
487 size_t msglen;
488
489 /*
490 * Attempt to get the full pathname of the currently running
491 * program.
492 */
493 if (GetModuleFileName(NULL, prog_pathname_w, G_N_ELEMENTS(prog_pathname_w)) != 0 && GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
494 /*
495 * XXX - Should we use g_utf16_to_utf8()?
496 */
497 prog_pathname = utf_16to8(prog_pathname_w);
498 /*
499 * We got it; strip off the last component, which would be
500 * the file name of the executable, giving us the pathname
501 * of the directory where the executable resides.
502 */
503 progfile_dir = g_path_get_dirname(prog_pathname);
504 if (progfile_dir != NULL) {
505 return NULL; /* we succeeded */
506 } else {
507 /*
508 * OK, no. What do we do now?
509 */
510 return g_strdup_printf("No \\ in executable pathname \"%s\"",
511 prog_pathname);
512 }
513 } else {
514 /*
515 * Oh, well. Return an indication of the error.
516 */
517 error = GetLastError();
518 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
519 NULL, error, 0, (LPTSTR) &msg_w, 0, NULL) == 0) {
520 /*
521 * Gak. We can't format the message.
522 */
523 return g_strdup_printf("GetModuleFileName failed: %u (FormatMessage failed: %u)",
524 error, GetLastError());
525 }
526 msg = utf_16to8(msg_w);
527 LocalFree(msg_w);
528 /*
529 * "FormatMessage()" "helpfully" sticks CR/LF at the
530 * end of the message. Get rid of it.
531 */
532 msglen = strlen(msg);
533 if (msglen >= 2) {
534 msg[msglen - 1] = '\0';
535 msg[msglen - 2] = '\0';
536 }
537 return g_strdup_printf("GetModuleFileName failed: %s (%u)",
538 msg, error);
539 }
540 #else
541 const char *execname;
542 char *prog_pathname;
543 char *curdir;
544 long path_max;
545 const char *pathstr;
546 const char *path_start, *path_end;
547 size_t path_component_len, path_len;
548 char *retstr;
549 char *path;
550 char *dir_end;
551
552 /*
553 * Check whether WIRESHARK_RUN_FROM_BUILD_DIRECTORY is set in the
554 * environment; if so, set running_in_build_directory_flag if we
555 * weren't started with special privileges. (If we were started
556 * with special privileges, it's not safe to allow the user to point
557 * us to some other directory; running_in_build_directory_flag, when
558 * set, causes us to look for plugins and the like in the build
559 * directory.)
560 */
561 if (g_getenv("WIRESHARK_RUN_FROM_BUILD_DIRECTORY") != NULL
562 && !started_with_special_privs())
563 running_in_build_directory_flag = TRUE;
564
565 execname = get_executable_path();
566 if (execname == NULL) {
567 /*
568 * OK, guess based on argv[0].
569 */
570 execname = arg0;
571 }
572
573 /*
574 * Try to figure out the directory in which the currently running
575 * program resides, given something purporting to be the executable
576 * name (from an OS mechanism or from the argv[0] it was started with).
577 * That might be the absolute path of the program, or a path relative
578 * to the current directory of the process that started it, or
579 * just a name for the program if it was started from the command
580 * line and was searched for in $PATH. It's not guaranteed to be
581 * any of those, however, so there are no guarantees....
582 */
583 if (execname[0] == '/') {
584 /*
585 * It's an absolute path.
586 */
587 prog_pathname = g_strdup(execname);
588 } else if (strchr(execname, '/') != NULL) {
589 /*
590 * It's a relative path, with a directory in it.
591 * Get the current directory, and combine it
592 * with that directory.
593 */
594 path_max = pathconf(".", _PC_PATH_MAX);
595 if (path_max == -1) {
596 /*
597 * We have no idea how big a buffer to
598 * allocate for the current directory.
599 */
600 return g_strdup_printf("pathconf failed: %s\n",
601 g_strerror(errno));
602 }
603 curdir = (char *)g_malloc(path_max);
604 if (getcwd(curdir, path_max) == NULL) {
605 /*
606 * It failed - give up, and just stick
607 * with DATA_DIR.
608 */
609 g_free(curdir);
610 return g_strdup_printf("getcwd failed: %s\n",
611 g_strerror(errno));
612 }
613 path = g_strdup_printf("%s/%s", curdir, execname);
614 g_free(curdir);
615 prog_pathname = path;
616 } else {
617 /*
618 * It's just a file name.
619 * Search the path for a file with that name
620 * that's executable.
621 */
622 prog_pathname = NULL; /* haven't found it yet */
623 pathstr = g_getenv("PATH");
624 path_start = pathstr;
625 if (path_start != NULL) {
626 while (*path_start != '\0') {
627 path_end = strchr(path_start, ':');
628 if (path_end == NULL)
629 path_end = path_start + strlen(path_start);
630 path_component_len = path_end - path_start;
631 path_len = path_component_len + 1
632 + strlen(execname) + 1;
633 path = (char *)g_malloc(path_len);
634 memcpy(path, path_start, path_component_len);
635 path[path_component_len] = '\0';
636 (void) g_strlcat(path, "/", path_len);
637 (void) g_strlcat(path, execname, path_len);
638 if (access(path, X_OK) == 0) {
639 /*
640 * Found it!
641 */
642 prog_pathname = path;
643 break;
644 }
645
646 /*
647 * That's not it. If there are more
648 * path components to test, try them.
649 */
650 if (*path_end == ':')
651 path_end++;
652 path_start = path_end;
653 g_free(path);
654 }
655 if (prog_pathname == NULL) {
656 /*
657 * Program not found in path.
658 */
659 return g_strdup_printf("\"%s\" not found in \"%s\"",
660 execname, pathstr);
661 }
662 } else {
663 /*
664 * PATH isn't set.
665 * XXX - should we pick a default?
666 */
667 return g_strdup("PATH isn't set");
668 }
669 }
670
671 /*
672 * OK, we have what we think is the pathname
673 * of the program.
674 *
675 * First, find the last "/" in the directory,
676 * as that marks the end of the directory pathname.
677 */
678 dir_end = strrchr(prog_pathname, '/');
679 if (dir_end != NULL) {
680 /*
681 * Found it. Strip off the last component,
682 * as that's the path of the program.
683 */
684 *dir_end = '\0';
685
686 /*
687 * Is there a "/run" at the end?
688 */
689 dir_end = strrchr(prog_pathname, '/');
690 if (dir_end != NULL) {
691 if (!started_with_special_privs()) {
692 /*
693 * Check for the CMake output directory. As people may name
694 * their directories "run" (really?), also check for the
695 * CMakeCache.txt file before assuming a CMake output dir.
696 */
697 if (strcmp(dir_end, "/run") == 0) {
698 gchar *cmake_file;
699 cmake_file = g_strdup_printf("%.*s/CMakeCache.txt",
700 (int)(dir_end - prog_pathname),
701 prog_pathname);
702 if (file_exists(cmake_file))
703 running_in_build_directory_flag = TRUE;
704 g_free(cmake_file);
705 }
706 #ifdef __APPLE__
707 {
708 /*
709 * Scan up the path looking for a component
710 * named "Contents". If we find it, we assume
711 * we're in a bundle, and that the top-level
712 * directory of the bundle is the one containing
713 * "Contents".
714 *
715 * Not all executables are in the Contents/MacOS
716 * directory, so we can't just check for those
717 * in the path and strip them off.
718 *
719 * XXX - should we assume that it's either
720 * Contents/MacOS or Resources/bin?
721 */
722 char *component_end, *p;
723
724 component_end = strchr(prog_pathname, '\0');
725 p = component_end;
726 for (;;) {
727 while (p >= prog_pathname && *p != '/')
728 p--;
729 if (p == prog_pathname) {
730 /*
731 * We're looking at the first component of
732 * the pathname now, so we're definitely
733 * not in a bundle, even if we're in
734 * "/Contents".
735 */
736 break;
737 }
738 if (strncmp(p, "/Contents", component_end - p) == 0) {
739 /* Found it. */
740 appbundle_dir = (char *)g_malloc(p - prog_pathname + 1);
741 memcpy(appbundle_dir, prog_pathname, p - prog_pathname);
742 appbundle_dir[p - prog_pathname] = '\0';
743 break;
744 }
745 component_end = p;
746 p--;
747 }
748 }
749 #endif
750 }
751 }
752
753 /*
754 * OK, we have the path we want.
755 */
756 progfile_dir = prog_pathname;
757 return NULL;
758 } else {
759 /*
760 * This "shouldn't happen"; we apparently
761 * have no "/" in the pathname.
762 * Just free up prog_pathname.
763 */
764 retstr = g_strdup_printf("No / found in \"%s\"", prog_pathname);
765 g_free(prog_pathname);
766 return retstr;
767 }
768 #endif
769 }
770
771 /*
772 * Get the directory in which the program resides.
773 */
774 const char *
get_progfile_dir(void)775 get_progfile_dir(void)
776 {
777 return progfile_dir;
778 }
779
780 /*
781 * Get the directory in which the global configuration and data files are
782 * stored.
783 *
784 * On Windows, we use the directory in which the executable for this
785 * process resides.
786 *
787 * On macOS (when executed from an app bundle), use a directory within
788 * that app bundle.
789 *
790 * Otherwise, if the program was executed from the build directory, use the
791 * directory in which the executable for this process resides. In all other
792 * cases, use the DATA_DIR value that was set at compile time.
793 *
794 * XXX - if we ever make libwireshark a real library, used by multiple
795 * applications (more than just TShark and versions of Wireshark with
796 * various UIs), should the configuration files belong to the library
797 * (and be shared by all those applications) or to the applications?
798 *
799 * If they belong to the library, that could be done on UNIX by the
800 * configure script, but it's trickier on Windows, as you can't just
801 * use the pathname of the executable.
802 *
803 * If they belong to the application, that could be done on Windows
804 * by using the pathname of the executable, but we'd have to have it
805 * passed in as an argument, in some call, on UNIX.
806 *
807 * Note that some of those configuration files might be used by code in
808 * libwireshark, some of them might be used by dissectors (would they
809 * belong to libwireshark, the application, or a separate library?),
810 * and some of them might be used by other code (the Wireshark preferences
811 * file includes resolver preferences that control the behavior of code
812 * in libwireshark, dissector preferences, and UI preferences, for
813 * example).
814 */
815 const char *
get_datafile_dir(void)816 get_datafile_dir(void)
817 {
818 if (datafile_dir != NULL)
819 return datafile_dir;
820
821 #ifdef _WIN32
822 /*
823 * Do we have the pathname of the program? If so, assume we're
824 * running an installed version of the program. If we fail,
825 * we don't change "datafile_dir", and thus end up using the
826 * default.
827 *
828 * XXX - does NSIS put the installation directory into
829 * "\HKEY_LOCAL_MACHINE\SOFTWARE\Wireshark\InstallDir"?
830 * If so, perhaps we should read that from the registry,
831 * instead.
832 */
833 if (progfile_dir != NULL) {
834 /*
835 * Yes, we do; use that.
836 */
837 datafile_dir = g_strdup(progfile_dir);
838 } else {
839 /*
840 * No, we don't.
841 * Fall back on the default installation directory.
842 */
843 datafile_dir = g_strdup("C:\\Program Files\\Wireshark\\");
844 }
845 #else
846
847 if (g_getenv("WIRESHARK_DATA_DIR") && !started_with_special_privs()) {
848 /*
849 * The user specified a different directory for data files
850 * and we aren't running with special privileges.
851 * XXX - We might be able to dispense with the priv check
852 */
853 datafile_dir = g_strdup(g_getenv("WIRESHARK_DATA_DIR"));
854 }
855 #ifdef __APPLE__
856 /*
857 * If we're running from an app bundle and weren't started
858 * with special privileges, use the Contents/Resources/share/wireshark
859 * subdirectory of the app bundle.
860 *
861 * (appbundle_dir is not set to a non-null value if we're
862 * started with special privileges, so we need only check
863 * it; we don't need to call started_with_special_privs().)
864 */
865 else if (appbundle_dir != NULL) {
866 datafile_dir = g_strdup_printf("%s/Contents/Resources/share/wireshark",
867 appbundle_dir);
868 }
869 #endif
870 else if (running_in_build_directory_flag && progfile_dir != NULL) {
871 /*
872 * We're (probably) being run from the build directory and
873 * weren't started with special privileges.
874 *
875 * (running_in_build_directory_flag is never set to TRUE
876 * if we're started with special privileges, so we need
877 * only check it; we don't need to call started_with_special_privs().)
878 *
879 * Data files (console.lua, radius/, etc.) are copied to the build
880 * directory during the build which also contains executables. A special
881 * exception is macOS (when built with an app bundle).
882 */
883 datafile_dir = g_strdup(progfile_dir);
884 } else {
885 datafile_dir = g_strdup(DATA_DIR);
886 }
887
888 #endif
889 return datafile_dir;
890 }
891
892 /*
893 * Find the directory where the plugins are stored.
894 *
895 * On Windows, we use the plugin\{VERSION} subdirectory of the datafile
896 * directory, where {VERSION} is the version number of this version of
897 * Wireshark.
898 *
899 * On UN*X:
900 *
901 * if we appear to be run from the build directory, we use the
902 * "plugin" subdirectory of the datafile directory;
903 *
904 * otherwise, if the WIRESHARK_PLUGIN_DIR environment variable is
905 * set and we aren't running with special privileges, we use the
906 * value of that environment variable;
907 *
908 * otherwise, if we're running from an app bundle in macOS, we
909 * use the Contents/PlugIns/wireshark subdirectory of the app bundle;
910 *
911 * otherwise, we use the PLUGIN_DIR value supplied by the
912 * configure script.
913 */
914 static char *plugin_dir = NULL;
915 static char *plugin_dir_with_version = NULL;
916 static char *plugin_pers_dir = NULL;
917 static char *plugin_pers_dir_with_version = NULL;
918
919 static void
init_plugin_dir(void)920 init_plugin_dir(void)
921 {
922 #if defined(HAVE_PLUGINS) || defined(HAVE_LUA)
923 #ifdef _WIN32
924 /*
925 * On Windows, the data file directory is the installation
926 * directory; the plugins are stored under it.
927 *
928 * Assume we're running the installed version of Wireshark;
929 * on Windows, the data file directory is the directory
930 * in which the Wireshark binary resides.
931 */
932 plugin_dir = g_build_filename(get_datafile_dir(), "plugins", (gchar *)NULL);
933
934 /*
935 * Make sure that pathname refers to a directory.
936 */
937 if (test_for_directory(plugin_dir) != EISDIR) {
938 /*
939 * Either it doesn't refer to a directory or it
940 * refers to something that doesn't exist.
941 *
942 * Assume that means we're running a version of
943 * Wireshark we've built in a build directory,
944 * in which case {datafile dir}\plugins is the
945 * top-level plugins source directory, and use
946 * that directory and set the "we're running in
947 * a build directory" flag, so the plugin
948 * scanner will check all subdirectories of that
949 * directory for plugins.
950 */
951 g_free(plugin_dir);
952 plugin_dir = g_build_filename(get_datafile_dir(), "plugins", (gchar *)NULL);
953 running_in_build_directory_flag = TRUE;
954 }
955 #else
956 if (running_in_build_directory_flag) {
957 /*
958 * We're (probably) being run from the build directory and
959 * weren't started with special privileges, so we'll use
960 * the "plugins" subdirectory of the directory where the program
961 * we're running is (that's the build directory).
962 */
963 plugin_dir = g_build_filename(get_progfile_dir(), "plugins", (gchar *)NULL);
964 } else {
965 if (g_getenv("WIRESHARK_PLUGIN_DIR") && !started_with_special_privs()) {
966 /*
967 * The user specified a different directory for plugins
968 * and we aren't running with special privileges.
969 */
970 plugin_dir = g_strdup(g_getenv("WIRESHARK_PLUGIN_DIR"));
971 }
972 #ifdef __APPLE__
973 /*
974 * If we're running from an app bundle and weren't started
975 * with special privileges, use the Contents/PlugIns/wireshark
976 * subdirectory of the app bundle.
977 *
978 * (appbundle_dir is not set to a non-null value if we're
979 * started with special privileges, so we need only check
980 * it; we don't need to call started_with_special_privs().)
981 */
982 else if (appbundle_dir != NULL) {
983 plugin_dir = g_build_filename(appbundle_dir, "Contents/PlugIns/wireshark", (gchar *)NULL);
984 }
985 #endif
986 else {
987 plugin_dir = g_strdup(PLUGIN_DIR);
988 }
989 }
990 #endif
991 #endif /* defined(HAVE_PLUGINS) || defined(HAVE_LUA) */
992 }
993
994 static void
init_plugin_pers_dir(void)995 init_plugin_pers_dir(void)
996 {
997 #if defined(HAVE_PLUGINS) || defined(HAVE_LUA)
998 #ifdef _WIN32
999 plugin_pers_dir = get_persconffile_path(PLUGINS_DIR_NAME, FALSE);
1000 #else
1001 plugin_pers_dir = g_build_filename(g_get_home_dir(), ".local/lib/wireshark/" PLUGINS_DIR_NAME, (gchar *)NULL);
1002 #endif
1003 #endif /* defined(HAVE_PLUGINS) || defined(HAVE_LUA) */
1004 }
1005
1006 /*
1007 * Get the directory in which the plugins are stored.
1008 */
1009 const char *
get_plugins_dir(void)1010 get_plugins_dir(void)
1011 {
1012 if (!plugin_dir)
1013 init_plugin_dir();
1014 return plugin_dir;
1015 }
1016
1017 const char *
get_plugins_dir_with_version(void)1018 get_plugins_dir_with_version(void)
1019 {
1020 if (!plugin_dir)
1021 init_plugin_dir();
1022 if (plugin_dir && !plugin_dir_with_version)
1023 plugin_dir_with_version = g_build_filename(plugin_dir, PLUGIN_PATH_ID, (gchar *)NULL);
1024 return plugin_dir_with_version;
1025 }
1026
1027 /* Get the personal plugin dir */
1028 const char *
get_plugins_pers_dir(void)1029 get_plugins_pers_dir(void)
1030 {
1031 if (!plugin_pers_dir)
1032 init_plugin_pers_dir();
1033 return plugin_pers_dir;
1034 }
1035
1036 const char *
get_plugins_pers_dir_with_version(void)1037 get_plugins_pers_dir_with_version(void)
1038 {
1039 if (!plugin_pers_dir)
1040 init_plugin_pers_dir();
1041 if (plugin_pers_dir && !plugin_pers_dir_with_version)
1042 plugin_pers_dir_with_version = g_build_filename(plugin_pers_dir, PLUGIN_PATH_ID, (gchar *)NULL);
1043 return plugin_pers_dir_with_version;
1044 }
1045
1046 /*
1047 * Find the directory where the extcap hooks are stored.
1048 *
1049 * If the WIRESHARK_EXTCAP_DIR environment variable is set and we are not
1050 * running with special privileges, use that. Otherwise:
1051 *
1052 * On Windows, we use the "extcap" subdirectory of the datafile directory.
1053 *
1054 * On UN*X:
1055 *
1056 * if we appear to be run from the build directory, we use the
1057 * "extcap" subdirectory of the build directory.
1058 *
1059 * otherwise, if we're running from an app bundle in macOS, we
1060 * use the Contents/MacOS/extcap subdirectory of the app bundle;
1061 *
1062 * otherwise, we use the EXTCAP_DIR value supplied by CMake.
1063 */
1064 static char *extcap_dir = NULL;
1065
init_extcap_dir(void)1066 static void init_extcap_dir(void) {
1067 if (g_getenv("WIRESHARK_EXTCAP_DIR") && !started_with_special_privs()) {
1068 /*
1069 * The user specified a different directory for extcap hooks
1070 * and we aren't running with special privileges.
1071 */
1072 extcap_dir = g_strdup(g_getenv("WIRESHARK_EXTCAP_DIR"));
1073 }
1074 #ifdef _WIN32
1075 else {
1076 /*
1077 * On Windows, the data file directory is the installation
1078 * directory; the extcap hooks are stored under it.
1079 *
1080 * Assume we're running the installed version of Wireshark;
1081 * on Windows, the data file directory is the directory
1082 * in which the Wireshark binary resides.
1083 */
1084 extcap_dir = g_build_filename(get_datafile_dir(), "extcap", (gchar *)NULL);
1085 }
1086 #else
1087 else if (running_in_build_directory_flag) {
1088 /*
1089 * We're (probably) being run from the build directory and
1090 * weren't started with special privileges, so we'll use
1091 * the "extcap hooks" subdirectory of the directory where the program
1092 * we're running is (that's the build directory).
1093 */
1094 extcap_dir = g_build_filename(get_progfile_dir(), "extcap", (gchar *)NULL);
1095 }
1096 #ifdef __APPLE__
1097 else if (appbundle_dir != NULL) {
1098 /*
1099 * If we're running from an app bundle and weren't started
1100 * with special privileges, use the Contents/MacOS/extcap
1101 * subdirectory of the app bundle.
1102 *
1103 * (appbundle_dir is not set to a non-null value if we're
1104 * started with special privileges, so we need only check
1105 * it; we don't need to call started_with_special_privs().)
1106 */
1107 extcap_dir = g_build_filename(appbundle_dir, "Contents/MacOS/extcap", (gchar *)NULL);
1108 }
1109 #endif
1110 else {
1111 extcap_dir = g_strdup(EXTCAP_DIR);
1112 }
1113 #endif
1114 }
1115
1116 /*
1117 * Get the directory in which the extcap hooks are stored.
1118 *
1119 */
1120 const char *
get_extcap_dir(void)1121 get_extcap_dir(void)
1122 {
1123 if (!extcap_dir)
1124 init_extcap_dir();
1125 return extcap_dir;
1126 }
1127
1128 /*
1129 * Get the flag indicating whether we're running from a build
1130 * directory.
1131 */
1132 gboolean
running_in_build_directory(void)1133 running_in_build_directory(void)
1134 {
1135 return running_in_build_directory_flag;
1136 }
1137
1138 /*
1139 * Get the directory in which files that, at least on UNIX, are
1140 * system files (such as "/etc/ethers") are stored; on Windows,
1141 * there's no "/etc" directory, so we get them from the global
1142 * configuration and data file directory.
1143 */
1144 const char *
get_systemfile_dir(void)1145 get_systemfile_dir(void)
1146 {
1147 #ifdef _WIN32
1148 return get_datafile_dir();
1149 #else
1150 return "/etc";
1151 #endif
1152 }
1153
1154 void
set_profile_name(const gchar * profilename)1155 set_profile_name(const gchar *profilename)
1156 {
1157 g_free (persconfprofile);
1158
1159 if (profilename && strlen(profilename) > 0 &&
1160 strcmp(profilename, DEFAULT_PROFILE) != 0) {
1161 persconfprofile = g_strdup (profilename);
1162 } else {
1163 /* Default Profile */
1164 persconfprofile = NULL;
1165 }
1166 }
1167
1168 const char *
get_profile_name(void)1169 get_profile_name(void)
1170 {
1171 if (persconfprofile) {
1172 return persconfprofile;
1173 } else {
1174 return DEFAULT_PROFILE;
1175 }
1176 }
1177
1178 gboolean
is_default_profile(void)1179 is_default_profile(void)
1180 {
1181 return (!persconfprofile || strcmp(persconfprofile, DEFAULT_PROFILE) == 0) ? TRUE : FALSE;
1182 }
1183
1184 gboolean
has_global_profiles(void)1185 has_global_profiles(void)
1186 {
1187 WS_DIR *dir;
1188 WS_DIRENT *file;
1189 gchar *global_dir = get_global_profiles_dir();
1190 gchar *filename;
1191 gboolean has_global = FALSE;
1192
1193 if ((test_for_directory(global_dir) == EISDIR) &&
1194 ((dir = ws_dir_open(global_dir, 0, NULL)) != NULL))
1195 {
1196 while ((file = ws_dir_read_name(dir)) != NULL) {
1197 filename = g_strdup_printf ("%s%s%s", global_dir, G_DIR_SEPARATOR_S,
1198 ws_dir_get_name(file));
1199 if (test_for_directory(filename) == EISDIR) {
1200 has_global = TRUE;
1201 g_free (filename);
1202 break;
1203 }
1204 g_free (filename);
1205 }
1206 ws_dir_close(dir);
1207 }
1208 g_free(global_dir);
1209 return has_global;
1210 }
1211
1212 void
profile_store_persconffiles(gboolean store)1213 profile_store_persconffiles(gboolean store)
1214 {
1215 if (store) {
1216 profile_files = g_hash_table_new (g_str_hash, g_str_equal);
1217 }
1218 do_store_persconffiles = store;
1219 }
1220
1221 void
profile_register_persconffile(const char * filename)1222 profile_register_persconffile(const char *filename)
1223 {
1224 if (do_store_persconffiles && !g_hash_table_lookup (profile_files, filename)) {
1225 /* Store filenames so we know which filenames belongs to a configuration profile */
1226 g_hash_table_insert (profile_files, g_strdup(filename), g_strdup(filename));
1227 }
1228 }
1229
1230 /*
1231 * Get the directory in which personal configuration files reside.
1232 *
1233 * On Windows, it's "Wireshark", under %APPDATA% or, if %APPDATA% isn't set,
1234 * it's "%USERPROFILE%\Application Data" (which is what %APPDATA% normally
1235 * is on Windows 2000).
1236 *
1237 * On UNIX-compatible systems, we first look in XDG_CONFIG_HOME/wireshark
1238 * and, if that doesn't exist, ~/.wireshark, for backwards compatibility.
1239 * If neither exists, we use XDG_CONFIG_HOME/wireshark, so that the directory
1240 * is initially created as XDG_CONFIG_HOME/wireshark. We use that regardless
1241 * of whether the user is running under an XDG desktop or not, so that
1242 * if the user's home directory is on a server and shared between
1243 * different desktop environments on different machines, they can all
1244 * share the same configuration file directory.
1245 *
1246 * XXX - what about stuff that shouldn't be shared between machines,
1247 * such as plugins in the form of shared loadable images?
1248 */
1249 static const char *
get_persconffile_dir_no_profile(void)1250 get_persconffile_dir_no_profile(void)
1251 {
1252 const char *env;
1253
1254 /* Return the cached value, if available */
1255 if (persconffile_dir != NULL)
1256 return persconffile_dir;
1257
1258 /*
1259 * See if the user has selected an alternate environment.
1260 */
1261 env = g_getenv(ENV_CONFIG_PATH_VAR);
1262 #ifdef _WIN32
1263 if (env == NULL) {
1264 /* for backward compatibility */
1265 env = g_getenv("WIRESHARK_APPDATA");
1266 }
1267 #endif
1268 if (env != NULL) {
1269 persconffile_dir = g_strdup(env);
1270 return persconffile_dir;
1271 }
1272
1273 #ifdef _WIN32
1274 /*
1275 * Use %APPDATA% or %USERPROFILE%, so that configuration
1276 * files are stored in the user profile, rather than in
1277 * the home directory. The Windows convention is to store
1278 * configuration information in the user profile, and doing
1279 * so means you can use Wireshark even if the home directory
1280 * is an inaccessible network drive.
1281 */
1282 env = g_getenv("APPDATA");
1283 if (env != NULL) {
1284 /*
1285 * Concatenate %APPDATA% with "\Wireshark".
1286 */
1287 persconffile_dir = g_build_filename(env, "Wireshark", NULL);
1288 return persconffile_dir;
1289 }
1290
1291 /*
1292 * OK, %APPDATA% wasn't set, so use %USERPROFILE%\Application Data.
1293 */
1294 env = g_getenv("USERPROFILE");
1295 if (env != NULL) {
1296 persconffile_dir = g_build_filename(env, "Application Data", "Wireshark", NULL);
1297 return persconffile_dir;
1298 }
1299
1300 /*
1301 * Give up and use "C:".
1302 */
1303 persconffile_dir = g_build_filename("C:", "Wireshark", NULL);
1304 return persconffile_dir;
1305 #else
1306 char *xdg_path, *path;
1307 struct passwd *pwd;
1308 const char *homedir;
1309
1310 /*
1311 * Check if XDG_CONFIG_HOME/wireshark exists and is a directory.
1312 */
1313 xdg_path = g_build_filename(g_get_user_config_dir(), "wireshark", NULL);
1314 if (g_file_test(xdg_path, G_FILE_TEST_IS_DIR)) {
1315 persconffile_dir = xdg_path;
1316 return persconffile_dir;
1317 }
1318
1319 /*
1320 * It doesn't exist, or it does but isn't a directory, so try
1321 * ~/.wireshark.
1322 *
1323 * If $HOME is set, use that for ~.
1324 *
1325 * (Note: before GLib 2.36, g_get_home_dir() didn't look at $HOME,
1326 * but we always want to do so, so we don't use g_get_home_dir().)
1327 */
1328 homedir = g_getenv("HOME");
1329 if (homedir == NULL) {
1330 /*
1331 * It's not set.
1332 *
1333 * Get their home directory from the password file.
1334 * If we can't even find a password file entry for them,
1335 * use "/tmp".
1336 */
1337 pwd = getpwuid(getuid());
1338 if (pwd != NULL) {
1339 homedir = pwd->pw_dir;
1340 } else {
1341 homedir = "/tmp";
1342 }
1343 }
1344 path = g_build_filename(homedir, ".wireshark", NULL);
1345 if (g_file_test(path, G_FILE_TEST_IS_DIR)) {
1346 g_free(xdg_path);
1347 persconffile_dir = path;
1348 return persconffile_dir;
1349 }
1350
1351 /*
1352 * Neither are directories that exist; use the XDG path, so we'll
1353 * create that as necessary.
1354 */
1355 g_free(path);
1356 persconffile_dir = xdg_path;
1357 return persconffile_dir;
1358 #endif
1359 }
1360
1361 void
set_persconffile_dir(const char * p)1362 set_persconffile_dir(const char *p)
1363 {
1364 g_free(persconffile_dir);
1365 persconffile_dir = g_strdup(p);
1366 }
1367
1368 char *
get_profiles_dir(void)1369 get_profiles_dir(void)
1370 {
1371 return g_strdup_printf ("%s%s%s", get_persconffile_dir_no_profile (),
1372 G_DIR_SEPARATOR_S, PROFILES_DIR);
1373 }
1374
1375 int
create_profiles_dir(char ** pf_dir_path_return)1376 create_profiles_dir(char **pf_dir_path_return)
1377 {
1378 char *pf_dir_path;
1379 ws_statb64 s_buf;
1380
1381 /*
1382 * Create the "Default" personal configuration files directory, if necessary.
1383 */
1384 if (create_persconffile_profile (NULL, pf_dir_path_return) == -1) {
1385 return -1;
1386 }
1387
1388 /*
1389 * Check if profiles directory exists.
1390 * If not then create it.
1391 */
1392 pf_dir_path = get_profiles_dir ();
1393 if (ws_stat64(pf_dir_path, &s_buf) != 0) {
1394 if (errno != ENOENT) {
1395 /* Some other problem; give up now. */
1396 *pf_dir_path_return = pf_dir_path;
1397 return -1;
1398 }
1399
1400 /*
1401 * It doesn't exist; try to create it.
1402 */
1403 int ret = ws_mkdir(pf_dir_path, 0755);
1404 if (ret == -1) {
1405 *pf_dir_path_return = pf_dir_path;
1406 return ret;
1407 }
1408 }
1409 g_free(pf_dir_path);
1410
1411 return 0;
1412 }
1413
1414 char *
get_global_profiles_dir(void)1415 get_global_profiles_dir(void)
1416 {
1417 return g_strdup_printf ("%s%s%s", get_datafile_dir(),
1418 G_DIR_SEPARATOR_S, PROFILES_DIR);
1419 }
1420
1421 static char *
get_persconffile_dir(const gchar * profilename)1422 get_persconffile_dir(const gchar *profilename)
1423 {
1424 char *persconffile_profile_dir = NULL, *profile_dir;
1425
1426 if (profilename && strlen(profilename) > 0 &&
1427 strcmp(profilename, DEFAULT_PROFILE) != 0) {
1428 profile_dir = get_profiles_dir();
1429 persconffile_profile_dir = g_strdup_printf ("%s%s%s", profile_dir,
1430 G_DIR_SEPARATOR_S, profilename);
1431 g_free(profile_dir);
1432 } else {
1433 persconffile_profile_dir = g_strdup (get_persconffile_dir_no_profile ());
1434 }
1435
1436 return persconffile_profile_dir;
1437 }
1438
1439 char *
get_profile_dir(const char * profilename,gboolean is_global)1440 get_profile_dir(const char *profilename, gboolean is_global)
1441 {
1442 gchar *profile_dir;
1443
1444 if (is_global) {
1445 if (profilename && strlen(profilename) > 0 &&
1446 strcmp(profilename, DEFAULT_PROFILE) != 0)
1447 {
1448 gchar *global_path = get_global_profiles_dir();
1449 profile_dir = g_build_filename(global_path, profilename, NULL);
1450 g_free(global_path);
1451 } else {
1452 profile_dir = g_strdup(get_datafile_dir());
1453 }
1454 } else {
1455 /*
1456 * If we didn't supply a profile name, i.e. if profilename is
1457 * null, get_persconffile_dir() returns the default profile.
1458 */
1459 profile_dir = get_persconffile_dir(profilename);
1460 }
1461
1462 return profile_dir;
1463 }
1464
1465 gboolean
profile_exists(const gchar * profilename,gboolean global)1466 profile_exists(const gchar *profilename, gboolean global)
1467 {
1468 gchar *path = NULL;
1469 gboolean exists;
1470
1471 /*
1472 * If we're looking up a global profile, we must have a
1473 * profile name.
1474 */
1475 if (global && !profilename)
1476 return FALSE;
1477
1478 path = get_profile_dir(profilename, global);
1479 exists = (test_for_directory(path) == EISDIR) ? TRUE : FALSE;
1480
1481 g_free(path);
1482 return exists;
1483 }
1484
1485 static int
delete_directory(const char * directory,char ** pf_dir_path_return)1486 delete_directory (const char *directory, char **pf_dir_path_return)
1487 {
1488 WS_DIR *dir;
1489 WS_DIRENT *file;
1490 gchar *filename;
1491 int ret = 0;
1492
1493 if ((dir = ws_dir_open(directory, 0, NULL)) != NULL) {
1494 while ((file = ws_dir_read_name(dir)) != NULL) {
1495 filename = g_strdup_printf ("%s%s%s", directory, G_DIR_SEPARATOR_S,
1496 ws_dir_get_name(file));
1497 if (test_for_directory(filename) != EISDIR) {
1498 ret = ws_remove(filename);
1499 #if 0
1500 } else {
1501 /* The user has manually created a directory in the profile directory */
1502 /* I do not want to delete the directory recursively yet */
1503 ret = delete_directory (filename, pf_dir_path_return);
1504 #endif
1505 }
1506 if (ret != 0) {
1507 *pf_dir_path_return = filename;
1508 break;
1509 }
1510 g_free (filename);
1511 }
1512 ws_dir_close(dir);
1513 }
1514
1515 if (ret == 0 && (ret = ws_remove(directory)) != 0) {
1516 *pf_dir_path_return = g_strdup (directory);
1517 }
1518
1519 return ret;
1520 }
1521
1522 static int
reset_default_profile(char ** pf_dir_path_return)1523 reset_default_profile(char **pf_dir_path_return)
1524 {
1525 char *profile_dir = get_persconffile_dir(NULL);
1526 gchar *filename, *del_file;
1527 GList *files, *file;
1528 int ret = 0;
1529
1530 files = g_hash_table_get_keys(profile_files);
1531 file = g_list_first(files);
1532 while (file) {
1533 filename = (gchar *)file->data;
1534 del_file = g_strdup_printf("%s%s%s", profile_dir, G_DIR_SEPARATOR_S, filename);
1535
1536 if (file_exists(del_file)) {
1537 ret = ws_remove(del_file);
1538 if (ret != 0) {
1539 *pf_dir_path_return = profile_dir;
1540 g_free(del_file);
1541 break;
1542 }
1543 }
1544
1545 g_free(del_file);
1546 file = g_list_next(file);
1547 }
1548 g_list_free(files);
1549
1550 g_free(profile_dir);
1551 return ret;
1552 }
1553
1554 int
delete_persconffile_profile(const char * profilename,char ** pf_dir_path_return)1555 delete_persconffile_profile(const char *profilename, char **pf_dir_path_return)
1556 {
1557 if (strcmp(profilename, DEFAULT_PROFILE) == 0) {
1558 return reset_default_profile(pf_dir_path_return);
1559 }
1560
1561 char *profile_dir = get_persconffile_dir(profilename);
1562 int ret = 0;
1563
1564 if (test_for_directory (profile_dir) == EISDIR) {
1565 ret = delete_directory (profile_dir, pf_dir_path_return);
1566 }
1567
1568 g_free(profile_dir);
1569 return ret;
1570 }
1571
1572 int
rename_persconffile_profile(const char * fromname,const char * toname,char ** pf_from_dir_path_return,char ** pf_to_dir_path_return)1573 rename_persconffile_profile(const char *fromname, const char *toname,
1574 char **pf_from_dir_path_return, char **pf_to_dir_path_return)
1575 {
1576 char *from_dir = get_persconffile_dir(fromname);
1577 char *to_dir = get_persconffile_dir(toname);
1578 int ret = 0;
1579
1580 ret = ws_rename (from_dir, to_dir);
1581 if (ret != 0) {
1582 *pf_from_dir_path_return = from_dir;
1583 *pf_to_dir_path_return = to_dir;
1584 return ret;
1585 }
1586
1587 g_free (from_dir);
1588 g_free (to_dir);
1589
1590 return 0;
1591 }
1592
1593 /*
1594 * Create the directory that holds personal configuration files, if
1595 * necessary. If we attempted to create it, and failed, return -1 and
1596 * set "*pf_dir_path_return" to the pathname of the directory we failed
1597 * to create (it's g_mallocated, so our caller should free it); otherwise,
1598 * return 0.
1599 */
1600 int
create_persconffile_profile(const char * profilename,char ** pf_dir_path_return)1601 create_persconffile_profile(const char *profilename, char **pf_dir_path_return)
1602 {
1603 char *pf_dir_path;
1604 #ifdef _WIN32
1605 char *pf_dir_path_copy, *pf_dir_parent_path;
1606 size_t pf_dir_parent_path_len;
1607 int save_errno;
1608 #endif
1609 ws_statb64 s_buf;
1610 int ret;
1611
1612 if (profilename) {
1613 /*
1614 * Create the personal profiles directory, if necessary.
1615 */
1616 if (create_profiles_dir(pf_dir_path_return) == -1) {
1617 return -1;
1618 }
1619 }
1620
1621 pf_dir_path = get_persconffile_dir(profilename);
1622 if (ws_stat64(pf_dir_path, &s_buf) != 0) {
1623 if (errno != ENOENT) {
1624 /* Some other problem; give up now. */
1625 *pf_dir_path_return = pf_dir_path;
1626 return -1;
1627 }
1628 #ifdef _WIN32
1629 /*
1630 * Does the parent directory of that directory
1631 * exist? %APPDATA% may not exist even though
1632 * %USERPROFILE% does.
1633 *
1634 * We check for the existence of the directory
1635 * by first checking whether the parent directory
1636 * is just a drive letter and, if it's not, by
1637 * doing a "stat()" on it. If it's a drive letter,
1638 * or if the "stat()" succeeds, we assume it exists.
1639 */
1640 pf_dir_path_copy = g_strdup(pf_dir_path);
1641 pf_dir_parent_path = get_dirname(pf_dir_path_copy);
1642 pf_dir_parent_path_len = strlen(pf_dir_parent_path);
1643 if (pf_dir_parent_path_len > 0
1644 && pf_dir_parent_path[pf_dir_parent_path_len - 1] != ':'
1645 && ws_stat64(pf_dir_parent_path, &s_buf) != 0) {
1646 /*
1647 * Not a drive letter and the stat() failed.
1648 */
1649 if (errno != ENOENT) {
1650 /* Some other problem; give up now. */
1651 *pf_dir_path_return = pf_dir_path;
1652 save_errno = errno;
1653 g_free(pf_dir_path_copy);
1654 errno = save_errno;
1655 return -1;
1656 }
1657 /*
1658 * No, it doesn't exist - make it first.
1659 */
1660 ret = ws_mkdir(pf_dir_parent_path, 0755);
1661 if (ret == -1) {
1662 *pf_dir_path_return = pf_dir_parent_path;
1663 save_errno = errno;
1664 g_free(pf_dir_path);
1665 errno = save_errno;
1666 return -1;
1667 }
1668 }
1669 g_free(pf_dir_path_copy);
1670 ret = ws_mkdir(pf_dir_path, 0755);
1671 #else
1672 ret = g_mkdir_with_parents(pf_dir_path, 0755);
1673 #endif
1674 } else {
1675 /*
1676 * Something with that pathname exists; if it's not
1677 * a directory, we'll get an error if we try to put
1678 * something in it, so we don't fail here, we wait
1679 * for that attempt to fail.
1680 */
1681 ret = 0;
1682 }
1683 if (ret == -1)
1684 *pf_dir_path_return = pf_dir_path;
1685 else
1686 g_free(pf_dir_path);
1687
1688 return ret;
1689 }
1690
1691 const GHashTable *
allowed_profile_filenames(void)1692 allowed_profile_filenames(void)
1693 {
1694 return profile_files;
1695 }
1696
1697 int
create_persconffile_dir(char ** pf_dir_path_return)1698 create_persconffile_dir(char **pf_dir_path_return)
1699 {
1700 return create_persconffile_profile(persconfprofile, pf_dir_path_return);
1701 }
1702
1703 int
copy_persconffile_profile(const char * toname,const char * fromname,gboolean from_global,char ** pf_filename_return,char ** pf_to_dir_path_return,char ** pf_from_dir_path_return)1704 copy_persconffile_profile(const char *toname, const char *fromname, gboolean from_global,
1705 char **pf_filename_return, char **pf_to_dir_path_return, char **pf_from_dir_path_return)
1706 {
1707 int ret = 0;
1708 gchar *from_dir;
1709 gchar *to_dir = get_persconffile_dir(toname);
1710 gchar *filename, *from_file, *to_file;
1711 GList *files, *file;
1712
1713 from_dir = get_profile_dir(fromname, from_global);
1714
1715 files = g_hash_table_get_keys(profile_files);
1716 file = g_list_first(files);
1717 while (file) {
1718 filename = (gchar *)file->data;
1719 from_file = g_strdup_printf ("%s%s%s", from_dir, G_DIR_SEPARATOR_S, filename);
1720 to_file = g_strdup_printf ("%s%s%s", to_dir, G_DIR_SEPARATOR_S, filename);
1721
1722 if (file_exists(from_file) && !copy_file_binary_mode(from_file, to_file)) {
1723 *pf_filename_return = g_strdup(filename);
1724 *pf_to_dir_path_return = to_dir;
1725 *pf_from_dir_path_return = from_dir;
1726 g_free (from_file);
1727 g_free (to_file);
1728 ret = -1;
1729 break;
1730 }
1731
1732 g_free (from_file);
1733 g_free (to_file);
1734
1735 file = g_list_next(file);
1736 }
1737
1738 g_list_free (files);
1739 g_free (from_dir);
1740 g_free (to_dir);
1741
1742 return ret;
1743 }
1744
1745 /*
1746 * Get the (default) directory in which personal data is stored.
1747 *
1748 * On Win32, this is the "My Documents" folder in the personal profile.
1749 * On UNIX this is simply the current directory.
1750 */
1751 /* XXX - should this and the get_home_dir() be merged? */
1752 extern const char *
get_persdatafile_dir(void)1753 get_persdatafile_dir(void)
1754 {
1755 #ifdef _WIN32
1756 TCHAR tszPath[MAX_PATH];
1757
1758 /* Return the cached value, if available */
1759 if (persdatafile_dir != NULL)
1760 return persdatafile_dir;
1761
1762 /*
1763 * Hint: SHGetFolderPath is not available on MSVC 6 - without
1764 * Platform SDK
1765 */
1766 if (SHGetSpecialFolderPath(NULL, tszPath, CSIDL_PERSONAL, FALSE)) {
1767 persdatafile_dir = g_utf16_to_utf8(tszPath, -1, NULL, NULL, NULL);
1768 return persdatafile_dir;
1769 } else {
1770 return "";
1771 }
1772 #else
1773 return "";
1774 #endif
1775 }
1776
1777 void
set_persdatafile_dir(const char * p)1778 set_persdatafile_dir(const char *p)
1779 {
1780 g_free(persdatafile_dir);
1781 persdatafile_dir = g_strdup(p);
1782 }
1783
1784 #ifdef _WIN32
1785 /*
1786 * Returns the user's home directory on Win32.
1787 */
1788 static const char *
get_home_dir(void)1789 get_home_dir(void)
1790 {
1791 static const char *home = NULL;
1792 const char *homedrive, *homepath;
1793 char *homestring;
1794 char *lastsep;
1795
1796 /* Return the cached value, if available */
1797 if (home)
1798 return home;
1799
1800 /*
1801 * XXX - should we use USERPROFILE anywhere in this process?
1802 * Is there a chance that it might be set but one or more of
1803 * HOMEDRIVE or HOMEPATH isn't set?
1804 */
1805 homedrive = g_getenv("HOMEDRIVE");
1806 if (homedrive != NULL) {
1807 homepath = g_getenv("HOMEPATH");
1808 if (homepath != NULL) {
1809 /*
1810 * This is cached, so we don't need to worry about
1811 * allocating multiple ones of them.
1812 */
1813 homestring = g_strdup_printf("%s%s", homedrive, homepath);
1814
1815 /*
1816 * Trim off any trailing slash or backslash.
1817 */
1818 lastsep = find_last_pathname_separator(homestring);
1819 if (lastsep != NULL && *(lastsep + 1) == '\0') {
1820 /*
1821 * Last separator is the last character
1822 * in the string. Nuke it.
1823 */
1824 *lastsep = '\0';
1825 }
1826 home = homestring;
1827 } else
1828 home = homedrive;
1829 } else {
1830 /*
1831 * Give up and use C:.
1832 */
1833 home = "C:";
1834 }
1835
1836 return home;
1837 }
1838 #endif
1839
1840 /*
1841 * Construct the path name of a personal configuration file, given the
1842 * file name.
1843 *
1844 * On Win32, if "for_writing" is FALSE, we check whether the file exists
1845 * and, if not, construct a path name relative to the ".wireshark"
1846 * subdirectory of the user's home directory, and check whether that
1847 * exists; if it does, we return that, so that configuration files
1848 * from earlier versions can be read.
1849 *
1850 * The returned file name was g_malloc()'d so it must be g_free()d when the
1851 * caller is done with it.
1852 */
1853 char *
get_persconffile_path(const char * filename,gboolean from_profile)1854 get_persconffile_path(const char *filename, gboolean from_profile)
1855 {
1856 char *path, *dir = NULL;
1857
1858 if (from_profile) {
1859 /* Store filenames so we know which filenames belongs to a configuration profile */
1860 profile_register_persconffile(filename);
1861
1862 dir = get_persconffile_dir(persconfprofile);
1863 } else {
1864 dir = get_persconffile_dir(NULL);
1865 }
1866 path = g_build_filename(dir, filename, NULL);
1867
1868 g_free(dir);
1869 return path;
1870 }
1871
1872 /*
1873 * Construct the path name of a global configuration file, given the
1874 * file name.
1875 *
1876 * The returned file name was g_malloc()'d so it must be g_free()d when the
1877 * caller is done with it.
1878 */
1879 char *
get_datafile_path(const char * filename)1880 get_datafile_path(const char *filename)
1881 {
1882 if (running_in_build_directory_flag &&
1883 (!strcmp(filename, "AUTHORS-SHORT") ||
1884 !strcmp(filename, "hosts"))) {
1885 /* We're running in the build directory and the requested file is a
1886 * generated (or a test) file. Return the file name in the build
1887 * directory (not in the source/data directory).
1888 * (Oh the things we do to keep the source directory pristine...)
1889 */
1890 return g_build_filename(get_progfile_dir(), filename, (char *)NULL);
1891 } else {
1892 return g_build_filename(get_datafile_dir(), filename, (char *)NULL);
1893 }
1894 }
1895
1896 /*
1897 * Return an error message for UNIX-style errno indications on open or
1898 * create operations.
1899 */
1900 const char *
file_open_error_message(int err,gboolean for_writing)1901 file_open_error_message(int err, gboolean for_writing)
1902 {
1903 const char *errmsg;
1904 static char errmsg_errno[1024+1];
1905
1906 switch (err) {
1907
1908 case ENOENT:
1909 if (for_writing)
1910 errmsg = "The path to the file \"%s\" doesn't exist.";
1911 else
1912 errmsg = "The file \"%s\" doesn't exist.";
1913 break;
1914
1915 case EACCES:
1916 if (for_writing)
1917 errmsg = "You don't have permission to create or write to the file \"%s\".";
1918 else
1919 errmsg = "You don't have permission to read the file \"%s\".";
1920 break;
1921
1922 case EISDIR:
1923 errmsg = "\"%s\" is a directory (folder), not a file.";
1924 break;
1925
1926 case ENOSPC:
1927 errmsg = "The file \"%s\" could not be created because there is no space left on the file system.";
1928 break;
1929
1930 #ifdef EDQUOT
1931 case EDQUOT:
1932 errmsg = "The file \"%s\" could not be created because you are too close to, or over, your disk quota.";
1933 break;
1934 #endif
1935
1936 case EINVAL:
1937 errmsg = "The file \"%s\" could not be created because an invalid filename was specified.";
1938 break;
1939
1940 #ifdef ENAMETOOLONG
1941 case ENAMETOOLONG:
1942 /* XXX Make sure we truncate on a character boundary. */
1943 errmsg = "The file name \"%.80s" UTF8_HORIZONTAL_ELLIPSIS "\" is too long.";
1944 break;
1945 #endif
1946
1947 case ENOMEM:
1948 /*
1949 * The problem probably has nothing to do with how much RAM the
1950 * user has on their machine, so don't confuse them by saying
1951 * "memory". The problem is probably either virtual address
1952 * space or swap space.
1953 */
1954 #if GLIB_SIZEOF_VOID_P == 4
1955 /*
1956 * ILP32; we probably ran out of virtual address space.
1957 */
1958 #define ENOMEM_REASON "it can't be handled by a 32-bit application"
1959 #else
1960 /*
1961 * LP64 or LLP64; we probably ran out of swap space.
1962 */
1963 #if defined(_WIN32)
1964 /*
1965 * You need to make the pagefile bigger.
1966 */
1967 #define ENOMEM_REASON "the pagefile is too small"
1968 #elif defined(__APPLE__)
1969 /*
1970 * dynamic_pager couldn't, or wouldn't, create more swap files.
1971 */
1972 #define ENOMEM_REASON "your system ran out of swap file space"
1973 #else
1974 /*
1975 * Either you have a fixed swap partition or a fixed swap file,
1976 * and it needs to be made bigger.
1977 *
1978 * This is UN*X, but it's not macOS, so we assume the user is
1979 * *somewhat* nerdy.
1980 */
1981 #define ENOMEM_REASON "your system is out of swap space"
1982 #endif
1983 #endif /* GLIB_SIZEOF_VOID_P == 4 */
1984 if (for_writing)
1985 errmsg = "The file \"%s\" could not be created because " ENOMEM_REASON ".";
1986 else
1987 errmsg = "The file \"%s\" could not be opened because " ENOMEM_REASON ".";
1988 break;
1989
1990 default:
1991 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1992 "The file \"%%s\" could not be %s: %s.",
1993 for_writing ? "created" : "opened",
1994 g_strerror(err));
1995 errmsg = errmsg_errno;
1996 break;
1997 }
1998 return errmsg;
1999 }
2000
2001 /*
2002 * Return an error message for UNIX-style errno indications on write
2003 * operations.
2004 */
2005 const char *
file_write_error_message(int err)2006 file_write_error_message(int err)
2007 {
2008 const char *errmsg;
2009 static char errmsg_errno[1024+1];
2010
2011 switch (err) {
2012
2013 case ENOSPC:
2014 errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
2015 break;
2016
2017 #ifdef EDQUOT
2018 case EDQUOT:
2019 errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
2020 break;
2021 #endif
2022
2023 default:
2024 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2025 "An error occurred while writing to the file \"%%s\": %s.",
2026 g_strerror(err));
2027 errmsg = errmsg_errno;
2028 break;
2029 }
2030 return errmsg;
2031 }
2032
2033
2034 gboolean
file_exists(const char * fname)2035 file_exists(const char *fname)
2036 {
2037 ws_statb64 file_stat;
2038
2039 if (!fname) {
2040 return FALSE;
2041 }
2042
2043 if (ws_stat64(fname, &file_stat) != 0 && errno == ENOENT) {
2044 return FALSE;
2045 } else {
2046 return TRUE;
2047 }
2048 }
2049
config_file_exists_with_entries(const char * fname,char comment_char)2050 gboolean config_file_exists_with_entries(const char *fname, char comment_char)
2051 {
2052 gboolean start_of_line = TRUE;
2053 gboolean has_entries = FALSE;
2054 FILE *file;
2055 int c;
2056
2057 if (!fname) {
2058 return FALSE;
2059 }
2060
2061 if ((file = ws_fopen(fname, "r")) == NULL) {
2062 return FALSE;
2063 }
2064
2065 do {
2066 c = ws_getc_unlocked(file);
2067 if (start_of_line && c != comment_char && !g_ascii_isspace(c) && g_ascii_isprint(c)) {
2068 has_entries = TRUE;
2069 break;
2070 }
2071 if (c == '\n' || !g_ascii_isspace(c)) {
2072 start_of_line = (c == '\n');
2073 }
2074 } while (c != EOF);
2075
2076 fclose(file);
2077 return has_entries;
2078 }
2079
2080 /*
2081 * Check that the from file is not the same as to file
2082 * We do it here so we catch all cases ...
2083 * Unfortunately, the file requester gives us an absolute file
2084 * name and the read file name may be relative (if supplied on
2085 * the command line), so we can't just compare paths. From Joerg Mayer.
2086 */
2087 gboolean
files_identical(const char * fname1,const char * fname2)2088 files_identical(const char *fname1, const char *fname2)
2089 {
2090 /* Two different implementations, because:
2091 *
2092 * - _fullpath is not available on UN*X, so we can't get full
2093 * paths and compare them (which wouldn't work with hard links
2094 * in any case);
2095 *
2096 * - st_ino isn't filled in with a meaningful value on Windows.
2097 */
2098 #ifdef _WIN32
2099 char full1[MAX_PATH], full2[MAX_PATH];
2100
2101 /*
2102 * Get the absolute full paths of the file and compare them.
2103 * That won't work if you have hard links, but those aren't
2104 * much used on Windows, even though NTFS supports them.
2105 *
2106 * XXX - will _fullpath work with UNC?
2107 */
2108 if( _fullpath( full1, fname1, MAX_PATH ) == NULL ) {
2109 return FALSE;
2110 }
2111
2112 if( _fullpath( full2, fname2, MAX_PATH ) == NULL ) {
2113 return FALSE;
2114 }
2115
2116 if(strcmp(full1, full2) == 0) {
2117 return TRUE;
2118 } else {
2119 return FALSE;
2120 }
2121 #else
2122 ws_statb64 filestat1, filestat2;
2123
2124 /*
2125 * Compare st_dev and st_ino.
2126 */
2127 if (ws_stat64(fname1, &filestat1) == -1)
2128 return FALSE; /* can't get info about the first file */
2129 if (ws_stat64(fname2, &filestat2) == -1)
2130 return FALSE; /* can't get info about the second file */
2131 return (filestat1.st_dev == filestat2.st_dev &&
2132 filestat1.st_ino == filestat2.st_ino);
2133 #endif
2134 }
2135
2136 gboolean
file_needs_reopen(int fd,const char * filename)2137 file_needs_reopen(int fd, const char* filename)
2138 {
2139 #ifdef _WIN32
2140 /* Windows handles st_dev in a way unsuitable here:
2141 * * _fstat() simply casts the file descriptor (ws_fileno(fp)) to unsigned
2142 * and assigns this value to st_dev and st_rdev
2143 * * _wstat() converts drive letter (eg. C) to number (A=0, B=1, C=2, ...)
2144 * and assigns such number to st_dev and st_rdev
2145 *
2146 * The st_ino parameter is simply zero as there is no specific assignment
2147 * to it in the Universal CRT source code.
2148 *
2149 * Thus instead of using fstat(), use Windows specific API.
2150 */
2151
2152 HANDLE open_handle = (HANDLE)_get_osfhandle(fd);
2153 HANDLE current_handle = CreateFile(utf_8to16(filename), FILE_READ_ATTRIBUTES,
2154 FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
2155 NULL, OPEN_EXISTING, 0, NULL);
2156 BY_HANDLE_FILE_INFORMATION open_info, current_info;
2157
2158 if (current_handle == INVALID_HANDLE_VALUE) {
2159 return TRUE;
2160 }
2161
2162 #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
2163 FILE_ID_INFO open_id, current_id;
2164 if (GetFileInformationByHandleEx(open_handle, FileIdInfo, &open_id, sizeof(open_id)) &&
2165 GetFileInformationByHandleEx(current_handle, FileIdInfo, ¤t_id, sizeof(current_id))) {
2166 /* 128-bit identifier is available, use it */
2167 CloseHandle(current_handle);
2168 return open_id.VolumeSerialNumber != current_id.VolumeSerialNumber ||
2169 memcmp(&open_id.FileId, ¤t_id.FileId, sizeof(open_id.FileId)) != 0;
2170 }
2171 #endif /* _WIN32_WINNT >= _WIN32_WINNT_WIN8 */
2172 if (GetFileInformationByHandle(open_handle, &open_info) &&
2173 GetFileInformationByHandle(current_handle, ¤t_info)) {
2174 /* Fallback to 64-bit identifier */
2175 CloseHandle(current_handle);
2176 guint64 open_size = (((guint64)open_info.nFileSizeHigh) << 32) | open_info.nFileSizeLow;
2177 guint64 current_size = (((guint64)current_info.nFileSizeHigh) << 32) | current_info.nFileSizeLow;
2178 return open_info.dwVolumeSerialNumber != current_info.dwVolumeSerialNumber ||
2179 open_info.nFileIndexHigh != current_info.nFileIndexHigh ||
2180 open_info.nFileIndexLow != current_info.nFileIndexLow ||
2181 open_size > current_size;
2182 }
2183 CloseHandle(current_handle);
2184 return TRUE;
2185 #else
2186 ws_statb64 open_stat, current_stat;
2187
2188 /* consider a file deleted when stat fails for either file,
2189 * or when the residing device / inode has changed. */
2190 if (0 != ws_fstat64(fd, &open_stat))
2191 return TRUE;
2192 if (0 != ws_stat64(filename, ¤t_stat))
2193 return TRUE;
2194
2195 return open_stat.st_dev != current_stat.st_dev ||
2196 open_stat.st_ino != current_stat.st_ino ||
2197 open_stat.st_size > current_stat.st_size;
2198 #endif
2199 }
2200
2201 gboolean
write_file_binary_mode(const char * filename,const void * content,size_t content_len)2202 write_file_binary_mode(const char *filename, const void *content, size_t content_len)
2203 {
2204 int fd;
2205 size_t bytes_left;
2206 unsigned int bytes_to_write;
2207 ssize_t bytes_written;
2208 const guint8 *ptr;
2209 int err;
2210
2211 fd = ws_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
2212 if (fd == -1) {
2213 report_open_failure(filename, errno, TRUE);
2214 return FALSE;
2215 }
2216
2217 /*
2218 * The third argument to _write() on Windows is an unsigned int,
2219 * so, on Windows, that's the size of the third argument to
2220 * ws_write().
2221 *
2222 * The third argument to write() on UN*X is a size_t, although
2223 * the return value is an ssize_t, so one probably shouldn't
2224 * write more than the max value of an ssize_t.
2225 *
2226 * In either case, there's no guarantee that a size_t such as
2227 * content_len can be passed to ws_write(), so we write in
2228 * chunks of at most 2^31 bytes.
2229 */
2230
2231 ptr = (const guint8 *)content;
2232 bytes_left = content_len;
2233 while (bytes_left != 0) {
2234 if (bytes_left > 0x40000000) {
2235 bytes_to_write = 0x40000000;
2236 } else {
2237 bytes_to_write = (unsigned int)bytes_left;
2238 }
2239 bytes_written = ws_write(fd, ptr, bytes_to_write);
2240 if (bytes_written <= 0) {
2241 if (bytes_written < 0) {
2242 err = errno;
2243 } else {
2244 err = WTAP_ERR_SHORT_WRITE;
2245 }
2246 report_write_failure(filename, err);
2247 ws_close(fd);
2248 return FALSE;
2249 }
2250 bytes_left -= bytes_written;
2251 ptr += bytes_written;
2252 }
2253
2254 ws_close(fd);
2255 return TRUE;
2256 }
2257
2258 /*
2259 * Copy a file in binary mode, for those operating systems that care about
2260 * such things. This should be OK for all files, even text files, as
2261 * we'll copy the raw bytes, and we don't look at the bytes as we copy
2262 * them.
2263 *
2264 * Returns TRUE on success, FALSE on failure. If a failure, it also
2265 * displays a simple dialog window with the error message.
2266 */
2267 gboolean
copy_file_binary_mode(const char * from_filename,const char * to_filename)2268 copy_file_binary_mode(const char *from_filename, const char *to_filename)
2269 {
2270 int from_fd, to_fd, err;
2271 ssize_t nread, nwritten;
2272 guint8 *pd = NULL;
2273
2274 /* Copy the raw bytes of the file. */
2275 from_fd = ws_open(from_filename, O_RDONLY | O_BINARY, 0000 /* no creation so don't matter */);
2276 if (from_fd < 0) {
2277 report_open_failure(from_filename, errno, FALSE);
2278 goto done;
2279 }
2280
2281 /* Use open() instead of creat() so that we can pass the O_BINARY
2282 flag, which is relevant on Win32; it appears that "creat()"
2283 may open the file in text mode, not binary mode, but we want
2284 to copy the raw bytes of the file, so we need the output file
2285 to be open in binary mode. */
2286 to_fd = ws_open(to_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
2287 if (to_fd < 0) {
2288 report_open_failure(to_filename, errno, TRUE);
2289 ws_close(from_fd);
2290 goto done;
2291 }
2292
2293 #define FS_READ_SIZE 65536
2294 pd = (guint8 *)g_malloc(FS_READ_SIZE);
2295 while ((nread = ws_read(from_fd, pd, FS_READ_SIZE)) > 0) {
2296 nwritten = ws_write(to_fd, pd, nread);
2297 if (nwritten < nread) {
2298 if (nwritten < 0)
2299 err = errno;
2300 else
2301 err = WTAP_ERR_SHORT_WRITE;
2302 report_write_failure(to_filename, err);
2303 ws_close(from_fd);
2304 ws_close(to_fd);
2305 goto done;
2306 }
2307 }
2308 if (nread < 0) {
2309 err = errno;
2310 report_read_failure(from_filename, err);
2311 ws_close(from_fd);
2312 ws_close(to_fd);
2313 goto done;
2314 }
2315 ws_close(from_fd);
2316 if (ws_close(to_fd) < 0) {
2317 report_write_failure(to_filename, errno);
2318 goto done;
2319 }
2320
2321 g_free(pd);
2322 pd = NULL;
2323 return TRUE;
2324
2325 done:
2326 g_free(pd);
2327 return FALSE;
2328 }
2329
2330 gchar *
data_file_url(const gchar * filename)2331 data_file_url(const gchar *filename)
2332 {
2333 gchar *file_path;
2334 gchar *uri;
2335
2336 /* Absolute path? */
2337 if(g_path_is_absolute(filename)) {
2338 file_path = g_strdup(filename);
2339 } else {
2340 file_path = g_strdup_printf("%s/%s", get_datafile_dir(), filename);
2341 }
2342
2343 /* XXX - check, if the file is really existing, otherwise display a simple_dialog about the problem */
2344
2345 /* convert filename to uri */
2346 uri = g_filename_to_uri(file_path, NULL, NULL);
2347 g_free(file_path);
2348 return uri;
2349 }
2350
2351 void
free_progdirs(void)2352 free_progdirs(void)
2353 {
2354 g_free(persconffile_dir);
2355 persconffile_dir = NULL;
2356 g_free(datafile_dir);
2357 datafile_dir = NULL;
2358 g_free(persdatafile_dir);
2359 persdatafile_dir = NULL;
2360 g_free(persconfprofile);
2361 persconfprofile = NULL;
2362 g_free(progfile_dir);
2363 progfile_dir = NULL;
2364 #if defined(HAVE_PLUGINS) || defined(HAVE_LUA)
2365 g_free(plugin_dir);
2366 plugin_dir = NULL;
2367 g_free(plugin_dir_with_version);
2368 plugin_dir_with_version = NULL;
2369 g_free(plugin_pers_dir);
2370 plugin_pers_dir = NULL;
2371 g_free(plugin_pers_dir_with_version);
2372 plugin_pers_dir_with_version = NULL;
2373 #endif
2374 g_free(extcap_dir);
2375 extcap_dir = NULL;
2376 }
2377
2378 /*
2379 * Editor modelines
2380 *
2381 * Local Variables:
2382 * c-basic-offset: 4
2383 * tab-width: 8
2384 * indent-tabs-mode: nil
2385 * End:
2386 *
2387 * ex: set shiftwidth=4 tabstop=8 expandtab:
2388 * :indentSize=4:tabSize=8:noTabs=true:
2389 */
2390