TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags
[wireshark-sm.git] / wsutil / filesystem.c
blob56939d9ef7137931a8686e4c43933cdbb9fe5032
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/application_flavor.h>
44 #include <wsutil/file_util.h>
45 #include <wsutil/privileges.h>
46 #include <wsutil/report_message.h>
47 #include <wsutil/utf8_entities.h>
49 #include <wiretap/wtap.h> /* for WTAP_ERR_SHORT_WRITE */
51 #include "path_config.h"
53 #define PROFILES_DIR "profiles"
54 #define PLUGINS_DIR_NAME "plugins"
55 #define EXTCAP_DIR_NAME "extcap"
56 #define PROFILES_INFO_NAME "profile_files.txt"
58 #define _S G_DIR_SEPARATOR_S
60 char *persconffile_dir;
61 char *datafile_dir;
62 char *persdatafile_dir;
63 char *persconfprofile;
64 char *doc_dir;
65 char *current_working_dir;
67 /* Directory from which the executable came. */
68 static char *progfile_dir;
69 static char *install_prefix;
71 static bool do_store_persconffiles;
72 static GHashTable *profile_files;
75 * Given a pathname, return a pointer to the last pathname separator
76 * character in the pathname, or NULL if the pathname contains no
77 * separators.
79 char *
80 find_last_pathname_separator(const char *path)
82 char *separator;
84 #ifdef _WIN32
85 char c;
88 * We have to scan for '\' or '/'.
89 * Get to the end of the string.
91 separator = strchr(path, '\0'); /* points to ending '\0' */
92 while (separator > path) {
93 c = *--separator;
94 if (c == '\\' || c == '/')
95 return separator; /* found it */
99 * OK, we didn't find any, so no directories - but there might
100 * be a drive letter....
102 return strchr(path, ':');
103 #else
104 separator = strrchr(path, '/');
105 return separator;
106 #endif
110 * Given a pathname, return the last component.
112 const char *
113 get_basename(const char *path)
115 const char *filename;
117 ws_assert(path != NULL);
118 filename = find_last_pathname_separator(path);
119 if (filename == NULL) {
121 * There're no directories, drive letters, etc. in the
122 * name; the pathname *is* the file name.
124 filename = path;
125 } else {
127 * Skip past the pathname or drive letter separator.
129 filename++;
131 return filename;
135 * Given a pathname, return a string containing everything but the
136 * last component. NOTE: this overwrites the pathname handed into
137 * it....
139 char *
140 get_dirname(char *path)
142 char *separator;
144 ws_assert(path != NULL);
145 separator = find_last_pathname_separator(path);
146 if (separator == NULL) {
148 * There're no directories, drive letters, etc. in the
149 * name; there is no directory path to return.
151 return NULL;
155 * Get rid of the last pathname separator and the final file
156 * name following it.
158 *separator = '\0';
161 * "path" now contains the pathname of the directory containing
162 * the file/directory to which it referred.
164 return path;
168 * Given a pathname, return:
170 * the errno, if an attempt to "stat()" the file fails;
172 * EISDIR, if the attempt succeeded and the file turned out
173 * to be a directory;
175 * 0, if the attempt succeeded and the file turned out not
176 * to be a directory.
180 test_for_directory(const char *path)
182 ws_statb64 statb;
184 if (ws_stat64(path, &statb) < 0)
185 return errno;
187 if (S_ISDIR(statb.st_mode))
188 return EISDIR;
189 else
190 return 0;
194 test_for_fifo(const char *path)
196 ws_statb64 statb;
198 if (ws_stat64(path, &statb) < 0)
199 return errno;
201 if (S_ISFIFO(statb.st_mode))
202 return ESPIPE;
203 else
204 return 0;
207 bool
208 test_for_regular_file(const char *path)
210 ws_statb64 statb;
212 if (!path) {
213 return false;
216 if (ws_stat64(path, &statb) != 0)
217 return false;
219 return S_ISREG(statb.st_mode);
222 #ifdef ENABLE_APPLICATION_BUNDLE
224 * Directory of the application bundle in which we're contained,
225 * if we're contained in an application bundle. Otherwise, NULL.
227 * Note: Table 2-5 "Subdirectories of the Contents directory" of
229 * https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/BundleTypes/BundleTypes.html#//apple_ref/doc/uid/10000123i-CH101-SW1
231 * says that the "Frameworks" directory
233 * Contains any private shared libraries and frameworks used by the
234 * executable. The frameworks in this directory are revision-locked
235 * to the application and cannot be superseded by any other, even
236 * newer, versions that may be available to the operating system. In
237 * other words, the frameworks included in this directory take precedence
238 * over any other similarly named frameworks found in other parts of
239 * the operating system. For information on how to add private
240 * frameworks to your application bundle, see Framework Programming Guide.
242 * so if we were to ship with any frameworks (e.g. Qt) we should
243 * perhaps put them in a Frameworks directory rather than under
244 * Resources.
246 * It also says that the "PlugIns" directory
248 * Contains loadable bundles that extend the basic features of your
249 * application. You use this directory to include code modules that
250 * must be loaded into your applicationbs process space in order to
251 * be used. You would not use this directory to store standalone
252 * executables.
254 * Our plugins are just raw .so/.dylib files; I don't know whether by
255 * "bundles" they mean application bundles (i.e., directory hierarchies)
256 * or just "bundles" in the Mach-O sense (which are an image type that
257 * can be loaded with dlopen() but not linked as libraries; our plugins
258 * are, I think, built as dylibs and can be loaded either way).
260 * And it says that the "SharedSupport" directory
262 * Contains additional non-critical resources that do not impact the
263 * ability of the application to run. You might use this directory to
264 * include things like document templates, clip art, and tutorials
265 * that your application expects to be present but that do not affect
266 * the ability of your application to run.
268 * I don't think I'd put the files that currently go under Resources/share
269 * into that category; they're not, for example, sample Lua scripts that
270 * don't actually get run by Wireshark, they're configuration/data files
271 * for Wireshark whose absence might not prevent Wireshark from running
272 * but that would affect how it behaves when run.
274 static char *appbundle_dir;
275 #endif
278 * true if we're running from the build directory and we aren't running
279 * with special privileges.
281 static bool running_in_build_directory_flag;
283 static char *configuration_environment_variable(const char *suffix) {
284 switch (get_application_flavor()) {
285 case APPLICATION_FLAVOR_WIRESHARK:
286 return g_strdup_printf("WIRESHARK_%s", suffix);
287 case APPLICATION_FLAVOR_STRATOSHARK:
288 return g_strdup_printf("STRATOSHARK_%s", suffix);
289 default:
290 ws_assert_not_reached();
294 #ifndef _WIN32
296 * Get the pathname of the executable using various platform-
297 * dependent mechanisms for various UN*Xes.
299 * These calls all should return something independent of the argv[0]
300 * passed to the program, so it shouldn't be fooled by an argv[0]
301 * that doesn't match the executable path.
303 * We don't use dladdr() because:
305 * not all UN*Xes necessarily have dladdr();
307 * those that do have it don't necessarily have dladdr(main)
308 * return information about the executable image;
310 * those that do have a dladdr() where dladdr(main) returns
311 * information about the executable image don't necessarily
312 * have a mechanism by which the executable image can get
313 * its own path from the kernel (either by a call or by it
314 * being handed to it along with argv[] and the environment),
315 * so they just fall back on getting it from argv[0], which we
316 * already have code to do;
318 * those that do have such a mechanism don't necessarily use
319 * it in dladdr(), and, instead, just fall back on getting it
320 * from argv[0];
322 * so the only places where it's worth bothering to use dladdr()
323 * are platforms where dladdr(main) return information about the
324 * executable image by getting it from the kernel rather than
325 * by looking at argv[0], and where we can't get at that information
326 * ourselves, and we haven't seen any indication that there are any
327 * such platforms.
329 * In particular, some dynamic linkers supply a dladdr() such that
330 * dladdr(main) just returns something derived from argv[0], so
331 * just using dladdr(main) is the wrong thing to do if there's
332 * another mechanism that can get you a more reliable version of
333 * the executable path.
335 * So, on platforms where we know of a mechanism to get that path
336 * (where getting that path doesn't involve argv[0], which is not
337 * guaranteed to reflect the path to the binary), this routine
338 * attempsts to use that platform's mechanism. On other platforms,
339 * it just returns NULL.
341 * This is not guaranteed to return an absolute path; if it doesn't,
342 * our caller must prepend the current directory if it's a path.
344 * This is not guaranteed to return the "real path"; it might return
345 * something with symbolic links in the path. Our caller must
346 * use realpath() if they want the real thing, but that's also true of
347 * something obtained by looking at argv[0].
349 #define xx_free free /* hack so checkAPIs doesn't complain */
350 static const char *
351 get_current_executable_path(void)
353 #if defined(ENABLE_APPLICATION_BUNDLE)
354 static char *executable_path;
355 uint32_t path_buf_size;
357 if (executable_path) {
358 return executable_path;
361 path_buf_size = PATH_MAX;
362 executable_path = (char *)g_malloc(path_buf_size);
363 if (_NSGetExecutablePath(executable_path, &path_buf_size) == -1) {
364 executable_path = (char *)g_realloc(executable_path, path_buf_size);
365 if (_NSGetExecutablePath(executable_path, &path_buf_size) == -1)
366 return NULL;
369 * Resolve our path so that it's possible to symlink the executables
370 * in our application bundle.
372 char *rp_execpath = realpath(executable_path, NULL);
373 if (rp_execpath) {
374 g_free(executable_path);
375 executable_path = g_strdup(rp_execpath);
376 xx_free(rp_execpath);
378 return executable_path;
379 #elif defined(__linux__)
381 * In older versions of GNU libc's dynamic linker, as used on Linux,
382 * dladdr(main) supplies a path based on argv[0], so we use
383 * /proc/self/exe instead; there are Linux distributions with
384 * kernels that support /proc/self/exe and those older versions
385 * of the dynamic linker, and this will get a better answer on
386 * those versions.
388 * It only works on Linux 2.2 or later, so we just give up on
389 * earlier versions.
391 * XXX - are there OS versions that support "exe" but not "self"?
393 struct utsname name;
394 static char executable_path[PATH_MAX + 1];
395 ssize_t r;
397 if (uname(&name) == -1)
398 return NULL;
399 if (strncmp(name.release, "1.", 2) == 0)
400 return NULL; /* Linux 1.x */
401 if (strcmp(name.release, "2.0") == 0 ||
402 strncmp(name.release, "2.0.", 4) == 0 ||
403 strcmp(name.release, "2.1") == 0 ||
404 strncmp(name.release, "2.1.", 4) == 0)
405 return NULL; /* Linux 2.0.x or 2.1.x */
406 if ((r = readlink("/proc/self/exe", executable_path, PATH_MAX)) == -1)
407 return NULL;
408 executable_path[r] = '\0';
409 return executable_path;
410 #elif defined(__FreeBSD__) && defined(KERN_PROC_PATHNAME)
412 * In older versions of FreeBSD's dynamic linker, dladdr(main)
413 * supplies a path based on argv[0], so we use the KERN_PROC_PATHNAME
414 * sysctl instead; there are, I think, versions of FreeBSD
415 * that support the sysctl that have and those older versions
416 * of the dynamic linker, and this will get a better answer on
417 * those versions.
419 int mib[4];
420 char *executable_path;
421 size_t path_buf_size;
423 mib[0] = CTL_KERN;
424 mib[1] = KERN_PROC;
425 mib[2] = KERN_PROC_PATHNAME;
426 mib[3] = -1;
427 path_buf_size = PATH_MAX;
428 executable_path = (char *)g_malloc(path_buf_size);
429 if (sysctl(mib, 4, executable_path, &path_buf_size, NULL, 0) == -1) {
430 if (errno != ENOMEM)
431 return NULL;
432 executable_path = (char *)g_realloc(executable_path, path_buf_size);
433 if (sysctl(mib, 4, executable_path, &path_buf_size, NULL, 0) == -1)
434 return NULL;
436 return executable_path;
437 #elif defined(__NetBSD__)
439 * In all versions of NetBSD's dynamic linker as of 2013-08-12,
440 * dladdr(main) supplies a path based on argv[0], so we use
441 * /proc/curproc/exe instead.
443 * XXX - are there OS versions that support "exe" but not "curproc"
444 * or "self"? Are there any that support "self" but not "curproc"?
446 static char executable_path[PATH_MAX + 1];
447 ssize_t r;
449 if ((r = readlink("/proc/curproc/exe", executable_path, PATH_MAX)) == -1)
450 return NULL;
451 executable_path[r] = '\0';
452 return executable_path;
453 #elif defined(__DragonFly__)
455 * In older versions of DragonFly BSD's dynamic linker, dladdr(main)
456 * supplies a path based on argv[0], so we use /proc/curproc/file
457 * instead; it appears to be supported by all versions of DragonFly
458 * BSD.
460 static char executable_path[PATH_MAX + 1];
461 ssize_t r;
463 if ((r = readlink("/proc/curproc/file", executable_path, PATH_MAX)) == -1)
464 return NULL;
465 executable_path[r] = '\0';
466 return executable_path;
467 #elif defined(HAVE_GETEXECNAME)
469 * Solaris, with getexecname().
470 * It appears that getexecname() dates back to at least Solaris 8,
471 * but /proc/{pid}/path is first documented in the Solaris 10 documentation,
472 * so we use getexecname() if available, rather than /proc/self/path/a.out
473 * (which isn't documented, but appears to be a symlink to the
474 * executable image file).
476 return getexecname();
477 #elif defined(HAVE_DLGET)
479 * HP-UX 11, with dlget(); use dlget() and dlgetname().
480 * See
482 * https://web.archive.org/web/20081025174755/http://h21007.www2.hp.com/portal/site/dspp/menuitem.863c3e4cbcdc3f3515b49c108973a801?ciid=88086d6e1de021106d6e1de02110275d6e10RCRD#two
484 struct load_module_desc desc;
486 if (dlget(-2, &desc, sizeof(desc)) != NULL)
487 return dlgetname(&desc, sizeof(desc), NULL, NULL, NULL);
488 else
489 return NULL;
490 #else
491 /* Fill in your favorite UN*X's code here, if there is something */
492 return NULL;
493 #endif
495 #endif /* _WIN32 */
497 /* Extcap executables are in their own subdirectory. This trims that off and
498 * reduces progfile_dir to the common program file directory. */
499 static void trim_progfile_dir(void)
501 char *progfile_last_dir = find_last_pathname_separator(progfile_dir);
503 #ifdef _WIN32
505 * Check the flavor of our extcap subdirectory.
506 * XXX - Do we only need to do this on Windows, or on other platforms too?
508 if (progfile_last_dir && strncmp(progfile_last_dir + 1, application_flavor_name_lower(), strlen(application_flavor_name_lower())) == 0) {
509 char* flavor_last_dir = find_last_pathname_separator(progfile_dir);
510 char flavor_sep = *flavor_last_dir;
511 *flavor_last_dir = '\0';
513 progfile_last_dir = find_last_pathname_separator(progfile_dir);
515 if (!(progfile_last_dir && strncmp(progfile_last_dir + 1, "extcap", sizeof("extcap")) == 0)) {
517 * Not an extcap, restore the flavor separator (it might have been
518 * some other "wireshark" directory, especially on case insensitive
519 * filesystems.)
521 *flavor_last_dir = flavor_sep;
522 return;
524 } else
525 #endif
526 if (! (progfile_last_dir && strncmp(progfile_last_dir + 1, "extcap", sizeof("extcap")) == 0)) {
527 /* Check for an unflavored extcap directory. */
528 return;
531 *progfile_last_dir = '\0';
532 char *extcap_progfile_dir = progfile_dir;
533 progfile_dir = g_strdup(extcap_progfile_dir);
534 g_free(extcap_progfile_dir);
537 #if !defined(_WIN32) || defined(HAVE_MSYSTEM)
538 static char *
539 trim_last_dir_from_path(const char *_path)
541 char *path = ws_strdup(_path);
542 char *last_dir = find_last_pathname_separator(path);
543 if (last_dir) {
544 *last_dir = '\0';
546 return path;
548 #endif
551 * Construct the path name of a non-extcap Wireshark executable file,
552 * given the program name. The executable name doesn't include ".exe";
553 * append it on Windows, so that callers don't have to worry about that.
555 * This presumes that all non-extcap executables are in the same directory.
557 * The returned file name was g_malloc()'d so it must be g_free()d when the
558 * caller is done with it.
560 char *
561 get_executable_path(const char *program_name)
564 * Fail if we don't know what directory contains the executables.
566 if (progfile_dir == NULL)
567 return NULL;
569 #ifdef _WIN32
570 return ws_strdup_printf("%s\\%s.exe", progfile_dir, program_name);
571 #else
572 return ws_strdup_printf("%s/%s", progfile_dir, program_name);
573 #endif
577 * Get the pathname of the directory from which the executable came,
578 * and save it for future use. Returns NULL on success, and a
579 * g_mallocated string containing an error on failure.
581 #ifdef _WIN32
582 static char *
583 configuration_init_w32(const char* arg0 _U_)
585 TCHAR prog_pathname_w[_MAX_PATH+2];
586 char *prog_pathname;
587 DWORD error;
588 TCHAR *msg_w;
589 unsigned char *msg;
590 size_t msglen;
593 * Attempt to get the full pathname of the currently running
594 * program.
596 if (GetModuleFileName(NULL, prog_pathname_w, G_N_ELEMENTS(prog_pathname_w)) != 0 && GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
598 * XXX - Should we use g_utf16_to_utf8()?
600 prog_pathname = utf_16to8(prog_pathname_w);
602 * We got it; strip off the last component, which would be
603 * the file name of the executable, giving us the pathname
604 * of the directory where the executable resides.
606 progfile_dir = g_path_get_dirname(prog_pathname);
607 if (progfile_dir != NULL) {
608 /* We succeeded. */
609 trim_progfile_dir();
610 /* Now try to figure out if we're running in a build directory. */
611 char *wsutil_lib = g_build_filename(progfile_dir, "wsutil.lib", (char *)NULL);
612 if (file_exists(wsutil_lib)) {
613 running_in_build_directory_flag = true;
615 g_free(wsutil_lib);
616 } else {
618 * OK, no. What do we do now?
620 return ws_strdup_printf("No \\ in executable pathname \"%s\"",
621 prog_pathname);
623 } else {
625 * Oh, well. Return an indication of the error.
627 error = GetLastError();
628 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
629 NULL, error, 0, (LPTSTR) &msg_w, 0, NULL) == 0) {
631 * Gak. We can't format the message.
633 return ws_strdup_printf("GetModuleFileName failed: %lu (FormatMessage failed: %lu)",
634 error, GetLastError());
636 msg = utf_16to8(msg_w);
637 LocalFree(msg_w);
639 * "FormatMessage()" "helpfully" sticks CR/LF at the
640 * end of the message. Get rid of it.
642 msglen = strlen(msg);
643 if (msglen >= 2) {
644 msg[msglen - 1] = '\0';
645 msg[msglen - 2] = '\0';
647 return ws_strdup_printf("GetModuleFileName failed: %s (%lu)",
648 msg, error);
651 #ifdef HAVE_MSYSTEM
653 * We already have the program_dir. Find the installation prefix.
654 * This is one level up from the bin_dir. If the program_dir does
655 * not end with "bin" then assume we are running in the build directory
656 * and the "installation prefix" (staging directory) is the same as
657 * the program_dir.
659 if (g_str_has_suffix(progfile_dir, _S"bin")) {
660 install_prefix = trim_last_dir_from_path(progfile_dir);
662 else {
663 install_prefix = g_strdup(progfile_dir);
664 running_in_build_directory_flag = true;
666 #endif /* HAVE_MSYSTEM */
668 return NULL;
671 #else /* !_WIN32 */
673 static char *
674 configuration_init_posix(const char* arg0)
676 const char *execname;
677 char *prog_pathname;
678 char *curdir;
679 long path_max;
680 const char *pathstr;
681 const char *path_start, *path_end;
682 size_t path_component_len, path_len;
683 char *retstr;
684 char *path;
685 char *dir_end;
687 /* Hard-coded value used if we cannot obtain the path of the running executable. */
688 install_prefix = g_strdup(INSTALL_PREFIX);
691 * Check whether XXX_RUN_FROM_BUILD_DIRECTORY is set in the
692 * environment; if so, set running_in_build_directory_flag if we
693 * weren't started with special privileges. (If we were started
694 * with special privileges, it's not safe to allow the user to point
695 * us to some other directory; running_in_build_directory_flag, when
696 * set, causes us to look for plugins and the like in the build
697 * directory.)
699 char *run_from_envar = configuration_environment_variable("RUN_FROM_BUILD_DIRECTORY");
700 if (g_getenv(run_from_envar) != NULL && !started_with_special_privs()) {
701 running_in_build_directory_flag = true;
703 g_free(run_from_envar);
705 execname = get_current_executable_path();
706 if (execname == NULL) {
708 * OK, guess based on argv[0].
710 execname = arg0;
714 * Try to figure out the directory in which the currently running
715 * program resides, given something purporting to be the executable
716 * name (from an OS mechanism or from the argv[0] it was started with).
717 * That might be the absolute path of the program, or a path relative
718 * to the current directory of the process that started it, or
719 * just a name for the program if it was started from the command
720 * line and was searched for in $PATH. It's not guaranteed to be
721 * any of those, however, so there are no guarantees....
723 if (execname[0] == '/') {
725 * It's an absolute path.
727 prog_pathname = g_strdup(execname);
728 } else if (strchr(execname, '/') != NULL) {
730 * It's a relative path, with a directory in it.
731 * Get the current directory, and combine it
732 * with that directory.
734 path_max = pathconf(".", _PC_PATH_MAX);
735 if (path_max == -1) {
737 * We have no idea how big a buffer to
738 * allocate for the current directory.
740 return ws_strdup_printf("pathconf failed: %s\n",
741 g_strerror(errno));
743 curdir = (char *)g_malloc(path_max);
744 if (getcwd(curdir, path_max) == NULL) {
746 * It failed - give up, and just stick
747 * with DATA_DIR.
749 g_free(curdir);
750 return ws_strdup_printf("getcwd failed: %s\n",
751 g_strerror(errno));
753 path = ws_strdup_printf("%s/%s", curdir, execname);
754 g_free(curdir);
755 prog_pathname = path;
756 } else {
758 * It's just a file name.
759 * Search the path for a file with that name
760 * that's executable.
762 prog_pathname = NULL; /* haven't found it yet */
763 pathstr = g_getenv("PATH");
764 path_start = pathstr;
765 if (path_start != NULL) {
766 while (*path_start != '\0') {
767 path_end = strchr(path_start, ':');
768 if (path_end == NULL)
769 path_end = path_start + strlen(path_start);
770 path_component_len = path_end - path_start;
771 path_len = path_component_len + 1
772 + strlen(execname) + 1;
773 path = (char *)g_malloc(path_len);
774 memcpy(path, path_start, path_component_len);
775 path[path_component_len] = '\0';
776 (void) g_strlcat(path, "/", path_len);
777 (void) g_strlcat(path, execname, path_len);
778 if (access(path, X_OK) == 0) {
780 * Found it!
782 prog_pathname = path;
783 break;
787 * That's not it. If there are more
788 * path components to test, try them.
790 if (*path_end == ':')
791 path_end++;
792 path_start = path_end;
793 g_free(path);
795 if (prog_pathname == NULL) {
797 * Program not found in path.
799 return ws_strdup_printf("\"%s\" not found in \"%s\"",
800 execname, pathstr);
802 } else {
804 * PATH isn't set.
805 * XXX - should we pick a default?
807 return g_strdup("PATH isn't set");
812 * OK, we have what we think is the pathname
813 * of the program.
815 * First, find the last "/" in the directory,
816 * as that marks the end of the directory pathname.
818 dir_end = strrchr(prog_pathname, '/');
819 if (dir_end != NULL) {
821 * Found it. Strip off the last component,
822 * as that's the path of the program.
824 *dir_end = '\0';
827 * Is there a "/run" at the end?
829 dir_end = strrchr(prog_pathname, '/');
830 if (dir_end != NULL) {
831 if (!started_with_special_privs()) {
833 * Check for the CMake output directory. As people may name
834 * their directories "run" (really?), also check for the
835 * CMakeCache.txt file before assuming a CMake output dir.
837 if (strcmp(dir_end, "/run") == 0) {
838 char *cmake_file;
839 cmake_file = ws_strdup_printf("%.*s/CMakeCache.txt",
840 (int)(dir_end - prog_pathname),
841 prog_pathname);
842 if (file_exists(cmake_file))
843 running_in_build_directory_flag = true;
844 g_free(cmake_file);
846 #ifdef ENABLE_APPLICATION_BUNDLE
849 * Scan up the path looking for a component
850 * named "Contents". If we find it, we assume
851 * we're in a bundle, and that the top-level
852 * directory of the bundle is the one containing
853 * "Contents".
855 * Not all executables are in the Contents/MacOS
856 * directory, so we can't just check for those
857 * in the path and strip them off.
859 * XXX - should we assume that it's either
860 * Contents/MacOS or Resources/bin?
862 char *component_end, *p;
864 component_end = strchr(prog_pathname, '\0');
865 p = component_end;
866 for (;;) {
867 while (p >= prog_pathname && *p != '/')
868 p--;
869 if (p == prog_pathname) {
871 * We're looking at the first component of
872 * the pathname now, so we're definitely
873 * not in a bundle, even if we're in
874 * "/Contents".
876 break;
878 if (strncmp(p, "/Contents", component_end - p) == 0) {
879 /* Found it. */
880 appbundle_dir = (char *)g_malloc(p - prog_pathname + 1);
881 memcpy(appbundle_dir, prog_pathname, p - prog_pathname);
882 appbundle_dir[p - prog_pathname] = '\0';
883 break;
885 component_end = p;
886 p--;
889 #endif
894 * OK, we have the path we want.
896 progfile_dir = prog_pathname;
897 trim_progfile_dir();
898 } else {
900 * This "shouldn't happen"; we apparently
901 * have no "/" in the pathname.
902 * Just free up prog_pathname.
904 retstr = ws_strdup_printf("No / found in \"%s\"", prog_pathname);
905 g_free(prog_pathname);
906 return retstr;
910 * We already have the program_dir. Find the installation prefix.
911 * This is one level up from the bin_dir. If the program_dir does
912 * not end with "bin" then assume we are running in the build directory
913 * and the "installation prefix" (staging directory) is the same as
914 * the program_dir.
916 g_free(install_prefix);
917 if (g_str_has_suffix(progfile_dir, _S"bin")) {
918 install_prefix = trim_last_dir_from_path(progfile_dir);
920 else {
921 install_prefix = g_strdup(progfile_dir);
922 running_in_build_directory_flag = true;
925 return NULL;
927 #endif /* ?_WIN32 */
929 char *
930 configuration_init(const char* arg0)
932 #ifdef _WIN32
933 return configuration_init_w32(arg0);
934 #else
935 return configuration_init_posix(arg0);
936 #endif
940 * Get the directory in which the program resides.
942 const char *
943 get_progfile_dir(void)
945 return progfile_dir;
948 extern const char *
949 get_current_working_dir(void)
951 if (current_working_dir != NULL) {
952 return current_working_dir;
956 * It's good to cache this because on Windows Microsoft cautions
957 * against using GetCurrentDirectory except early on, e.g. when
958 * parsing command line options.
960 current_working_dir = g_get_current_dir();
962 * The above always returns something, with a fallback, e.g., on macOS
963 * if the program is run from Finder, of G_DIR_SEPARATOR_S.
964 * On Windows when run from a shortcut / taskbar it returns whatever
965 * the "run in" directory is on the shortcut, which is usually the
966 * directory where the program resides, which isn't that useful.
967 * Should we set it to the home directory on macOS or the
968 * "My Documents" folder on Windows in those cases,
969 * as we do in get_persdatafile_dir()? This isn't the default preference
970 * setting so perhaps caveat emptor is ok.
972 return current_working_dir;
976 * Get the directory in which the global configuration and data files are
977 * stored.
979 * On Windows, we use the directory in which the executable for this
980 * process resides.
982 * On macOS (when executed from an app bundle), use a directory within
983 * that app bundle.
985 * Otherwise, if the program was executed from the build directory, use the
986 * directory in which the executable for this process resides. In all other
987 * cases, use the DATA_DIR value that was set at compile time.
989 * XXX - if we ever make libwireshark a real library, used by multiple
990 * applications (more than just TShark and versions of Wireshark with
991 * various UIs), should the configuration files belong to the library
992 * (and be shared by all those applications) or to the applications?
994 * If they belong to the library, that could be done on UNIX by the
995 * configure script, but it's trickier on Windows, as you can't just
996 * use the pathname of the executable.
998 * If they belong to the application, that could be done on Windows
999 * by using the pathname of the executable, but we'd have to have it
1000 * passed in as an argument, in some call, on UNIX.
1002 * Note that some of those configuration files might be used by code in
1003 * libwireshark, some of them might be used by dissectors (would they
1004 * belong to libwireshark, the application, or a separate library?),
1005 * and some of them might be used by other code (the Wireshark preferences
1006 * file includes resolver preferences that control the behavior of code
1007 * in libwireshark, dissector preferences, and UI preferences, for
1008 * example).
1010 const char *
1011 get_datafile_dir(void)
1013 if (datafile_dir != NULL)
1014 return datafile_dir;
1016 char *data_dir_envar = configuration_environment_variable("DATA_DIR");
1017 if (g_getenv(data_dir_envar) && !started_with_special_privs()) {
1019 * The user specified a different directory for data files
1020 * and we aren't running with special privileges.
1021 * Let {WIRESHARK,STRATOSHARK}_DATA_DIR take precedence.
1022 * XXX - We might be able to dispense with the priv check
1024 datafile_dir = g_strdup(g_getenv(data_dir_envar));
1027 #if defined(HAVE_MSYSTEM)
1028 if (running_in_build_directory_flag) {
1029 datafile_dir = g_strdup(install_prefix);
1030 } else {
1031 datafile_dir = g_build_filename(install_prefix, DATA_DIR, application_flavor_name_lower(), (char *)NULL);
1033 #elif defined(_WIN32)
1035 * Do we have the pathname of the program? If so, assume we're
1036 * running an installed version of the program. If we fail,
1037 * we don't change "datafile_dir", and thus end up using the
1038 * default.
1040 * XXX - does NSIS put the installation directory into
1041 * "\HKEY_LOCAL_MACHINE\SOFTWARE\Wireshark\InstallDir"?
1042 * If so, perhaps we should read that from the registry,
1043 * instead.
1045 if (progfile_dir != NULL) {
1047 * Yes, we do; use that.
1049 datafile_dir = g_strdup(progfile_dir);
1050 } else {
1052 * No, we don't.
1053 * Fall back on the default installation directory.
1055 datafile_dir = g_strdup("C:\\Program Files\\Wireshark\\");
1057 #else
1058 #ifdef ENABLE_APPLICATION_BUNDLE
1060 * If we're running from an app bundle and weren't started
1061 * with special privileges, use the Contents/Resources/share/wireshark
1062 * subdirectory of the app bundle.
1064 * (appbundle_dir is not set to a non-null value if we're
1065 * started with special privileges, so we need only check
1066 * it; we don't need to call started_with_special_privs().)
1068 else if (appbundle_dir != NULL) {
1069 datafile_dir = ws_strdup_printf("%s/Contents/Resources/share/%s",
1070 appbundle_dir, application_flavor_name_lower());
1072 #endif
1073 else if (running_in_build_directory_flag && progfile_dir != NULL) {
1075 * We're (probably) being run from the build directory and
1076 * weren't started with special privileges.
1078 * (running_in_build_directory_flag is never set to true
1079 * if we're started with special privileges, so we need
1080 * only check it; we don't need to call started_with_special_privs().)
1082 * Data files (dtds/, radius/, etc.) are copied to the build
1083 * directory during the build which also contains executables. A special
1084 * exception is macOS (when built with an app bundle).
1086 datafile_dir = g_strdup(progfile_dir);
1087 } else {
1088 if (g_path_is_absolute(DATA_DIR)) {
1089 datafile_dir = g_build_filename(DATA_DIR, application_flavor_name_lower(), (char *)NULL);
1090 } else {
1091 datafile_dir = g_build_filename(install_prefix, DATA_DIR, application_flavor_name_lower(), (char *)NULL);
1094 #endif
1095 g_free(data_dir_envar);
1096 return datafile_dir;
1099 const char *
1100 get_doc_dir(void)
1102 if (doc_dir != NULL)
1103 return doc_dir;
1105 /* No environment variable for this. */
1106 if (false) {
1110 #if defined(HAVE_MSYSTEM)
1111 if (running_in_build_directory_flag) {
1112 doc_dir = g_strdup(install_prefix);
1113 } else {
1114 doc_dir = g_build_filename(install_prefix, DOC_DIR, (char *)NULL);
1116 #elif defined(_WIN32)
1117 if (progfile_dir != NULL) {
1118 doc_dir = g_strdup(progfile_dir);
1119 } else {
1120 /* Fall back on the default installation directory. */
1121 doc_dir = g_strdup("C:\\Program Files\\Wireshark\\");
1123 #else
1124 #ifdef ENABLE_APPLICATION_BUNDLE
1126 * If we're running from an app bundle and weren't started
1127 * with special privileges, use the Contents/Resources/share/wireshark
1128 * subdirectory of the app bundle.
1130 * (appbundle_dir is not set to a non-null value if we're
1131 * started with special privileges, so we need only check
1132 * it; we don't need to call started_with_special_privs().)
1134 else if (appbundle_dir != NULL) {
1135 doc_dir = g_strdup(get_datafile_dir());
1137 #endif
1138 else if (running_in_build_directory_flag && progfile_dir != NULL) {
1140 * We're (probably) being run from the build directory and
1141 * weren't started with special privileges.
1143 doc_dir = g_strdup(progfile_dir);
1144 } else {
1145 if (g_path_is_absolute(DOC_DIR)) {
1146 doc_dir = g_strdup(DOC_DIR);
1147 } else {
1148 doc_dir = g_build_filename(install_prefix, DOC_DIR, (char *)NULL);
1151 #endif
1152 return doc_dir;
1156 * Find the directory where the plugins are stored.
1158 * On Windows, we use the plugin\{VERSION} subdirectory of the datafile
1159 * directory, where {VERSION} is the version number of this version of
1160 * Wireshark.
1162 * On UN*X:
1164 * if we appear to be run from the build directory, we use the
1165 * "plugin" subdirectory of the datafile directory;
1167 * otherwise, if the WIRESHARK_PLUGIN_DIR environment variable is
1168 * set and we aren't running with special privileges, we use the
1169 * value of that environment variable;
1171 * otherwise, if we're running from an app bundle in macOS, we
1172 * use the Contents/PlugIns/wireshark subdirectory of the app bundle;
1174 * otherwise, we use the PLUGIN_DIR value supplied by the
1175 * configure script.
1177 static char *plugin_dir;
1178 static char *plugin_dir_with_version;
1179 static char *plugin_pers_dir;
1180 static char *plugin_pers_dir_with_version;
1181 static char *extcap_pers_dir;
1183 static void
1184 init_plugin_dir(void)
1186 char *plugin_dir_envar = configuration_environment_variable("PLUGIN_DIR");
1187 if (g_getenv(plugin_dir_envar) && !started_with_special_privs()) {
1189 * The user specified a different directory for plugins
1190 * and we aren't running with special privileges.
1191 * Let {WIRESHARK,STRATOSHARK}_PLUGIN_DIR take precedence.
1193 plugin_dir = g_strdup(g_getenv(plugin_dir_envar));
1196 #if defined(HAVE_PLUGINS) || defined(HAVE_LUA)
1197 #if defined(HAVE_MSYSTEM)
1198 else if (running_in_build_directory_flag) {
1199 plugin_dir = g_build_filename(install_prefix, "plugins", (char *)NULL);
1200 } else {
1201 plugin_dir = g_build_filename(install_prefix, PLUGIN_DIR, (char *)NULL);
1203 #elif defined(_WIN32)
1204 else {
1206 * On Windows, plugins are stored under the program file directory
1207 * in both the build and the installation directories.
1209 plugin_dir = g_build_filename(get_progfile_dir(), "plugins", (char *)NULL);
1211 #else
1212 #ifdef ENABLE_APPLICATION_BUNDLE
1214 * If we're running from an app bundle and weren't started
1215 * with special privileges, use the Contents/PlugIns/wireshark
1216 * subdirectory of the app bundle.
1218 * (appbundle_dir is not set to a non-null value if we're
1219 * started with special privileges, so we need only check
1220 * it; we don't need to call started_with_special_privs().)
1222 else if (appbundle_dir != NULL) {
1223 plugin_dir = g_build_filename(appbundle_dir, "Contents/PlugIns",
1224 application_flavor_name_lower(), (char *)NULL);
1226 #endif // ENABLE_APPLICATION_BUNDLE
1227 else if (running_in_build_directory_flag) {
1229 * We're (probably) being run from the build directory and
1230 * weren't started with special privileges, so we'll use
1231 * the "plugins" subdirectory of the directory where the program
1232 * we're running is (that's the build directory).
1234 plugin_dir = g_build_filename(get_progfile_dir(), "plugins", (char *)NULL);
1235 } else {
1236 if (g_path_is_absolute(PLUGIN_DIR)) {
1237 plugin_dir = g_strdup(PLUGIN_DIR);
1238 } else {
1239 plugin_dir = g_build_filename(install_prefix, PLUGIN_DIR, (char *)NULL);
1242 #endif // HAVE_MSYSTEM / _WIN32
1243 #endif /* defined(HAVE_PLUGINS) || defined(HAVE_LUA) */
1244 g_free(plugin_dir_envar);
1247 static void
1248 init_plugin_pers_dir(void)
1250 #if defined(HAVE_PLUGINS) || defined(HAVE_LUA)
1251 #ifdef _WIN32
1252 plugin_pers_dir = get_persconffile_path(PLUGINS_DIR_NAME, false);
1253 #else
1254 plugin_pers_dir = g_build_filename(g_get_home_dir(), ".local/lib",
1255 application_flavor_name_lower(), PLUGINS_DIR_NAME, (char *)NULL);
1256 #endif
1257 #endif /* defined(HAVE_PLUGINS) || defined(HAVE_LUA) */
1261 * Get the directory in which the plugins are stored.
1263 const char *
1264 get_plugins_dir(void)
1266 if (!plugin_dir)
1267 init_plugin_dir();
1268 return plugin_dir;
1271 const char *
1272 get_plugins_dir_with_version(void)
1274 if (!plugin_dir)
1275 init_plugin_dir();
1276 if (plugin_dir && !plugin_dir_with_version)
1277 plugin_dir_with_version = g_build_filename(plugin_dir, PLUGIN_PATH_ID, (char *)NULL);
1278 return plugin_dir_with_version;
1281 /* Get the personal plugin dir */
1282 const char *
1283 get_plugins_pers_dir(void)
1285 if (!plugin_pers_dir)
1286 init_plugin_pers_dir();
1287 return plugin_pers_dir;
1290 const char *
1291 get_plugins_pers_dir_with_version(void)
1293 if (!plugin_pers_dir)
1294 init_plugin_pers_dir();
1295 if (plugin_pers_dir && !plugin_pers_dir_with_version)
1296 plugin_pers_dir_with_version = g_build_filename(plugin_pers_dir, PLUGIN_PATH_ID, (char *)NULL);
1297 return plugin_pers_dir_with_version;
1301 * Find the directory where the extcap hooks are stored.
1303 * If the WIRESHARK_EXTCAP_DIR environment variable is set and we are not
1304 * running with special privileges, use that. Otherwise:
1306 * On Windows, we use the "extcap" subdirectory of the program directory.
1308 * On UN*X:
1310 * if we appear to be run from the build directory, we use the
1311 * "extcap" subdirectory of the build directory.
1313 * otherwise, if we're running from an app bundle in macOS, we
1314 * use the Contents/MacOS/extcap subdirectory of the app bundle;
1316 * otherwise, we use the EXTCAP_DIR value supplied by CMake.
1318 static char *extcap_dir;
1320 static void
1321 init_extcap_dir(void)
1323 char *extcap_dir_envar = configuration_environment_variable("EXTCAP_DIR");
1324 if (g_getenv(extcap_dir_envar) && !started_with_special_privs()) {
1326 * The user specified a different directory for extcap hooks
1327 * and we aren't running with special privileges.
1329 extcap_dir = g_strdup(g_getenv(extcap_dir_envar));
1332 #if defined(HAVE_MSYSTEM)
1333 else if (running_in_build_directory_flag) {
1334 extcap_dir = g_build_filename(install_prefix, "extcap", (char *)NULL);
1335 } else {
1336 extcap_dir = g_build_filename(install_prefix, EXTCAP_DIR, (char *)NULL);
1338 #elif defined(_WIN32)
1340 * On Windows, extcap utilities are stored in "extcap/<program name>"
1341 * in the build directory and in "extcap" in the installation
1342 * directory.
1344 else if (running_in_build_directory_flag) {
1345 extcap_dir = g_build_filename(get_progfile_dir(), EXTCAP_DIR_NAME,
1346 application_flavor_name_lower(), (char *)NULL);
1347 } else {
1348 extcap_dir = g_build_filename(get_progfile_dir(), EXTCAP_DIR_NAME,
1349 (char *)NULL);
1351 #else
1352 #ifdef ENABLE_APPLICATION_BUNDLE
1353 else if (appbundle_dir != NULL) {
1355 * If we're running from an app bundle and weren't started
1356 * with special privileges, use the Contents/MacOS/extcap
1357 * subdirectory of the app bundle.
1359 * (appbundle_dir is not set to a non-null value if we're
1360 * started with special privileges, so we need only check
1361 * it; we don't need to call started_with_special_privs().)
1363 extcap_dir = g_build_filename(appbundle_dir, "Contents/MacOS/extcap", (char *)NULL);
1365 #endif // ENABLE_APPLICATION_BUNDLE
1366 else if (running_in_build_directory_flag) {
1368 * We're (probably) being run from the build directory and
1369 * weren't started with special privileges, so we'll use
1370 * the "extcap hooks" subdirectory of the directory where the program
1371 * we're running is (that's the build directory).
1373 extcap_dir = g_build_filename(get_progfile_dir(), EXTCAP_DIR_NAME,
1374 application_flavor_name_lower(), (char *)NULL);
1376 else {
1377 if (g_path_is_absolute(EXTCAP_DIR)) {
1378 extcap_dir = g_strdup(get_application_flavor() == APPLICATION_FLAVOR_WIRESHARK ? EXTCAP_DIR : LOG_EXTCAP_DIR);
1379 } else {
1380 extcap_dir = g_build_filename(install_prefix,
1381 get_application_flavor() == APPLICATION_FLAVOR_WIRESHARK ? EXTCAP_DIR : LOG_EXTCAP_DIR, (char *)NULL);
1384 #endif // HAVE_MSYSTEM / _WIN32
1385 g_free(extcap_dir_envar);
1388 static void
1389 init_extcap_pers_dir(void)
1391 #ifdef _WIN32
1392 extcap_pers_dir = get_persconffile_path(EXTCAP_DIR_NAME, false);
1393 #else
1394 extcap_pers_dir = g_build_filename(g_get_home_dir(), ".local/lib",
1395 application_flavor_name_lower(), EXTCAP_DIR_NAME, (char *)NULL);
1396 #endif
1400 * Get the directory in which the extcap hooks are stored.
1403 const char *
1404 get_extcap_dir(void)
1406 if (!extcap_dir)
1407 init_extcap_dir();
1408 return extcap_dir;
1411 /* Get the personal plugin dir */
1412 const char *
1413 get_extcap_pers_dir(void)
1415 if (!extcap_pers_dir)
1416 init_extcap_pers_dir();
1417 return extcap_pers_dir;
1421 * Get the flag indicating whether we're running from a build
1422 * directory.
1424 bool
1425 running_in_build_directory(void)
1427 return running_in_build_directory_flag;
1431 * Get the directory in which files that, at least on UNIX, are
1432 * system files (such as "/etc/ethers") are stored; on Windows,
1433 * there's no "/etc" directory, so we get them from the global
1434 * configuration and data file directory.
1436 const char *
1437 get_systemfile_dir(void)
1439 #ifdef _WIN32
1440 return get_datafile_dir();
1441 #else
1442 return "/etc";
1443 #endif
1446 void
1447 set_profile_name(const char *profilename)
1449 g_free (persconfprofile);
1451 if (profilename && strlen(profilename) > 0 &&
1452 strcmp(profilename, DEFAULT_PROFILE) != 0) {
1453 persconfprofile = g_strdup (profilename);
1454 } else {
1455 /* Default Profile */
1456 persconfprofile = NULL;
1460 const char *
1461 get_profile_name(void)
1463 if (persconfprofile) {
1464 return persconfprofile;
1465 } else {
1466 return DEFAULT_PROFILE;
1470 bool
1471 is_default_profile(void)
1473 return (!persconfprofile || strcmp(persconfprofile, DEFAULT_PROFILE) == 0) ? true : false;
1476 bool
1477 has_global_profiles(void)
1479 WS_DIR *dir;
1480 WS_DIRENT *file;
1481 char *global_dir = get_global_profiles_dir();
1482 char *filename;
1483 bool has_global = false;
1485 if ((test_for_directory(global_dir) == EISDIR) &&
1486 ((dir = ws_dir_open(global_dir, 0, NULL)) != NULL))
1488 while ((file = ws_dir_read_name(dir)) != NULL) {
1489 filename = ws_strdup_printf ("%s%s%s", global_dir, G_DIR_SEPARATOR_S,
1490 ws_dir_get_name(file));
1491 if (test_for_directory(filename) == EISDIR) {
1492 has_global = true;
1493 g_free (filename);
1494 break;
1496 g_free (filename);
1498 ws_dir_close(dir);
1500 g_free(global_dir);
1501 return has_global;
1504 void
1505 profile_store_persconffiles(bool store)
1507 if (store) {
1508 profile_files = g_hash_table_new (g_str_hash, g_str_equal);
1510 do_store_persconffiles = store;
1513 void
1514 profile_register_persconffile(const char *filename)
1516 if (do_store_persconffiles && !g_hash_table_lookup (profile_files, filename)) {
1517 /* Store filenames so we know which filenames belongs to a configuration profile */
1518 g_hash_table_insert (profile_files, g_strdup(filename), g_strdup(filename));
1523 * Get the directory in which personal configuration files reside.
1525 * On Windows, it's "Wireshark", under %APPDATA% or, if %APPDATA% isn't set,
1526 * it's "%USERPROFILE%\Application Data" (which is what %APPDATA% normally
1527 * is on Windows 2000).
1529 * On UNIX-compatible systems, we first look in XDG_CONFIG_HOME/wireshark
1530 * and, if that doesn't exist, ~/.wireshark, for backwards compatibility.
1531 * If neither exists, we use XDG_CONFIG_HOME/wireshark, so that the directory
1532 * is initially created as XDG_CONFIG_HOME/wireshark. We use that regardless
1533 * of whether the user is running under an XDG desktop or not, so that
1534 * if the user's home directory is on a server and shared between
1535 * different desktop environments on different machines, they can all
1536 * share the same configuration file directory.
1538 * XXX - what about stuff that shouldn't be shared between machines,
1539 * such as plugins in the form of shared loadable images?
1541 static const char *
1542 get_persconffile_dir_no_profile(void)
1544 const char *env;
1546 /* Return the cached value, if available */
1547 if (persconffile_dir != NULL)
1548 return persconffile_dir;
1551 * See if the user has selected an alternate environment.
1553 char *config_dir_envar = configuration_environment_variable("CONFIG_DIR");
1554 env = g_getenv(config_dir_envar);
1555 g_free(config_dir_envar);
1556 #ifdef _WIN32
1557 if (env == NULL) {
1559 * The PortableApps launcher sets this environment variable.
1560 * XXX - That's only for the GUI. We don't have launchers/batch
1561 * scripts for the command line tools, and just package the same
1562 * binaries as built for NSIS and WiX, so if the user is running
1563 * tshark from the PortableApps directory, how do we tell? (#20095)
1565 env = g_getenv("WIRESHARK_APPDATA");
1567 #endif
1568 if (env != NULL) {
1569 persconffile_dir = g_strdup(env);
1570 return persconffile_dir;
1573 #ifdef _WIN32
1575 * Use %APPDATA% or %USERPROFILE%, so that configuration
1576 * files are stored in the user profile, rather than in
1577 * the home directory. The Windows convention is to store
1578 * configuration information in the user profile, and doing
1579 * so means you can use Wireshark even if the home directory
1580 * is an inaccessible network drive.
1582 env = g_getenv("APPDATA");
1583 if (env != NULL) {
1585 * Concatenate %APPDATA% with "\Wireshark" or "\Stratoshark".
1587 persconffile_dir = g_build_filename(env, application_flavor_name_proper(), NULL);
1588 return persconffile_dir;
1592 * OK, %APPDATA% wasn't set, so use %USERPROFILE%\Application Data.
1594 env = g_getenv("USERPROFILE");
1595 if (env != NULL) {
1596 persconffile_dir = g_build_filename(env, "Application Data", application_flavor_name_proper(), NULL);
1597 return persconffile_dir;
1601 * Give up and use "C:".
1603 persconffile_dir = g_build_filename("C:", application_flavor_name_proper(), NULL);
1604 return persconffile_dir;
1605 #else
1606 char *xdg_path, *path;
1607 struct passwd *pwd;
1608 const char *homedir;
1611 * Check if XDG_CONFIG_HOME/wireshark exists and is a directory.
1613 xdg_path = g_build_filename(g_get_user_config_dir(),
1614 application_flavor_name_lower(), NULL);
1615 if (g_file_test(xdg_path, G_FILE_TEST_IS_DIR)) {
1616 persconffile_dir = xdg_path;
1617 return persconffile_dir;
1621 * It doesn't exist, or it does but isn't a directory, so try
1622 * ~/.wireshark.
1624 * If $HOME is set, use that for ~.
1626 * (Note: before GLib 2.36, g_get_home_dir() didn't look at $HOME,
1627 * but we always want to do so, so we don't use g_get_home_dir().)
1629 homedir = g_getenv("HOME");
1630 if (homedir == NULL) {
1632 * It's not set.
1634 * Get their home directory from the password file.
1635 * If we can't even find a password file entry for them,
1636 * use "/tmp".
1638 pwd = getpwuid(getuid());
1639 if (pwd != NULL) {
1640 homedir = pwd->pw_dir;
1641 } else {
1642 homedir = "/tmp";
1645 char *dotted_app = g_strdup_printf(".%s", application_flavor_name_lower());
1646 path = g_build_filename(homedir, dotted_app, NULL);
1647 g_free(dotted_app);
1648 if (g_file_test(path, G_FILE_TEST_IS_DIR)) {
1649 g_free(xdg_path);
1650 persconffile_dir = path;
1651 return persconffile_dir;
1655 * Neither are directories that exist; use the XDG path, so we'll
1656 * create that as necessary.
1658 g_free(path);
1659 persconffile_dir = xdg_path;
1660 return persconffile_dir;
1661 #endif
1664 void
1665 set_persconffile_dir(const char *p)
1667 g_free(persconffile_dir);
1668 persconffile_dir = g_strdup(p);
1671 char *
1672 get_profiles_dir(void)
1674 return ws_strdup_printf ("%s%s%s", get_persconffile_dir_no_profile (),
1675 G_DIR_SEPARATOR_S, PROFILES_DIR);
1679 create_profiles_dir(char **pf_dir_path_return)
1681 char *pf_dir_path;
1682 ws_statb64 s_buf;
1685 * Create the "Default" personal configuration files directory, if necessary.
1687 if (create_persconffile_profile (NULL, pf_dir_path_return) == -1) {
1688 return -1;
1692 * Check if profiles directory exists.
1693 * If not then create it.
1695 pf_dir_path = get_profiles_dir ();
1696 if (ws_stat64(pf_dir_path, &s_buf) != 0) {
1697 if (errno != ENOENT) {
1698 /* Some other problem; give up now. */
1699 *pf_dir_path_return = pf_dir_path;
1700 return -1;
1704 * It doesn't exist; try to create it.
1706 int ret = ws_mkdir(pf_dir_path, 0755);
1707 if (ret == -1) {
1708 *pf_dir_path_return = pf_dir_path;
1709 return ret;
1712 g_free(pf_dir_path);
1714 return 0;
1717 char *
1718 get_global_profiles_dir(void)
1720 return ws_strdup_printf ("%s%s%s", get_datafile_dir(),
1721 G_DIR_SEPARATOR_S, PROFILES_DIR);
1724 static char *
1725 get_persconffile_dir(const char *profilename)
1727 char *persconffile_profile_dir = NULL, *profile_dir;
1729 if (profilename && strlen(profilename) > 0 &&
1730 strcmp(profilename, DEFAULT_PROFILE) != 0) {
1731 profile_dir = get_profiles_dir();
1732 persconffile_profile_dir = ws_strdup_printf ("%s%s%s", profile_dir,
1733 G_DIR_SEPARATOR_S, profilename);
1734 g_free(profile_dir);
1735 } else {
1736 persconffile_profile_dir = g_strdup (get_persconffile_dir_no_profile ());
1739 return persconffile_profile_dir;
1742 char *
1743 get_profile_dir(const char *profilename, bool is_global)
1745 char *profile_dir;
1747 if (is_global) {
1748 if (profilename && strlen(profilename) > 0 &&
1749 strcmp(profilename, DEFAULT_PROFILE) != 0)
1751 char *global_path = get_global_profiles_dir();
1752 profile_dir = g_build_filename(global_path, profilename, NULL);
1753 g_free(global_path);
1754 } else {
1755 profile_dir = g_strdup(get_datafile_dir());
1757 } else {
1759 * If we didn't supply a profile name, i.e. if profilename is
1760 * null, get_persconffile_dir() returns the default profile.
1762 profile_dir = get_persconffile_dir(profilename);
1765 return profile_dir;
1768 bool
1769 profile_exists(const char *profilename, bool global)
1771 char *path = NULL;
1772 bool exists;
1775 * If we're looking up a global profile, we must have a
1776 * profile name.
1778 if (global && !profilename)
1779 return false;
1781 path = get_profile_dir(profilename, global);
1782 exists = (test_for_directory(path) == EISDIR) ? true : false;
1784 g_free(path);
1785 return exists;
1788 static int
1789 delete_directory (const char *directory, char **pf_dir_path_return)
1791 WS_DIR *dir;
1792 WS_DIRENT *file;
1793 char *filename;
1794 int ret = 0;
1796 if ((dir = ws_dir_open(directory, 0, NULL)) != NULL) {
1797 while ((file = ws_dir_read_name(dir)) != NULL) {
1798 filename = ws_strdup_printf ("%s%s%s", directory, G_DIR_SEPARATOR_S,
1799 ws_dir_get_name(file));
1800 if (test_for_directory(filename) != EISDIR) {
1801 ret = ws_remove(filename);
1802 #if 0
1803 } else {
1804 /* The user has manually created a directory in the profile directory */
1805 /* I do not want to delete the directory recursively yet */
1806 ret = delete_directory (filename, pf_dir_path_return);
1807 #endif
1809 if (ret != 0) {
1810 *pf_dir_path_return = filename;
1811 break;
1813 g_free (filename);
1815 ws_dir_close(dir);
1818 if (ret == 0 && (ret = ws_remove(directory)) != 0) {
1819 *pf_dir_path_return = g_strdup (directory);
1822 return ret;
1825 /* Copy files from one directory to another. Does not recursively copy directories */
1826 static int
1827 copy_directory(const char *from_dir, const char *to_dir, char **pf_filename_return)
1829 int ret = 0;
1830 char *from_file, *to_file;
1831 const char *filename;
1832 WS_DIR *dir;
1833 WS_DIRENT *file;
1835 if ((dir = ws_dir_open(from_dir, 0, NULL)) != NULL) {
1836 while ((file = ws_dir_read_name(dir)) != NULL) {
1837 filename = ws_dir_get_name(file);
1838 from_file = ws_strdup_printf ("%s%s%s", from_dir, G_DIR_SEPARATOR_S, filename);
1839 if (test_for_directory(from_file) != EISDIR) {
1840 to_file = ws_strdup_printf ("%s%s%s", to_dir, G_DIR_SEPARATOR_S, filename);
1841 if (!copy_file_binary_mode(from_file, to_file)) {
1842 *pf_filename_return = g_strdup(filename);
1843 g_free (from_file);
1844 g_free (to_file);
1845 ret = -1;
1846 break;
1848 g_free (to_file);
1849 #if 0
1850 } else {
1851 /* The user has manually created a directory in the profile
1852 * directory. Do not copy the directory recursively (yet?)
1854 #endif
1856 g_free (from_file);
1858 ws_dir_close(dir);
1861 return ret;
1864 static int
1865 reset_default_profile(char **pf_dir_path_return)
1867 char *profile_dir = get_persconffile_dir(NULL);
1868 char *filename, *del_file;
1869 GList *files, *file;
1870 int ret = 0;
1872 files = g_hash_table_get_keys(profile_files);
1873 file = g_list_first(files);
1874 while (file) {
1875 filename = (char *)file->data;
1876 del_file = ws_strdup_printf("%s%s%s", profile_dir, G_DIR_SEPARATOR_S, filename);
1878 if (file_exists(del_file)) {
1879 ret = ws_remove(del_file);
1880 if (ret != 0) {
1881 *pf_dir_path_return = profile_dir;
1882 g_free(del_file);
1883 break;
1887 g_free(del_file);
1888 file = g_list_next(file);
1890 g_list_free(files);
1892 g_free(profile_dir);
1893 return ret;
1897 delete_persconffile_profile(const char *profilename, char **pf_dir_path_return)
1899 if (strcmp(profilename, DEFAULT_PROFILE) == 0) {
1900 return reset_default_profile(pf_dir_path_return);
1903 char *profile_dir = get_persconffile_dir(profilename);
1904 int ret = 0;
1906 if (test_for_directory (profile_dir) == EISDIR) {
1907 ret = delete_directory (profile_dir, pf_dir_path_return);
1910 g_free(profile_dir);
1911 return ret;
1915 rename_persconffile_profile(const char *fromname, const char *toname,
1916 char **pf_from_dir_path_return, char **pf_to_dir_path_return)
1918 char *from_dir = get_persconffile_dir(fromname);
1919 char *to_dir = get_persconffile_dir(toname);
1920 int ret = 0;
1922 ret = ws_rename (from_dir, to_dir);
1923 if (ret != 0) {
1924 *pf_from_dir_path_return = from_dir;
1925 *pf_to_dir_path_return = to_dir;
1926 return ret;
1929 g_free (from_dir);
1930 g_free (to_dir);
1932 return 0;
1936 * Create the directory that holds personal configuration files, if
1937 * necessary. If we attempted to create it, and failed, return -1 and
1938 * set "*pf_dir_path_return" to the pathname of the directory we failed
1939 * to create (it's g_mallocated, so our caller should free it); otherwise,
1940 * return 0.
1943 create_persconffile_profile(const char *profilename, char **pf_dir_path_return)
1945 char *pf_dir_path;
1946 #ifdef _WIN32
1947 char *pf_dir_path_copy, *pf_dir_parent_path;
1948 size_t pf_dir_parent_path_len;
1949 int save_errno;
1950 #endif
1951 ws_statb64 s_buf;
1952 int ret;
1954 if (profilename) {
1956 * Create the personal profiles directory, if necessary.
1958 if (create_profiles_dir(pf_dir_path_return) == -1) {
1959 return -1;
1963 pf_dir_path = get_persconffile_dir(profilename);
1964 if (ws_stat64(pf_dir_path, &s_buf) != 0) {
1965 if (errno != ENOENT) {
1966 /* Some other problem; give up now. */
1967 *pf_dir_path_return = pf_dir_path;
1968 return -1;
1970 #ifdef _WIN32
1972 * Does the parent directory of that directory
1973 * exist? %APPDATA% may not exist even though
1974 * %USERPROFILE% does.
1976 * We check for the existence of the directory
1977 * by first checking whether the parent directory
1978 * is just a drive letter and, if it's not, by
1979 * doing a "stat()" on it. If it's a drive letter,
1980 * or if the "stat()" succeeds, we assume it exists.
1982 pf_dir_path_copy = g_strdup(pf_dir_path);
1983 pf_dir_parent_path = get_dirname(pf_dir_path_copy);
1984 pf_dir_parent_path_len = strlen(pf_dir_parent_path);
1985 if (pf_dir_parent_path_len > 0
1986 && pf_dir_parent_path[pf_dir_parent_path_len - 1] != ':'
1987 && ws_stat64(pf_dir_parent_path, &s_buf) != 0) {
1989 * Not a drive letter and the stat() failed.
1991 if (errno != ENOENT) {
1992 /* Some other problem; give up now. */
1993 *pf_dir_path_return = pf_dir_path;
1994 save_errno = errno;
1995 g_free(pf_dir_path_copy);
1996 errno = save_errno;
1997 return -1;
2000 * No, it doesn't exist - make it first.
2002 ret = ws_mkdir(pf_dir_parent_path, 0755);
2003 if (ret == -1) {
2004 *pf_dir_path_return = pf_dir_parent_path;
2005 save_errno = errno;
2006 g_free(pf_dir_path);
2007 errno = save_errno;
2008 return -1;
2011 g_free(pf_dir_path_copy);
2012 ret = ws_mkdir(pf_dir_path, 0755);
2013 #else
2014 ret = g_mkdir_with_parents(pf_dir_path, 0755);
2015 #endif
2016 } else {
2018 * Something with that pathname exists; if it's not
2019 * a directory, we'll get an error if we try to put
2020 * something in it, so we don't fail here, we wait
2021 * for that attempt to fail.
2023 ret = 0;
2025 if (ret == -1)
2026 *pf_dir_path_return = pf_dir_path;
2027 else
2028 g_free(pf_dir_path);
2030 return ret;
2033 const GHashTable *
2034 allowed_profile_filenames(void)
2036 return profile_files;
2040 create_persconffile_dir(char **pf_dir_path_return)
2042 return create_persconffile_profile(persconfprofile, pf_dir_path_return);
2046 copy_persconffile_profile(const char *toname, const char *fromname, bool from_global,
2047 char **pf_filename_return, char **pf_to_dir_path_return, char **pf_from_dir_path_return)
2049 int ret = 0;
2050 char *from_dir;
2051 char *to_dir = get_persconffile_dir(toname);
2052 char *from_file, *to_file;
2053 const char *filename;
2054 GHashTableIter files;
2055 void * file;
2057 from_dir = get_profile_dir(fromname, from_global);
2059 if (!profile_files || do_store_persconffiles) {
2060 /* Either the profile_files hashtable does not exist yet
2061 * (this is very early in startup) or we are still adding
2062 * files to it. Just copy all the non-directories.
2064 ret = copy_directory(from_dir, to_dir, pf_filename_return);
2065 } else {
2067 g_hash_table_iter_init(&files, profile_files);
2068 while (g_hash_table_iter_next(&files, &file, NULL)) {
2069 filename = (const char *)file;
2070 from_file = ws_strdup_printf ("%s%s%s", from_dir, G_DIR_SEPARATOR_S, filename);
2071 to_file = ws_strdup_printf ("%s%s%s", to_dir, G_DIR_SEPARATOR_S, filename);
2073 if (test_for_regular_file(from_file) && !copy_file_binary_mode(from_file, to_file)) {
2074 *pf_filename_return = g_strdup(filename);
2075 g_free (from_file);
2076 g_free (to_file);
2077 ret = -1;
2078 break;
2081 g_free (to_file);
2082 g_free (from_file);
2086 if (ret != 0) {
2087 *pf_to_dir_path_return = to_dir;
2088 *pf_from_dir_path_return = from_dir;
2089 } else {
2090 g_free (to_dir);
2091 g_free (from_dir);
2094 return ret;
2098 * Get the (default) directory in which personal data is stored.
2100 * On Win32, this is the "My Documents" folder in the personal profile.
2101 * On UNIX this is simply the current directory, unless that's "/",
2102 * which it will be, for example, when Wireshark is run from the
2103 * Finder in macOS, in which case we use the user's home directory.
2105 /* XXX - should this and the get_home_dir() be merged? */
2106 extern const char *
2107 get_persdatafile_dir(void)
2109 /* Return the cached value, if available */
2110 if (persdatafile_dir != NULL)
2111 return persdatafile_dir;
2113 #ifdef _WIN32
2114 TCHAR tszPath[MAX_PATH];
2117 * Hint: SHGetFolderPath is not available on MSVC 6 - without
2118 * Platform SDK
2120 if (SHGetSpecialFolderPath(NULL, tszPath, CSIDL_PERSONAL, false)) {
2121 persdatafile_dir = g_utf16_to_utf8(tszPath, -1, NULL, NULL, NULL);
2122 return persdatafile_dir;
2123 } else {
2124 return "";
2126 #else
2128 * Get the current directory.
2130 persdatafile_dir = g_get_current_dir();
2131 if (persdatafile_dir == NULL) {
2132 /* XXX - can this fail? */
2134 * g_get_home_dir() returns a const gchar *; g_strdup() it
2135 * so that it's something that can be freed.
2137 persdatafile_dir = g_strdup(g_get_home_dir());
2138 } else if (strcmp(persdatafile_dir, "/") == 0) {
2139 g_free(persdatafile_dir);
2141 * See above.
2143 persdatafile_dir = g_strdup(g_get_home_dir());
2145 return persdatafile_dir;
2146 #endif
2149 void
2150 set_persdatafile_dir(const char *p)
2152 g_free(persdatafile_dir);
2153 persdatafile_dir = g_strdup(p);
2157 * Construct the path name of a personal configuration file, given the
2158 * file name.
2160 * On Win32, if "for_writing" is false, we check whether the file exists
2161 * and, if not, construct a path name relative to the ".wireshark"
2162 * subdirectory of the user's home directory, and check whether that
2163 * exists; if it does, we return that, so that configuration files
2164 * from earlier versions can be read.
2166 * The returned file name was g_malloc()'d so it must be g_free()d when the
2167 * caller is done with it.
2169 char *
2170 get_persconffile_path(const char *filename, bool from_profile)
2172 char *path, *dir = NULL;
2174 if (from_profile) {
2175 /* Store filenames so we know which filenames belongs to a configuration profile */
2176 profile_register_persconffile(filename);
2178 dir = get_persconffile_dir(persconfprofile);
2179 } else {
2180 dir = get_persconffile_dir(NULL);
2182 path = g_build_filename(dir, filename, NULL);
2184 g_free(dir);
2185 return path;
2189 * Construct the path name of a global configuration file, given the
2190 * file name.
2192 * The returned file name was g_malloc()'d so it must be g_free()d when the
2193 * caller is done with it.
2195 char *
2196 get_datafile_path(const char *filename)
2198 if (running_in_build_directory_flag && !strcmp(filename, "hosts")) {
2199 /* We're running in the build directory and the requested file is a
2200 * generated (or a test) file. Return the file name in the build
2201 * directory (not in the source/data directory).
2202 * (Oh the things we do to keep the source directory pristine...)
2204 return g_build_filename(get_progfile_dir(), filename, (char *)NULL);
2205 } else {
2206 return g_build_filename(get_datafile_dir(), filename, (char *)NULL);
2211 * Construct the path name of a global documentation file, given the
2212 * file name.
2214 * The returned file name was g_malloc()'d so it must be g_free()d when the
2215 * caller is done with it.
2217 char *
2218 get_docfile_path(const char *filename)
2220 if (running_in_build_directory_flag) {
2221 /* We're running in the build directory and the requested file is a
2222 * generated (or a test) file. Return the file name in the build
2223 * directory (not in the source/data directory).
2224 * (Oh the things we do to keep the source directory pristine...)
2226 return g_build_filename(get_progfile_dir(), filename, (char *)NULL);
2227 } else {
2228 return g_build_filename(get_doc_dir(), filename, (char *)NULL);
2233 * Return an error message for UNIX-style errno indications on open or
2234 * create operations.
2236 const char *
2237 file_open_error_message(int err, bool for_writing)
2239 const char *errmsg;
2240 static char errmsg_errno[1024+1];
2242 switch (err) {
2244 case ENOENT:
2245 if (for_writing)
2246 errmsg = "The path to the file \"%s\" doesn't exist.";
2247 else
2248 errmsg = "The file \"%s\" doesn't exist.";
2249 break;
2251 case EACCES:
2252 if (for_writing)
2253 errmsg = "You don't have permission to create or write to the file \"%s\".";
2254 else
2255 errmsg = "You don't have permission to read the file \"%s\".";
2256 break;
2258 case EISDIR:
2259 errmsg = "\"%s\" is a directory (folder), not a file.";
2260 break;
2262 case ENOSPC:
2263 errmsg = "The file \"%s\" could not be created because there is no space left on the file system.";
2264 break;
2266 #ifdef EDQUOT
2267 case EDQUOT:
2268 errmsg = "The file \"%s\" could not be created because you are too close to, or over, your disk quota.";
2269 break;
2270 #endif
2272 case EINVAL:
2273 errmsg = "The file \"%s\" could not be created because an invalid filename was specified.";
2274 break;
2276 #ifdef ENAMETOOLONG
2277 case ENAMETOOLONG:
2278 /* XXX Make sure we truncate on a character boundary. */
2279 errmsg = "The file name \"%.80s" UTF8_HORIZONTAL_ELLIPSIS "\" is too long.";
2280 break;
2281 #endif
2283 case ENOMEM:
2285 * The problem probably has nothing to do with how much RAM the
2286 * user has on their machine, so don't confuse them by saying
2287 * "memory". The problem is probably either virtual address
2288 * space or swap space.
2290 #if GLIB_SIZEOF_VOID_P == 4
2292 * ILP32; we probably ran out of virtual address space.
2294 #define ENOMEM_REASON "it can't be handled by a 32-bit application"
2295 #else
2297 * LP64 or LLP64; we probably ran out of swap space.
2299 #if defined(_WIN32)
2301 * You need to make the pagefile bigger.
2303 #define ENOMEM_REASON "the pagefile is too small"
2304 #elif defined(ENABLE_APPLICATION_BUNDLE)
2306 * dynamic_pager couldn't, or wouldn't, create more swap files.
2308 #define ENOMEM_REASON "your system ran out of swap file space"
2309 #else
2311 * Either you have a fixed swap partition or a fixed swap file,
2312 * and it needs to be made bigger.
2314 * This is UN*X, but it's not macOS, so we assume the user is
2315 * *somewhat* nerdy.
2317 #define ENOMEM_REASON "your system is out of swap space"
2318 #endif
2319 #endif /* GLIB_SIZEOF_VOID_P == 4 */
2320 if (for_writing)
2321 errmsg = "The file \"%s\" could not be created because " ENOMEM_REASON ".";
2322 else
2323 errmsg = "The file \"%s\" could not be opened because " ENOMEM_REASON ".";
2324 break;
2326 default:
2327 snprintf(errmsg_errno, sizeof(errmsg_errno),
2328 "The file \"%%s\" could not be %s: %s.",
2329 for_writing ? "created" : "opened",
2330 g_strerror(err));
2331 errmsg = errmsg_errno;
2332 break;
2334 return errmsg;
2338 * Return an error message for UNIX-style errno indications on write
2339 * operations.
2341 const char *
2342 file_write_error_message(int err)
2344 const char *errmsg;
2345 static char errmsg_errno[1024+1];
2347 switch (err) {
2349 case ENOSPC:
2350 errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
2351 break;
2353 #ifdef EDQUOT
2354 case EDQUOT:
2355 errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
2356 break;
2357 #endif
2359 default:
2360 snprintf(errmsg_errno, sizeof(errmsg_errno),
2361 "An error occurred while writing to the file \"%%s\": %s.",
2362 g_strerror(err));
2363 errmsg = errmsg_errno;
2364 break;
2366 return errmsg;
2370 bool
2371 file_exists(const char *fname)
2373 ws_statb64 file_stat;
2375 if (!fname) {
2376 return false;
2379 if (ws_stat64(fname, &file_stat) != 0 && errno == ENOENT) {
2380 return false;
2381 } else {
2382 return true;
2386 bool config_file_exists_with_entries(const char *fname, char comment_char)
2388 bool start_of_line = true;
2389 bool has_entries = false;
2390 FILE *file;
2391 int c;
2393 if (!fname) {
2394 return false;
2397 if ((file = ws_fopen(fname, "r")) == NULL) {
2398 return false;
2401 do {
2402 c = ws_getc_unlocked(file);
2403 if (start_of_line && c != comment_char && !g_ascii_isspace(c) && g_ascii_isprint(c)) {
2404 has_entries = true;
2405 break;
2407 if (c == '\n' || !g_ascii_isspace(c)) {
2408 start_of_line = (c == '\n');
2410 } while (c != EOF);
2412 fclose(file);
2413 return has_entries;
2417 * Check that the from file is not the same as to file
2418 * We do it here so we catch all cases ...
2419 * Unfortunately, the file requester gives us an absolute file
2420 * name and the read file name may be relative (if supplied on
2421 * the command line), so we can't just compare paths. From Joerg Mayer.
2423 bool
2424 files_identical(const char *fname1, const char *fname2)
2426 /* Two different implementations, because st_ino isn't filled in with
2427 * a meaningful value on Windows. Use the Windows API and FILE_ID_INFO
2428 * instead.
2430 #ifdef _WIN32
2432 FILE_ID_INFO filestat1, filestat2;
2435 * Compare VolumeSerialNumber and FileId.
2438 HANDLE h1 = CreateFile(utf_8to16(fname1), 0,
2439 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
2440 NULL, OPEN_EXISTING, 0, NULL);
2442 if (h1 == INVALID_HANDLE_VALUE) {
2443 return false;
2446 if (!GetFileInformationByHandleEx(h1, FileIdInfo, &filestat1, sizeof(FILE_ID_INFO))) {
2447 CloseHandle(h1);
2448 return false;
2450 CloseHandle(h1);
2452 HANDLE h2 = CreateFile(utf_8to16(fname2), 0,
2453 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
2454 NULL, OPEN_EXISTING, 0, NULL);
2456 if (h2 == INVALID_HANDLE_VALUE) {
2457 return false;
2460 if (!GetFileInformationByHandleEx(h2, FileIdInfo, &filestat2, sizeof(FILE_ID_INFO))) {
2461 CloseHandle(h2);
2462 return false;
2464 CloseHandle(h2);
2466 return ((memcmp(&filestat1.FileId, &filestat2.FileId, sizeof(FILE_ID_128)) == 0) &&
2467 filestat1.VolumeSerialNumber == filestat2.VolumeSerialNumber);
2468 #else
2469 ws_statb64 filestat1, filestat2;
2472 * Compare st_dev and st_ino.
2474 if (ws_stat64(fname1, &filestat1) == -1)
2475 return false; /* can't get info about the first file */
2476 if (ws_stat64(fname2, &filestat2) == -1)
2477 return false; /* can't get info about the second file */
2478 return (filestat1.st_dev == filestat2.st_dev &&
2479 filestat1.st_ino == filestat2.st_ino);
2480 #endif
2483 bool
2484 file_needs_reopen(int fd, const char* filename)
2486 #ifdef _WIN32
2487 /* Windows handles st_dev in a way unsuitable here:
2488 * * _fstat() simply casts the file descriptor (ws_fileno(fp)) to unsigned
2489 * and assigns this value to st_dev and st_rdev
2490 * * _wstat() converts drive letter (eg. C) to number (A=0, B=1, C=2, ...)
2491 * and assigns such number to st_dev and st_rdev
2493 * The st_ino parameter is simply zero as there is no specific assignment
2494 * to it in the Universal CRT source code.
2496 * Thus instead of using fstat(), use Windows specific API.
2499 HANDLE open_handle = (HANDLE)_get_osfhandle(fd);
2500 HANDLE current_handle = CreateFile(utf_8to16(filename), FILE_READ_ATTRIBUTES,
2501 FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
2502 NULL, OPEN_EXISTING, 0, NULL);
2503 BY_HANDLE_FILE_INFORMATION open_info, current_info;
2505 if (current_handle == INVALID_HANDLE_VALUE) {
2506 return true;
2509 #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
2510 FILE_ID_INFO open_id, current_id;
2511 if (GetFileInformationByHandleEx(open_handle, FileIdInfo, &open_id, sizeof(open_id)) &&
2512 GetFileInformationByHandleEx(current_handle, FileIdInfo, &current_id, sizeof(current_id))) {
2513 /* 128-bit identifier is available, use it */
2514 CloseHandle(current_handle);
2515 return open_id.VolumeSerialNumber != current_id.VolumeSerialNumber ||
2516 memcmp(&open_id.FileId, &current_id.FileId, sizeof(open_id.FileId)) != 0;
2518 #endif /* _WIN32_WINNT >= _WIN32_WINNT_WIN8 */
2519 if (GetFileInformationByHandle(open_handle, &open_info) &&
2520 GetFileInformationByHandle(current_handle, &current_info)) {
2521 /* Fallback to 64-bit identifier */
2522 CloseHandle(current_handle);
2523 uint64_t open_size = (((uint64_t)open_info.nFileSizeHigh) << 32) | open_info.nFileSizeLow;
2524 uint64_t current_size = (((uint64_t)current_info.nFileSizeHigh) << 32) | current_info.nFileSizeLow;
2525 return open_info.dwVolumeSerialNumber != current_info.dwVolumeSerialNumber ||
2526 open_info.nFileIndexHigh != current_info.nFileIndexHigh ||
2527 open_info.nFileIndexLow != current_info.nFileIndexLow ||
2528 open_size > current_size;
2530 CloseHandle(current_handle);
2531 return true;
2532 #else
2533 ws_statb64 open_stat, current_stat;
2535 /* consider a file deleted when stat fails for either file,
2536 * or when the residing device / inode has changed. */
2537 if (0 != ws_fstat64(fd, &open_stat))
2538 return true;
2539 if (0 != ws_stat64(filename, &current_stat))
2540 return true;
2542 return open_stat.st_dev != current_stat.st_dev ||
2543 open_stat.st_ino != current_stat.st_ino ||
2544 open_stat.st_size > current_stat.st_size;
2545 #endif
2548 bool
2549 write_file_binary_mode(const char *filename, const void *content, size_t content_len)
2551 int fd;
2552 size_t bytes_left;
2553 unsigned int bytes_to_write;
2554 ssize_t bytes_written;
2555 const uint8_t *ptr;
2556 int err;
2558 fd = ws_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
2559 if (fd == -1) {
2560 report_open_failure(filename, errno, true);
2561 return false;
2565 * The third argument to _write() on Windows is an unsigned int,
2566 * so, on Windows, that's the size of the third argument to
2567 * ws_write().
2569 * The third argument to write() on UN*X is a size_t, although
2570 * the return value is an ssize_t, so one probably shouldn't
2571 * write more than the max value of an ssize_t.
2573 * In either case, there's no guarantee that a size_t such as
2574 * content_len can be passed to ws_write(), so we write in
2575 * chunks of at most 2^31 bytes.
2578 ptr = (const uint8_t *)content;
2579 bytes_left = content_len;
2580 while (bytes_left != 0) {
2581 if (bytes_left > 0x40000000) {
2582 bytes_to_write = 0x40000000;
2583 } else {
2584 bytes_to_write = (unsigned int)bytes_left;
2586 bytes_written = ws_write(fd, ptr, bytes_to_write);
2587 if (bytes_written <= 0) {
2588 if (bytes_written < 0) {
2589 err = errno;
2590 } else {
2591 err = WTAP_ERR_SHORT_WRITE;
2593 report_write_failure(filename, err);
2594 ws_close(fd);
2595 return false;
2597 bytes_left -= bytes_written;
2598 ptr += bytes_written;
2601 ws_close(fd);
2602 return true;
2606 * Copy a file in binary mode, for those operating systems that care about
2607 * such things. This should be OK for all files, even text files, as
2608 * we'll copy the raw bytes, and we don't look at the bytes as we copy
2609 * them.
2611 * Returns true on success, false on failure. If a failure, it also
2612 * displays a simple dialog window with the error message.
2614 bool
2615 copy_file_binary_mode(const char *from_filename, const char *to_filename)
2617 int from_fd, to_fd, err;
2618 ws_file_ssize_t nread, nwritten;
2619 uint8_t *pd = NULL;
2621 /* Copy the raw bytes of the file. */
2622 from_fd = ws_open(from_filename, O_RDONLY | O_BINARY, 0000 /* no creation so don't matter */);
2623 if (from_fd < 0) {
2624 report_open_failure(from_filename, errno, false);
2625 goto done;
2628 /* Use open() instead of creat() so that we can pass the O_BINARY
2629 flag, which is relevant on Win32; it appears that "creat()"
2630 may open the file in text mode, not binary mode, but we want
2631 to copy the raw bytes of the file, so we need the output file
2632 to be open in binary mode. */
2633 to_fd = ws_open(to_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
2634 if (to_fd < 0) {
2635 report_open_failure(to_filename, errno, true);
2636 ws_close(from_fd);
2637 goto done;
2640 #define FS_READ_SIZE 65536
2641 pd = (uint8_t *)g_malloc(FS_READ_SIZE);
2642 while ((nread = ws_read(from_fd, pd, FS_READ_SIZE)) > 0) {
2643 nwritten = ws_write(to_fd, pd, nread);
2644 if (nwritten < nread) {
2645 if (nwritten < 0)
2646 err = errno;
2647 else
2648 err = WTAP_ERR_SHORT_WRITE;
2649 report_write_failure(to_filename, err);
2650 ws_close(from_fd);
2651 ws_close(to_fd);
2652 goto done;
2655 if (nread < 0) {
2656 err = errno;
2657 report_read_failure(from_filename, err);
2658 ws_close(from_fd);
2659 ws_close(to_fd);
2660 goto done;
2662 ws_close(from_fd);
2663 if (ws_close(to_fd) < 0) {
2664 report_write_failure(to_filename, errno);
2665 goto done;
2668 g_free(pd);
2669 pd = NULL;
2670 return true;
2672 done:
2673 g_free(pd);
2674 return false;
2677 char *
2678 data_file_url(const char *filename)
2680 char *file_path;
2681 char *uri;
2683 /* Absolute path? */
2684 if(g_path_is_absolute(filename)) {
2685 file_path = g_strdup(filename);
2686 } else {
2687 file_path = ws_strdup_printf("%s/%s", get_datafile_dir(), filename);
2690 /* XXX - check, if the file is really existing, otherwise display a simple_dialog about the problem */
2692 /* convert filename to uri */
2693 uri = g_filename_to_uri(file_path, NULL, NULL);
2694 g_free(file_path);
2695 return uri;
2698 char *
2699 doc_file_url(const char *filename)
2701 char *file_path;
2702 char *uri;
2704 /* Absolute path? */
2705 if(g_path_is_absolute(filename)) {
2706 file_path = g_strdup(filename);
2707 } else {
2708 file_path = ws_strdup_printf("%s/%s", get_doc_dir(), filename);
2711 /* XXX - check, if the file is really existing, otherwise display a simple_dialog about the problem */
2713 /* convert filename to uri */
2714 uri = g_filename_to_uri(file_path, NULL, NULL);
2715 g_free(file_path);
2716 return uri;
2719 void
2720 free_progdirs(void)
2722 g_free(persconffile_dir);
2723 persconffile_dir = NULL;
2724 g_free(datafile_dir);
2725 datafile_dir = NULL;
2726 g_free(persdatafile_dir);
2727 persdatafile_dir = NULL;
2728 g_free(persconfprofile);
2729 persconfprofile = NULL;
2730 g_free(progfile_dir);
2731 progfile_dir = NULL;
2732 g_free(doc_dir);
2733 doc_dir = NULL;
2734 g_free(install_prefix);
2735 install_prefix = NULL;
2736 g_free(current_working_dir);
2737 current_working_dir = NULL;
2738 #if defined(HAVE_PLUGINS) || defined(HAVE_LUA)
2739 g_free(plugin_dir);
2740 plugin_dir = NULL;
2741 g_free(plugin_dir_with_version);
2742 plugin_dir_with_version = NULL;
2743 g_free(plugin_pers_dir);
2744 plugin_pers_dir = NULL;
2745 g_free(plugin_pers_dir_with_version);
2746 plugin_pers_dir_with_version = NULL;
2747 #endif
2748 g_free(extcap_dir);
2749 extcap_dir = NULL;
2750 g_free(extcap_pers_dir);
2751 extcap_pers_dir = NULL;
2755 * Editor modelines
2757 * Local Variables:
2758 * c-basic-offset: 4
2759 * tab-width: 8
2760 * indent-tabs-mode: nil
2761 * End:
2763 * ex: set shiftwidth=4 tabstop=8 expandtab:
2764 * :indentSize=4:tabSize=8:noTabs=true: