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