Don't put a 65536 byte variable on the stack: instead, malloc/free it.
[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         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 #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                             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                             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 && progfile_dir != NULL) {
626                 /*
627                  * We're (probably) being run from the build directory and
628                  * weren't started with special privileges, and we were
629                  * able to determine the directory in which the program
630                  * was found, so use that.
631                  */
632                 datafile_dir = progfile_dir;
633         } else {
634                 /*
635                  * Return the directory specified when the build was
636                  * configured, prepending the run path prefix if it exists.
637                  */
638                 if (getenv("WIRESHARK_DATA_DIR") && !started_with_special_privs()) {
639                         /*
640                          * The user specified a different directory for data files
641                          * and we aren't running with special privileges.
642                          * XXX - We might be able to dispense with the priv check
643                          */
644                         datafile_dir = g_strdup(getenv("WIRESHARK_DATA_DIR"));
645                 } else {
646                         datafile_dir = DATAFILE_DIR;
647                 }
648         }
649
650 #endif
651         return datafile_dir;
652 }
653
654 #ifdef HAVE_PYTHON
655 /*
656  * Find the directory where the python dissectors are stored.
657  *
658  * On Windows, we use the "py_dissector" subdirectory of the datafile directory.
659  *
660  * On UN*X, we use the PYTHON_DIR value supplied by the configure
661  * script, unless we think we're being run from the build directory,
662  * in which case we use the "py_dissector" subdirectory of the datafile directory.
663  *
664  * In both cases, we then use the subdirectory of that directory whose
665  * name is the version number.
666  *
667  * XXX - if we think we're being run from the build directory, perhaps we
668  * should have the plugin code not look in the version subdirectory
669  * of the plugin directory, but look in all of the subdirectories
670  * of the plugin directory, so it can just fetch the plugins built
671  * as part of the build process.
672  */
673 static const char *wspython_dir = NULL;
674
675 static void
676 init_wspython_dir(void)
677 {
678 #ifdef _WIN32
679         /*
680          * On Windows, the data file directory is the installation
681          * directory; the python dissectors are stored under it.
682          *
683          * Assume we're running the installed version of Wireshark;
684          * on Windows, the data file directory is the directory
685          * in which the Wireshark binary resides.
686          */
687         wspython_dir = g_strdup_printf("%s\\python\\%s", get_datafile_dir(),
688                                         VERSION);
689
690         /*
691          * Make sure that pathname refers to a directory.
692          */
693         if (test_for_directory(wspython_dir) != EISDIR) {
694                 /*
695                  * Either it doesn't refer to a directory or it
696                  * refers to something that doesn't exist.
697                  *
698                  * Assume that means we're running a version of
699                  * Wireshark we've built in a build directory,
700                  * in which case {datafile dir}\python is the
701                  * top-level plugins source directory, and use
702                  * that directory and set the "we're running in
703                  * a build directory" flag, so the plugin
704                  * scanner will check all subdirectories of that
705                  * directory for python dissectors.
706                  */
707                 g_free( (gpointer) wspython_dir);
708                 wspython_dir = g_strdup_printf("%s\\python", get_datafile_dir());
709                 running_in_build_directory_flag = TRUE;
710         }
711 #else
712         if (running_in_build_directory_flag) {
713                 /*
714                  * We're (probably) being run from the build directory and
715                  * weren't started with special privileges, so we'll use
716                  * the "python" subdirectory of the datafile directory
717                  * (the datafile directory is the build directory).
718                  */
719                 wspython_dir = g_strdup_printf("%s/epan/wspython/", get_datafile_dir());
720         } else {
721                 if (getenv("WIRESHARK_PYTHON_DIR") && !started_with_special_privs()) {
722                         /*
723                          * The user specified a different directory for plugins
724                          * and we aren't running with special privileges.
725                          */
726                         wspython_dir = g_strdup(getenv("WIRESHARK_PYTHON_DIR"));
727                 } else {
728                         wspython_dir = PYTHON_DIR;
729                 }
730         }
731 #endif
732 }
733 #endif /* HAVE_PYTHON */
734
735 /*
736  * Get the directory in which the python dissectors are stored.
737  */
738 const char *
739 get_wspython_dir(void)
740 {
741 #ifdef HAVE_PYTHON
742         if (!wspython_dir) init_wspython_dir();
743         return wspython_dir;
744 #else
745         return NULL;
746 #endif
747 }
748
749
750 #if defined(HAVE_PLUGINS) || defined(HAVE_LUA_5_1)
751 /*
752  * Find the directory where the plugins are stored.
753  *
754  * On Windows, we use the "plugin" subdirectory of the datafile directory.
755  *
756  * On UN*X, we use the PLUGIN_DIR value supplied by the configure
757  * script, unless we think we're being run from the build directory,
758  * in which case we use the "plugin" subdirectory of the datafile directory.
759  *
760  * In both cases, we then use the subdirectory of that directory whose
761  * name is the version number.
762  *
763  * XXX - if we think we're being run from the build directory, perhaps we
764  * should have the plugin code not look in the version subdirectory
765  * of the plugin directory, but look in all of the subdirectories
766  * of the plugin directory, so it can just fetch the plugins built
767  * as part of the build process.
768  */
769 static const char *plugin_dir = NULL;
770
771 static void
772 init_plugin_dir(void)
773 {
774 #ifdef _WIN32
775         /*
776          * On Windows, the data file directory is the installation
777          * directory; the plugins are stored under it.
778          *
779          * Assume we're running the installed version of Wireshark;
780          * on Windows, the data file directory is the directory
781          * in which the Wireshark binary resides.
782          */
783         plugin_dir = g_strdup_printf("%s\\plugins\\%s", get_datafile_dir(),
784                                      VERSION);
785
786         /*
787          * Make sure that pathname refers to a directory.
788          */
789         if (test_for_directory(plugin_dir) != EISDIR) {
790                 /*
791                  * Either it doesn't refer to a directory or it
792                  * refers to something that doesn't exist.
793                  *
794                  * Assume that means we're running a version of
795                  * Wireshark we've built in a build directory,
796                  * in which case {datafile dir}\plugins is the
797                  * top-level plugins source directory, and use
798                  * that directory and set the "we're running in
799                  * a build directory" flag, so the plugin
800                  * scanner will check all subdirectories of that
801                  * directory for plugins.
802                  */
803                 g_free( (gpointer) plugin_dir);
804                 plugin_dir = g_strdup_printf("%s\\plugins", get_datafile_dir());
805                 running_in_build_directory_flag = TRUE;
806         }
807 #else
808         if (running_in_build_directory_flag) {
809                 /*
810                  * We're (probably) being run from the build directory and
811                  * weren't started with special privileges, so we'll use
812                  * the "plugins" subdirectory of the datafile directory
813                  * (the datafile directory is the build directory).
814                  */
815                 plugin_dir = g_strdup_printf("%s/plugins", get_datafile_dir());
816         } else {
817                 if (getenv("WIRESHARK_PLUGIN_DIR") && !started_with_special_privs()) {
818                         /*
819                          * The user specified a different directory for plugins
820                          * and we aren't running with special privileges.
821                          */
822                         plugin_dir = g_strdup(getenv("WIRESHARK_PLUGIN_DIR"));
823                 } else {
824                         plugin_dir = PLUGIN_DIR;
825                 }
826         }
827 #endif
828 }
829 #endif /* HAVE_PLUGINS || HAVE_LUA_5_1 */
830
831 /*
832  * Get the directory in which the plugins are stored.
833  */
834 const char *
835 get_plugin_dir(void)
836 {
837 #if defined(HAVE_PLUGINS) || defined(HAVE_LUA_5_1)
838         if (!plugin_dir) init_plugin_dir();
839         return plugin_dir;
840 #else
841         return NULL;
842 #endif
843 }
844
845 /*
846  * Get the flag indicating whether we're running from a build
847  * directory.
848  */
849 gboolean
850 running_in_build_directory(void)
851 {
852         return running_in_build_directory_flag;
853 }
854
855 /*
856  * Get the directory in which files that, at least on UNIX, are
857  * system files (such as "/etc/ethers") are stored; on Windows,
858  * there's no "/etc" directory, so we get them from the global
859  * configuration and data file directory.
860  */
861 const char *
862 get_systemfile_dir(void)
863 {
864 #ifdef _WIN32
865         return get_datafile_dir();
866 #else
867         return "/etc";
868 #endif
869 }
870
871 /*
872  * Name of directory, under the user's home directory, in which
873  * personal configuration files are stored.
874  */
875 #ifdef _WIN32
876 #define PF_DIR "Wireshark"
877 #else
878 /*
879  * XXX - should this be ".libepan"? For backwards-compatibility, I'll keep
880  * it ".wireshark" for now.
881  */
882 #define PF_DIR ".wireshark"
883 #endif
884
885 void
886 set_profile_name(const gchar *profilename)
887 {
888         g_free (persconfprofile);
889
890         if (profilename && strlen(profilename) > 0 &&
891             strcmp(profilename, DEFAULT_PROFILE) != 0) {
892                 persconfprofile = g_strdup (profilename);
893         } else {
894                 /* Default Profile */
895                 persconfprofile = NULL;
896         }
897 }
898
899 const char *
900 get_profile_name(void)
901 {
902         if (persconfprofile) {
903                 return persconfprofile;
904         } else {
905                 return DEFAULT_PROFILE;
906         }
907 }
908
909 gboolean
910 is_default_profile(void)
911 {
912         return (!persconfprofile || strcmp(persconfprofile, DEFAULT_PROFILE) == 0) ? TRUE : FALSE;
913 }
914
915 gboolean
916 has_global_profiles(void)
917 {
918         WS_DIR *dir;
919         WS_DIRENT *file;
920         const gchar *global_dir = get_global_profiles_dir();
921         gchar *filename;
922         gboolean has_global = FALSE;
923
924         if ((test_for_directory(global_dir) == EISDIR) &&
925                 ((dir = ws_dir_open(global_dir, 0, NULL)) != NULL))
926     {
927                 while ((file = ws_dir_read_name(dir)) != NULL) {
928                         filename = g_strdup_printf ("%s%s%s", global_dir, G_DIR_SEPARATOR_S,
929                                                     ws_dir_get_name(file));
930                         if (test_for_directory(filename) == EISDIR) {
931                                 has_global = TRUE;
932                                 g_free (filename);
933                                 break;
934                         }
935                         g_free (filename);
936                 }
937                 ws_dir_close(dir);
938         }
939
940         return has_global;
941 }
942
943 void
944 profile_store_persconffiles(gboolean store)
945 {
946         if (store) {
947                 profile_files = g_hash_table_new (g_str_hash, g_str_equal);
948         }
949         do_store_persconffiles = store;
950 }
951
952 /*
953  * Get the directory in which personal configuration files reside;
954  * in UNIX-compatible systems, it's ".wireshark", under the user's home
955  * directory, and on Windows systems, it's "Wireshark", under %APPDATA%
956  * or, if %APPDATA% isn't set, it's "%USERPROFILE%\Application Data"
957  * (which is what %APPDATA% normally is on Windows 2000).
958  */
959 static const char *
960 get_persconffile_dir_no_profile(void)
961 {
962 #ifdef _WIN32
963         char *appdatadir;
964         char *userprofiledir;
965         char *u3appdatapath;
966 #else
967         const char *homedir;
968         struct passwd *pwd;
969 #endif
970
971         /* Return the cached value, if available */
972         if (persconffile_dir != NULL)
973                 return persconffile_dir;
974
975 #ifdef _WIN32
976         /*
977          * See if we are running in a U3 environment.
978          */
979         u3appdatapath = getenv_utf8("U3_APP_DATA_PATH");
980         if (u3appdatapath != NULL) {
981                 /*
982                  * We are; use the U3 application data path.
983                  */
984                 persconffile_dir = u3appdatapath;
985         } else {
986                 /*
987                  * Use %APPDATA% or %USERPROFILE%, so that configuration
988                  * files are stored in the user profile, rather than in
989                  * the home directory.  The Windows convention is to store
990                  * configuration information in the user profile, and doing
991                  * so means you can use Wireshark even if the home directory
992                  * is an inaccessible network drive.
993                  */
994                 appdatadir = getenv_utf8("APPDATA");
995                 if (appdatadir != NULL) {
996                         /*
997                          * Concatenate %APPDATA% with "\Wireshark".
998                          */
999                         persconffile_dir = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
1000                                                            appdatadir, PF_DIR);
1001                 } else {
1002                         /*
1003                          * OK, %APPDATA% wasn't set, so use
1004                          * %USERPROFILE%\Application Data.
1005                          */
1006                         userprofiledir = getenv_utf8("USERPROFILE");
1007                         if (userprofiledir != NULL) {
1008                                 persconffile_dir = g_strdup_printf(
1009                                     "%s" G_DIR_SEPARATOR_S "Application Data" G_DIR_SEPARATOR_S "%s",
1010                                     userprofiledir, PF_DIR);
1011                         } else {
1012                                 /*
1013                                  * Give up and use "C:".
1014                                  */
1015                                 persconffile_dir = g_strdup_printf("C:" G_DIR_SEPARATOR_S "%s", PF_DIR);
1016                         }
1017                 }
1018         }
1019 #else
1020         /*
1021          * If $HOME is set, use that.
1022          */
1023         homedir = getenv("HOME");
1024         if (homedir == NULL) {
1025                 /*
1026                  * Get their home directory from the password file.
1027                  * If we can't even find a password file entry for them,
1028                  * use "/tmp".
1029                  */
1030                 pwd = getpwuid(getuid());
1031                 if (pwd != NULL) {
1032                         /*
1033                          * This is cached, so we don't need to worry
1034                          * about allocating multiple ones of them.
1035                          */
1036                         homedir = g_strdup(pwd->pw_dir);
1037                 } else
1038                         homedir = "/tmp";
1039         }
1040         persconffile_dir = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", homedir, PF_DIR);
1041 #endif
1042
1043         return persconffile_dir;
1044 }
1045
1046 const char *
1047 get_profiles_dir(void)
1048 {
1049         static char *profiles_dir = NULL;
1050
1051         g_free (profiles_dir);
1052         profiles_dir = g_strdup_printf ("%s%s%s", get_persconffile_dir_no_profile (),
1053                                         G_DIR_SEPARATOR_S, PROFILES_DIR);
1054
1055         return profiles_dir;
1056 }
1057
1058 const char *
1059 get_global_profiles_dir(void)
1060 {
1061         static char *global_profiles_dir = NULL;
1062
1063         if (!global_profiles_dir) {
1064                 global_profiles_dir = g_strdup_printf ("%s%s%s", get_datafile_dir(),
1065                                                        G_DIR_SEPARATOR_S, PROFILES_DIR);
1066         }
1067
1068         return global_profiles_dir;
1069 }
1070
1071 static const char *
1072 get_persconffile_dir(const gchar *profilename)
1073 {
1074         static char *persconffile_profile_dir = NULL;
1075
1076         g_free (persconffile_profile_dir);
1077
1078         if (profilename && strlen(profilename) > 0 &&
1079             strcmp(profilename, DEFAULT_PROFILE) != 0) {
1080           persconffile_profile_dir = g_strdup_printf ("%s%s%s", get_profiles_dir (),
1081                                                       G_DIR_SEPARATOR_S, profilename);
1082         } else {
1083           persconffile_profile_dir = g_strdup (get_persconffile_dir_no_profile ());
1084         }
1085
1086         return persconffile_profile_dir;
1087 }
1088
1089 gboolean
1090 profile_exists(const gchar *profilename, gboolean global)
1091 {
1092         if (global) {
1093                 gchar *path = g_strdup_printf ("%s%s%s", get_global_profiles_dir(),
1094                                                G_DIR_SEPARATOR_S, profilename);
1095                 if (test_for_directory (path) == EISDIR) {
1096                         g_free (path);
1097                         return TRUE;
1098                 }
1099                 g_free (path);
1100         } else {
1101                 if (test_for_directory (get_persconffile_dir (profilename)) == EISDIR) {
1102                         return TRUE;
1103                 }
1104         }
1105
1106         return FALSE;
1107 }
1108
1109 static int
1110 delete_directory (const char *directory, char **pf_dir_path_return)
1111 {
1112         WS_DIR *dir;
1113         WS_DIRENT *file;
1114         gchar *filename;
1115         int ret = 0;
1116
1117         if ((dir = ws_dir_open(directory, 0, NULL)) != NULL) {
1118                 while ((file = ws_dir_read_name(dir)) != NULL) {
1119                         filename = g_strdup_printf ("%s%s%s", directory, G_DIR_SEPARATOR_S,
1120                                                     ws_dir_get_name(file));
1121                         if (test_for_directory(filename) != EISDIR) {
1122                                 ret = ws_remove(filename);
1123 #if 0
1124                         } else {
1125                                 /* The user has manually created a directory in the profile directory */
1126                                 /* I do not want to delete the directory recursively yet */
1127                                 ret = delete_directory (filename, pf_dir_path_return);
1128 #endif
1129                         }
1130                         if (ret != 0) {
1131                                 *pf_dir_path_return = filename;
1132                                 break;
1133                         }
1134                         g_free (filename);
1135                 }
1136                 ws_dir_close(dir);
1137         }
1138
1139         if (ret == 0 && (ret = ws_remove(directory)) != 0) {
1140                 *pf_dir_path_return = g_strdup (directory);
1141         }
1142
1143         return ret;
1144 }
1145
1146 int
1147 delete_persconffile_profile(const char *profilename, char **pf_dir_path_return)
1148 {
1149         const char *profile_dir = get_persconffile_dir(profilename);
1150         int ret = 0;
1151
1152         if (test_for_directory (profile_dir) == EISDIR) {
1153                 ret = delete_directory (profile_dir, pf_dir_path_return);
1154         }
1155
1156         return ret;
1157 }
1158
1159 int
1160 rename_persconffile_profile(const char *fromname, const char *toname,
1161                             char **pf_from_dir_path_return, char **pf_to_dir_path_return)
1162 {
1163         char *from_dir = g_strdup (get_persconffile_dir(fromname));
1164         char *to_dir = g_strdup (get_persconffile_dir(toname));
1165         int ret = 0;
1166
1167         ret = ws_rename (from_dir, to_dir);
1168         if (ret != 0) {
1169                 *pf_from_dir_path_return = g_strdup (from_dir);
1170                 *pf_to_dir_path_return = g_strdup (to_dir);
1171         }
1172
1173         g_free (from_dir);
1174         g_free (to_dir);
1175
1176         return ret;
1177 }
1178
1179 /*
1180  * Create the directory that holds personal configuration files, if
1181  * necessary.  If we attempted to create it, and failed, return -1 and
1182  * set "*pf_dir_path_return" to the pathname of the directory we failed
1183  * to create (it's g_mallocated, so our caller should free it); otherwise,
1184  * return 0.
1185  */
1186 int
1187 create_persconffile_profile(const char *profilename, char **pf_dir_path_return)
1188 {
1189         const char *pf_dir_path;
1190 #ifdef _WIN32
1191         char *pf_dir_path_copy, *pf_dir_parent_path;
1192         size_t pf_dir_parent_path_len;
1193 #endif
1194         struct stat s_buf;
1195         int ret;
1196
1197         if (profilename) {
1198                 /*
1199                  * Create the "Default" personal configuration files directory, if necessary.
1200                  */
1201                 if (create_persconffile_profile (NULL, pf_dir_path_return) == -1) {
1202                         return -1;
1203                 }
1204
1205                 /*
1206                  * Check if profiles directory exists.
1207                  * If not then create it.
1208                  */
1209                 pf_dir_path = get_profiles_dir ();
1210                 if (ws_stat(pf_dir_path, &s_buf) != 0 && errno == ENOENT) {
1211                         ret = ws_mkdir(pf_dir_path, 0755);
1212                         if (ret == -1) {
1213                                 *pf_dir_path_return = g_strdup(pf_dir_path);
1214                                 return ret;
1215                         }
1216                 }
1217         }
1218
1219         pf_dir_path = get_persconffile_dir(profilename);
1220         if (ws_stat(pf_dir_path, &s_buf) != 0 && errno == ENOENT) {
1221 #ifdef _WIN32
1222                 /*
1223                  * Does the parent directory of that directory
1224                  * exist?  %APPDATA% may not exist even though
1225                  * %USERPROFILE% does.
1226                  *
1227                  * We check for the existence of the directory
1228                  * by first checking whether the parent directory
1229                  * is just a drive letter and, if it's not, by
1230                  * doing a "stat()" on it.  If it's a drive letter,
1231                  * or if the "stat()" succeeds, we assume it exists.
1232                  */
1233                 pf_dir_path_copy = g_strdup(pf_dir_path);
1234                 pf_dir_parent_path = get_dirname(pf_dir_path_copy);
1235                 pf_dir_parent_path_len = strlen(pf_dir_parent_path);
1236                 if (pf_dir_parent_path_len > 0
1237                     && pf_dir_parent_path[pf_dir_parent_path_len - 1] != ':'
1238                     && ws_stat(pf_dir_parent_path, &s_buf) != 0) {
1239                         /*
1240                          * No, it doesn't exist - make it first.
1241                          */
1242                         ret = ws_mkdir(pf_dir_parent_path, 0755);
1243                         if (ret == -1) {
1244                                 *pf_dir_path_return = pf_dir_parent_path;
1245                                 return -1;
1246                         }
1247                 }
1248                 g_free(pf_dir_path_copy);
1249                 ret = ws_mkdir(pf_dir_path, 0755);
1250 #else
1251                 ret = ws_mkdir(pf_dir_path, 0755);
1252 #endif
1253         } else {
1254                 /*
1255                  * Something with that pathname exists; if it's not
1256                  * a directory, we'll get an error if we try to put
1257                  * something in it, so we don't fail here, we wait
1258                  * for that attempt fo fail.
1259                  */
1260                 ret = 0;
1261         }
1262         if (ret == -1)
1263                 *pf_dir_path_return = g_strdup(pf_dir_path);
1264         return ret;
1265 }
1266
1267 int
1268 create_persconffile_dir(char **pf_dir_path_return)
1269 {
1270   return create_persconffile_profile(persconfprofile, pf_dir_path_return);
1271 }
1272
1273 #if ! GLIB_CHECK_VERSION(2,14,0)
1274 static void
1275 hash_table_get_keys(gpointer key, gpointer value _U_, gpointer user_data)
1276 {
1277         GList **files = ((GList **)user_data);
1278         *files = g_list_append (*files, key);
1279 }
1280 #endif
1281
1282 int
1283 copy_persconffile_profile(const char *toname, const char *fromname, gboolean from_global,
1284                           char **pf_filename_return, char **pf_to_dir_path_return, char **pf_from_dir_path_return)
1285 {
1286         gchar *from_dir;
1287         gchar *to_dir = g_strdup (get_persconffile_dir(toname));
1288         gchar *filename, *from_file, *to_file;
1289         GList *files, *file;
1290
1291         if (from_global) {
1292             if (strcmp(fromname, DEFAULT_PROFILE) == 0) {
1293                         from_dir = g_strdup (get_global_profiles_dir());
1294                 } else {
1295                         from_dir = g_strdup_printf ("%s%s%s", get_global_profiles_dir(), G_DIR_SEPARATOR_S, fromname);
1296                 }
1297         } else {
1298                 from_dir = g_strdup (get_persconffile_dir(fromname));
1299         }
1300
1301 #if GLIB_CHECK_VERSION(2,14,0)
1302         files = g_hash_table_get_keys(profile_files);
1303 #else
1304         files = NULL;
1305         g_hash_table_foreach(profile_files, hash_table_get_keys, &files);
1306 #endif
1307
1308         file = g_list_first(files);
1309         while (file) {
1310                 filename = (gchar *)file->data;
1311                 from_file = g_strdup_printf ("%s%s%s", from_dir, G_DIR_SEPARATOR_S, filename);
1312                 to_file =  g_strdup_printf ("%s%s%s", to_dir, G_DIR_SEPARATOR_S, filename);
1313
1314                 if (file_exists(from_file) && !copy_file_binary_mode(from_file, to_file)) {
1315                         *pf_filename_return = g_strdup(filename);
1316                         *pf_to_dir_path_return = to_dir;
1317                         *pf_from_dir_path_return = from_dir;
1318                         g_free (from_file);
1319                         g_free (to_file);
1320                         return -1;
1321                 }
1322
1323                 g_free (from_file);
1324                 g_free (to_file);
1325
1326                 file = g_list_next(file);
1327         }
1328
1329         g_list_free (files);
1330         g_free (from_dir);
1331         g_free (to_dir);
1332
1333         return 0;
1334 }
1335
1336 /*
1337  * Get the (default) directory in which personal data is stored.
1338  *
1339  * On Win32, this is the "My Documents" folder in the personal profile,
1340  * except that, if we're running from a U3 device, this is the
1341  * "$U3_DEVICE_DOCUMENT_PATH\My Captures" folder.
1342  * On UNIX this is simply the current directory.
1343  */
1344 /* XXX - should this and the get_home_dir() be merged? */
1345 extern const char *
1346 get_persdatafile_dir(void)
1347 {
1348 #ifdef _WIN32
1349         char *u3devicedocumentpath;
1350         TCHAR tszPath[MAX_PATH];
1351         char *szPath;
1352         BOOL bRet;
1353
1354         /* Return the cached value, if available */
1355         if (persdatafile_dir != NULL)
1356                 return persdatafile_dir;
1357
1358         /*
1359          * See if we are running in a U3 environment.
1360          */
1361         u3devicedocumentpath = getenv_utf8("U3_DEVICE_DOCUMENT_PATH");
1362
1363         if (u3devicedocumentpath != NULL) {
1364                 /* the "My Captures" sub-directory is created (if it doesn't
1365                    exist) by u3util.exe when the U3 Wireshark is first run */
1366
1367                 szPath = g_strdup_printf("%s%s", u3devicedocumentpath, U3_MY_CAPTURES);
1368
1369                 persdatafile_dir = szPath;
1370                 return szPath;
1371         } else {
1372                 /*
1373                  * Hint: SHGetFolderPath is not available on MSVC 6 - without
1374                  * Platform SDK
1375                  */
1376                 bRet = SHGetSpecialFolderPath(NULL, tszPath, CSIDL_PERSONAL,
1377                     FALSE);
1378                 if(bRet == TRUE) {
1379                         szPath = utf_16to8(tszPath);
1380                         persdatafile_dir = szPath;
1381                         return szPath;
1382                 } else {
1383                         return "";
1384                 }
1385         }
1386 #else
1387         return "";
1388 #endif
1389 }
1390
1391 #ifdef _WIN32
1392 /*
1393  * Returns the user's home directory on Win32.
1394  */
1395 static const char *
1396 get_home_dir(void)
1397 {
1398         static const char *home = NULL;
1399         char *homedrive, *homepath;
1400         char *homestring;
1401         char *lastsep;
1402
1403         /* Return the cached value, if available */
1404         if (home)
1405                 return home;
1406
1407         /*
1408          * XXX - should we use USERPROFILE anywhere in this process?
1409          * Is there a chance that it might be set but one or more of
1410          * HOMEDRIVE or HOMEPATH isn't set?
1411          */
1412         homedrive = getenv_utf8("HOMEDRIVE");
1413         if (homedrive != NULL) {
1414                 homepath = getenv_utf8("HOMEPATH");
1415                 if (homepath != NULL) {
1416                         /*
1417                          * This is cached, so we don't need to worry about
1418                          * allocating multiple ones of them.
1419                          */
1420                         homestring = g_strdup_printf("%s%s", homedrive, homepath);
1421
1422                         /*
1423                          * Trim off any trailing slash or backslash.
1424                          */
1425                         lastsep = find_last_pathname_separator(homestring);
1426                         if (lastsep != NULL && *(lastsep + 1) == '\0') {
1427                                 /*
1428                                  * Last separator is the last character
1429                                  * in the string.  Nuke it.
1430                                  */
1431                                 *lastsep = '\0';
1432                         }
1433                         home = homestring;
1434                 } else
1435                         home = homedrive;
1436         } else {
1437                 /*
1438                  * Give up and use C:.
1439                  */
1440                 home = "C:";
1441         }
1442
1443         return home;
1444 }
1445 #endif
1446
1447 /*
1448  * Construct the path name of a personal configuration file, given the
1449  * file name.
1450  *
1451  * On Win32, if "for_writing" is FALSE, we check whether the file exists
1452  * and, if not, construct a path name relative to the ".wireshark"
1453  * subdirectory of the user's home directory, and check whether that
1454  * exists; if it does, we return that, so that configuration files
1455  * from earlier versions can be read.
1456  *
1457  * The returned file name was g_malloc()'d so it must be g_free()d when the
1458  * caller is done with it.
1459  */
1460 char *
1461 get_persconffile_path(const char *filename, gboolean from_profile, gboolean for_writing
1462 #ifndef _WIN32
1463         _U_
1464 #endif
1465 )
1466 {
1467         char *path;
1468 #ifdef _WIN32
1469         struct stat s_buf;
1470         char *old_path;
1471 #endif
1472         if (do_store_persconffiles && from_profile && !g_hash_table_lookup (profile_files, filename)) {
1473                 /* Store filenames so we know which filenames belongs to a configuration profile */
1474                 g_hash_table_insert (profile_files, g_strdup(filename), g_strdup(filename));
1475         }
1476
1477         if (from_profile) {
1478           path = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
1479                                  get_persconffile_dir(persconfprofile), filename);
1480         } else {
1481           path = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
1482                                  get_persconffile_dir(NULL), filename);
1483         }
1484 #ifdef _WIN32
1485         if (!for_writing) {
1486                 if (ws_stat(path, &s_buf) != 0 && errno == ENOENT) {
1487                         /*
1488                          * OK, it's not in the personal configuration file
1489                          * directory; is it in the ".wireshark" subdirectory
1490                          * of their home directory?
1491                          */
1492                         old_path = g_strdup_printf(
1493                             "%s" G_DIR_SEPARATOR_S ".wireshark" G_DIR_SEPARATOR_S "%s",
1494                             get_home_dir(), filename);
1495                         if (ws_stat(old_path, &s_buf) == 0) {
1496                                 /*
1497                                  * OK, it exists; return it instead.
1498                                  */
1499                                 g_free(path);
1500                                 path = old_path;
1501                         }
1502                 }
1503         }
1504 #endif
1505
1506         return path;
1507 }
1508
1509 /*
1510  * process command line option belonging to the filesystem settings
1511  * (move this e.g. to main.c and have set_persconffile_dir() instead in this file?)
1512  */
1513 int
1514 filesystem_opt(int opt _U_, const char *optstr)
1515 {
1516         gchar *p, *colonp;
1517
1518         colonp = strchr(optstr, ':');
1519         if (colonp == NULL) {
1520                 return 1;
1521         }
1522
1523         p = colonp;
1524         *p++ = '\0';
1525
1526         /*
1527         * Skip over any white space (there probably won't be any, but
1528         * as we allow it in the preferences file, we might as well
1529         * allow it here).
1530         */
1531         while (isspace((guchar)*p))
1532                 p++;
1533         if (*p == '\0') {
1534                 /*
1535                  * Put the colon back, so if our caller uses, in an
1536                  * error message, the string they passed us, the message
1537                  * looks correct.
1538                  */
1539                 *colonp = ':';
1540                 return 1;
1541         }
1542
1543         /* directory should be existing */
1544         /* XXX - is this a requirement? */
1545         if(test_for_directory(p) != EISDIR) {
1546                 /*
1547                  * Put the colon back, so if our caller uses, in an
1548                  * error message, the string they passed us, the message
1549                  * looks correct.
1550                  */
1551                 *colonp = ':';
1552                 return 1;
1553         }
1554
1555         if (strcmp(optstr,"persconf") == 0) {
1556                 persconffile_dir = p;
1557         } else if (strcmp(optstr,"persdata") == 0) {
1558                 persdatafile_dir = p;
1559                 /* XXX - might need to add the temp file path */
1560         } else {
1561                 return 1;
1562         }
1563         *colonp = ':'; /* put the colon back */
1564         return 0;
1565 }
1566
1567 /*
1568  * Construct the path name of a global configuration file, given the
1569  * file name.
1570  *
1571  * The returned file name was g_malloc()'d so it must be g_free()d when the
1572  * caller is done with it.
1573  */
1574 char *
1575 get_datafile_path(const char *filename)
1576 {
1577
1578         return g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", get_datafile_dir(), filename);
1579 }
1580
1581 /* Get the personal plugin dir */
1582 /* Return value is malloced so the caller should g_free() it. */
1583 char *
1584 get_plugins_pers_dir(void)
1585 {
1586     return get_persconffile_path(PLUGINS_DIR_NAME, FALSE, FALSE);
1587 }
1588
1589 /* Delete a file */
1590 gboolean
1591 deletefile(const char *path)
1592 {
1593         return ws_unlink(path) == 0;
1594 }
1595
1596 /*
1597  * Construct and return the path name of a file in the
1598  * appropriate temporary file directory.
1599  */
1600 char *get_tempfile_path(const char *filename)
1601 {
1602         return g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", g_get_tmp_dir(), filename);
1603 }
1604
1605 /*
1606  * Return an error message for UNIX-style errno indications on open or
1607  * create operations.
1608  */
1609 const char *
1610 file_open_error_message(int err, gboolean for_writing)
1611 {
1612         const char *errmsg;
1613         static char errmsg_errno[1024+1];
1614
1615         switch (err) {
1616
1617         case ENOENT:
1618                 if (for_writing)
1619                         errmsg = "The path to the file \"%s\" doesn't exist.";
1620                 else
1621                         errmsg = "The file \"%s\" doesn't exist.";
1622                 break;
1623
1624         case EACCES:
1625                 if (for_writing)
1626                         errmsg = "You don't have permission to create or write to the file \"%s\".";
1627                 else
1628                         errmsg = "You don't have permission to read the file \"%s\".";
1629                 break;
1630
1631         case EISDIR:
1632                 errmsg = "\"%s\" is a directory (folder), not a file.";
1633                 break;
1634
1635         case ENOSPC:
1636                 errmsg = "The file \"%s\" could not be created because there is no space left on the file system.";
1637                 break;
1638
1639 #ifdef EDQUOT
1640         case EDQUOT:
1641                 errmsg = "The file \"%s\" could not be created because you are too close to, or over, your disk quota.";
1642                 break;
1643 #endif
1644
1645         case EINVAL:
1646                 errmsg = "The file \"%s\" could not be created because an invalid filename was specified.";
1647                 break;
1648
1649         default:
1650                 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1651                            "The file \"%%s\" could not be %s: %s.",
1652                            for_writing ? "created" : "opened",
1653                            strerror(err));
1654                 errmsg = errmsg_errno;
1655                 break;
1656         }
1657         return errmsg;
1658 }
1659
1660 /*
1661  * Return an error message for UNIX-style errno indications on write
1662  * operations.
1663  */
1664 const char *
1665 file_write_error_message(int err)
1666 {
1667         const char *errmsg;
1668         static char errmsg_errno[1024+1];
1669
1670         switch (err) {
1671
1672         case ENOSPC:
1673                 errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
1674                 break;
1675
1676 #ifdef EDQUOT
1677         case EDQUOT:
1678                 errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
1679                 break;
1680 #endif
1681
1682         case WTAP_ERR_SHORT_WRITE:
1683                 errmsg = "A full write couldn't be done to the file \"%s\".";
1684                 break;
1685
1686         default:
1687                 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1688                            "An error occurred while writing to the file \"%%s\": %s.",
1689                            strerror(err));
1690                 errmsg = errmsg_errno;
1691                 break;
1692         }
1693         return errmsg;
1694 }
1695
1696
1697 gboolean
1698 file_exists(const char *fname)
1699 {
1700         struct stat   file_stat;
1701
1702 #ifdef _WIN32
1703         /*
1704          * This is a bit tricky on win32. The st_ino field is documented as:
1705          * "The inode, and therefore st_ino, has no meaning in the FAT, ..."
1706          * but it *is* set to zero if stat() returns without an error,
1707          * so this is working, but maybe not quite the way expected. ULFL
1708          */
1709         file_stat.st_ino = 1;   /* this will make things work if an error occured */
1710         ws_stat(fname, &file_stat);
1711         if (file_stat.st_ino == 0) {
1712                 return TRUE;
1713         } else {
1714                 return FALSE;
1715         }
1716 #else
1717         if (ws_stat(fname, &file_stat) != 0 && errno == ENOENT) {
1718                 return FALSE;
1719         } else {
1720                 return TRUE;
1721         }
1722 #endif
1723 }
1724
1725 /*
1726  * Check that the from file is not the same as to file
1727  * We do it here so we catch all cases ...
1728  * Unfortunately, the file requester gives us an absolute file
1729  * name and the read file name may be relative (if supplied on
1730  * the command line), so we can't just compare paths. From Joerg Mayer.
1731  */
1732 gboolean
1733 files_identical(const char *fname1, const char *fname2)
1734 {
1735         /* Two different implementations, because:
1736          *
1737          * - _fullpath is not available on UN*X, so we can't get full
1738          *   paths and compare them (which wouldn't work with hard links
1739          *   in any case);
1740          *
1741          * - st_ino isn't filled in with a meaningful value on Windows.
1742          */
1743 #ifdef _WIN32
1744         char full1[MAX_PATH], full2[MAX_PATH];
1745
1746         /*
1747          * Get the absolute full paths of the file and compare them.
1748          * That won't work if you have hard links, but those aren't
1749          * much used on Windows, even though NTFS supports them.
1750          *
1751          * XXX - will _fullpath work with UNC?
1752          */
1753         if( _fullpath( full1, fname1, MAX_PATH ) == NULL ) {
1754                 return FALSE;
1755         }
1756
1757         if( _fullpath( full2, fname2, MAX_PATH ) == NULL ) {
1758                 return FALSE;
1759         }
1760
1761         if(strcmp(full1, full2) == 0) {
1762                 return TRUE;
1763         } else {
1764                 return FALSE;
1765         }
1766 #else
1767         struct stat   filestat1, filestat2;
1768
1769         /*
1770          * Compare st_dev and st_ino.
1771          */
1772         if (ws_stat(fname1, &filestat1) == -1)
1773                 return FALSE;   /* can't get info about the first file */
1774         if (ws_stat(fname2, &filestat2) == -1)
1775                 return FALSE;   /* can't get info about the second file */
1776         return (filestat1.st_dev == filestat2.st_dev &&
1777                 filestat1.st_ino == filestat2.st_ino);
1778 #endif
1779 }
1780
1781 /*
1782  * Copy a file in binary mode, for those operating systems that care about
1783  * such things.  This should be OK for all files, even text files, as
1784  * we'll copy the raw bytes, and we don't look at the bytes as we copy
1785  * them.
1786  *
1787  * Returns TRUE on success, FALSE on failure. If a failure, it also
1788  * displays a simple dialog window with the error message.
1789  */
1790 gboolean
1791 copy_file_binary_mode(const char *from_filename, const char *to_filename)
1792 {
1793   int           from_fd, to_fd, nread, nwritten, err;
1794   guint8        *pd = NULL;
1795
1796   /* Copy the raw bytes of the file. */
1797   from_fd = ws_open(from_filename, O_RDONLY | O_BINARY, 0000 /* no creation so don't matter */);
1798   if (from_fd < 0) {
1799     report_open_failure(from_filename, errno, FALSE);
1800     goto done;
1801   }
1802
1803   /* Use open() instead of creat() so that we can pass the O_BINARY
1804      flag, which is relevant on Win32; it appears that "creat()"
1805      may open the file in text mode, not binary mode, but we want
1806      to copy the raw bytes of the file, so we need the output file
1807      to be open in binary mode. */
1808   to_fd = ws_open(to_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
1809   if (to_fd < 0) {
1810     report_open_failure(to_filename, errno, TRUE);
1811     ws_close(from_fd);
1812     goto done;
1813   }
1814
1815 #define FS_READ_SIZE 65536
1816   pd = g_malloc(FS_READ_SIZE);
1817   while ((nread = ws_read(from_fd, pd, FS_READ_SIZE)) > 0) {
1818     nwritten = ws_write(to_fd, pd, nread);
1819     if (nwritten < nread) {
1820       if (nwritten < 0)
1821         err = errno;
1822       else
1823         err = WTAP_ERR_SHORT_WRITE;
1824       report_write_failure(to_filename, err);
1825       ws_close(from_fd);
1826       ws_close(to_fd);
1827       goto done;
1828     }
1829   }
1830   if (nread < 0) {
1831     err = errno;
1832     report_read_failure(from_filename, err);
1833     ws_close(from_fd);
1834     ws_close(to_fd);
1835     goto done;
1836   }
1837   ws_close(from_fd);
1838   if (ws_close(to_fd) < 0) {
1839     report_write_failure(to_filename, errno);
1840     goto done;
1841   }
1842
1843   g_free(pd);
1844   pd = NULL;
1845   return TRUE;
1846
1847 done:
1848   g_free(pd);
1849   return FALSE;
1850 }
1851
1852 /*
1853  * Editor modelines
1854  *
1855  * Local Variables:
1856  * c-basic-offset: 4
1857  * tab-width: 4
1858  * indent-tabs-mode: t
1859  * End:
1860  *
1861  * ex: set shiftwidth=4 tabstop=4 noexpandtab
1862  * :indentSize=4:tabSize=4:noTabs=false:
1863  */