update epan/dissectors/pidl/drsuapi/drsuapi.idl from samba
[wireshark-sm.git] / wsutil / filesystem.c
blob28e2acb4b856017308bfca90c6f1148bbfee8ce0
1 /* filesystem.c
2 * Filesystem utility routines
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
11 #include "config.h"
12 #define WS_LOG_DOMAIN LOG_DOMAIN_WSUTIL
14 #include "filesystem.h"
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <errno.h>
21 #ifdef _WIN32
22 #include <windows.h>
23 #include <tchar.h>
24 #include <shlobj.h>
25 #include <wsutil/unicode-utils.h>
26 #else /* _WIN32 */
27 #ifdef ENABLE_APPLICATION_BUNDLE
28 #include <mach-o/dyld.h>
29 #endif
30 #ifdef __linux__
31 #include <sys/utsname.h>
32 #endif
33 #ifdef __FreeBSD__
34 #include <sys/types.h>
35 #include <sys/sysctl.h>
36 #endif
37 #ifdef HAVE_DLGET
38 #include <dlfcn.h>
39 #endif
40 #include <pwd.h>
41 #endif /* _WIN32 */
43 #include <wsutil/report_message.h>
44 #include <wsutil/privileges.h>
45 #include <wsutil/file_util.h>
46 #include <wsutil/utf8_entities.h>
48 #include <wiretap/wtap.h> /* for WTAP_ERR_SHORT_WRITE */
50 #include "path_config.h"
52 #define PROFILES_DIR "profiles"
53 #define PLUGINS_DIR_NAME "plugins"
54 #define EXTCAP_DIR_NAME "extcap"
55 #define PROFILES_INFO_NAME "profile_files.txt"
57 #define _S G_DIR_SEPARATOR_S
60 * Application configuration namespace. Used to construct configuration
61 * paths and environment variables.
62 * XXX We might want to use the term "application flavor" instead, with
63 * "packet" and "log" flavors.
65 enum configuration_namespace_e {
66 CONFIGURATION_NAMESPACE_UNINITIALIZED,
67 CONFIGURATION_NAMESPACE_WIRESHARK,
68 CONFIGURATION_NAMESPACE_STRATOSHARK
70 enum configuration_namespace_e configuration_namespace = CONFIGURATION_NAMESPACE_UNINITIALIZED;
72 #define CONFIGURATION_NAMESPACE_PROPER (configuration_namespace == CONFIGURATION_NAMESPACE_WIRESHARK ? "Wireshark" : "Stratoshark")
73 #define CONFIGURATION_NAMESPACE_LOWER (configuration_namespace == CONFIGURATION_NAMESPACE_WIRESHARK ? "wireshark" : "stratoshark")
74 #define CONFIGURATION_ENVIRONMENT_VARIABLE(suffix) (configuration_namespace == CONFIGURATION_NAMESPACE_WIRESHARK ? "WIRESHARK_" suffix : "STRATOSHARK_" suffix)
76 char *persconffile_dir;
77 char *datafile_dir;
78 char *persdatafile_dir;
79 char *persconfprofile;
80 char *doc_dir;
81 char *current_working_dir;
83 /* Directory from which the executable came. */
84 static char *progfile_dir;
85 static char *install_prefix;
87 static bool do_store_persconffiles;
88 static GHashTable *profile_files;
91 * Given a pathname, return a pointer to the last pathname separator
92 * character in the pathname, or NULL if the pathname contains no
93 * separators.
95 char *
96 find_last_pathname_separator(const char *path)
98 char *separator;
100 #ifdef _WIN32
101 char c;
104 * We have to scan for '\' or '/'.
105 * Get to the end of the string.
107 separator = strchr(path, '\0'); /* points to ending '\0' */
108 while (separator > path) {
109 c = *--separator;
110 if (c == '\\' || c == '/')
111 return separator; /* found it */
115 * OK, we didn't find any, so no directories - but there might
116 * be a drive letter....
118 return strchr(path, ':');
119 #else
120 separator = strrchr(path, '/');
121 return separator;
122 #endif
126 * Given a pathname, return the last component.
128 const char *
129 get_basename(const char *path)
131 const char *filename;
133 ws_assert(path != NULL);
134 filename = find_last_pathname_separator(path);
135 if (filename == NULL) {
137 * There're no directories, drive letters, etc. in the
138 * name; the pathname *is* the file name.
140 filename = path;
141 } else {
143 * Skip past the pathname or drive letter separator.
145 filename++;
147 return filename;
151 * Given a pathname, return a string containing everything but the
152 * last component. NOTE: this overwrites the pathname handed into
153 * it....
155 char *
156 get_dirname(char *path)
158 char *separator;
160 ws_assert(path != NULL);
161 separator = find_last_pathname_separator(path);
162 if (separator == NULL) {
164 * There're no directories, drive letters, etc. in the
165 * name; there is no directory path to return.
167 return NULL;
171 * Get rid of the last pathname separator and the final file
172 * name following it.
174 *separator = '\0';
177 * "path" now contains the pathname of the directory containing
178 * the file/directory to which it referred.
180 return path;
184 * Given a pathname, return:
186 * the errno, if an attempt to "stat()" the file fails;
188 * EISDIR, if the attempt succeeded and the file turned out
189 * to be a directory;
191 * 0, if the attempt succeeded and the file turned out not
192 * to be a directory.
196 test_for_directory(const char *path)
198 ws_statb64 statb;
200 if (ws_stat64(path, &statb) < 0)
201 return errno;
203 if (S_ISDIR(statb.st_mode))
204 return EISDIR;
205 else
206 return 0;
210 test_for_fifo(const char *path)
212 ws_statb64 statb;
214 if (ws_stat64(path, &statb) < 0)
215 return errno;
217 if (S_ISFIFO(statb.st_mode))
218 return ESPIPE;
219 else
220 return 0;
223 bool
224 test_for_regular_file(const char *path)
226 ws_statb64 statb;
228 if (!path) {
229 return false;
232 if (ws_stat64(path, &statb) != 0)
233 return false;
235 return S_ISREG(statb.st_mode);
238 #ifdef ENABLE_APPLICATION_BUNDLE
240 * Directory of the application bundle in which we're contained,
241 * if we're contained in an application bundle. Otherwise, NULL.
243 * Note: Table 2-5 "Subdirectories of the Contents directory" of
245 * https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/BundleTypes/BundleTypes.html#//apple_ref/doc/uid/10000123i-CH101-SW1
247 * says that the "Frameworks" directory
249 * Contains any private shared libraries and frameworks used by the
250 * executable. The frameworks in this directory are revision-locked
251 * to the application and cannot be superseded by any other, even
252 * newer, versions that may be available to the operating system. In
253 * other words, the frameworks included in this directory take precedence
254 * over any other similarly named frameworks found in other parts of
255 * the operating system. For information on how to add private
256 * frameworks to your application bundle, see Framework Programming Guide.
258 * so if we were to ship with any frameworks (e.g. Qt) we should
259 * perhaps put them in a Frameworks directory rather than under
260 * Resources.
262 * It also says that the "PlugIns" directory
264 * Contains loadable bundles that extend the basic features of your
265 * application. You use this directory to include code modules that
266 * must be loaded into your applicationbs process space in order to
267 * be used. You would not use this directory to store standalone
268 * executables.
270 * Our plugins are just raw .so/.dylib files; I don't know whether by
271 * "bundles" they mean application bundles (i.e., directory hierarchies)
272 * or just "bundles" in the Mach-O sense (which are an image type that
273 * can be loaded with dlopen() but not linked as libraries; our plugins
274 * are, I think, built as dylibs and can be loaded either way).
276 * And it says that the "SharedSupport" directory
278 * Contains additional non-critical resources that do not impact the
279 * ability of the application to run. You might use this directory to
280 * include things like document templates, clip art, and tutorials
281 * that your application expects to be present but that do not affect
282 * the ability of your application to run.
284 * I don't think I'd put the files that currently go under Resources/share
285 * into that category; they're not, for example, sample Lua scripts that
286 * don't actually get run by Wireshark, they're configuration/data files
287 * for Wireshark whose absence might not prevent Wireshark from running
288 * but that would affect how it behaves when run.
290 static char *appbundle_dir;
291 #endif
294 * true if we're running from the build directory and we aren't running
295 * with special privileges.
297 static bool running_in_build_directory_flag;
300 * Set our configuration namespace. This will be used for top-level
301 * configuration directory names and environment variable prefixes.
303 static void
304 set_configuration_namespace(const char *namespace_name)
307 if (configuration_namespace != CONFIGURATION_NAMESPACE_UNINITIALIZED) {
308 return;
311 if (!namespace_name || g_ascii_strcasecmp(namespace_name, "wireshark") == 0)
313 configuration_namespace = CONFIGURATION_NAMESPACE_WIRESHARK;
315 else if (g_ascii_strcasecmp(namespace_name, "stratoshark") == 0)
317 configuration_namespace = CONFIGURATION_NAMESPACE_STRATOSHARK;
319 else
321 ws_error("Unknown configuration namespace %s", namespace_name);
324 ws_debug("Using configuration namespace %s.", CONFIGURATION_NAMESPACE_PROPER);
327 const char *
328 get_configuration_namespace(void)
330 return CONFIGURATION_NAMESPACE_PROPER;
333 bool is_packet_configuration_namespace(void)
335 return configuration_namespace != CONFIGURATION_NAMESPACE_STRATOSHARK;
338 #ifndef _WIN32
340 * Get the pathname of the executable using various platform-
341 * dependent mechanisms for various UN*Xes.
343 * These calls all should return something independent of the argv[0]
344 * passed to the program, so it shouldn't be fooled by an argv[0]
345 * that doesn't match the executable path.
347 * We don't use dladdr() because:
349 * not all UN*Xes necessarily have dladdr();
351 * those that do have it don't necessarily have dladdr(main)
352 * return information about the executable image;
354 * those that do have a dladdr() where dladdr(main) returns
355 * information about the executable image don't necessarily
356 * have a mechanism by which the executable image can get
357 * its own path from the kernel (either by a call or by it
358 * being handed to it along with argv[] and the environment),
359 * so they just fall back on getting it from argv[0], which we
360 * already have code to do;
362 * those that do have such a mechanism don't necessarily use
363 * it in dladdr(), and, instead, just fall back on getting it
364 * from argv[0];
366 * so the only places where it's worth bothering to use dladdr()
367 * are platforms where dladdr(main) return information about the
368 * executable image by getting it from the kernel rather than
369 * by looking at argv[0], and where we can't get at that information
370 * ourselves, and we haven't seen any indication that there are any
371 * such platforms.
373 * In particular, some dynamic linkers supply a dladdr() such that
374 * dladdr(main) just returns something derived from argv[0], so
375 * just using dladdr(main) is the wrong thing to do if there's
376 * another mechanism that can get you a more reliable version of
377 * the executable path.
379 * So, on platforms where we know of a mechanism to get that path
380 * (where getting that path doesn't involve argv[0], which is not
381 * guaranteed to reflect the path to the binary), this routine
382 * attempsts to use that platform's mechanism. On other platforms,
383 * it just returns NULL.
385 * This is not guaranteed to return an absolute path; if it doesn't,
386 * our caller must prepend the current directory if it's a path.
388 * This is not guaranteed to return the "real path"; it might return
389 * something with symbolic links in the path. Our caller must
390 * use realpath() if they want the real thing, but that's also true of
391 * something obtained by looking at argv[0].
393 #define xx_free free /* hack so checkAPIs doesn't complain */
394 static const char *
395 get_current_executable_path(void)
397 #if defined(ENABLE_APPLICATION_BUNDLE)
398 static char *executable_path;
399 uint32_t path_buf_size;
401 if (executable_path) {
402 return executable_path;
405 path_buf_size = PATH_MAX;
406 executable_path = (char *)g_malloc(path_buf_size);
407 if (_NSGetExecutablePath(executable_path, &path_buf_size) == -1) {
408 executable_path = (char *)g_realloc(executable_path, path_buf_size);
409 if (_NSGetExecutablePath(executable_path, &path_buf_size) == -1)
410 return NULL;
413 * Resolve our path so that it's possible to symlink the executables
414 * in our application bundle.
416 char *rp_execpath = realpath(executable_path, NULL);
417 if (rp_execpath) {
418 g_free(executable_path);
419 executable_path = g_strdup(rp_execpath);
420 xx_free(rp_execpath);
422 return executable_path;
423 #elif defined(__linux__)
425 * In older versions of GNU libc's dynamic linker, as used on Linux,
426 * dladdr(main) supplies a path based on argv[0], so we use
427 * /proc/self/exe instead; there are Linux distributions with
428 * kernels that support /proc/self/exe and those older versions
429 * of the dynamic linker, and this will get a better answer on
430 * those versions.
432 * It only works on Linux 2.2 or later, so we just give up on
433 * earlier versions.
435 * XXX - are there OS versions that support "exe" but not "self"?
437 struct utsname name;
438 static char executable_path[PATH_MAX + 1];
439 ssize_t r;
441 if (uname(&name) == -1)
442 return NULL;
443 if (strncmp(name.release, "1.", 2) == 0)
444 return NULL; /* Linux 1.x */
445 if (strcmp(name.release, "2.0") == 0 ||
446 strncmp(name.release, "2.0.", 4) == 0 ||
447 strcmp(name.release, "2.1") == 0 ||
448 strncmp(name.release, "2.1.", 4) == 0)
449 return NULL; /* Linux 2.0.x or 2.1.x */
450 if ((r = readlink("/proc/self/exe", executable_path, PATH_MAX)) == -1)
451 return NULL;
452 executable_path[r] = '\0';
453 return executable_path;
454 #elif defined(__FreeBSD__) && defined(KERN_PROC_PATHNAME)
456 * In older versions of FreeBSD's dynamic linker, dladdr(main)
457 * supplies a path based on argv[0], so we use the KERN_PROC_PATHNAME
458 * sysctl instead; there are, I think, versions of FreeBSD
459 * that support the sysctl that have and those older versions
460 * of the dynamic linker, and this will get a better answer on
461 * those versions.
463 int mib[4];
464 char *executable_path;
465 size_t path_buf_size;
467 mib[0] = CTL_KERN;
468 mib[1] = KERN_PROC;
469 mib[2] = KERN_PROC_PATHNAME;
470 mib[3] = -1;
471 path_buf_size = PATH_MAX;
472 executable_path = (char *)g_malloc(path_buf_size);
473 if (sysctl(mib, 4, executable_path, &path_buf_size, NULL, 0) == -1) {
474 if (errno != ENOMEM)
475 return NULL;
476 executable_path = (char *)g_realloc(executable_path, path_buf_size);
477 if (sysctl(mib, 4, executable_path, &path_buf_size, NULL, 0) == -1)
478 return NULL;
480 return executable_path;
481 #elif defined(__NetBSD__)
483 * In all versions of NetBSD's dynamic linker as of 2013-08-12,
484 * dladdr(main) supplies a path based on argv[0], so we use
485 * /proc/curproc/exe instead.
487 * XXX - are there OS versions that support "exe" but not "curproc"
488 * or "self"? Are there any that support "self" but not "curproc"?
490 static char executable_path[PATH_MAX + 1];
491 ssize_t r;
493 if ((r = readlink("/proc/curproc/exe", executable_path, PATH_MAX)) == -1)
494 return NULL;
495 executable_path[r] = '\0';
496 return executable_path;
497 #elif defined(__DragonFly__)
499 * In older versions of DragonFly BSD's dynamic linker, dladdr(main)
500 * supplies a path based on argv[0], so we use /proc/curproc/file
501 * instead; it appears to be supported by all versions of DragonFly
502 * BSD.
504 static char executable_path[PATH_MAX + 1];
505 ssize_t r;
507 if ((r = readlink("/proc/curproc/file", executable_path, PATH_MAX)) == -1)
508 return NULL;
509 executable_path[r] = '\0';
510 return executable_path;
511 #elif defined(HAVE_GETEXECNAME)
513 * Solaris, with getexecname().
514 * It appears that getexecname() dates back to at least Solaris 8,
515 * but /proc/{pid}/path is first documented in the Solaris 10 documentation,
516 * so we use getexecname() if available, rather than /proc/self/path/a.out
517 * (which isn't documented, but appears to be a symlink to the
518 * executable image file).
520 return getexecname();
521 #elif defined(HAVE_DLGET)
523 * HP-UX 11, with dlget(); use dlget() and dlgetname().
524 * See
526 * https://web.archive.org/web/20081025174755/http://h21007.www2.hp.com/portal/site/dspp/menuitem.863c3e4cbcdc3f3515b49c108973a801?ciid=88086d6e1de021106d6e1de02110275d6e10RCRD#two
528 struct load_module_desc desc;
530 if (dlget(-2, &desc, sizeof(desc)) != NULL)
531 return dlgetname(&desc, sizeof(desc), NULL, NULL, NULL);
532 else
533 return NULL;
534 #else
535 /* Fill in your favorite UN*X's code here, if there is something */
536 return NULL;
537 #endif
539 #endif /* _WIN32 */
541 /* Extcap executables are in their own subdirectory. This trims that off and
542 * reduces progfile_dir to the common program file directory. */
543 static void trim_progfile_dir(void)
545 char *progfile_last_dir = find_last_pathname_separator(progfile_dir);
547 #ifdef _WIN32
549 * Check for a namespaced extcap subdirectory.
550 * XXX - Do we only need to do this on Windows, or on other platforms too?
552 if (progfile_last_dir && strncmp(progfile_last_dir + 1, CONFIGURATION_NAMESPACE_LOWER, sizeof(CONFIGURATION_NAMESPACE_LOWER)) == 0) {
553 char* namespace_last_dir = find_last_pathname_separator(progfile_dir);
554 char namespace_sep = *namespace_last_dir;
555 *namespace_last_dir = '\0';
557 progfile_last_dir = find_last_pathname_separator(progfile_dir);
559 if (!(progfile_last_dir && strncmp(progfile_last_dir + 1, "extcap", sizeof("extcap")) == 0)) {
561 * Not an extcap, restore the namespace separator (it might have been
562 * some other "wireshark" directory, especially on case insensitive
563 * filesystems.)
565 *namespace_last_dir = namespace_sep;
566 return;
568 } else
569 #endif
570 if (! (progfile_last_dir && strncmp(progfile_last_dir + 1, "extcap", sizeof("extcap")) == 0)) {
571 /* Check for a non namespaced extcap directory. */
572 return;
575 *progfile_last_dir = '\0';
576 char *extcap_progfile_dir = progfile_dir;
577 progfile_dir = g_strdup(extcap_progfile_dir);
578 g_free(extcap_progfile_dir);
581 #if !defined(_WIN32) || defined(HAVE_MSYSTEM)
582 static char *
583 trim_last_dir_from_path(const char *_path)
585 char *path = ws_strdup(_path);
586 char *last_dir = find_last_pathname_separator(path);
587 if (last_dir) {
588 *last_dir = '\0';
590 return path;
592 #endif
595 * Construct the path name of a non-extcap Wireshark executable file,
596 * given the program name. The executable name doesn't include ".exe";
597 * append it on Windows, so that callers don't have to worry about that.
599 * This presumes that all non-extcap executables are in the same directory.
601 * The returned file name was g_malloc()'d so it must be g_free()d when the
602 * caller is done with it.
604 char *
605 get_executable_path(const char *program_name)
608 * Fail if we don't know what directory contains the executables.
610 if (progfile_dir == NULL)
611 return NULL;
613 #ifdef _WIN32
614 return ws_strdup_printf("%s\\%s.exe", progfile_dir, program_name);
615 #else
616 return ws_strdup_printf("%s/%s", progfile_dir, program_name);
617 #endif
621 * Get the pathname of the directory from which the executable came,
622 * and save it for future use. Returns NULL on success, and a
623 * g_mallocated string containing an error on failure.
625 #ifdef _WIN32
626 static char *
627 configuration_init_w32(const char* arg0 _U_)
629 TCHAR prog_pathname_w[_MAX_PATH+2];
630 char *prog_pathname;
631 DWORD error;
632 TCHAR *msg_w;
633 unsigned char *msg;
634 size_t msglen;
637 * Attempt to get the full pathname of the currently running
638 * program.
640 if (GetModuleFileName(NULL, prog_pathname_w, G_N_ELEMENTS(prog_pathname_w)) != 0 && GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
642 * XXX - Should we use g_utf16_to_utf8()?
644 prog_pathname = utf_16to8(prog_pathname_w);
646 * We got it; strip off the last component, which would be
647 * the file name of the executable, giving us the pathname
648 * of the directory where the executable resides.
650 progfile_dir = g_path_get_dirname(prog_pathname);
651 if (progfile_dir != NULL) {
652 /* We succeeded. */
653 trim_progfile_dir();
654 /* Now try to figure out if we're running in a build directory. */
655 char *wsutil_lib = g_build_filename(progfile_dir, "wsutil.lib", (char *)NULL);
656 if (file_exists(wsutil_lib)) {
657 running_in_build_directory_flag = true;
659 g_free(wsutil_lib);
660 } else {
662 * OK, no. What do we do now?
664 return ws_strdup_printf("No \\ in executable pathname \"%s\"",
665 prog_pathname);
667 } else {
669 * Oh, well. Return an indication of the error.
671 error = GetLastError();
672 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
673 NULL, error, 0, (LPTSTR) &msg_w, 0, NULL) == 0) {
675 * Gak. We can't format the message.
677 return ws_strdup_printf("GetModuleFileName failed: %lu (FormatMessage failed: %lu)",
678 error, GetLastError());
680 msg = utf_16to8(msg_w);
681 LocalFree(msg_w);
683 * "FormatMessage()" "helpfully" sticks CR/LF at the
684 * end of the message. Get rid of it.
686 msglen = strlen(msg);
687 if (msglen >= 2) {
688 msg[msglen - 1] = '\0';
689 msg[msglen - 2] = '\0';
691 return ws_strdup_printf("GetModuleFileName failed: %s (%lu)",
692 msg, error);
695 #ifdef HAVE_MSYSTEM
697 * We already have the program_dir. Find the installation prefix.
698 * This is one level up from the bin_dir. If the program_dir does
699 * not end with "bin" then assume we are running in the build directory
700 * and the "installation prefix" (staging directory) is the same as
701 * the program_dir.
703 if (g_str_has_suffix(progfile_dir, _S"bin")) {
704 install_prefix = trim_last_dir_from_path(progfile_dir);
706 else {
707 install_prefix = g_strdup(progfile_dir);
708 running_in_build_directory_flag = true;
710 #endif /* HAVE_MSYSTEM */
712 return NULL;
715 #else /* !_WIN32 */
717 static char *
718 configuration_init_posix(const char* arg0)
720 const char *execname;
721 char *prog_pathname;
722 char *curdir;
723 long path_max;
724 const char *pathstr;
725 const char *path_start, *path_end;
726 size_t path_component_len, path_len;
727 char *retstr;
728 char *path;
729 char *dir_end;
731 /* Hard-coded value used if we cannot obtain the path of the running executable. */
732 install_prefix = g_strdup(INSTALL_PREFIX);
735 * Check whether XXX_RUN_FROM_BUILD_DIRECTORY is set in the
736 * environment; if so, set running_in_build_directory_flag if we
737 * weren't started with special privileges. (If we were started
738 * with special privileges, it's not safe to allow the user to point
739 * us to some other directory; running_in_build_directory_flag, when
740 * set, causes us to look for plugins and the like in the build
741 * directory.)
743 const char *run_from_envar = CONFIGURATION_ENVIRONMENT_VARIABLE("RUN_FROM_BUILD_DIRECTORY");
744 if (g_getenv(run_from_envar) != NULL
745 && !started_with_special_privs()) {
746 running_in_build_directory_flag = true;
749 execname = get_current_executable_path();
750 if (execname == NULL) {
752 * OK, guess based on argv[0].
754 execname = arg0;
758 * Try to figure out the directory in which the currently running
759 * program resides, given something purporting to be the executable
760 * name (from an OS mechanism or from the argv[0] it was started with).
761 * That might be the absolute path of the program, or a path relative
762 * to the current directory of the process that started it, or
763 * just a name for the program if it was started from the command
764 * line and was searched for in $PATH. It's not guaranteed to be
765 * any of those, however, so there are no guarantees....
767 if (execname[0] == '/') {
769 * It's an absolute path.
771 prog_pathname = g_strdup(execname);
772 } else if (strchr(execname, '/') != NULL) {
774 * It's a relative path, with a directory in it.
775 * Get the current directory, and combine it
776 * with that directory.
778 path_max = pathconf(".", _PC_PATH_MAX);
779 if (path_max == -1) {
781 * We have no idea how big a buffer to
782 * allocate for the current directory.
784 return ws_strdup_printf("pathconf failed: %s\n",
785 g_strerror(errno));
787 curdir = (char *)g_malloc(path_max);
788 if (getcwd(curdir, path_max) == NULL) {
790 * It failed - give up, and just stick
791 * with DATA_DIR.
793 g_free(curdir);
794 return ws_strdup_printf("getcwd failed: %s\n",
795 g_strerror(errno));
797 path = ws_strdup_printf("%s/%s", curdir, execname);
798 g_free(curdir);
799 prog_pathname = path;
800 } else {
802 * It's just a file name.
803 * Search the path for a file with that name
804 * that's executable.
806 prog_pathname = NULL; /* haven't found it yet */
807 pathstr = g_getenv("PATH");
808 path_start = pathstr;
809 if (path_start != NULL) {
810 while (*path_start != '\0') {
811 path_end = strchr(path_start, ':');
812 if (path_end == NULL)
813 path_end = path_start + strlen(path_start);
814 path_component_len = path_end - path_start;
815 path_len = path_component_len + 1
816 + strlen(execname) + 1;
817 path = (char *)g_malloc(path_len);
818 memcpy(path, path_start, path_component_len);
819 path[path_component_len] = '\0';
820 (void) g_strlcat(path, "/", path_len);
821 (void) g_strlcat(path, execname, path_len);
822 if (access(path, X_OK) == 0) {
824 * Found it!
826 prog_pathname = path;
827 break;
831 * That's not it. If there are more
832 * path components to test, try them.
834 if (*path_end == ':')
835 path_end++;
836 path_start = path_end;
837 g_free(path);
839 if (prog_pathname == NULL) {
841 * Program not found in path.
843 return ws_strdup_printf("\"%s\" not found in \"%s\"",
844 execname, pathstr);
846 } else {
848 * PATH isn't set.
849 * XXX - should we pick a default?
851 return g_strdup("PATH isn't set");
856 * OK, we have what we think is the pathname
857 * of the program.
859 * First, find the last "/" in the directory,
860 * as that marks the end of the directory pathname.
862 dir_end = strrchr(prog_pathname, '/');
863 if (dir_end != NULL) {
865 * Found it. Strip off the last component,
866 * as that's the path of the program.
868 *dir_end = '\0';
871 * Is there a "/run" at the end?
873 dir_end = strrchr(prog_pathname, '/');
874 if (dir_end != NULL) {
875 if (!started_with_special_privs()) {
877 * Check for the CMake output directory. As people may name
878 * their directories "run" (really?), also check for the
879 * CMakeCache.txt file before assuming a CMake output dir.
881 if (strcmp(dir_end, "/run") == 0) {
882 char *cmake_file;
883 cmake_file = ws_strdup_printf("%.*s/CMakeCache.txt",
884 (int)(dir_end - prog_pathname),
885 prog_pathname);
886 if (file_exists(cmake_file))
887 running_in_build_directory_flag = true;
888 g_free(cmake_file);
890 #ifdef ENABLE_APPLICATION_BUNDLE
893 * Scan up the path looking for a component
894 * named "Contents". If we find it, we assume
895 * we're in a bundle, and that the top-level
896 * directory of the bundle is the one containing
897 * "Contents".
899 * Not all executables are in the Contents/MacOS
900 * directory, so we can't just check for those
901 * in the path and strip them off.
903 * XXX - should we assume that it's either
904 * Contents/MacOS or Resources/bin?
906 char *component_end, *p;
908 component_end = strchr(prog_pathname, '\0');
909 p = component_end;
910 for (;;) {
911 while (p >= prog_pathname && *p != '/')
912 p--;
913 if (p == prog_pathname) {
915 * We're looking at the first component of
916 * the pathname now, so we're definitely
917 * not in a bundle, even if we're in
918 * "/Contents".
920 break;
922 if (strncmp(p, "/Contents", component_end - p) == 0) {
923 /* Found it. */
924 appbundle_dir = (char *)g_malloc(p - prog_pathname + 1);
925 memcpy(appbundle_dir, prog_pathname, p - prog_pathname);
926 appbundle_dir[p - prog_pathname] = '\0';
927 break;
929 component_end = p;
930 p--;
933 #endif
938 * OK, we have the path we want.
940 progfile_dir = prog_pathname;
941 trim_progfile_dir();
942 } else {
944 * This "shouldn't happen"; we apparently
945 * have no "/" in the pathname.
946 * Just free up prog_pathname.
948 retstr = ws_strdup_printf("No / found in \"%s\"", prog_pathname);
949 g_free(prog_pathname);
950 return retstr;
954 * We already have the program_dir. Find the installation prefix.
955 * This is one level up from the bin_dir. If the program_dir does
956 * not end with "bin" then assume we are running in the build directory
957 * and the "installation prefix" (staging directory) is the same as
958 * the program_dir.
960 g_free(install_prefix);
961 if (g_str_has_suffix(progfile_dir, _S"bin")) {
962 install_prefix = trim_last_dir_from_path(progfile_dir);
964 else {
965 install_prefix = g_strdup(progfile_dir);
966 running_in_build_directory_flag = true;
969 return NULL;
971 #endif /* ?_WIN32 */
973 char *
974 configuration_init(const char* arg0, const char *namespace_name)
976 set_configuration_namespace(namespace_name);
978 #ifdef _WIN32
979 return configuration_init_w32(arg0);
980 #else
981 return configuration_init_posix(arg0);
982 #endif
986 * Get the directory in which the program resides.
988 const char *
989 get_progfile_dir(void)
991 return progfile_dir;
994 extern const char *
995 get_current_working_dir(void)
997 if (current_working_dir != NULL) {
998 return current_working_dir;
1002 * It's good to cache this because on Windows Microsoft cautions
1003 * against using GetCurrentDirectory except early on, e.g. when
1004 * parsing command line options.
1006 current_working_dir = g_get_current_dir();
1008 * The above always returns something, with a fallback, e.g., on macOS
1009 * if the program is run from Finder, of G_DIR_SEPARATOR_S.
1010 * On Windows when run from a shortcut / taskbar it returns whatever
1011 * the "run in" directory is on the shortcut, which is usually the
1012 * directory where the program resides, which isn't that useful.
1013 * Should we set it to the home directory on macOS or the
1014 * "My Documents" folder on Windows in those cases,
1015 * as we do in get_persdatafile_dir()? This isn't the default preference
1016 * setting so perhaps caveat emptor is ok.
1018 return current_working_dir;
1022 * Get the directory in which the global configuration and data files are
1023 * stored.
1025 * On Windows, we use the directory in which the executable for this
1026 * process resides.
1028 * On macOS (when executed from an app bundle), use a directory within
1029 * that app bundle.
1031 * Otherwise, if the program was executed from the build directory, use the
1032 * directory in which the executable for this process resides. In all other
1033 * cases, use the DATA_DIR value that was set at compile time.
1035 * XXX - if we ever make libwireshark a real library, used by multiple
1036 * applications (more than just TShark and versions of Wireshark with
1037 * various UIs), should the configuration files belong to the library
1038 * (and be shared by all those applications) or to the applications?
1040 * If they belong to the library, that could be done on UNIX by the
1041 * configure script, but it's trickier on Windows, as you can't just
1042 * use the pathname of the executable.
1044 * If they belong to the application, that could be done on Windows
1045 * by using the pathname of the executable, but we'd have to have it
1046 * passed in as an argument, in some call, on UNIX.
1048 * Note that some of those configuration files might be used by code in
1049 * libwireshark, some of them might be used by dissectors (would they
1050 * belong to libwireshark, the application, or a separate library?),
1051 * and some of them might be used by other code (the Wireshark preferences
1052 * file includes resolver preferences that control the behavior of code
1053 * in libwireshark, dissector preferences, and UI preferences, for
1054 * example).
1056 const char *
1057 get_datafile_dir(void)
1059 if (datafile_dir != NULL)
1060 return datafile_dir;
1062 const char *data_dir_envar = CONFIGURATION_ENVIRONMENT_VARIABLE("DATA_DIR");
1063 if (g_getenv(data_dir_envar) && !started_with_special_privs()) {
1065 * The user specified a different directory for data files
1066 * and we aren't running with special privileges.
1067 * Let {WIRESHARK,STRATOSHARK}_DATA_DIR take precedence.
1068 * XXX - We might be able to dispense with the priv check
1070 datafile_dir = g_strdup(g_getenv(data_dir_envar));
1071 return datafile_dir;
1074 #if defined(HAVE_MSYSTEM)
1075 if (running_in_build_directory_flag) {
1076 datafile_dir = g_strdup(install_prefix);
1077 } else {
1078 datafile_dir = g_build_filename(install_prefix, DATA_DIR, CONFIGURATION_NAMESPACE_LOWER, (char *)NULL);
1080 #elif defined(_WIN32)
1082 * Do we have the pathname of the program? If so, assume we're
1083 * running an installed version of the program. If we fail,
1084 * we don't change "datafile_dir", and thus end up using the
1085 * default.
1087 * XXX - does NSIS put the installation directory into
1088 * "\HKEY_LOCAL_MACHINE\SOFTWARE\Wireshark\InstallDir"?
1089 * If so, perhaps we should read that from the registry,
1090 * instead.
1092 if (progfile_dir != NULL) {
1094 * Yes, we do; use that.
1096 datafile_dir = g_strdup(progfile_dir);
1097 } else {
1099 * No, we don't.
1100 * Fall back on the default installation directory.
1102 datafile_dir = g_strdup("C:\\Program Files\\Wireshark\\");
1104 #else
1105 #ifdef ENABLE_APPLICATION_BUNDLE
1107 * If we're running from an app bundle and weren't started
1108 * with special privileges, use the Contents/Resources/share/wireshark
1109 * subdirectory of the app bundle.
1111 * (appbundle_dir is not set to a non-null value if we're
1112 * started with special privileges, so we need only check
1113 * it; we don't need to call started_with_special_privs().)
1115 else if (appbundle_dir != NULL) {
1116 datafile_dir = ws_strdup_printf("%s/Contents/Resources/share/%s",
1117 appbundle_dir, CONFIGURATION_NAMESPACE_LOWER);
1119 #endif
1120 else if (running_in_build_directory_flag && progfile_dir != NULL) {
1122 * We're (probably) being run from the build directory and
1123 * weren't started with special privileges.
1125 * (running_in_build_directory_flag is never set to true
1126 * if we're started with special privileges, so we need
1127 * only check it; we don't need to call started_with_special_privs().)
1129 * Data files (dtds/, radius/, etc.) are copied to the build
1130 * directory during the build which also contains executables. A special
1131 * exception is macOS (when built with an app bundle).
1133 datafile_dir = g_strdup(progfile_dir);
1134 } else {
1135 if (g_path_is_absolute(DATA_DIR)) {
1136 datafile_dir = g_build_filename(DATA_DIR, CONFIGURATION_NAMESPACE_LOWER, (char *)NULL);
1137 } else {
1138 datafile_dir = g_build_filename(install_prefix, DATA_DIR, CONFIGURATION_NAMESPACE_LOWER, (char *)NULL);
1141 #endif
1142 return datafile_dir;
1145 const char *
1146 get_doc_dir(void)
1148 if (doc_dir != NULL)
1149 return doc_dir;
1151 /* No environment variable for this. */
1152 if (false) {
1156 #if defined(HAVE_MSYSTEM)
1157 if (running_in_build_directory_flag) {
1158 doc_dir = g_strdup(install_prefix);
1159 } else {
1160 doc_dir = g_build_filename(install_prefix, DOC_DIR, (char *)NULL);
1162 #elif defined(_WIN32)
1163 if (progfile_dir != NULL) {
1164 doc_dir = g_strdup(progfile_dir);
1165 } else {
1166 /* Fall back on the default installation directory. */
1167 doc_dir = g_strdup("C:\\Program Files\\Wireshark\\");
1169 #else
1170 #ifdef ENABLE_APPLICATION_BUNDLE
1172 * If we're running from an app bundle and weren't started
1173 * with special privileges, use the Contents/Resources/share/wireshark
1174 * subdirectory of the app bundle.
1176 * (appbundle_dir is not set to a non-null value if we're
1177 * started with special privileges, so we need only check
1178 * it; we don't need to call started_with_special_privs().)
1180 else if (appbundle_dir != NULL) {
1181 doc_dir = g_strdup(get_datafile_dir());
1183 #endif
1184 else if (running_in_build_directory_flag && progfile_dir != NULL) {
1186 * We're (probably) being run from the build directory and
1187 * weren't started with special privileges.
1189 doc_dir = g_strdup(progfile_dir);
1190 } else {
1191 if (g_path_is_absolute(DOC_DIR)) {
1192 doc_dir = g_strdup(DOC_DIR);
1193 } else {
1194 doc_dir = g_build_filename(install_prefix, DOC_DIR, (char *)NULL);
1197 #endif
1198 return doc_dir;
1202 * Find the directory where the plugins are stored.
1204 * On Windows, we use the plugin\{VERSION} subdirectory of the datafile
1205 * directory, where {VERSION} is the version number of this version of
1206 * Wireshark.
1208 * On UN*X:
1210 * if we appear to be run from the build directory, we use the
1211 * "plugin" subdirectory of the datafile directory;
1213 * otherwise, if the WIRESHARK_PLUGIN_DIR environment variable is
1214 * set and we aren't running with special privileges, we use the
1215 * value of that environment variable;
1217 * otherwise, if we're running from an app bundle in macOS, we
1218 * use the Contents/PlugIns/wireshark subdirectory of the app bundle;
1220 * otherwise, we use the PLUGIN_DIR value supplied by the
1221 * configure script.
1223 static char *plugin_dir;
1224 static char *plugin_dir_with_version;
1225 static char *plugin_pers_dir;
1226 static char *plugin_pers_dir_with_version;
1227 static char *extcap_pers_dir;
1229 static void
1230 init_plugin_dir(void)
1232 const char *plugin_dir_envar = CONFIGURATION_ENVIRONMENT_VARIABLE("PLUGIN_DIR");
1233 if (g_getenv(plugin_dir_envar) && !started_with_special_privs()) {
1235 * The user specified a different directory for plugins
1236 * and we aren't running with special privileges.
1237 * Let {WIRESHARK,STRATOSHARK}_PLUGIN_DIR take precedence.
1239 plugin_dir = g_strdup(g_getenv(plugin_dir_envar));
1242 #if defined(HAVE_PLUGINS) || defined(HAVE_LUA)
1243 #if defined(HAVE_MSYSTEM)
1244 else if (running_in_build_directory_flag) {
1245 plugin_dir = g_build_filename(install_prefix, "plugins", (char *)NULL);
1246 } else {
1247 plugin_dir = g_build_filename(install_prefix, PLUGIN_DIR, (char *)NULL);
1249 #elif defined(_WIN32)
1250 else {
1252 * On Windows, plugins are stored under the program file directory
1253 * in both the build and the installation directories.
1255 plugin_dir = g_build_filename(get_progfile_dir(), "plugins", (char *)NULL);
1257 #else
1258 #ifdef ENABLE_APPLICATION_BUNDLE
1260 * If we're running from an app bundle and weren't started
1261 * with special privileges, use the Contents/PlugIns/wireshark
1262 * subdirectory of the app bundle.
1264 * (appbundle_dir is not set to a non-null value if we're
1265 * started with special privileges, so we need only check
1266 * it; we don't need to call started_with_special_privs().)
1268 else if (appbundle_dir != NULL) {
1269 plugin_dir = g_build_filename(appbundle_dir, "Contents/PlugIns",
1270 CONFIGURATION_NAMESPACE_LOWER, (char *)NULL);
1272 #endif // ENABLE_APPLICATION_BUNDLE
1273 else if (running_in_build_directory_flag) {
1275 * We're (probably) being run from the build directory and
1276 * weren't started with special privileges, so we'll use
1277 * the "plugins" subdirectory of the directory where the program
1278 * we're running is (that's the build directory).
1280 plugin_dir = g_build_filename(get_progfile_dir(), "plugins", (char *)NULL);
1281 } else {
1282 if (g_path_is_absolute(PLUGIN_DIR)) {
1283 plugin_dir = g_strdup(PLUGIN_DIR);
1284 } else {
1285 plugin_dir = g_build_filename(install_prefix, PLUGIN_DIR, (char *)NULL);
1288 #endif // HAVE_MSYSTEM / _WIN32
1289 #endif /* defined(HAVE_PLUGINS) || defined(HAVE_LUA) */
1292 static void
1293 init_plugin_pers_dir(void)
1295 #if defined(HAVE_PLUGINS) || defined(HAVE_LUA)
1296 #ifdef _WIN32
1297 plugin_pers_dir = get_persconffile_path(PLUGINS_DIR_NAME, false);
1298 #else
1299 plugin_pers_dir = g_build_filename(g_get_home_dir(), ".local/lib",
1300 CONFIGURATION_NAMESPACE_LOWER, PLUGINS_DIR_NAME, (char *)NULL);
1301 #endif
1302 #endif /* defined(HAVE_PLUGINS) || defined(HAVE_LUA) */
1306 * Get the directory in which the plugins are stored.
1308 const char *
1309 get_plugins_dir(void)
1311 if (!plugin_dir)
1312 init_plugin_dir();
1313 return plugin_dir;
1316 const char *
1317 get_plugins_dir_with_version(void)
1319 if (!plugin_dir)
1320 init_plugin_dir();
1321 if (plugin_dir && !plugin_dir_with_version)
1322 plugin_dir_with_version = g_build_filename(plugin_dir, PLUGIN_PATH_ID, (char *)NULL);
1323 return plugin_dir_with_version;
1326 /* Get the personal plugin dir */
1327 const char *
1328 get_plugins_pers_dir(void)
1330 if (!plugin_pers_dir)
1331 init_plugin_pers_dir();
1332 return plugin_pers_dir;
1335 const char *
1336 get_plugins_pers_dir_with_version(void)
1338 if (!plugin_pers_dir)
1339 init_plugin_pers_dir();
1340 if (plugin_pers_dir && !plugin_pers_dir_with_version)
1341 plugin_pers_dir_with_version = g_build_filename(plugin_pers_dir, PLUGIN_PATH_ID, (char *)NULL);
1342 return plugin_pers_dir_with_version;
1346 * Find the directory where the extcap hooks are stored.
1348 * If the WIRESHARK_EXTCAP_DIR environment variable is set and we are not
1349 * running with special privileges, use that. Otherwise:
1351 * On Windows, we use the "extcap" subdirectory of the program directory.
1353 * On UN*X:
1355 * if we appear to be run from the build directory, we use the
1356 * "extcap" subdirectory of the build directory.
1358 * otherwise, if we're running from an app bundle in macOS, we
1359 * use the Contents/MacOS/extcap subdirectory of the app bundle;
1361 * otherwise, we use the EXTCAP_DIR value supplied by CMake.
1363 static char *extcap_dir;
1365 static void
1366 init_extcap_dir(void)
1368 const char *extcap_dir_envar = CONFIGURATION_ENVIRONMENT_VARIABLE("EXTCAP_DIR");
1369 if (g_getenv(extcap_dir_envar) && !started_with_special_privs()) {
1371 * The user specified a different directory for extcap hooks
1372 * and we aren't running with special privileges.
1374 extcap_dir = g_strdup(g_getenv(extcap_dir_envar));
1377 #if defined(HAVE_MSYSTEM)
1378 else if (running_in_build_directory_flag) {
1379 extcap_dir = g_build_filename(install_prefix, "extcap", (char *)NULL);
1380 } else {
1381 extcap_dir = g_build_filename(install_prefix, EXTCAP_DIR, (char *)NULL);
1383 #elif defined(_WIN32)
1385 * On Windows, extcap utilities are stored in "extcap/<program name>"
1386 * in the build directory and in "extcap" in the installation
1387 * directory.
1389 else if (running_in_build_directory_flag) {
1390 extcap_dir = g_build_filename(get_progfile_dir(), EXTCAP_DIR_NAME,
1391 CONFIGURATION_NAMESPACE_LOWER, (char *)NULL);
1392 } else {
1393 extcap_dir = g_build_filename(get_progfile_dir(), EXTCAP_DIR_NAME,
1394 (char *)NULL);
1396 #else
1397 #ifdef ENABLE_APPLICATION_BUNDLE
1398 else if (appbundle_dir != NULL) {
1400 * If we're running from an app bundle and weren't started
1401 * with special privileges, use the Contents/MacOS/extcap
1402 * subdirectory of the app bundle.
1404 * (appbundle_dir is not set to a non-null value if we're
1405 * started with special privileges, so we need only check
1406 * it; we don't need to call started_with_special_privs().)
1408 extcap_dir = g_build_filename(appbundle_dir, "Contents/MacOS/extcap", (char *)NULL);
1410 #endif // ENABLE_APPLICATION_BUNDLE
1411 else if (running_in_build_directory_flag) {
1413 * We're (probably) being run from the build directory and
1414 * weren't started with special privileges, so we'll use
1415 * the "extcap hooks" subdirectory of the directory where the program
1416 * we're running is (that's the build directory).
1418 extcap_dir = g_build_filename(get_progfile_dir(), EXTCAP_DIR_NAME,
1419 CONFIGURATION_NAMESPACE_LOWER, (char *)NULL);
1421 else {
1422 if (g_path_is_absolute(EXTCAP_DIR)) {
1423 extcap_dir = g_strdup(is_packet_configuration_namespace() ? EXTCAP_DIR : LOG_EXTCAP_DIR);
1424 } else {
1425 extcap_dir = g_build_filename(install_prefix,
1426 is_packet_configuration_namespace() ? EXTCAP_DIR : LOG_EXTCAP_DIR, (char *)NULL);
1429 #endif // HAVE_MSYSTEM / _WIN32
1432 static void
1433 init_extcap_pers_dir(void)
1435 #ifdef _WIN32
1436 extcap_pers_dir = get_persconffile_path(EXTCAP_DIR_NAME, false);
1437 #else
1438 extcap_pers_dir = g_build_filename(g_get_home_dir(), ".local/lib",
1439 CONFIGURATION_NAMESPACE_LOWER, EXTCAP_DIR_NAME, (char *)NULL);
1440 #endif
1444 * Get the directory in which the extcap hooks are stored.
1447 const char *
1448 get_extcap_dir(void)
1450 if (!extcap_dir)
1451 init_extcap_dir();
1452 return extcap_dir;
1455 /* Get the personal plugin dir */
1456 const char *
1457 get_extcap_pers_dir(void)
1459 if (!extcap_pers_dir)
1460 init_extcap_pers_dir();
1461 return extcap_pers_dir;
1465 * Get the flag indicating whether we're running from a build
1466 * directory.
1468 bool
1469 running_in_build_directory(void)
1471 return running_in_build_directory_flag;
1475 * Get the directory in which files that, at least on UNIX, are
1476 * system files (such as "/etc/ethers") are stored; on Windows,
1477 * there's no "/etc" directory, so we get them from the global
1478 * configuration and data file directory.
1480 const char *
1481 get_systemfile_dir(void)
1483 #ifdef _WIN32
1484 return get_datafile_dir();
1485 #else
1486 return "/etc";
1487 #endif
1490 void
1491 set_profile_name(const char *profilename)
1493 g_free (persconfprofile);
1495 if (profilename && strlen(profilename) > 0 &&
1496 strcmp(profilename, DEFAULT_PROFILE) != 0) {
1497 persconfprofile = g_strdup (profilename);
1498 } else {
1499 /* Default Profile */
1500 persconfprofile = NULL;
1504 const char *
1505 get_profile_name(void)
1507 if (persconfprofile) {
1508 return persconfprofile;
1509 } else {
1510 return DEFAULT_PROFILE;
1514 bool
1515 is_default_profile(void)
1517 return (!persconfprofile || strcmp(persconfprofile, DEFAULT_PROFILE) == 0) ? true : false;
1520 bool
1521 has_global_profiles(void)
1523 WS_DIR *dir;
1524 WS_DIRENT *file;
1525 char *global_dir = get_global_profiles_dir();
1526 char *filename;
1527 bool has_global = false;
1529 if ((test_for_directory(global_dir) == EISDIR) &&
1530 ((dir = ws_dir_open(global_dir, 0, NULL)) != NULL))
1532 while ((file = ws_dir_read_name(dir)) != NULL) {
1533 filename = ws_strdup_printf ("%s%s%s", global_dir, G_DIR_SEPARATOR_S,
1534 ws_dir_get_name(file));
1535 if (test_for_directory(filename) == EISDIR) {
1536 has_global = true;
1537 g_free (filename);
1538 break;
1540 g_free (filename);
1542 ws_dir_close(dir);
1544 g_free(global_dir);
1545 return has_global;
1548 void
1549 profile_store_persconffiles(bool store)
1551 if (store) {
1552 profile_files = g_hash_table_new (g_str_hash, g_str_equal);
1554 do_store_persconffiles = store;
1557 void
1558 profile_register_persconffile(const char *filename)
1560 if (do_store_persconffiles && !g_hash_table_lookup (profile_files, filename)) {
1561 /* Store filenames so we know which filenames belongs to a configuration profile */
1562 g_hash_table_insert (profile_files, g_strdup(filename), g_strdup(filename));
1567 * Get the directory in which personal configuration files reside.
1569 * On Windows, it's "Wireshark", under %APPDATA% or, if %APPDATA% isn't set,
1570 * it's "%USERPROFILE%\Application Data" (which is what %APPDATA% normally
1571 * is on Windows 2000).
1573 * On UNIX-compatible systems, we first look in XDG_CONFIG_HOME/wireshark
1574 * and, if that doesn't exist, ~/.wireshark, for backwards compatibility.
1575 * If neither exists, we use XDG_CONFIG_HOME/wireshark, so that the directory
1576 * is initially created as XDG_CONFIG_HOME/wireshark. We use that regardless
1577 * of whether the user is running under an XDG desktop or not, so that
1578 * if the user's home directory is on a server and shared between
1579 * different desktop environments on different machines, they can all
1580 * share the same configuration file directory.
1582 * XXX - what about stuff that shouldn't be shared between machines,
1583 * such as plugins in the form of shared loadable images?
1585 static const char *
1586 get_persconffile_dir_no_profile(void)
1588 const char *env;
1590 /* Return the cached value, if available */
1591 if (persconffile_dir != NULL)
1592 return persconffile_dir;
1595 * See if the user has selected an alternate environment.
1597 const char *config_dir_envar = CONFIGURATION_ENVIRONMENT_VARIABLE("CONFIG_DIR");
1598 env = g_getenv(config_dir_envar);
1599 #ifdef _WIN32
1600 if (env == NULL) {
1602 * The PortableApps launcher sets this environment variable.
1603 * XXX - That's only for the GUI. We don't have launchers/batch
1604 * scripts for the command line tools, and just package the same
1605 * binaries as built for NSIS and WiX, so if the user is running
1606 * tshark from the PortableApps directory, how do we tell? (#20095)
1608 env = g_getenv("WIRESHARK_APPDATA");
1610 #endif
1611 if (env != NULL) {
1612 persconffile_dir = g_strdup(env);
1613 return persconffile_dir;
1616 #ifdef _WIN32
1618 * Use %APPDATA% or %USERPROFILE%, so that configuration
1619 * files are stored in the user profile, rather than in
1620 * the home directory. The Windows convention is to store
1621 * configuration information in the user profile, and doing
1622 * so means you can use Wireshark even if the home directory
1623 * is an inaccessible network drive.
1625 env = g_getenv("APPDATA");
1626 const char *persconf_namespace = CONFIGURATION_NAMESPACE_PROPER;
1627 if (env != NULL) {
1629 * Concatenate %APPDATA% with "\Wireshark" or "\Stratoshark".
1631 persconffile_dir = g_build_filename(env, persconf_namespace, NULL);
1632 return persconffile_dir;
1636 * OK, %APPDATA% wasn't set, so use %USERPROFILE%\Application Data.
1638 env = g_getenv("USERPROFILE");
1639 if (env != NULL) {
1640 persconffile_dir = g_build_filename(env, "Application Data", persconf_namespace, NULL);
1641 return persconffile_dir;
1645 * Give up and use "C:".
1647 persconffile_dir = g_build_filename("C:", persconf_namespace, NULL);
1648 return persconffile_dir;
1649 #else
1650 char *xdg_path, *path;
1651 struct passwd *pwd;
1652 const char *homedir;
1655 * Check if XDG_CONFIG_HOME/wireshark exists and is a directory.
1657 xdg_path = g_build_filename(g_get_user_config_dir(),
1658 CONFIGURATION_NAMESPACE_LOWER, NULL);
1659 if (g_file_test(xdg_path, G_FILE_TEST_IS_DIR)) {
1660 persconffile_dir = xdg_path;
1661 return persconffile_dir;
1665 * It doesn't exist, or it does but isn't a directory, so try
1666 * ~/.wireshark.
1668 * If $HOME is set, use that for ~.
1670 * (Note: before GLib 2.36, g_get_home_dir() didn't look at $HOME,
1671 * but we always want to do so, so we don't use g_get_home_dir().)
1673 homedir = g_getenv("HOME");
1674 if (homedir == NULL) {
1676 * It's not set.
1678 * Get their home directory from the password file.
1679 * If we can't even find a password file entry for them,
1680 * use "/tmp".
1682 pwd = getpwuid(getuid());
1683 if (pwd != NULL) {
1684 homedir = pwd->pw_dir;
1685 } else {
1686 homedir = "/tmp";
1689 path = g_build_filename(homedir,
1690 configuration_namespace == CONFIGURATION_NAMESPACE_WIRESHARK ? ".wireshark" : ".stratoshark",
1691 NULL);
1692 if (g_file_test(path, G_FILE_TEST_IS_DIR)) {
1693 g_free(xdg_path);
1694 persconffile_dir = path;
1695 return persconffile_dir;
1699 * Neither are directories that exist; use the XDG path, so we'll
1700 * create that as necessary.
1702 g_free(path);
1703 persconffile_dir = xdg_path;
1704 return persconffile_dir;
1705 #endif
1708 void
1709 set_persconffile_dir(const char *p)
1711 g_free(persconffile_dir);
1712 persconffile_dir = g_strdup(p);
1715 char *
1716 get_profiles_dir(void)
1718 return ws_strdup_printf ("%s%s%s", get_persconffile_dir_no_profile (),
1719 G_DIR_SEPARATOR_S, PROFILES_DIR);
1723 create_profiles_dir(char **pf_dir_path_return)
1725 char *pf_dir_path;
1726 ws_statb64 s_buf;
1729 * Create the "Default" personal configuration files directory, if necessary.
1731 if (create_persconffile_profile (NULL, pf_dir_path_return) == -1) {
1732 return -1;
1736 * Check if profiles directory exists.
1737 * If not then create it.
1739 pf_dir_path = get_profiles_dir ();
1740 if (ws_stat64(pf_dir_path, &s_buf) != 0) {
1741 if (errno != ENOENT) {
1742 /* Some other problem; give up now. */
1743 *pf_dir_path_return = pf_dir_path;
1744 return -1;
1748 * It doesn't exist; try to create it.
1750 int ret = ws_mkdir(pf_dir_path, 0755);
1751 if (ret == -1) {
1752 *pf_dir_path_return = pf_dir_path;
1753 return ret;
1756 g_free(pf_dir_path);
1758 return 0;
1761 char *
1762 get_global_profiles_dir(void)
1764 return ws_strdup_printf ("%s%s%s", get_datafile_dir(),
1765 G_DIR_SEPARATOR_S, PROFILES_DIR);
1768 static char *
1769 get_persconffile_dir(const char *profilename)
1771 char *persconffile_profile_dir = NULL, *profile_dir;
1773 if (profilename && strlen(profilename) > 0 &&
1774 strcmp(profilename, DEFAULT_PROFILE) != 0) {
1775 profile_dir = get_profiles_dir();
1776 persconffile_profile_dir = ws_strdup_printf ("%s%s%s", profile_dir,
1777 G_DIR_SEPARATOR_S, profilename);
1778 g_free(profile_dir);
1779 } else {
1780 persconffile_profile_dir = g_strdup (get_persconffile_dir_no_profile ());
1783 return persconffile_profile_dir;
1786 char *
1787 get_profile_dir(const char *profilename, bool is_global)
1789 char *profile_dir;
1791 if (is_global) {
1792 if (profilename && strlen(profilename) > 0 &&
1793 strcmp(profilename, DEFAULT_PROFILE) != 0)
1795 char *global_path = get_global_profiles_dir();
1796 profile_dir = g_build_filename(global_path, profilename, NULL);
1797 g_free(global_path);
1798 } else {
1799 profile_dir = g_strdup(get_datafile_dir());
1801 } else {
1803 * If we didn't supply a profile name, i.e. if profilename is
1804 * null, get_persconffile_dir() returns the default profile.
1806 profile_dir = get_persconffile_dir(profilename);
1809 return profile_dir;
1812 bool
1813 profile_exists(const char *profilename, bool global)
1815 char *path = NULL;
1816 bool exists;
1819 * If we're looking up a global profile, we must have a
1820 * profile name.
1822 if (global && !profilename)
1823 return false;
1825 path = get_profile_dir(profilename, global);
1826 exists = (test_for_directory(path) == EISDIR) ? true : false;
1828 g_free(path);
1829 return exists;
1832 static int
1833 delete_directory (const char *directory, char **pf_dir_path_return)
1835 WS_DIR *dir;
1836 WS_DIRENT *file;
1837 char *filename;
1838 int ret = 0;
1840 if ((dir = ws_dir_open(directory, 0, NULL)) != NULL) {
1841 while ((file = ws_dir_read_name(dir)) != NULL) {
1842 filename = ws_strdup_printf ("%s%s%s", directory, G_DIR_SEPARATOR_S,
1843 ws_dir_get_name(file));
1844 if (test_for_directory(filename) != EISDIR) {
1845 ret = ws_remove(filename);
1846 #if 0
1847 } else {
1848 /* The user has manually created a directory in the profile directory */
1849 /* I do not want to delete the directory recursively yet */
1850 ret = delete_directory (filename, pf_dir_path_return);
1851 #endif
1853 if (ret != 0) {
1854 *pf_dir_path_return = filename;
1855 break;
1857 g_free (filename);
1859 ws_dir_close(dir);
1862 if (ret == 0 && (ret = ws_remove(directory)) != 0) {
1863 *pf_dir_path_return = g_strdup (directory);
1866 return ret;
1869 /* Copy files from one directory to another. Does not recursively copy directories */
1870 static int
1871 copy_directory(const char *from_dir, const char *to_dir, char **pf_filename_return)
1873 int ret = 0;
1874 char *from_file, *to_file;
1875 const char *filename;
1876 WS_DIR *dir;
1877 WS_DIRENT *file;
1879 if ((dir = ws_dir_open(from_dir, 0, NULL)) != NULL) {
1880 while ((file = ws_dir_read_name(dir)) != NULL) {
1881 filename = ws_dir_get_name(file);
1882 from_file = ws_strdup_printf ("%s%s%s", from_dir, G_DIR_SEPARATOR_S, filename);
1883 if (test_for_directory(from_file) != EISDIR) {
1884 to_file = ws_strdup_printf ("%s%s%s", to_dir, G_DIR_SEPARATOR_S, filename);
1885 if (!copy_file_binary_mode(from_file, to_file)) {
1886 *pf_filename_return = g_strdup(filename);
1887 g_free (from_file);
1888 g_free (to_file);
1889 ret = -1;
1890 break;
1892 g_free (to_file);
1893 #if 0
1894 } else {
1895 /* The user has manually created a directory in the profile
1896 * directory. Do not copy the directory recursively (yet?)
1898 #endif
1900 g_free (from_file);
1902 ws_dir_close(dir);
1905 return ret;
1908 static int
1909 reset_default_profile(char **pf_dir_path_return)
1911 char *profile_dir = get_persconffile_dir(NULL);
1912 char *filename, *del_file;
1913 GList *files, *file;
1914 int ret = 0;
1916 files = g_hash_table_get_keys(profile_files);
1917 file = g_list_first(files);
1918 while (file) {
1919 filename = (char *)file->data;
1920 del_file = ws_strdup_printf("%s%s%s", profile_dir, G_DIR_SEPARATOR_S, filename);
1922 if (file_exists(del_file)) {
1923 ret = ws_remove(del_file);
1924 if (ret != 0) {
1925 *pf_dir_path_return = profile_dir;
1926 g_free(del_file);
1927 break;
1931 g_free(del_file);
1932 file = g_list_next(file);
1934 g_list_free(files);
1936 g_free(profile_dir);
1937 return ret;
1941 delete_persconffile_profile(const char *profilename, char **pf_dir_path_return)
1943 if (strcmp(profilename, DEFAULT_PROFILE) == 0) {
1944 return reset_default_profile(pf_dir_path_return);
1947 char *profile_dir = get_persconffile_dir(profilename);
1948 int ret = 0;
1950 if (test_for_directory (profile_dir) == EISDIR) {
1951 ret = delete_directory (profile_dir, pf_dir_path_return);
1954 g_free(profile_dir);
1955 return ret;
1959 rename_persconffile_profile(const char *fromname, const char *toname,
1960 char **pf_from_dir_path_return, char **pf_to_dir_path_return)
1962 char *from_dir = get_persconffile_dir(fromname);
1963 char *to_dir = get_persconffile_dir(toname);
1964 int ret = 0;
1966 ret = ws_rename (from_dir, to_dir);
1967 if (ret != 0) {
1968 *pf_from_dir_path_return = from_dir;
1969 *pf_to_dir_path_return = to_dir;
1970 return ret;
1973 g_free (from_dir);
1974 g_free (to_dir);
1976 return 0;
1980 * Create the directory that holds personal configuration files, if
1981 * necessary. If we attempted to create it, and failed, return -1 and
1982 * set "*pf_dir_path_return" to the pathname of the directory we failed
1983 * to create (it's g_mallocated, so our caller should free it); otherwise,
1984 * return 0.
1987 create_persconffile_profile(const char *profilename, char **pf_dir_path_return)
1989 char *pf_dir_path;
1990 #ifdef _WIN32
1991 char *pf_dir_path_copy, *pf_dir_parent_path;
1992 size_t pf_dir_parent_path_len;
1993 int save_errno;
1994 #endif
1995 ws_statb64 s_buf;
1996 int ret;
1998 if (profilename) {
2000 * Create the personal profiles directory, if necessary.
2002 if (create_profiles_dir(pf_dir_path_return) == -1) {
2003 return -1;
2007 pf_dir_path = get_persconffile_dir(profilename);
2008 if (ws_stat64(pf_dir_path, &s_buf) != 0) {
2009 if (errno != ENOENT) {
2010 /* Some other problem; give up now. */
2011 *pf_dir_path_return = pf_dir_path;
2012 return -1;
2014 #ifdef _WIN32
2016 * Does the parent directory of that directory
2017 * exist? %APPDATA% may not exist even though
2018 * %USERPROFILE% does.
2020 * We check for the existence of the directory
2021 * by first checking whether the parent directory
2022 * is just a drive letter and, if it's not, by
2023 * doing a "stat()" on it. If it's a drive letter,
2024 * or if the "stat()" succeeds, we assume it exists.
2026 pf_dir_path_copy = g_strdup(pf_dir_path);
2027 pf_dir_parent_path = get_dirname(pf_dir_path_copy);
2028 pf_dir_parent_path_len = strlen(pf_dir_parent_path);
2029 if (pf_dir_parent_path_len > 0
2030 && pf_dir_parent_path[pf_dir_parent_path_len - 1] != ':'
2031 && ws_stat64(pf_dir_parent_path, &s_buf) != 0) {
2033 * Not a drive letter and the stat() failed.
2035 if (errno != ENOENT) {
2036 /* Some other problem; give up now. */
2037 *pf_dir_path_return = pf_dir_path;
2038 save_errno = errno;
2039 g_free(pf_dir_path_copy);
2040 errno = save_errno;
2041 return -1;
2044 * No, it doesn't exist - make it first.
2046 ret = ws_mkdir(pf_dir_parent_path, 0755);
2047 if (ret == -1) {
2048 *pf_dir_path_return = pf_dir_parent_path;
2049 save_errno = errno;
2050 g_free(pf_dir_path);
2051 errno = save_errno;
2052 return -1;
2055 g_free(pf_dir_path_copy);
2056 ret = ws_mkdir(pf_dir_path, 0755);
2057 #else
2058 ret = g_mkdir_with_parents(pf_dir_path, 0755);
2059 #endif
2060 } else {
2062 * Something with that pathname exists; if it's not
2063 * a directory, we'll get an error if we try to put
2064 * something in it, so we don't fail here, we wait
2065 * for that attempt to fail.
2067 ret = 0;
2069 if (ret == -1)
2070 *pf_dir_path_return = pf_dir_path;
2071 else
2072 g_free(pf_dir_path);
2074 return ret;
2077 const GHashTable *
2078 allowed_profile_filenames(void)
2080 return profile_files;
2084 create_persconffile_dir(char **pf_dir_path_return)
2086 return create_persconffile_profile(persconfprofile, pf_dir_path_return);
2090 copy_persconffile_profile(const char *toname, const char *fromname, bool from_global,
2091 char **pf_filename_return, char **pf_to_dir_path_return, char **pf_from_dir_path_return)
2093 int ret = 0;
2094 char *from_dir;
2095 char *to_dir = get_persconffile_dir(toname);
2096 char *from_file, *to_file;
2097 const char *filename;
2098 GHashTableIter files;
2099 void * file;
2101 from_dir = get_profile_dir(fromname, from_global);
2103 if (!profile_files || do_store_persconffiles) {
2104 /* Either the profile_files hashtable does not exist yet
2105 * (this is very early in startup) or we are still adding
2106 * files to it. Just copy all the non-directories.
2108 ret = copy_directory(from_dir, to_dir, pf_filename_return);
2109 } else {
2111 g_hash_table_iter_init(&files, profile_files);
2112 while (g_hash_table_iter_next(&files, &file, NULL)) {
2113 filename = (const char *)file;
2114 from_file = ws_strdup_printf ("%s%s%s", from_dir, G_DIR_SEPARATOR_S, filename);
2115 to_file = ws_strdup_printf ("%s%s%s", to_dir, G_DIR_SEPARATOR_S, filename);
2117 if (test_for_regular_file(from_file) && !copy_file_binary_mode(from_file, to_file)) {
2118 *pf_filename_return = g_strdup(filename);
2119 g_free (from_file);
2120 g_free (to_file);
2121 ret = -1;
2122 break;
2125 g_free (to_file);
2126 g_free (from_file);
2130 if (ret != 0) {
2131 *pf_to_dir_path_return = to_dir;
2132 *pf_from_dir_path_return = from_dir;
2133 } else {
2134 g_free (to_dir);
2135 g_free (from_dir);
2138 return ret;
2142 * Get the (default) directory in which personal data is stored.
2144 * On Win32, this is the "My Documents" folder in the personal profile.
2145 * On UNIX this is simply the current directory, unless that's "/",
2146 * which it will be, for example, when Wireshark is run from the
2147 * Finder in macOS, in which case we use the user's home directory.
2149 /* XXX - should this and the get_home_dir() be merged? */
2150 extern const char *
2151 get_persdatafile_dir(void)
2153 /* Return the cached value, if available */
2154 if (persdatafile_dir != NULL)
2155 return persdatafile_dir;
2157 #ifdef _WIN32
2158 TCHAR tszPath[MAX_PATH];
2161 * Hint: SHGetFolderPath is not available on MSVC 6 - without
2162 * Platform SDK
2164 if (SHGetSpecialFolderPath(NULL, tszPath, CSIDL_PERSONAL, false)) {
2165 persdatafile_dir = g_utf16_to_utf8(tszPath, -1, NULL, NULL, NULL);
2166 return persdatafile_dir;
2167 } else {
2168 return "";
2170 #else
2172 * Get the current directory.
2174 persdatafile_dir = g_get_current_dir();
2175 if (persdatafile_dir == NULL) {
2176 /* XXX - can this fail? */
2178 * g_get_home_dir() returns a const gchar *; g_strdup() it
2179 * so that it's something that can be freed.
2181 persdatafile_dir = g_strdup(g_get_home_dir());
2182 } else if (strcmp(persdatafile_dir, "/") == 0) {
2183 g_free(persdatafile_dir);
2185 * See above.
2187 persdatafile_dir = g_strdup(g_get_home_dir());
2189 return persdatafile_dir;
2190 #endif
2193 void
2194 set_persdatafile_dir(const char *p)
2196 g_free(persdatafile_dir);
2197 persdatafile_dir = g_strdup(p);
2201 * Construct the path name of a personal configuration file, given the
2202 * file name.
2204 * On Win32, if "for_writing" is false, we check whether the file exists
2205 * and, if not, construct a path name relative to the ".wireshark"
2206 * subdirectory of the user's home directory, and check whether that
2207 * exists; if it does, we return that, so that configuration files
2208 * from earlier versions can be read.
2210 * The returned file name was g_malloc()'d so it must be g_free()d when the
2211 * caller is done with it.
2213 char *
2214 get_persconffile_path(const char *filename, bool from_profile)
2216 char *path, *dir = NULL;
2218 if (from_profile) {
2219 /* Store filenames so we know which filenames belongs to a configuration profile */
2220 profile_register_persconffile(filename);
2222 dir = get_persconffile_dir(persconfprofile);
2223 } else {
2224 dir = get_persconffile_dir(NULL);
2226 path = g_build_filename(dir, filename, NULL);
2228 g_free(dir);
2229 return path;
2233 * Construct the path name of a global configuration file, given the
2234 * file name.
2236 * The returned file name was g_malloc()'d so it must be g_free()d when the
2237 * caller is done with it.
2239 char *
2240 get_datafile_path(const char *filename)
2242 if (running_in_build_directory_flag && !strcmp(filename, "hosts")) {
2243 /* We're running in the build directory and the requested file is a
2244 * generated (or a test) file. Return the file name in the build
2245 * directory (not in the source/data directory).
2246 * (Oh the things we do to keep the source directory pristine...)
2248 return g_build_filename(get_progfile_dir(), filename, (char *)NULL);
2249 } else {
2250 return g_build_filename(get_datafile_dir(), filename, (char *)NULL);
2255 * Construct the path name of a global documentation file, given the
2256 * file name.
2258 * The returned file name was g_malloc()'d so it must be g_free()d when the
2259 * caller is done with it.
2261 char *
2262 get_docfile_path(const char *filename)
2264 if (running_in_build_directory_flag) {
2265 /* We're running in the build directory and the requested file is a
2266 * generated (or a test) file. Return the file name in the build
2267 * directory (not in the source/data directory).
2268 * (Oh the things we do to keep the source directory pristine...)
2270 return g_build_filename(get_progfile_dir(), filename, (char *)NULL);
2271 } else {
2272 return g_build_filename(get_doc_dir(), filename, (char *)NULL);
2277 * Return an error message for UNIX-style errno indications on open or
2278 * create operations.
2280 const char *
2281 file_open_error_message(int err, bool for_writing)
2283 const char *errmsg;
2284 static char errmsg_errno[1024+1];
2286 switch (err) {
2288 case ENOENT:
2289 if (for_writing)
2290 errmsg = "The path to the file \"%s\" doesn't exist.";
2291 else
2292 errmsg = "The file \"%s\" doesn't exist.";
2293 break;
2295 case EACCES:
2296 if (for_writing)
2297 errmsg = "You don't have permission to create or write to the file \"%s\".";
2298 else
2299 errmsg = "You don't have permission to read the file \"%s\".";
2300 break;
2302 case EISDIR:
2303 errmsg = "\"%s\" is a directory (folder), not a file.";
2304 break;
2306 case ENOSPC:
2307 errmsg = "The file \"%s\" could not be created because there is no space left on the file system.";
2308 break;
2310 #ifdef EDQUOT
2311 case EDQUOT:
2312 errmsg = "The file \"%s\" could not be created because you are too close to, or over, your disk quota.";
2313 break;
2314 #endif
2316 case EINVAL:
2317 errmsg = "The file \"%s\" could not be created because an invalid filename was specified.";
2318 break;
2320 #ifdef ENAMETOOLONG
2321 case ENAMETOOLONG:
2322 /* XXX Make sure we truncate on a character boundary. */
2323 errmsg = "The file name \"%.80s" UTF8_HORIZONTAL_ELLIPSIS "\" is too long.";
2324 break;
2325 #endif
2327 case ENOMEM:
2329 * The problem probably has nothing to do with how much RAM the
2330 * user has on their machine, so don't confuse them by saying
2331 * "memory". The problem is probably either virtual address
2332 * space or swap space.
2334 #if GLIB_SIZEOF_VOID_P == 4
2336 * ILP32; we probably ran out of virtual address space.
2338 #define ENOMEM_REASON "it can't be handled by a 32-bit application"
2339 #else
2341 * LP64 or LLP64; we probably ran out of swap space.
2343 #if defined(_WIN32)
2345 * You need to make the pagefile bigger.
2347 #define ENOMEM_REASON "the pagefile is too small"
2348 #elif defined(ENABLE_APPLICATION_BUNDLE)
2350 * dynamic_pager couldn't, or wouldn't, create more swap files.
2352 #define ENOMEM_REASON "your system ran out of swap file space"
2353 #else
2355 * Either you have a fixed swap partition or a fixed swap file,
2356 * and it needs to be made bigger.
2358 * This is UN*X, but it's not macOS, so we assume the user is
2359 * *somewhat* nerdy.
2361 #define ENOMEM_REASON "your system is out of swap space"
2362 #endif
2363 #endif /* GLIB_SIZEOF_VOID_P == 4 */
2364 if (for_writing)
2365 errmsg = "The file \"%s\" could not be created because " ENOMEM_REASON ".";
2366 else
2367 errmsg = "The file \"%s\" could not be opened because " ENOMEM_REASON ".";
2368 break;
2370 default:
2371 snprintf(errmsg_errno, sizeof(errmsg_errno),
2372 "The file \"%%s\" could not be %s: %s.",
2373 for_writing ? "created" : "opened",
2374 g_strerror(err));
2375 errmsg = errmsg_errno;
2376 break;
2378 return errmsg;
2382 * Return an error message for UNIX-style errno indications on write
2383 * operations.
2385 const char *
2386 file_write_error_message(int err)
2388 const char *errmsg;
2389 static char errmsg_errno[1024+1];
2391 switch (err) {
2393 case ENOSPC:
2394 errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
2395 break;
2397 #ifdef EDQUOT
2398 case EDQUOT:
2399 errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
2400 break;
2401 #endif
2403 default:
2404 snprintf(errmsg_errno, sizeof(errmsg_errno),
2405 "An error occurred while writing to the file \"%%s\": %s.",
2406 g_strerror(err));
2407 errmsg = errmsg_errno;
2408 break;
2410 return errmsg;
2414 bool
2415 file_exists(const char *fname)
2417 ws_statb64 file_stat;
2419 if (!fname) {
2420 return false;
2423 if (ws_stat64(fname, &file_stat) != 0 && errno == ENOENT) {
2424 return false;
2425 } else {
2426 return true;
2430 bool config_file_exists_with_entries(const char *fname, char comment_char)
2432 bool start_of_line = true;
2433 bool has_entries = false;
2434 FILE *file;
2435 int c;
2437 if (!fname) {
2438 return false;
2441 if ((file = ws_fopen(fname, "r")) == NULL) {
2442 return false;
2445 do {
2446 c = ws_getc_unlocked(file);
2447 if (start_of_line && c != comment_char && !g_ascii_isspace(c) && g_ascii_isprint(c)) {
2448 has_entries = true;
2449 break;
2451 if (c == '\n' || !g_ascii_isspace(c)) {
2452 start_of_line = (c == '\n');
2454 } while (c != EOF);
2456 fclose(file);
2457 return has_entries;
2461 * Check that the from file is not the same as to file
2462 * We do it here so we catch all cases ...
2463 * Unfortunately, the file requester gives us an absolute file
2464 * name and the read file name may be relative (if supplied on
2465 * the command line), so we can't just compare paths. From Joerg Mayer.
2467 bool
2468 files_identical(const char *fname1, const char *fname2)
2470 /* Two different implementations, because st_ino isn't filled in with
2471 * a meaningful value on Windows. Use the Windows API and FILE_ID_INFO
2472 * instead.
2474 #ifdef _WIN32
2476 FILE_ID_INFO filestat1, filestat2;
2479 * Compare VolumeSerialNumber and FileId.
2482 HANDLE h1 = CreateFile(utf_8to16(fname1), 0,
2483 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
2484 NULL, OPEN_EXISTING, 0, NULL);
2486 if (h1 == INVALID_HANDLE_VALUE) {
2487 return false;
2490 if (!GetFileInformationByHandleEx(h1, FileIdInfo, &filestat1, sizeof(FILE_ID_INFO))) {
2491 CloseHandle(h1);
2492 return false;
2494 CloseHandle(h1);
2496 HANDLE h2 = CreateFile(utf_8to16(fname2), 0,
2497 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
2498 NULL, OPEN_EXISTING, 0, NULL);
2500 if (h2 == INVALID_HANDLE_VALUE) {
2501 return false;
2504 if (!GetFileInformationByHandleEx(h2, FileIdInfo, &filestat2, sizeof(FILE_ID_INFO))) {
2505 CloseHandle(h2);
2506 return false;
2508 CloseHandle(h2);
2510 return ((memcmp(&filestat1.FileId, &filestat2.FileId, sizeof(FILE_ID_128)) == 0) &&
2511 filestat1.VolumeSerialNumber == filestat2.VolumeSerialNumber);
2512 #else
2513 ws_statb64 filestat1, filestat2;
2516 * Compare st_dev and st_ino.
2518 if (ws_stat64(fname1, &filestat1) == -1)
2519 return false; /* can't get info about the first file */
2520 if (ws_stat64(fname2, &filestat2) == -1)
2521 return false; /* can't get info about the second file */
2522 return (filestat1.st_dev == filestat2.st_dev &&
2523 filestat1.st_ino == filestat2.st_ino);
2524 #endif
2527 bool
2528 file_needs_reopen(int fd, const char* filename)
2530 #ifdef _WIN32
2531 /* Windows handles st_dev in a way unsuitable here:
2532 * * _fstat() simply casts the file descriptor (ws_fileno(fp)) to unsigned
2533 * and assigns this value to st_dev and st_rdev
2534 * * _wstat() converts drive letter (eg. C) to number (A=0, B=1, C=2, ...)
2535 * and assigns such number to st_dev and st_rdev
2537 * The st_ino parameter is simply zero as there is no specific assignment
2538 * to it in the Universal CRT source code.
2540 * Thus instead of using fstat(), use Windows specific API.
2543 HANDLE open_handle = (HANDLE)_get_osfhandle(fd);
2544 HANDLE current_handle = CreateFile(utf_8to16(filename), FILE_READ_ATTRIBUTES,
2545 FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
2546 NULL, OPEN_EXISTING, 0, NULL);
2547 BY_HANDLE_FILE_INFORMATION open_info, current_info;
2549 if (current_handle == INVALID_HANDLE_VALUE) {
2550 return true;
2553 #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
2554 FILE_ID_INFO open_id, current_id;
2555 if (GetFileInformationByHandleEx(open_handle, FileIdInfo, &open_id, sizeof(open_id)) &&
2556 GetFileInformationByHandleEx(current_handle, FileIdInfo, &current_id, sizeof(current_id))) {
2557 /* 128-bit identifier is available, use it */
2558 CloseHandle(current_handle);
2559 return open_id.VolumeSerialNumber != current_id.VolumeSerialNumber ||
2560 memcmp(&open_id.FileId, &current_id.FileId, sizeof(open_id.FileId)) != 0;
2562 #endif /* _WIN32_WINNT >= _WIN32_WINNT_WIN8 */
2563 if (GetFileInformationByHandle(open_handle, &open_info) &&
2564 GetFileInformationByHandle(current_handle, &current_info)) {
2565 /* Fallback to 64-bit identifier */
2566 CloseHandle(current_handle);
2567 uint64_t open_size = (((uint64_t)open_info.nFileSizeHigh) << 32) | open_info.nFileSizeLow;
2568 uint64_t current_size = (((uint64_t)current_info.nFileSizeHigh) << 32) | current_info.nFileSizeLow;
2569 return open_info.dwVolumeSerialNumber != current_info.dwVolumeSerialNumber ||
2570 open_info.nFileIndexHigh != current_info.nFileIndexHigh ||
2571 open_info.nFileIndexLow != current_info.nFileIndexLow ||
2572 open_size > current_size;
2574 CloseHandle(current_handle);
2575 return true;
2576 #else
2577 ws_statb64 open_stat, current_stat;
2579 /* consider a file deleted when stat fails for either file,
2580 * or when the residing device / inode has changed. */
2581 if (0 != ws_fstat64(fd, &open_stat))
2582 return true;
2583 if (0 != ws_stat64(filename, &current_stat))
2584 return true;
2586 return open_stat.st_dev != current_stat.st_dev ||
2587 open_stat.st_ino != current_stat.st_ino ||
2588 open_stat.st_size > current_stat.st_size;
2589 #endif
2592 bool
2593 write_file_binary_mode(const char *filename, const void *content, size_t content_len)
2595 int fd;
2596 size_t bytes_left;
2597 unsigned int bytes_to_write;
2598 ssize_t bytes_written;
2599 const uint8_t *ptr;
2600 int err;
2602 fd = ws_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
2603 if (fd == -1) {
2604 report_open_failure(filename, errno, true);
2605 return false;
2609 * The third argument to _write() on Windows is an unsigned int,
2610 * so, on Windows, that's the size of the third argument to
2611 * ws_write().
2613 * The third argument to write() on UN*X is a size_t, although
2614 * the return value is an ssize_t, so one probably shouldn't
2615 * write more than the max value of an ssize_t.
2617 * In either case, there's no guarantee that a size_t such as
2618 * content_len can be passed to ws_write(), so we write in
2619 * chunks of at most 2^31 bytes.
2622 ptr = (const uint8_t *)content;
2623 bytes_left = content_len;
2624 while (bytes_left != 0) {
2625 if (bytes_left > 0x40000000) {
2626 bytes_to_write = 0x40000000;
2627 } else {
2628 bytes_to_write = (unsigned int)bytes_left;
2630 bytes_written = ws_write(fd, ptr, bytes_to_write);
2631 if (bytes_written <= 0) {
2632 if (bytes_written < 0) {
2633 err = errno;
2634 } else {
2635 err = WTAP_ERR_SHORT_WRITE;
2637 report_write_failure(filename, err);
2638 ws_close(fd);
2639 return false;
2641 bytes_left -= bytes_written;
2642 ptr += bytes_written;
2645 ws_close(fd);
2646 return true;
2650 * Copy a file in binary mode, for those operating systems that care about
2651 * such things. This should be OK for all files, even text files, as
2652 * we'll copy the raw bytes, and we don't look at the bytes as we copy
2653 * them.
2655 * Returns true on success, false on failure. If a failure, it also
2656 * displays a simple dialog window with the error message.
2658 bool
2659 copy_file_binary_mode(const char *from_filename, const char *to_filename)
2661 int from_fd, to_fd, err;
2662 ws_file_ssize_t nread, nwritten;
2663 uint8_t *pd = NULL;
2665 /* Copy the raw bytes of the file. */
2666 from_fd = ws_open(from_filename, O_RDONLY | O_BINARY, 0000 /* no creation so don't matter */);
2667 if (from_fd < 0) {
2668 report_open_failure(from_filename, errno, false);
2669 goto done;
2672 /* Use open() instead of creat() so that we can pass the O_BINARY
2673 flag, which is relevant on Win32; it appears that "creat()"
2674 may open the file in text mode, not binary mode, but we want
2675 to copy the raw bytes of the file, so we need the output file
2676 to be open in binary mode. */
2677 to_fd = ws_open(to_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
2678 if (to_fd < 0) {
2679 report_open_failure(to_filename, errno, true);
2680 ws_close(from_fd);
2681 goto done;
2684 #define FS_READ_SIZE 65536
2685 pd = (uint8_t *)g_malloc(FS_READ_SIZE);
2686 while ((nread = ws_read(from_fd, pd, FS_READ_SIZE)) > 0) {
2687 nwritten = ws_write(to_fd, pd, nread);
2688 if (nwritten < nread) {
2689 if (nwritten < 0)
2690 err = errno;
2691 else
2692 err = WTAP_ERR_SHORT_WRITE;
2693 report_write_failure(to_filename, err);
2694 ws_close(from_fd);
2695 ws_close(to_fd);
2696 goto done;
2699 if (nread < 0) {
2700 err = errno;
2701 report_read_failure(from_filename, err);
2702 ws_close(from_fd);
2703 ws_close(to_fd);
2704 goto done;
2706 ws_close(from_fd);
2707 if (ws_close(to_fd) < 0) {
2708 report_write_failure(to_filename, errno);
2709 goto done;
2712 g_free(pd);
2713 pd = NULL;
2714 return true;
2716 done:
2717 g_free(pd);
2718 return false;
2721 char *
2722 data_file_url(const char *filename)
2724 char *file_path;
2725 char *uri;
2727 /* Absolute path? */
2728 if(g_path_is_absolute(filename)) {
2729 file_path = g_strdup(filename);
2730 } else {
2731 file_path = ws_strdup_printf("%s/%s", get_datafile_dir(), filename);
2734 /* XXX - check, if the file is really existing, otherwise display a simple_dialog about the problem */
2736 /* convert filename to uri */
2737 uri = g_filename_to_uri(file_path, NULL, NULL);
2738 g_free(file_path);
2739 return uri;
2742 char *
2743 doc_file_url(const char *filename)
2745 char *file_path;
2746 char *uri;
2748 /* Absolute path? */
2749 if(g_path_is_absolute(filename)) {
2750 file_path = g_strdup(filename);
2751 } else {
2752 file_path = ws_strdup_printf("%s/%s", get_doc_dir(), filename);
2755 /* XXX - check, if the file is really existing, otherwise display a simple_dialog about the problem */
2757 /* convert filename to uri */
2758 uri = g_filename_to_uri(file_path, NULL, NULL);
2759 g_free(file_path);
2760 return uri;
2763 void
2764 free_progdirs(void)
2766 g_free(persconffile_dir);
2767 persconffile_dir = NULL;
2768 g_free(datafile_dir);
2769 datafile_dir = NULL;
2770 g_free(persdatafile_dir);
2771 persdatafile_dir = NULL;
2772 g_free(persconfprofile);
2773 persconfprofile = NULL;
2774 g_free(progfile_dir);
2775 progfile_dir = NULL;
2776 g_free(doc_dir);
2777 doc_dir = NULL;
2778 g_free(install_prefix);
2779 install_prefix = NULL;
2780 g_free(current_working_dir);
2781 current_working_dir = NULL;
2782 #if defined(HAVE_PLUGINS) || defined(HAVE_LUA)
2783 g_free(plugin_dir);
2784 plugin_dir = NULL;
2785 g_free(plugin_dir_with_version);
2786 plugin_dir_with_version = NULL;
2787 g_free(plugin_pers_dir);
2788 plugin_pers_dir = NULL;
2789 g_free(plugin_pers_dir_with_version);
2790 plugin_pers_dir_with_version = NULL;
2791 #endif
2792 g_free(extcap_dir);
2793 extcap_dir = NULL;
2794 g_free(extcap_pers_dir);
2795 extcap_pers_dir = NULL;
2799 * Editor modelines
2801 * Local Variables:
2802 * c-basic-offset: 4
2803 * tab-width: 8
2804 * indent-tabs-mode: nil
2805 * End:
2807 * ex: set shiftwidth=4 tabstop=8 expandtab:
2808 * :indentSize=4:tabSize=8:noTabs=true: