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