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