smb2-dissector: learn the "REPLAY_OPERATION" flag
[obnox/wireshark/wip.git] / epan / filesystem.c
1 /* filesystem.c
2  * Filesystem utility routines
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 /*
30  * Required with GNU libc to get dladdr().
31  * We define it here because <dlfcn.h> apparently gets included by
32  * one of the headers we include below.
33  */
34 #define _GNU_SOURCE
35
36 #ifdef HAVE_DIRENT_H
37 #include <dirent.h>
38 #endif
39
40 #include <stdio.h>
41 #include <ctype.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <errno.h>
45
46 #include <glib.h>
47
48 #ifdef HAVE_UNISTD_H
49 #include <unistd.h>
50 #endif
51
52 #ifdef HAVE_FCNTL_H
53 #include <fcntl.h>
54 #endif
55
56 #ifdef HAVE_SYS_STAT_H
57 #include <sys/stat.h>
58 #endif
59
60 #ifdef _WIN32
61 #include <windows.h>
62 #include <tchar.h>
63 #include <shlobj.h>
64 #include <wsutil/unicode-utils.h>
65 #else /* _WIN32 */
66 #ifdef DLADDR_FINDS_EXECUTABLE_PATH
67 #include <dlfcn.h>
68 #endif /* DLADDR_FINDS_EXECUTABLE_PATH */
69 #include <pwd.h>
70 #endif /* _WIN32 */
71
72 #include "filesystem.h"
73 #include "report_err.h"
74 #include <wsutil/privileges.h>
75 #include <wsutil/file_util.h>
76
77 #include <wiretap/wtap.h>   /* for WTAP_ERR_SHORT_WRITE */
78
79 #define PROFILES_DIR    "profiles"
80 #define PLUGINS_DIR_NAME    "plugins"
81
82 #define U3_MY_CAPTURES  "\\My Captures"
83
84 char *persconffile_dir = NULL;
85 char *persdatafile_dir = NULL;
86 char *persconfprofile = NULL;
87
88 static gboolean do_store_persconffiles = FALSE;
89 static GHashTable *profile_files = NULL;
90
91 /*
92  * Given a pathname, return a pointer to the last pathname separator
93  * character in the pathname, or NULL if the pathname contains no
94  * separators.
95  */
96 char *
97 find_last_pathname_separator(const char *path)
98 {
99     char *separator;
100
101 #ifdef _WIN32
102     char c;
103
104     /*
105      * We have to scan for '\' or '/'.
106      * Get to the end of the string.
107      */
108     separator = strchr(path, '\0');     /* points to ending '\0' */
109     while (separator > path) {
110         c = *--separator;
111         if (c == '\\' || c == '/')
112             return separator;   /* found it */
113     }
114
115     /*
116      * OK, we didn't find any, so no directories - but there might
117      * be a drive letter....
118      */
119     return strchr(path, ':');
120 #else
121     separator = strrchr(path, '/');
122     return separator;
123 #endif
124 }
125
126 /*
127  * Given a pathname, return the last component.
128  */
129 const char *
130 get_basename(const char *path)
131 {
132     const char *filename;
133
134     g_assert(path != NULL);
135     filename = find_last_pathname_separator(path);
136     if (filename == NULL) {
137         /*
138          * There're no directories, drive letters, etc. in the
139          * name; the pathname *is* the file name.
140          */
141         filename = path;
142     } else {
143         /*
144          * Skip past the pathname or drive letter separator.
145          */
146         filename++;
147     }
148     return filename;
149 }
150
151 /*
152  * Given a pathname, return a string containing everything but the
153  * last component.  NOTE: this overwrites the pathname handed into
154  * it....
155  */
156 char *
157 get_dirname(char *path)
158 {
159     char *separator;
160
161     g_assert(path != NULL);
162     separator = find_last_pathname_separator(path);
163     if (separator == NULL) {
164         /*
165          * There're no directories, drive letters, etc. in the
166          * name; there is no directory path to return.
167          */
168         return NULL;
169     }
170
171     /*
172      * Get rid of the last pathname separator and the final file
173      * name following it.
174      */
175     *separator = '\0';
176
177     /*
178      * "path" now contains the pathname of the directory containing
179      * the file/directory to which it referred.
180      */
181     return path;
182 }
183
184 /*
185  * Given a pathname, return:
186  *
187  *  the errno, if an attempt to "stat()" the file fails;
188  *
189  *  EISDIR, if the attempt succeeded and the file turned out
190  *  to be a directory;
191  *
192  *  0, if the attempt succeeded and the file turned out not
193  *  to be a directory.
194  */
195
196 /*
197  * Visual C++ on Win32 systems doesn't define these.  (Old UNIX systems don't
198  * define them either.)
199  *
200  * Visual C++ on Win32 systems doesn't define S_IFIFO, it defines _S_IFIFO.
201  */
202 #ifndef S_ISREG
203 #define S_ISREG(mode)   (((mode) & S_IFMT) == S_IFREG)
204 #endif
205 #ifndef S_IFIFO
206 #define S_IFIFO _S_IFIFO
207 #endif
208 #ifndef S_ISFIFO
209 #define S_ISFIFO(mode)  (((mode) & S_IFMT) == S_IFIFO)
210 #endif
211 #ifndef S_ISDIR
212 #define S_ISDIR(mode)   (((mode) & S_IFMT) == S_IFDIR)
213 #endif
214
215 int
216 test_for_directory(const char *path)
217 {
218     ws_statb64 statb;
219
220     if (ws_stat64(path, &statb) < 0)
221         return errno;
222
223     if (S_ISDIR(statb.st_mode))
224         return EISDIR;
225     else
226         return 0;
227 }
228
229 int
230 test_for_fifo(const char *path)
231 {
232     ws_statb64 statb;
233
234     if (ws_stat64(path, &statb) < 0)
235         return errno;
236
237     if (S_ISFIFO(statb.st_mode))
238         return ESPIPE;
239     else
240         return 0;
241 }
242
243 /*
244  * Directory from which the executable came.
245  */
246 static char *progfile_dir;
247
248 /*
249  * TRUE if we're running from the build directory and we aren't running
250  * with special privileges.
251  */
252 static gboolean running_in_build_directory_flag = FALSE;
253
254 /*
255  * Get the pathname of the directory from which the executable came,
256  * and save it for future use.  Returns NULL on success, and a
257  * g_mallocated string containing an error on failure.
258  */
259 char *
260 init_progfile_dir(const char *arg0
261 #ifdef _WIN32
262     _U_
263 #endif
264 , int (*main_addr)(int, char **)
265 #if defined(_WIN32) || !defined(DLADDR_FINDS_EXECUTABLE_PATH)
266     _U_
267 #endif
268 )
269 {
270 #ifdef _WIN32
271     TCHAR prog_pathname_w[_MAX_PATH+2];
272     char *prog_pathname;
273     DWORD error;
274     TCHAR *msg_w;
275     guchar *msg;
276     size_t msglen;
277
278     /*
279      * Attempt to get the full pathname of the currently running
280      * program.
281      */
282     if (GetModuleFileName(NULL, prog_pathname_w, G_N_ELEMENTS(prog_pathname_w)) != 0 && GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
283         /*
284          * XXX - Should we use g_utf16_to_utf8(), as in
285          * getenv_utf8()?
286          */
287         prog_pathname = utf_16to8(prog_pathname_w);
288         /*
289          * We got it; strip off the last component, which would be
290          * the file name of the executable, giving us the pathname
291          * of the directory where the executable resides.
292          */
293         progfile_dir = g_path_get_dirname(prog_pathname);
294         if (progfile_dir != NULL) {
295             return NULL;    /* we succeeded */
296         } else {
297             /*
298              * OK, no. What do we do now?
299              */
300             return g_strdup_printf("No \\ in executable pathname \"%s\"",
301                 prog_pathname);
302         }
303     } else {
304         /*
305          * Oh, well.  Return an indication of the error.
306          */
307         error = GetLastError();
308         if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
309             NULL, error, 0, (LPTSTR) &msg_w, 0, NULL) == 0) {
310             /*
311              * Gak.  We can't format the message.
312              */
313             return g_strdup_printf("GetModuleFileName failed: %u (FormatMessage failed: %u)",
314                 error, GetLastError());
315         }
316         msg = utf_16to8(msg_w);
317         LocalFree(msg_w);
318         /*
319          * "FormatMessage()" "helpfully" sticks CR/LF at the
320          * end of the message.  Get rid of it.
321          */
322         msglen = strlen(msg);
323         if (msglen >= 2) {
324             msg[msglen - 1] = '\0';
325             msg[msglen - 2] = '\0';
326         }
327         return g_strdup_printf("GetModuleFileName failed: %s (%u)",
328             msg, error);
329     }
330 #else
331 #ifdef DLADDR_FINDS_EXECUTABLE_PATH
332     Dl_info info;
333 #endif
334     char *prog_pathname;
335     char *curdir;
336     long path_max;
337     char *pathstr;
338     char *path_start, *path_end;
339     size_t path_component_len;
340     char *retstr;
341     char *path;
342     char *dir_end;
343
344     /*
345      * Check whether WIRESHARK_RUN_FROM_BUILD_DIRECTORY is set in the
346      * environment; if so, set running_in_build_directory_flag if we
347      * weren't started with special privileges.  (If we were started
348      * with special privileges, it's not safe to allow the user to point
349      * us to some other directory; running_in_build_directory_flag, when
350      * set, causes us to look for plugins and the like in the build
351      * directory.)
352      */
353     if (getenv("WIRESHARK_RUN_FROM_BUILD_DIRECTORY") != NULL
354         && !started_with_special_privs())
355         running_in_build_directory_flag = TRUE;
356
357 #ifdef DLADDR_FINDS_EXECUTABLE_PATH
358     /*
359      * Try to use dladdr() to find the pathname of the executable.
360      * dladdr() is not guaranteed to give you anything better than
361      * argv[0] (i.e., it might not contain a / at all, much less
362      * being an absolute path), and doesn't appear to do so on
363      * Linux, but on other platforms it could give you an absolute
364      * path and obviate the need for us to determine the absolute
365      * path.
366      */
367     if (dladdr((void *)main_addr, &info))
368         arg0 = info.dli_fname;
369 #endif
370     /*
371      * Try to figure out the directory in which the currently running
372      * program resides, given something purporting to be the executable
373      * name (from dladdr() or from the argv[0] it was started with.
374      * That might be the absolute path of the program, or a path relative
375      * to the current directory of the process that started it, or
376      * just a name for the program if it was started from the command
377      * line and was searched for in $PATH.  It's not guaranteed to be
378      * any of those, however, so there are no guarantees....
379      */
380     if (arg0[0] == '/') {
381         /*
382          * It's an absolute path.
383          */
384         prog_pathname = g_strdup(arg0);
385     } else if (strchr(arg0, '/') != NULL) {
386         /*
387          * It's a relative path, with a directory in it.
388          * Get the current directory, and combine it
389          * with that directory.
390          */
391         path_max = pathconf(".", _PC_PATH_MAX);
392         if (path_max == -1) {
393             /*
394              * We have no idea how big a buffer to
395              * allocate for the current directory.
396              */
397             return g_strdup_printf("pathconf failed: %s\n",
398                 g_strerror(errno));
399         }
400         curdir = (char *)g_malloc(path_max);
401         if (getcwd(curdir, path_max) == NULL) {
402             /*
403              * It failed - give up, and just stick
404              * with DATAFILE_DIR.
405              */
406             g_free(curdir);
407             return g_strdup_printf("getcwd failed: %s\n",
408                 g_strerror(errno));
409         }
410         path = g_strdup_printf("%s/%s", curdir, arg0);
411         g_free(curdir);
412         prog_pathname = path;
413     } else {
414         /*
415          * It's just a file name.
416          * Search the path for a file with that name
417          * that's executable.
418          */
419         prog_pathname = NULL;   /* haven't found it yet */
420         pathstr = getenv("PATH");
421         path_start = pathstr;
422         if (path_start != NULL) {
423             while (*path_start != '\0') {
424                 path_end = strchr(path_start, ':');
425                 if (path_end == NULL)
426                     path_end = path_start + strlen(path_start);
427                 path_component_len = path_end - path_start;
428                 path = (char *)g_malloc(path_component_len + 1
429                     + strlen(arg0) + 1);
430                 memcpy(path, path_start, path_component_len);
431                 path[path_component_len] = '\0';
432                 strncat(path, "/", 2);
433                 strncat(path, arg0, strlen(arg0) + 1);
434                 if (access(path, X_OK) == 0) {
435                     /*
436                      * Found it!
437                      */
438                     prog_pathname = path;
439                     break;
440                 }
441
442                 /*
443                  * That's not it.  If there are more
444                  * path components to test, try them.
445                  */
446                 if (*path_end == '\0') {
447                     /*
448                      * There's nothing more to try.
449                      */
450                     break;
451                 }
452                 if (*path_end == ':')
453                     path_end++;
454                 path_start = path_end;
455                 g_free(path);
456             }
457             if (prog_pathname == NULL) {
458                 /*
459                  * Program not found in path.
460                  */
461                 return g_strdup_printf("\"%s\" not found in \"%s\"",
462                     arg0, pathstr);
463             }
464         } else {
465             /*
466              * PATH isn't set.
467              * XXX - should we pick a default?
468              */
469             return g_strdup("PATH isn't set");
470         }
471     }
472
473     /*
474      * OK, we have what we think is the pathname
475      * of the program.
476      *
477      * First, find the last "/" in the directory,
478      * as that marks the end of the directory pathname.
479      */
480     dir_end = strrchr(prog_pathname, '/');
481     if (dir_end != NULL) {
482         /*
483          * Found it.  Strip off the last component,
484          * as that's the path of the program.
485          */
486         *dir_end = '\0';
487
488         /*
489          * Is there a "/.libs" at the end?
490          */
491         dir_end = strrchr(prog_pathname, '/');
492         if (dir_end != NULL) {
493             if (strcmp(dir_end, "/.libs") == 0) {
494                 /*
495                  * Yup, it's ".libs".
496                  * Strip that off; it's an
497                  * artifact of libtool.
498                  */
499                 *dir_end = '\0';
500
501                 /*
502                  * This presumably means we're run from
503                  * the libtool wrapper, which probably
504                  * means we're being run from the build
505                  * directory.  If we weren't started
506                  * with special privileges, set
507                  * running_in_build_directory_flag.
508                  *
509                  * XXX - should we check whether what
510                  * follows ".libs/" begins with "lt-"?
511                  */
512                 if (!started_with_special_privs())
513                     running_in_build_directory_flag = TRUE;
514             }
515         }
516
517         /*
518          * OK, we have the path we want.
519          */
520         progfile_dir = prog_pathname;
521         return NULL;
522     } else {
523         /*
524          * This "shouldn't happen"; we apparently
525          * have no "/" in the pathname.
526          * Just free up prog_pathname.
527          */
528         retstr = g_strdup_printf("No / found in \"%s\"", prog_pathname);
529         g_free(prog_pathname);
530         return retstr;
531     }
532 #endif
533 }
534
535 /*
536  * Get the directory in which the program resides.
537  */
538 const char *
539 get_progfile_dir(void)
540 {
541     return progfile_dir;
542 }
543
544 /*
545  * Get the directory in which the global configuration and data files are
546  * stored.
547  *
548  * On Windows, we use the directory in which the executable for this
549  * process resides.
550  *
551  * On UN*X, we use the DATAFILE_DIR value supplied by the configure
552  * script, unless we think we're being run from the build directory,
553  * in which case we use the directory in which the executable for this
554  * process resides.
555  *
556  * XXX - if we ever make libwireshark a real library, used by multiple
557  * applications (more than just TShark and versions of Wireshark with
558  * various UIs), should the configuration files belong to the library
559  * (and be shared by all those applications) or to the applications?
560  *
561  * If they belong to the library, that could be done on UNIX by the
562  * configure script, but it's trickier on Windows, as you can't just
563  * use the pathname of the executable.
564  *
565  * If they belong to the application, that could be done on Windows
566  * by using the pathname of the executable, but we'd have to have it
567  * passed in as an argument, in some call, on UNIX.
568  *
569  * Note that some of those configuration files might be used by code in
570  * libwireshark, some of them might be used by dissectors (would they
571  * belong to libwireshark, the application, or a separate library?),
572  * and some of them might be used by other code (the Wireshark preferences
573  * file includes resolver preferences that control the behavior of code
574  * in libwireshark, dissector preferences, and UI preferences, for
575  * example).
576  */
577 const char *
578 get_datafile_dir(void)
579 {
580 #ifdef _WIN32
581     char *u3deviceexecpath;
582 #endif
583     static const char *datafile_dir = NULL;
584
585     if (datafile_dir != NULL)
586         return datafile_dir;
587
588 #ifdef _WIN32
589     /*
590      * See if we are running in a U3 environment.
591      */
592     u3deviceexecpath = getenv_utf8("U3_DEVICE_EXEC_PATH");
593
594     if (u3deviceexecpath != NULL) {
595         /*
596          * We are; use the U3 device executable path.
597          */
598         datafile_dir = u3deviceexecpath;
599     } else {
600         /*
601          * Do we have the pathname of the program?  If so, assume we're
602          * running an installed version of the program.  If we fail,
603          * we don't change "datafile_dir", and thus end up using the
604          * default.
605          *
606          * XXX - does NSIS put the installation directory into
607          * "\HKEY_LOCAL_MACHINE\SOFTWARE\Wireshark\InstallDir"?
608          * If so, perhaps we should read that from the registry,
609          * instead.
610          */
611         if (progfile_dir != NULL) {
612             /*
613              * Yes, we do; use that.
614              */
615             datafile_dir = progfile_dir;
616         } else {
617             /*
618              * No, we don't.
619              * Fall back on the default installation directory.
620              */
621             datafile_dir = "C:\\Program Files\\Wireshark\\";
622         }
623     }
624 #else
625     if (running_in_build_directory_flag) {
626         /*
627          * We're (probably) being run from the build directory and
628          * weren't started with special privileges.
629          *
630          * The data files we want are the ones from the source
631          * directory; to handle builds out of the source tree,
632          * we check whether WIRESHARK_SRC_DIR is set and, if so,
633          * use that as the source directory.
634          */
635         datafile_dir = getenv("WIRESHARK_SRC_DIR");
636         if (datafile_dir != NULL)
637             return datafile_dir;
638     }
639
640     /*
641      * Well, that didn't work.
642      * Check again whether we were (probably) run from the build
643      * directory and started without special privileges, and also
644      * check whether we were able to determine the directory in
645      * which the program was found.
646      */
647     if (running_in_build_directory_flag && progfile_dir != NULL) {
648         /*
649          * We're (probably) being run from the build directory and
650          * weren't started with special privileges, and we were
651          * able to determine the directory in which the program
652          * was found.  Assume that directory is the build
653          * directory and that it's the same as the source
654          * directory.
655          */
656         datafile_dir = progfile_dir;
657     } else {
658         /*
659          * Return the directory specified when the build was
660          * configured, prepending the run path prefix if it exists.
661          */
662         if (getenv("WIRESHARK_DATA_DIR") && !started_with_special_privs()) {
663             /*
664              * The user specified a different directory for data files
665              * and we aren't running with special privileges.
666              * XXX - We might be able to dispense with the priv check
667              */
668             datafile_dir = g_strdup(getenv("WIRESHARK_DATA_DIR"));
669         } else {
670             datafile_dir = DATAFILE_DIR;
671         }
672     }
673
674 #endif
675     return datafile_dir;
676 }
677
678 #ifdef HAVE_PYTHON
679 /*
680  * Find the directory where the python dissectors are stored.
681  *
682  * On Windows, we use the "py_dissector" subdirectory of the datafile directory.
683  *
684  * On UN*X, we use the PYTHON_DIR value supplied by the configure
685  * script, unless we think we're being run from the build directory,
686  * in which case we use the "py_dissector" subdirectory of the datafile directory.
687  *
688  * In both cases, we then use the subdirectory of that directory whose
689  * name is the version number.
690  *
691  * XXX - if we think we're being run from the build directory, perhaps we
692  * should have the plugin code not look in the version subdirectory
693  * of the plugin directory, but look in all of the subdirectories
694  * of the plugin directory, so it can just fetch the plugins built
695  * as part of the build process.
696  */
697 static const char *wspython_dir = NULL;
698
699 static void
700 init_wspython_dir(void)
701 {
702 #ifdef _WIN32
703     /*
704      * On Windows, the data file directory is the installation
705      * directory; the python dissectors are stored under it.
706      *
707      * Assume we're running the installed version of Wireshark;
708      * on Windows, the data file directory is the directory
709      * in which the Wireshark binary resides.
710      */
711         wspython_dir = g_strdup_printf("%s\\python\\%s", get_datafile_dir(),
712                                         VERSION);
713
714     /*
715      * Make sure that pathname refers to a directory.
716      */
717     if (test_for_directory(wspython_dir) != EISDIR) {
718         /*
719          * Either it doesn't refer to a directory or it
720          * refers to something that doesn't exist.
721          *
722          * Assume that means we're running a version of
723          * Wireshark we've built in a build directory,
724          * in which case {datafile dir}\python is the
725          * top-level plugins source directory, and use
726          * that directory and set the "we're running in
727          * a build directory" flag, so the plugin
728          * scanner will check all subdirectories of that
729          * directory for python dissectors.
730          */
731         g_free( (gpointer) wspython_dir);
732         wspython_dir = g_strdup_printf("%s\\python", get_datafile_dir());
733         running_in_build_directory_flag = TRUE;
734     }
735 #else
736     if (running_in_build_directory_flag) {
737         /*
738          * We're (probably) being run from the build directory and
739          * weren't started with special privileges, so we'll use
740          * the "python" subdirectory of the datafile directory
741          * (the datafile directory is the build directory).
742          */
743         wspython_dir = g_strdup_printf("%s/epan/wspython/", get_datafile_dir());
744     } else {
745         if (getenv("WIRESHARK_PYTHON_DIR") && !started_with_special_privs()) {
746             /*
747              * The user specified a different directory for plugins
748              * and we aren't running with special privileges.
749              */
750             wspython_dir = g_strdup(getenv("WIRESHARK_PYTHON_DIR"));
751         } else {
752             wspython_dir = PYTHON_DIR;
753         }
754     }
755 #endif
756 }
757 #endif /* HAVE_PYTHON */
758
759 /*
760  * Get the directory in which the python dissectors are stored.
761  */
762 const char *
763 get_wspython_dir(void)
764 {
765 #ifdef HAVE_PYTHON
766     if (!wspython_dir) init_wspython_dir();
767     return wspython_dir;
768 #else
769     return NULL;
770 #endif
771 }
772
773
774 #if defined(HAVE_PLUGINS) || defined(HAVE_LUA_5_1)
775 /*
776  * Find the directory where the plugins are stored.
777  *
778  * On Windows, we use the "plugin" subdirectory of the datafile directory.
779  *
780  * On UN*X, we use the PLUGIN_DIR value supplied by the configure
781  * script, unless we think we're being run from the build directory,
782  * in which case we use the "plugin" subdirectory of the datafile directory.
783  *
784  * In both cases, we then use the subdirectory of that directory whose
785  * name is the version number.
786  *
787  * XXX - if we think we're being run from the build directory, perhaps we
788  * should have the plugin code not look in the version subdirectory
789  * of the plugin directory, but look in all of the subdirectories
790  * of the plugin directory, so it can just fetch the plugins built
791  * as part of the build process.
792  */
793 static const char *plugin_dir = NULL;
794
795 static void
796 init_plugin_dir(void)
797 {
798 #ifdef _WIN32
799     /*
800      * On Windows, the data file directory is the installation
801      * directory; the plugins are stored under it.
802      *
803      * Assume we're running the installed version of Wireshark;
804      * on Windows, the data file directory is the directory
805      * in which the Wireshark binary resides.
806      */
807     plugin_dir = g_strdup_printf("%s\\plugins\\%s", get_datafile_dir(),
808                      VERSION);
809
810     /*
811      * Make sure that pathname refers to a directory.
812      */
813     if (test_for_directory(plugin_dir) != EISDIR) {
814         /*
815          * Either it doesn't refer to a directory or it
816          * refers to something that doesn't exist.
817          *
818          * Assume that means we're running a version of
819          * Wireshark we've built in a build directory,
820          * in which case {datafile dir}\plugins is the
821          * top-level plugins source directory, and use
822          * that directory and set the "we're running in
823          * a build directory" flag, so the plugin
824          * scanner will check all subdirectories of that
825          * directory for plugins.
826          */
827         g_free( (gpointer) plugin_dir);
828         plugin_dir = g_strdup_printf("%s\\plugins", get_datafile_dir());
829         running_in_build_directory_flag = TRUE;
830     }
831 #else
832     if (running_in_build_directory_flag) {
833         /*
834          * We're (probably) being run from the build directory and
835          * weren't started with special privileges, so we'll use
836          * the "plugins" subdirectory of the datafile directory
837          * (the datafile directory is the build directory).
838          */
839         plugin_dir = g_strdup_printf("%s/plugins", get_datafile_dir());
840     } else {
841         if (getenv("WIRESHARK_PLUGIN_DIR") && !started_with_special_privs()) {
842             /*
843              * The user specified a different directory for plugins
844              * and we aren't running with special privileges.
845              */
846             plugin_dir = g_strdup(getenv("WIRESHARK_PLUGIN_DIR"));
847         } else {
848             plugin_dir = PLUGIN_DIR;
849         }
850     }
851 #endif
852 }
853 #endif /* HAVE_PLUGINS || HAVE_LUA_5_1 */
854
855 /*
856  * Get the directory in which the plugins are stored.
857  */
858 const char *
859 get_plugin_dir(void)
860 {
861 #if defined(HAVE_PLUGINS) || defined(HAVE_LUA_5_1)
862     if (!plugin_dir) init_plugin_dir();
863     return plugin_dir;
864 #else
865     return NULL;
866 #endif
867 }
868
869 /*
870  * Get the flag indicating whether we're running from a build
871  * directory.
872  */
873 gboolean
874 running_in_build_directory(void)
875 {
876     return running_in_build_directory_flag;
877 }
878
879 /*
880  * Get the directory in which files that, at least on UNIX, are
881  * system files (such as "/etc/ethers") are stored; on Windows,
882  * there's no "/etc" directory, so we get them from the global
883  * configuration and data file directory.
884  */
885 const char *
886 get_systemfile_dir(void)
887 {
888 #ifdef _WIN32
889     return get_datafile_dir();
890 #else
891     return "/etc";
892 #endif
893 }
894
895 /*
896  * Name of directory, under the user's home directory, in which
897  * personal configuration files are stored.
898  */
899 #ifdef _WIN32
900 #define PF_DIR "Wireshark"
901 #else
902 /*
903  * XXX - should this be ".libepan"? For backwards-compatibility, I'll keep
904  * it ".wireshark" for now.
905  */
906 #define PF_DIR ".wireshark"
907 #endif
908
909 void
910 set_profile_name(const gchar *profilename)
911 {
912     g_free (persconfprofile);
913
914     if (profilename && strlen(profilename) > 0 &&
915         strcmp(profilename, DEFAULT_PROFILE) != 0) {
916         persconfprofile = g_strdup (profilename);
917     } else {
918         /* Default Profile */
919         persconfprofile = NULL;
920     }
921 }
922
923 const char *
924 get_profile_name(void)
925 {
926     if (persconfprofile) {
927         return persconfprofile;
928     } else {
929         return DEFAULT_PROFILE;
930     }
931 }
932
933 gboolean
934 is_default_profile(void)
935 {
936     return (!persconfprofile || strcmp(persconfprofile, DEFAULT_PROFILE) == 0) ? TRUE : FALSE;
937 }
938
939 gboolean
940 has_global_profiles(void)
941 {
942     WS_DIR *dir;
943     WS_DIRENT *file;
944     const gchar *global_dir = get_global_profiles_dir();
945     gchar *filename;
946     gboolean has_global = FALSE;
947
948     if ((test_for_directory(global_dir) == EISDIR) &&
949         ((dir = ws_dir_open(global_dir, 0, NULL)) != NULL))
950     {
951         while ((file = ws_dir_read_name(dir)) != NULL) {
952             filename = g_strdup_printf ("%s%s%s", global_dir, G_DIR_SEPARATOR_S,
953                             ws_dir_get_name(file));
954             if (test_for_directory(filename) == EISDIR) {
955                 has_global = TRUE;
956                 g_free (filename);
957                 break;
958             }
959             g_free (filename);
960         }
961         ws_dir_close(dir);
962     }
963
964     return has_global;
965 }
966
967 void
968 profile_store_persconffiles(gboolean store)
969 {
970     if (store) {
971         profile_files = g_hash_table_new (g_str_hash, g_str_equal);
972     }
973     do_store_persconffiles = store;
974 }
975
976 /*
977  * Get the directory in which personal configuration files reside;
978  * in UNIX-compatible systems, it's ".wireshark", under the user's home
979  * directory, and on Windows systems, it's "Wireshark", under %APPDATA%
980  * or, if %APPDATA% isn't set, it's "%USERPROFILE%\Application Data"
981  * (which is what %APPDATA% normally is on Windows 2000).
982  */
983 static const char *
984 get_persconffile_dir_no_profile(void)
985 {
986 #ifdef _WIN32
987     char *appdatadir;
988     char *userprofiledir;
989     char *u3appdatapath;
990 #else
991     const char *homedir;
992     struct passwd *pwd;
993 #endif
994
995     /* Return the cached value, if available */
996     if (persconffile_dir != NULL)
997         return persconffile_dir;
998
999 #ifdef _WIN32
1000     /*
1001      * See if we are running in a U3 environment.
1002      */
1003     u3appdatapath = getenv_utf8("U3_APP_DATA_PATH");
1004     if (u3appdatapath != NULL) {
1005         /*
1006          * We are; use the U3 application data path.
1007          */
1008         persconffile_dir = u3appdatapath;
1009     } else {
1010         /*
1011          * Use %APPDATA% or %USERPROFILE%, so that configuration
1012          * files are stored in the user profile, rather than in
1013          * the home directory.  The Windows convention is to store
1014          * configuration information in the user profile, and doing
1015          * so means you can use Wireshark even if the home directory
1016          * is an inaccessible network drive.
1017          */
1018         appdatadir = getenv_utf8("APPDATA");
1019         if (appdatadir != NULL) {
1020             /*
1021              * Concatenate %APPDATA% with "\Wireshark".
1022              */
1023             persconffile_dir = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
1024                                appdatadir, PF_DIR);
1025         } else {
1026             /*
1027              * OK, %APPDATA% wasn't set, so use
1028              * %USERPROFILE%\Application Data.
1029              */
1030             userprofiledir = getenv_utf8("USERPROFILE");
1031             if (userprofiledir != NULL) {
1032                 persconffile_dir = g_strdup_printf(
1033                     "%s" G_DIR_SEPARATOR_S "Application Data" G_DIR_SEPARATOR_S "%s",
1034                     userprofiledir, PF_DIR);
1035             } else {
1036                 /*
1037                  * Give up and use "C:".
1038                  */
1039                 persconffile_dir = g_strdup_printf("C:" G_DIR_SEPARATOR_S "%s", PF_DIR);
1040             }
1041         }
1042     }
1043 #else
1044     /*
1045      * If $HOME is set, use that.
1046      */
1047     homedir = getenv("HOME");
1048     if (homedir == NULL) {
1049         /*
1050          * Get their home directory from the password file.
1051          * If we can't even find a password file entry for them,
1052          * use "/tmp".
1053          */
1054         pwd = getpwuid(getuid());
1055         if (pwd != NULL) {
1056             /*
1057              * This is cached, so we don't need to worry
1058              * about allocating multiple ones of them.
1059              */
1060             homedir = g_strdup(pwd->pw_dir);
1061         } else
1062             homedir = "/tmp";
1063     }
1064     persconffile_dir = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", homedir, PF_DIR);
1065 #endif
1066
1067     return persconffile_dir;
1068 }
1069
1070 const char *
1071 get_profiles_dir(void)
1072 {
1073     static char *profiles_dir = NULL;
1074
1075     g_free (profiles_dir);
1076     profiles_dir = g_strdup_printf ("%s%s%s", get_persconffile_dir_no_profile (),
1077                     G_DIR_SEPARATOR_S, PROFILES_DIR);
1078
1079     return profiles_dir;
1080 }
1081
1082 const char *
1083 get_global_profiles_dir(void)
1084 {
1085     static char *global_profiles_dir = NULL;
1086
1087     if (!global_profiles_dir) {
1088         global_profiles_dir = g_strdup_printf ("%s%s%s", get_datafile_dir(),
1089                                G_DIR_SEPARATOR_S, PROFILES_DIR);
1090     }
1091
1092     return global_profiles_dir;
1093 }
1094
1095 static const char *
1096 get_persconffile_dir(const gchar *profilename)
1097 {
1098     static char *persconffile_profile_dir = NULL;
1099
1100     g_free (persconffile_profile_dir);
1101
1102     if (profilename && strlen(profilename) > 0 &&
1103         strcmp(profilename, DEFAULT_PROFILE) != 0) {
1104       persconffile_profile_dir = g_strdup_printf ("%s%s%s", get_profiles_dir (),
1105                               G_DIR_SEPARATOR_S, profilename);
1106     } else {
1107       persconffile_profile_dir = g_strdup (get_persconffile_dir_no_profile ());
1108     }
1109
1110     return persconffile_profile_dir;
1111 }
1112
1113 gboolean
1114 profile_exists(const gchar *profilename, gboolean global)
1115 {
1116     if (global) {
1117         gchar *path = g_strdup_printf ("%s%s%s", get_global_profiles_dir(),
1118                            G_DIR_SEPARATOR_S, profilename);
1119         if (test_for_directory (path) == EISDIR) {
1120             g_free (path);
1121             return TRUE;
1122         }
1123         g_free (path);
1124     } else {
1125         if (test_for_directory (get_persconffile_dir (profilename)) == EISDIR) {
1126             return TRUE;
1127         }
1128     }
1129
1130     return FALSE;
1131 }
1132
1133 static int
1134 delete_directory (const char *directory, char **pf_dir_path_return)
1135 {
1136     WS_DIR *dir;
1137     WS_DIRENT *file;
1138     gchar *filename;
1139     int ret = 0;
1140
1141     if ((dir = ws_dir_open(directory, 0, NULL)) != NULL) {
1142         while ((file = ws_dir_read_name(dir)) != NULL) {
1143             filename = g_strdup_printf ("%s%s%s", directory, G_DIR_SEPARATOR_S,
1144                             ws_dir_get_name(file));
1145             if (test_for_directory(filename) != EISDIR) {
1146                 ret = ws_remove(filename);
1147 #if 0
1148             } else {
1149                 /* The user has manually created a directory in the profile directory */
1150                 /* I do not want to delete the directory recursively yet */
1151                 ret = delete_directory (filename, pf_dir_path_return);
1152 #endif
1153             }
1154             if (ret != 0) {
1155                 *pf_dir_path_return = filename;
1156                 break;
1157             }
1158             g_free (filename);
1159         }
1160         ws_dir_close(dir);
1161     }
1162
1163     if (ret == 0 && (ret = ws_remove(directory)) != 0) {
1164         *pf_dir_path_return = g_strdup (directory);
1165     }
1166
1167     return ret;
1168 }
1169
1170 int
1171 delete_persconffile_profile(const char *profilename, char **pf_dir_path_return)
1172 {
1173     const char *profile_dir = get_persconffile_dir(profilename);
1174     int ret = 0;
1175
1176     if (test_for_directory (profile_dir) == EISDIR) {
1177         ret = delete_directory (profile_dir, pf_dir_path_return);
1178     }
1179
1180     return ret;
1181 }
1182
1183 int
1184 rename_persconffile_profile(const char *fromname, const char *toname,
1185                 char **pf_from_dir_path_return, char **pf_to_dir_path_return)
1186 {
1187     char *from_dir = g_strdup (get_persconffile_dir(fromname));
1188     char *to_dir = g_strdup (get_persconffile_dir(toname));
1189     int ret = 0;
1190
1191     ret = ws_rename (from_dir, to_dir);
1192     if (ret != 0) {
1193         *pf_from_dir_path_return = g_strdup (from_dir);
1194         *pf_to_dir_path_return = g_strdup (to_dir);
1195     }
1196
1197     g_free (from_dir);
1198     g_free (to_dir);
1199
1200     return ret;
1201 }
1202
1203 /*
1204  * Create the directory that holds personal configuration files, if
1205  * necessary.  If we attempted to create it, and failed, return -1 and
1206  * set "*pf_dir_path_return" to the pathname of the directory we failed
1207  * to create (it's g_mallocated, so our caller should free it); otherwise,
1208  * return 0.
1209  */
1210 int
1211 create_persconffile_profile(const char *profilename, char **pf_dir_path_return)
1212 {
1213     const char *pf_dir_path;
1214 #ifdef _WIN32
1215     char *pf_dir_path_copy, *pf_dir_parent_path;
1216     size_t pf_dir_parent_path_len;
1217 #endif
1218     ws_statb64 s_buf;
1219     int ret;
1220
1221     if (profilename) {
1222         /*
1223          * Create the "Default" personal configuration files directory, if necessary.
1224          */
1225         if (create_persconffile_profile (NULL, pf_dir_path_return) == -1) {
1226             return -1;
1227         }
1228
1229         /*
1230          * Check if profiles directory exists.
1231          * If not then create it.
1232          */
1233         pf_dir_path = get_profiles_dir ();
1234         if (ws_stat64(pf_dir_path, &s_buf) != 0 && errno == ENOENT) {
1235             ret = ws_mkdir(pf_dir_path, 0755);
1236             if (ret == -1) {
1237                 *pf_dir_path_return = g_strdup(pf_dir_path);
1238                 return ret;
1239             }
1240         }
1241     }
1242
1243     pf_dir_path = get_persconffile_dir(profilename);
1244     if (ws_stat64(pf_dir_path, &s_buf) != 0 && errno == ENOENT) {
1245 #ifdef _WIN32
1246         /*
1247          * Does the parent directory of that directory
1248          * exist?  %APPDATA% may not exist even though
1249          * %USERPROFILE% does.
1250          *
1251          * We check for the existence of the directory
1252          * by first checking whether the parent directory
1253          * is just a drive letter and, if it's not, by
1254          * doing a "stat()" on it.  If it's a drive letter,
1255          * or if the "stat()" succeeds, we assume it exists.
1256          */
1257         pf_dir_path_copy = g_strdup(pf_dir_path);
1258         pf_dir_parent_path = get_dirname(pf_dir_path_copy);
1259         pf_dir_parent_path_len = strlen(pf_dir_parent_path);
1260         if (pf_dir_parent_path_len > 0
1261             && pf_dir_parent_path[pf_dir_parent_path_len - 1] != ':'
1262             && ws_stat64(pf_dir_parent_path, &s_buf) != 0) {
1263             /*
1264              * No, it doesn't exist - make it first.
1265              */
1266             ret = ws_mkdir(pf_dir_parent_path, 0755);
1267             if (ret == -1) {
1268                 *pf_dir_path_return = pf_dir_parent_path;
1269                 return -1;
1270             }
1271         }
1272         g_free(pf_dir_path_copy);
1273         ret = ws_mkdir(pf_dir_path, 0755);
1274 #else
1275         ret = ws_mkdir(pf_dir_path, 0755);
1276 #endif
1277     } else {
1278         /*
1279          * Something with that pathname exists; if it's not
1280          * a directory, we'll get an error if we try to put
1281          * something in it, so we don't fail here, we wait
1282          * for that attempt fo fail.
1283          */
1284         ret = 0;
1285     }
1286     if (ret == -1)
1287         *pf_dir_path_return = g_strdup(pf_dir_path);
1288     return ret;
1289 }
1290
1291 int
1292 create_persconffile_dir(char **pf_dir_path_return)
1293 {
1294   return create_persconffile_profile(persconfprofile, pf_dir_path_return);
1295 }
1296
1297 int
1298 copy_persconffile_profile(const char *toname, const char *fromname, gboolean from_global,
1299               char **pf_filename_return, char **pf_to_dir_path_return, char **pf_from_dir_path_return)
1300 {
1301     gchar *from_dir;
1302     gchar *to_dir = g_strdup (get_persconffile_dir(toname));
1303     gchar *filename, *from_file, *to_file;
1304     GList *files, *file;
1305
1306     if (from_global) {
1307         if (strcmp(fromname, DEFAULT_PROFILE) == 0) {
1308             from_dir = g_strdup (get_global_profiles_dir());
1309         } else {
1310             from_dir = g_strdup_printf ("%s%s%s", get_global_profiles_dir(), G_DIR_SEPARATOR_S, fromname);
1311         }
1312     } else {
1313         from_dir = g_strdup (get_persconffile_dir(fromname));
1314     }
1315
1316     files = g_hash_table_get_keys(profile_files);
1317     file = g_list_first(files);
1318     while (file) {
1319         filename = (gchar *)file->data;
1320         from_file = g_strdup_printf ("%s%s%s", from_dir, G_DIR_SEPARATOR_S, filename);
1321         to_file =  g_strdup_printf ("%s%s%s", to_dir, G_DIR_SEPARATOR_S, filename);
1322
1323         if (file_exists(from_file) && !copy_file_binary_mode(from_file, to_file)) {
1324             *pf_filename_return = g_strdup(filename);
1325             *pf_to_dir_path_return = to_dir;
1326             *pf_from_dir_path_return = from_dir;
1327             g_free (from_file);
1328             g_free (to_file);
1329             return -1;
1330         }
1331
1332         g_free (from_file);
1333         g_free (to_file);
1334
1335         file = g_list_next(file);
1336     }
1337
1338     g_list_free (files);
1339     g_free (from_dir);
1340     g_free (to_dir);
1341
1342     return 0;
1343 }
1344
1345 /*
1346  * Get the (default) directory in which personal data is stored.
1347  *
1348  * On Win32, this is the "My Documents" folder in the personal profile,
1349  * except that, if we're running from a U3 device, this is the
1350  * "$U3_DEVICE_DOCUMENT_PATH\My Captures" folder.
1351  * On UNIX this is simply the current directory.
1352  */
1353 /* XXX - should this and the get_home_dir() be merged? */
1354 extern const char *
1355 get_persdatafile_dir(void)
1356 {
1357 #ifdef _WIN32
1358     char *u3devicedocumentpath;
1359     TCHAR tszPath[MAX_PATH];
1360     char *szPath;
1361     BOOL bRet;
1362
1363     /* Return the cached value, if available */
1364     if (persdatafile_dir != NULL)
1365         return persdatafile_dir;
1366
1367     /*
1368      * See if we are running in a U3 environment.
1369      */
1370     u3devicedocumentpath = getenv_utf8("U3_DEVICE_DOCUMENT_PATH");
1371
1372     if (u3devicedocumentpath != NULL) {
1373         /* the "My Captures" sub-directory is created (if it doesn't
1374            exist) by u3util.exe when the U3 Wireshark is first run */
1375
1376         szPath = g_strdup_printf("%s%s", u3devicedocumentpath, U3_MY_CAPTURES);
1377
1378         persdatafile_dir = szPath;
1379         return szPath;
1380     } else {
1381         /*
1382          * Hint: SHGetFolderPath is not available on MSVC 6 - without
1383          * Platform SDK
1384          */
1385         bRet = SHGetSpecialFolderPath(NULL, tszPath, CSIDL_PERSONAL,
1386             FALSE);
1387         if(bRet == TRUE) {
1388             szPath = utf_16to8(tszPath);
1389             persdatafile_dir = szPath;
1390             return szPath;
1391         } else {
1392             return "";
1393         }
1394     }
1395 #else
1396     return "";
1397 #endif
1398 }
1399
1400 #ifdef _WIN32
1401 /*
1402  * Returns the user's home directory on Win32.
1403  */
1404 static const char *
1405 get_home_dir(void)
1406 {
1407     static const char *home = NULL;
1408     char *homedrive, *homepath;
1409     char *homestring;
1410     char *lastsep;
1411
1412     /* Return the cached value, if available */
1413     if (home)
1414         return home;
1415
1416     /*
1417      * XXX - should we use USERPROFILE anywhere in this process?
1418      * Is there a chance that it might be set but one or more of
1419      * HOMEDRIVE or HOMEPATH isn't set?
1420      */
1421     homedrive = getenv_utf8("HOMEDRIVE");
1422     if (homedrive != NULL) {
1423         homepath = getenv_utf8("HOMEPATH");
1424         if (homepath != NULL) {
1425             /*
1426              * This is cached, so we don't need to worry about
1427              * allocating multiple ones of them.
1428              */
1429             homestring = g_strdup_printf("%s%s", homedrive, homepath);
1430
1431             /*
1432              * Trim off any trailing slash or backslash.
1433              */
1434             lastsep = find_last_pathname_separator(homestring);
1435             if (lastsep != NULL && *(lastsep + 1) == '\0') {
1436                 /*
1437                  * Last separator is the last character
1438                  * in the string.  Nuke it.
1439                  */
1440                 *lastsep = '\0';
1441             }
1442             home = homestring;
1443         } else
1444             home = homedrive;
1445     } else {
1446         /*
1447          * Give up and use C:.
1448          */
1449         home = "C:";
1450     }
1451
1452     return home;
1453 }
1454 #endif
1455
1456 /*
1457  * Construct the path name of a personal configuration file, given the
1458  * file name.
1459  *
1460  * On Win32, if "for_writing" is FALSE, we check whether the file exists
1461  * and, if not, construct a path name relative to the ".wireshark"
1462  * subdirectory of the user's home directory, and check whether that
1463  * exists; if it does, we return that, so that configuration files
1464  * from earlier versions can be read.
1465  *
1466  * The returned file name was g_malloc()'d so it must be g_free()d when the
1467  * caller is done with it.
1468  */
1469 char *
1470 get_persconffile_path(const char *filename, gboolean from_profile, gboolean for_writing
1471 #ifndef _WIN32
1472     _U_
1473 #endif
1474 )
1475 {
1476     char *path;
1477 #ifdef _WIN32
1478     ws_statb64 s_buf;
1479     char *old_path;
1480 #endif
1481     if (do_store_persconffiles && from_profile && !g_hash_table_lookup (profile_files, filename)) {
1482         /* Store filenames so we know which filenames belongs to a configuration profile */
1483         g_hash_table_insert (profile_files, g_strdup(filename), g_strdup(filename));
1484     }
1485
1486     if (from_profile) {
1487       path = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
1488                  get_persconffile_dir(persconfprofile), filename);
1489     } else {
1490       path = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
1491                  get_persconffile_dir(NULL), filename);
1492     }
1493 #ifdef _WIN32
1494     if (!for_writing) {
1495         if (ws_stat64(path, &s_buf) != 0 && errno == ENOENT) {
1496             /*
1497              * OK, it's not in the personal configuration file
1498              * directory; is it in the ".wireshark" subdirectory
1499              * of their home directory?
1500              */
1501             old_path = g_strdup_printf(
1502                 "%s" G_DIR_SEPARATOR_S ".wireshark" G_DIR_SEPARATOR_S "%s",
1503                 get_home_dir(), filename);
1504             if (ws_stat64(old_path, &s_buf) == 0) {
1505                 /*
1506                  * OK, it exists; return it instead.
1507                  */
1508                 g_free(path);
1509                 path = old_path;
1510             }
1511         }
1512     }
1513 #endif
1514
1515     return path;
1516 }
1517
1518 /*
1519  * process command line option belonging to the filesystem settings
1520  * (move this e.g. to main.c and have set_persconffile_dir() instead in this file?)
1521  */
1522 int
1523 filesystem_opt(int opt _U_, const char *optstr)
1524 {
1525     gchar *p, *colonp;
1526
1527     colonp = strchr(optstr, ':');
1528     if (colonp == NULL) {
1529         return 1;
1530     }
1531
1532     p = colonp;
1533     *p++ = '\0';
1534
1535     /*
1536     * Skip over any white space (there probably won't be any, but
1537     * as we allow it in the preferences file, we might as well
1538     * allow it here).
1539     */
1540     while (isspace((guchar)*p))
1541         p++;
1542     if (*p == '\0') {
1543         /*
1544          * Put the colon back, so if our caller uses, in an
1545          * error message, the string they passed us, the message
1546          * looks correct.
1547          */
1548         *colonp = ':';
1549         return 1;
1550     }
1551
1552     /* directory should be existing */
1553     /* XXX - is this a requirement? */
1554     if(test_for_directory(p) != EISDIR) {
1555         /*
1556          * Put the colon back, so if our caller uses, in an
1557          * error message, the string they passed us, the message
1558          * looks correct.
1559          */
1560         *colonp = ':';
1561         return 1;
1562     }
1563
1564     if (strcmp(optstr,"persconf") == 0) {
1565         persconffile_dir = p;
1566     } else if (strcmp(optstr,"persdata") == 0) {
1567         persdatafile_dir = p;
1568         /* XXX - might need to add the temp file path */
1569     } else {
1570         return 1;
1571     }
1572     *colonp = ':'; /* put the colon back */
1573     return 0;
1574 }
1575
1576 /*
1577  * Construct the path name of a global configuration file, given the
1578  * file name.
1579  *
1580  * The returned file name was g_malloc()'d so it must be g_free()d when the
1581  * caller is done with it.
1582  */
1583 char *
1584 get_datafile_path(const char *filename)
1585 {
1586
1587     return g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", get_datafile_dir(), filename);
1588 }
1589
1590 /* Get the personal plugin dir */
1591 /* Return value is malloced so the caller should g_free() it. */
1592 char *
1593 get_plugins_pers_dir(void)
1594 {
1595     return get_persconffile_path(PLUGINS_DIR_NAME, FALSE, FALSE);
1596 }
1597
1598 /* Delete a file */
1599 gboolean
1600 deletefile(const char *path)
1601 {
1602     return ws_unlink(path) == 0;
1603 }
1604
1605 /*
1606  * Construct and return the path name of a file in the
1607  * appropriate temporary file directory.
1608  */
1609 char *get_tempfile_path(const char *filename)
1610 {
1611     return g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", g_get_tmp_dir(), filename);
1612 }
1613
1614 /*
1615  * Return an error message for UNIX-style errno indications on open or
1616  * create operations.
1617  */
1618 const char *
1619 file_open_error_message(int err, gboolean for_writing)
1620 {
1621     const char *errmsg;
1622     static char errmsg_errno[1024+1];
1623
1624     switch (err) {
1625
1626     case ENOENT:
1627         if (for_writing)
1628             errmsg = "The path to the file \"%s\" doesn't exist.";
1629         else
1630             errmsg = "The file \"%s\" doesn't exist.";
1631         break;
1632
1633     case EACCES:
1634         if (for_writing)
1635             errmsg = "You don't have permission to create or write to the file \"%s\".";
1636         else
1637             errmsg = "You don't have permission to read the file \"%s\".";
1638         break;
1639
1640     case EISDIR:
1641         errmsg = "\"%s\" is a directory (folder), not a file.";
1642         break;
1643
1644     case ENOSPC:
1645         errmsg = "The file \"%s\" could not be created because there is no space left on the file system.";
1646         break;
1647
1648 #ifdef EDQUOT
1649     case EDQUOT:
1650         errmsg = "The file \"%s\" could not be created because you are too close to, or over, your disk quota.";
1651         break;
1652 #endif
1653
1654     case EINVAL:
1655         errmsg = "The file \"%s\" could not be created because an invalid filename was specified.";
1656         break;
1657
1658     default:
1659         g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1660                "The file \"%%s\" could not be %s: %s.",
1661                for_writing ? "created" : "opened",
1662                g_strerror(err));
1663         errmsg = errmsg_errno;
1664         break;
1665     }
1666     return errmsg;
1667 }
1668
1669 /*
1670  * Return an error message for UNIX-style errno indications on write
1671  * operations.
1672  */
1673 const char *
1674 file_write_error_message(int err)
1675 {
1676     const char *errmsg;
1677     static char errmsg_errno[1024+1];
1678
1679     switch (err) {
1680
1681     case ENOSPC:
1682         errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
1683         break;
1684
1685 #ifdef EDQUOT
1686     case EDQUOT:
1687         errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
1688         break;
1689 #endif
1690
1691     default:
1692         g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1693                "An error occurred while writing to the file \"%%s\": %s.",
1694                g_strerror(err));
1695         errmsg = errmsg_errno;
1696         break;
1697     }
1698     return errmsg;
1699 }
1700
1701
1702 gboolean
1703 file_exists(const char *fname)
1704 {
1705     ws_statb64 file_stat;
1706
1707     if (!fname) {
1708         return FALSE;
1709     }
1710
1711 #ifdef _WIN32
1712     /*
1713      * This is a bit tricky on win32. The st_ino field is documented as:
1714      * "The inode, and therefore st_ino, has no meaning in the FAT, ..."
1715      * but it *is* set to zero if stat() returns without an error,
1716      * so this is working, but maybe not quite the way expected. ULFL
1717      */
1718     file_stat.st_ino = 1;   /* this will make things work if an error occured */
1719     ws_stat64(fname, &file_stat);
1720     if (file_stat.st_ino == 0) {
1721         return TRUE;
1722     } else {
1723         return FALSE;
1724     }
1725 #else
1726     if (ws_stat64(fname, &file_stat) != 0 && errno == ENOENT) {
1727         return FALSE;
1728     } else {
1729         return TRUE;
1730     }
1731 #endif
1732 }
1733
1734 /*
1735  * Check that the from file is not the same as to file
1736  * We do it here so we catch all cases ...
1737  * Unfortunately, the file requester gives us an absolute file
1738  * name and the read file name may be relative (if supplied on
1739  * the command line), so we can't just compare paths. From Joerg Mayer.
1740  */
1741 gboolean
1742 files_identical(const char *fname1, const char *fname2)
1743 {
1744     /* Two different implementations, because:
1745      *
1746      * - _fullpath is not available on UN*X, so we can't get full
1747      *   paths and compare them (which wouldn't work with hard links
1748      *   in any case);
1749      *
1750      * - st_ino isn't filled in with a meaningful value on Windows.
1751      */
1752 #ifdef _WIN32
1753     char full1[MAX_PATH], full2[MAX_PATH];
1754
1755     /*
1756      * Get the absolute full paths of the file and compare them.
1757      * That won't work if you have hard links, but those aren't
1758      * much used on Windows, even though NTFS supports them.
1759      *
1760      * XXX - will _fullpath work with UNC?
1761      */
1762     if( _fullpath( full1, fname1, MAX_PATH ) == NULL ) {
1763         return FALSE;
1764     }
1765
1766     if( _fullpath( full2, fname2, MAX_PATH ) == NULL ) {
1767         return FALSE;
1768     }
1769
1770     if(strcmp(full1, full2) == 0) {
1771         return TRUE;
1772     } else {
1773         return FALSE;
1774     }
1775 #else
1776     ws_statb64 filestat1, filestat2;
1777
1778     /*
1779      * Compare st_dev and st_ino.
1780      */
1781     if (ws_stat64(fname1, &filestat1) == -1)
1782         return FALSE;   /* can't get info about the first file */
1783     if (ws_stat64(fname2, &filestat2) == -1)
1784         return FALSE;   /* can't get info about the second file */
1785     return (filestat1.st_dev == filestat2.st_dev &&
1786         filestat1.st_ino == filestat2.st_ino);
1787 #endif
1788 }
1789
1790 /*
1791  * Copy a file in binary mode, for those operating systems that care about
1792  * such things.  This should be OK for all files, even text files, as
1793  * we'll copy the raw bytes, and we don't look at the bytes as we copy
1794  * them.
1795  *
1796  * Returns TRUE on success, FALSE on failure. If a failure, it also
1797  * displays a simple dialog window with the error message.
1798  */
1799 gboolean
1800 copy_file_binary_mode(const char *from_filename, const char *to_filename)
1801 {
1802     int           from_fd, to_fd, nread, nwritten, err;
1803     guint8        *pd = NULL;
1804
1805     /* Copy the raw bytes of the file. */
1806     from_fd = ws_open(from_filename, O_RDONLY | O_BINARY, 0000 /* no creation so don't matter */);
1807     if (from_fd < 0) {
1808         report_open_failure(from_filename, errno, FALSE);
1809         goto done;
1810     }
1811
1812     /* Use open() instead of creat() so that we can pass the O_BINARY
1813        flag, which is relevant on Win32; it appears that "creat()"
1814        may open the file in text mode, not binary mode, but we want
1815        to copy the raw bytes of the file, so we need the output file
1816        to be open in binary mode. */
1817     to_fd = ws_open(to_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
1818     if (to_fd < 0) {
1819         report_open_failure(to_filename, errno, TRUE);
1820         ws_close(from_fd);
1821         goto done;
1822     }
1823
1824 #define FS_READ_SIZE 65536
1825     pd = g_malloc(FS_READ_SIZE);
1826     while ((nread = ws_read(from_fd, pd, FS_READ_SIZE)) > 0) {
1827         nwritten = ws_write(to_fd, pd, nread);
1828         if (nwritten < nread) {
1829             if (nwritten < 0)
1830                 err = errno;
1831             else
1832                 err = WTAP_ERR_SHORT_WRITE;
1833             report_write_failure(to_filename, err);
1834             ws_close(from_fd);
1835             ws_close(to_fd);
1836             goto done;
1837         }
1838     }
1839     if (nread < 0) {
1840         err = errno;
1841         report_read_failure(from_filename, err);
1842         ws_close(from_fd);
1843         ws_close(to_fd);
1844         goto done;
1845     }
1846     ws_close(from_fd);
1847     if (ws_close(to_fd) < 0) {
1848         report_write_failure(to_filename, errno);
1849         goto done;
1850     }
1851
1852     g_free(pd);
1853     pd = NULL;
1854     return TRUE;
1855
1856 done:
1857     g_free(pd);
1858     return FALSE;
1859 }
1860
1861 /*
1862  * Editor modelines
1863  *
1864  * Local Variables:
1865  * c-basic-offset: 4
1866  * tab-width: 8
1867  * indent-tabs-mode: nil
1868  * End:
1869  *
1870  * ex: set shiftwidth=4 tabstop=8 expandtab:
1871  * :indentSize=4:tabSize=8:noTabs=true:
1872  */