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