2 * Filesystem utility routines
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
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.
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.
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.
49 #ifdef HAVE_SYS_STAT_H
57 #include <wsutil/unicode-utils.h>
59 #ifdef DLADDR_FINDS_EXECUTABLE_PATH
61 #endif /* DLADDR_FINDS_EXECUTABLE_PATH */
65 #include "filesystem.h"
66 #include "report_err.h"
67 #include <wsutil/privileges.h>
68 #include <wsutil/file_util.h>
70 #include <wiretap/wtap.h> /* for WTAP_ERR_SHORT_WRITE */
72 #define PROFILES_DIR "profiles"
73 #define U3_MY_CAPTURES "\\My Captures"
75 char *persconffile_dir = NULL;
76 char *persdatafile_dir = NULL;
77 char *persconfprofile = NULL;
80 * Given a pathname, return a pointer to the last pathname separator
81 * character in the pathname, or NULL if the pathname contains no
85 find_last_pathname_separator(const char *path)
93 * We have to scan for '\' or '/'.
94 * Get to the end of the string.
96 separator = strchr(path, '\0'); /* points to ending '\0' */
97 while (separator > path) {
99 if (c == '\\' || c == '/')
100 return separator; /* found it */
104 * OK, we didn't find any, so no directories - but there might
105 * be a drive letter....
107 return strchr(path, ':');
109 separator = strrchr(path, '/');
115 * Given a pathname, return the last component.
118 get_basename(const char *path)
120 const char *filename;
122 g_assert(path != NULL);
123 filename = find_last_pathname_separator(path);
124 if (filename == NULL) {
126 * There're no directories, drive letters, etc. in the
127 * name; the pathname *is* the file name.
132 * Skip past the pathname or drive letter separator.
140 * Given a pathname, return a string containing everything but the
141 * last component. NOTE: this overwrites the pathname handed into
145 get_dirname(char *path)
149 g_assert(path != NULL);
150 separator = find_last_pathname_separator(path);
151 if (separator == NULL) {
153 * There're no directories, drive letters, etc. in the
154 * name; there is no directory path to return.
160 * Get rid of the last pathname separator and the final file
166 * "path" now contains the pathname of the directory containing
167 * the file/directory to which it referred.
173 * Given a pathname, return:
175 * the errno, if an attempt to "stat()" the file fails;
177 * EISDIR, if the attempt succeeded and the file turned out
180 * 0, if the attempt succeeded and the file turned out not
185 * Visual C++ on Win32 systems doesn't define these. (Old UNIX systems don't
186 * define them either.)
188 * Visual C++ on Win32 systems doesn't define S_IFIFO, it defines _S_IFIFO.
191 #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
194 #define S_IFIFO _S_IFIFO
197 #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
200 #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
204 test_for_directory(const char *path)
208 if (ws_stat(path, &statb) < 0)
211 if (S_ISDIR(statb.st_mode))
218 test_for_fifo(const char *path)
222 if (ws_stat(path, &statb) < 0)
225 if (S_ISFIFO(statb.st_mode))
232 * Directory from which the executable came.
234 static char *progfile_dir;
237 * TRUE if we're running from the build directory and we aren't running
238 * with special privileges.
240 static gboolean running_in_build_directory_flag = FALSE;
243 * Get the pathname of the directory from which the executable came,
244 * and save it for future use. Returns NULL on success, and a
245 * g_mallocated string containing an error on failure.
248 init_progfile_dir(const char *arg0
253 #if defined(_WIN32) || !defined(DLADDR_FINDS_EXECUTABLE_PATH)
261 TCHAR prog_pathname_w[_MAX_PATH+2];
262 size_t progfile_dir_len;
270 * Attempt to get the full pathname of the currently running
273 if (GetModuleFileName(NULL, prog_pathname_w, sizeof prog_pathname_w) != 0) {
275 * XXX - Should we use g_utf16_to_utf8(), as in
278 prog_pathname = utf_16to8(prog_pathname_w);
280 * We got it; strip off the last component, which would be
281 * the file name of the executable, giving us the pathname
282 * of the directory where the executable resies
284 * First, find the last "\" in the directory, as that
285 * marks the end of the directory pathname.
287 * XXX - Can the pathname be something such as
288 * "C:wireshark.exe"? Or is it always a full pathname
289 * beginning with "\" after the drive letter?
291 dir_end = strrchr(prog_pathname, '\\');
292 if (dir_end != NULL) {
294 * Found it - now figure out how long the program
295 * directory pathname will be.
297 progfile_dir_len = (dir_end - prog_pathname);
300 * Allocate a buffer for the program directory
301 * pathname, and construct it.
303 path = g_malloc(progfile_dir_len + 1);
304 strncpy(path, prog_pathname, progfile_dir_len);
305 path[progfile_dir_len] = '\0';
308 return NULL; /* we succeeded */
311 * OK, no \ - what do we do now?
313 return g_strdup_printf("No \\ in executable pathname \"%s\"",
318 * Oh, well. Return an indication of the error.
320 error = GetLastError();
321 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
322 NULL, error, 0, (LPTSTR) &msg_w, 0, NULL) == 0) {
324 * Gak. We can't format the message.
326 return g_strdup_printf("GetModuleFileName failed: %u (FormatMessage failed: %u)",
327 error, GetLastError());
329 msg = utf_16to8(msg_w);
332 * "FormatMessage()" "helpfully" sticks CR/LF at the
333 * end of the message. Get rid of it.
335 msglen = strlen(msg);
337 msg[msglen - 1] = '\0';
338 msg[msglen - 2] = '\0';
340 return g_strdup_printf("GetModuleFileName failed: %s (%u)",
344 #ifdef DLADDR_FINDS_EXECUTABLE_PATH
351 char *path_start, *path_end;
352 size_t path_component_len;
356 * Check whether WIRESHARK_RUN_FROM_BUILD_DIRECTORY is set in the
357 * environment; if so, set running_in_build_directory_flag if we
358 * weren't started with special privileges. (If we were started
359 * with special privileges, it's not safe to allow the user to point
360 * us to some other directory; running_in_build_directory_flag, when
361 * set, causes us to look for plugins and the like in the build
364 if (getenv("WIRESHARK_RUN_FROM_BUILD_DIRECTORY") != NULL
365 && !started_with_special_privs())
366 running_in_build_directory_flag = TRUE;
368 #ifdef DLADDR_FINDS_EXECUTABLE_PATH
370 * Try to use dladdr() to find the pathname of the executable.
372 if (dladdr(main_addr, &info) && info.dli_fname[0] == '/') {
374 * dladdr() succeeded, and we got an absolute path
375 * for the module containing main() (I don't know
376 * whether it's guaranteed to return an absolute path
377 * on all platforms), so we'll use that as the
378 * executable image's path.
380 prog_pathname = g_strdup(info.dli_fname);
385 * Try to figure out the directory in which the currently running
386 * program resides, given the argv[0] it was started with. That
387 * might be the absolute path of the program, or a path relative
388 * to the current directory of the process that started it, or
389 * just a name for the program if it was started from the command
390 * line and was searched for in $PATH. It's not guaranteed to be
391 * any of those, however, so there are no guarantees....
393 if (arg0[0] == '/') {
395 * It's an absolute path.
397 prog_pathname = g_strdup(arg0);
398 } else if (strchr(arg0, '/') != NULL) {
400 * It's a relative path, with a directory in it.
401 * Get the current directory, and combine it
402 * with that directory.
404 path_max = pathconf(".", _PC_PATH_MAX);
405 if (path_max == -1) {
407 * We have no idea how big a buffer to
408 * allocate for the current directory.
410 return g_strdup_printf("pathconf failed: %s\n",
413 curdir = g_malloc(path_max);
414 if (getcwd(curdir, path_max) == NULL) {
416 * It failed - give up, and just stick
420 return g_strdup_printf("getcwd failed: %s\n",
423 path = g_strdup_printf("%s/%s", curdir, arg0);
425 prog_pathname = path;
428 * It's just a file name.
429 * Search the path for a file with that name
432 prog_pathname = NULL; /* haven't found it yet */
433 pathstr = getenv("PATH");
434 path_start = pathstr;
435 if (path_start != NULL) {
436 while (*path_start != '\0') {
437 path_end = strchr(path_start, ':');
438 if (path_end == NULL)
439 path_end = path_start + strlen(path_start);
440 path_component_len = path_end - path_start;
441 path = g_malloc(path_component_len + 1
443 memcpy(path, path_start, path_component_len);
444 path[path_component_len] = '\0';
445 strncat(path, "/", 2);
446 strncat(path, arg0, strlen(arg0) + 1);
447 if (access(path, X_OK) == 0) {
451 prog_pathname = path;
456 * That's not it. If there are more
457 * path components to test, try them.
459 if (*path_end == '\0') {
461 * There's nothing more to try.
465 if (*path_end == ':')
467 path_start = path_end;
470 if (prog_pathname == NULL) {
472 * Program not found in path.
474 return g_strdup_printf("\"%s\" not found in \"%s\"",
480 * XXX - should we pick a default?
482 return g_strdup("PATH isn't set");
488 * OK, we have what we think is the pathname
491 * First, find the last "/" in the directory,
492 * as that marks the end of the directory pathname.
494 dir_end = strrchr(prog_pathname, '/');
495 if (dir_end != NULL) {
497 * Found it. Strip off the last component,
498 * as that's the path of the program.
503 * Is there a "/.libs" at the end?
505 dir_end = strrchr(prog_pathname, '/');
506 if (dir_end != NULL) {
507 if (strcmp(dir_end, "/.libs") == 0) {
510 * Strip that off; it's an
511 * artifact of libtool.
516 * This presumably means we're run from
517 * the libtool wrapper, which probably
518 * means we're being run from the build
519 * directory. If we weren't started
520 * with special privileges, set
521 * running_in_build_directory_flag.
523 * XXX - should we check whether what
524 * follows ".libs/" begins with "lt-"?
526 if (!started_with_special_privs())
527 running_in_build_directory_flag = TRUE;
532 * OK, we have the path we want.
534 progfile_dir = prog_pathname;
538 * This "shouldn't happen"; we apparently
539 * have no "/" in the pathname.
540 * Just free up prog_pathname.
542 retstr = g_strdup_printf("No / found in \"%s\"", prog_pathname);
543 g_free(prog_pathname);
550 * Get the directory in which the program resides.
553 get_progfile_dir(void)
559 * Get the directory in which the global configuration and data files are
562 * On Windows, we use the directory in which the executable for this
565 * On UN*X, we use the DATAFILE_DIR value supplied by the configure
566 * script, unless we think we're being run from the build directory,
567 * in which case we use the directory in which the executable for this
570 * XXX - if we ever make libwireshark a real library, used by multiple
571 * applications (more than just TShark and versions of Wireshark with
572 * various UIs), should the configuration files belong to the library
573 * (and be shared by all those applications) or to the applications?
575 * If they belong to the library, that could be done on UNIX by the
576 * configure script, but it's trickier on Windows, as you can't just
577 * use the pathname of the executable.
579 * If they belong to the application, that could be done on Windows
580 * by using the pathname of the executable, but we'd have to have it
581 * passed in as an argument, in some call, on UNIX.
583 * Note that some of those configuration files might be used by code in
584 * libwireshark, some of them might be used by dissectors (would they
585 * belong to libwireshark, the application, or a separate library?),
586 * and some of them might be used by other code (the Wireshark preferences
587 * file includes resolver preferences that control the behavior of code
588 * in libwireshark, dissector preferences, and UI preferences, for
592 get_datafile_dir(void)
595 char *u3deviceexecpath;
597 static char *datafile_dir = NULL;
599 if (datafile_dir != NULL)
604 * See if we are running in a U3 environment.
606 u3deviceexecpath = getenv_utf8("U3_DEVICE_EXEC_PATH");
608 if (u3deviceexecpath != NULL) {
610 * We are; use the U3 device executable path.
612 datafile_dir = u3deviceexecpath;
615 * Do we have the pathname of the program? If so, assume we're
616 * running an installed version of the program. If we fail,
617 * we don't change "datafile_dir", and thus end up using the
620 * XXX - does NSIS put the installation directory into
621 * "\HKEY_LOCAL_MACHINE\SOFTWARE\Wireshark\InstallDir"?
622 * If so, perhaps we should read that from the registry,
625 if (progfile_dir != NULL) {
627 * Yes, we do; use that.
629 datafile_dir = progfile_dir;
633 * Fall back on the default installation directory.
635 datafile_dir = "C:\\Program Files\\Wireshark\\";
639 if (running_in_build_directory_flag && progfile_dir != NULL) {
641 * We're (probably) being run from the build directory and
642 * weren't started with special privileges, and we were
643 * able to determine the directory in which the program
644 * was found, so use that.
646 datafile_dir = progfile_dir;
649 * Return the directory specified when the build was
650 * configured, prepending the run path prefix if it exists.
652 if (getenv("WIRESHARK_DATA_DIR") && !started_with_special_privs()) {
654 * The user specified a different directory for data files
655 * and we aren't running with special privileges.
656 * XXX - We might be able to dispense with the priv check
658 datafile_dir = g_strdup(getenv("WIRESHARK_DATA_DIR"));
660 datafile_dir = DATAFILE_DIR;
670 * Find the directory where the plugins are stored.
672 * On Windows, we use the "plugin" subdirectory of the datafile directory.
674 * On UN*X, we use the PLUGIN_DIR value supplied by the configure
675 * script, unless we think we're being run from the build directory,
676 * in which case we use the "plugin" subdirectory of the datafile directory.
678 * In both cases, we then use the subdirectory of that directory whose
679 * name is the version number.
681 * XXX - if we think we're being run from the build directory, perhaps we
682 * should have the plugin code not look in the version subdirectory
683 * of the plugin directory, but look in all of the subdirectories
684 * of the plugin directory, so it can just fetch the plugins built
685 * as part of the build process.
687 static const char *plugin_dir = NULL;
690 init_plugin_dir(void)
694 * On Windows, the data file directory is the installation
695 * directory; the plugins are stored under it.
697 * Assume we're running the installed version of Wireshark;
698 * on Windows, the data file directory is the directory
699 * in which the Wireshark binary resides.
701 plugin_dir = g_strdup_printf("%s\\plugins\\%s", get_datafile_dir(),
705 * Make sure that pathname refers to a directory.
707 if (test_for_directory(plugin_dir) != EISDIR) {
709 * Either it doesn't refer to a directory or it
710 * refers to something that doesn't exist.
712 * Assume that means we're running a version of
713 * Wireshark we've built in a build directory,
714 * in which case {datafile dir}\plugins is the
715 * top-level plugins source directory, and use
716 * that directory and set the "we're running in
717 * a build directory" flag, so the plugin
718 * scanner will check all subdirectories of that
719 * directory for plugins.
721 g_free( (gpointer) plugin_dir);
722 plugin_dir = g_strdup_printf("%s\\plugins", get_datafile_dir());
723 running_in_build_directory_flag = TRUE;
726 if (running_in_build_directory_flag) {
728 * We're (probably) being run from the build directory and
729 * weren't started with special privileges, so we'll use
730 * the "plugins" subdirectory of the datafile directory
731 * (the datafile directory is the build directory).
733 plugin_dir = g_strdup_printf("%s/plugins", get_datafile_dir());
735 if (getenv("WIRESHARK_PLUGIN_DIR") && !started_with_special_privs()) {
737 * The user specified a different directory for plugins
738 * and we aren't running with special privileges.
740 plugin_dir = g_strdup(getenv("WIRESHARK_PLUGIN_DIR"));
742 plugin_dir = PLUGIN_DIR;
747 #endif /* HAVE_PLUGINS */
750 * Get the directory in which the plugins are stored.
756 if (!plugin_dir) init_plugin_dir();
764 * Get the flag indicating whether we're running from a build
768 running_in_build_directory(void)
770 return running_in_build_directory_flag;
774 * Get the directory in which files that, at least on UNIX, are
775 * system files (such as "/etc/ethers") are stored; on Windows,
776 * there's no "/etc" directory, so we get them from the global
777 * configuration and data file directory.
780 get_systemfile_dir(void)
783 return get_datafile_dir();
790 * Name of directory, under the user's home directory, in which
791 * personal configuration files are stored.
794 #define PF_DIR "Wireshark"
797 * XXX - should this be ".libepan"? For backwards-compatibility, I'll keep
798 * it ".wireshark" for now.
800 #define PF_DIR ".wireshark"
804 /* utf8 version of getenv, needed to get win32 filename paths */
805 char *getenv_utf8(const char *varname)
811 envvar = getenv(varname);
813 /* since GLib 2.6 we need an utf8 version of the filename */
814 #if GLIB_CHECK_VERSION(2,6,0)
815 /* using the wide char version of getenv should work under all circumstances */
817 /* convert given varname to utf16, needed by _wgetenv */
818 varnamew = g_utf8_to_utf16(varname, -1, NULL, NULL, NULL);
819 if (varnamew == NULL) {
823 /* use wide char version of getenv */
824 envvarw = _wgetenv(varnamew);
826 if (envvarw == NULL) {
830 /* convert value to utf8 */
831 envvar = g_utf16_to_utf8(envvarw, -1, NULL, NULL, NULL);
840 set_profile_name(const gchar *profilename)
842 g_free (persconfprofile);
844 if (profilename && strlen(profilename) > 0 &&
845 strcmp(profilename, DEFAULT_PROFILE) != 0) {
846 persconfprofile = g_strdup (profilename);
848 /* Default Profile */
849 persconfprofile = NULL;
854 get_profile_name(void)
856 if (persconfprofile) {
857 return persconfprofile;
859 return DEFAULT_PROFILE;
864 * Get the directory in which personal configuration files reside;
865 * in UNIX-compatible systems, it's ".wireshark", under the user's home
866 * directory, and on Windows systems, it's "Wireshark", under %APPDATA%
867 * or, if %APPDATA% isn't set, it's "%USERPROFILE%\Application Data"
868 * (which is what %APPDATA% normally is on Windows 2000).
871 get_persconffile_dir_no_profile(void)
875 char *userprofiledir;
882 /* Return the cached value, if available */
883 if (persconffile_dir != NULL)
884 return persconffile_dir;
888 * See if we are running in a U3 environment.
890 u3appdatapath = getenv_utf8("U3_APP_DATA_PATH");
891 if (u3appdatapath != NULL) {
893 * We are; use the U3 application data path.
895 persconffile_dir = u3appdatapath;
898 * Use %APPDATA% or %USERPROFILE%, so that configuration
899 * files are stored in the user profile, rather than in
900 * the home directory. The Windows convention is to store
901 * configuration information in the user profile, and doing
902 * so means you can use Wireshark even if the home directory
903 * is an inaccessible network drive.
905 appdatadir = getenv_utf8("APPDATA");
906 if (appdatadir != NULL) {
908 * Concatenate %APPDATA% with "\Wireshark".
910 persconffile_dir = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
914 * OK, %APPDATA% wasn't set, so use
915 * %USERPROFILE%\Application Data.
917 userprofiledir = getenv_utf8("USERPROFILE");
918 if (userprofiledir != NULL) {
919 persconffile_dir = g_strdup_printf(
920 "%s" G_DIR_SEPARATOR_S "Application Data" G_DIR_SEPARATOR_S "%s",
921 userprofiledir, PF_DIR);
924 * Give up and use "C:".
926 persconffile_dir = g_strdup_printf("C:" G_DIR_SEPARATOR_S "%s", PF_DIR);
932 * If $HOME is set, use that.
934 homedir = getenv("HOME");
935 if (homedir == NULL) {
937 * Get their home directory from the password file.
938 * If we can't even find a password file entry for them,
941 pwd = getpwuid(getuid());
944 * This is cached, so we don't need to worry
945 * about allocating multiple ones of them.
947 homedir = g_strdup(pwd->pw_dir);
951 persconffile_dir = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", homedir, PF_DIR);
954 return persconffile_dir;
958 get_profiles_dir(void)
960 static char *profiles_dir = NULL;
962 g_free (profiles_dir);
963 profiles_dir = g_strdup_printf ("%s%s%s", get_persconffile_dir_no_profile (),
964 G_DIR_SEPARATOR_S, PROFILES_DIR);
970 get_persconffile_dir(const gchar *profilename)
972 static char *persconffile_profile_dir = NULL;
974 g_free (persconffile_profile_dir);
976 if (profilename && strlen(profilename) > 0 &&
977 strcmp(profilename, DEFAULT_PROFILE) != 0) {
978 persconffile_profile_dir = g_strdup_printf ("%s%s%s", get_profiles_dir (),
979 G_DIR_SEPARATOR_S, profilename);
981 persconffile_profile_dir = g_strdup (get_persconffile_dir_no_profile ());
984 return persconffile_profile_dir;
988 profile_exists(const gchar *profilename)
990 if (test_for_directory (get_persconffile_dir (profilename)) == EISDIR) {
998 delete_directory (const char *directory, char **pf_dir_path_return)
1005 if ((dir = ws_dir_open(directory, 0, NULL)) != NULL) {
1006 while ((file = ws_dir_read_name(dir)) != NULL) {
1007 filename = g_strdup_printf ("%s%s%s", directory, G_DIR_SEPARATOR_S,
1008 ws_dir_get_name(file));
1009 if (test_for_directory(filename) != EISDIR) {
1010 ret = ws_remove(filename);
1013 /* The user has manually created a directory in the profile directory */
1014 /* I do not want to delete the directory recursively yet */
1015 ret = delete_directory (filename, pf_dir_path_return);
1019 *pf_dir_path_return = filename;
1027 if (ret == 0 && (ret = ws_remove(directory)) != 0) {
1028 *pf_dir_path_return = g_strdup (directory);
1035 delete_persconffile_profile(const char *profilename, char **pf_dir_path_return)
1037 const char *profile_dir = get_persconffile_dir(profilename);
1040 if (test_for_directory (profile_dir) == EISDIR) {
1041 ret = delete_directory (profile_dir, pf_dir_path_return);
1048 rename_persconffile_profile(const char *fromname, const char *toname,
1049 char **pf_from_dir_path_return, char **pf_to_dir_path_return)
1051 char *from_dir = g_strdup (get_persconffile_dir(fromname));
1052 char *to_dir = g_strdup (get_persconffile_dir(toname));
1055 ret = ws_rename (from_dir, to_dir);
1057 *pf_from_dir_path_return = g_strdup (from_dir);
1058 *pf_to_dir_path_return = g_strdup (to_dir);
1068 * Create the directory that holds personal configuration files, if
1069 * necessary. If we attempted to create it, and failed, return -1 and
1070 * set "*pf_dir_path_return" to the pathname of the directory we failed
1071 * to create (it's g_mallocated, so our caller should free it); otherwise,
1075 create_persconffile_profile(const char *profilename, char **pf_dir_path_return)
1077 const char *pf_dir_path;
1079 char *pf_dir_path_copy, *pf_dir_parent_path;
1080 size_t pf_dir_parent_path_len;
1087 * Check if profiles directory exists.
1088 * If not then create it.
1090 pf_dir_path = get_profiles_dir ();
1091 if (ws_stat(pf_dir_path, &s_buf) != 0 && errno == ENOENT) {
1092 ret = ws_mkdir(pf_dir_path, 0755);
1094 *pf_dir_path_return = g_strdup(pf_dir_path);
1100 pf_dir_path = get_persconffile_dir(profilename);
1101 if (ws_stat(pf_dir_path, &s_buf) != 0 && errno == ENOENT) {
1104 * Does the parent directory of that directory
1105 * exist? %APPDATA% may not exist even though
1106 * %USERPROFILE% does.
1108 * We check for the existence of the directory
1109 * by first checking whether the parent directory
1110 * is just a drive letter and, if it's not, by
1111 * doing a "stat()" on it. If it's a drive letter,
1112 * or if the "stat()" succeeds, we assume it exists.
1114 pf_dir_path_copy = g_strdup(pf_dir_path);
1115 pf_dir_parent_path = get_dirname(pf_dir_path_copy);
1116 pf_dir_parent_path_len = strlen(pf_dir_parent_path);
1117 if (pf_dir_parent_path_len > 0
1118 && pf_dir_parent_path[pf_dir_parent_path_len - 1] != ':'
1119 && ws_stat(pf_dir_parent_path, &s_buf) != 0) {
1121 * No, it doesn't exist - make it first.
1123 ret = ws_mkdir(pf_dir_parent_path, 0755);
1125 *pf_dir_path_return = pf_dir_parent_path;
1129 g_free(pf_dir_path_copy);
1130 ret = ws_mkdir(pf_dir_path, 0755);
1132 ret = ws_mkdir(pf_dir_path, 0755);
1136 * Something with that pathname exists; if it's not
1137 * a directory, we'll get an error if we try to put
1138 * something in it, so we don't fail here, we wait
1139 * for that attempt fo fail.
1144 *pf_dir_path_return = g_strdup(pf_dir_path);
1149 create_persconffile_dir(char **pf_dir_path_return)
1151 return create_persconffile_profile(persconfprofile, pf_dir_path_return);
1155 * Get the (default) directory in which personal data is stored.
1157 * On Win32, this is the "My Documents" folder in the personal profile.
1158 * On UNIX this is simply the current directory.
1159 * On a U3 device this is "$U3_DEVICE_DOCUMENT_PATH\My Captures" folder.
1161 /* XXX - should this and the get_home_dir() be merged? */
1163 get_persdatafile_dir(void)
1166 char *u3devicedocumentpath;
1167 TCHAR tszPath[MAX_PATH];
1172 /* Return the cached value, if available */
1173 if (persdatafile_dir != NULL)
1174 return persdatafile_dir;
1177 * See if we are running in a U3 environment.
1179 u3devicedocumentpath = getenv_utf8("U3_DEVICE_DOCUMENT_PATH");
1181 if (u3devicedocumentpath != NULL) {
1183 /* the "My Captures" sub-directory is created (if it doesn't exist)
1184 by u3util.exe when the U3 Wireshark is first run */
1186 szPath = g_strdup_printf("%s%s", u3devicedocumentpath, U3_MY_CAPTURES);
1188 persdatafile_dir = szPath;
1192 /* Hint: SHGetFolderPath is not available on MSVC 6 - without Platform SDK */
1193 bRet = SHGetSpecialFolderPath(NULL, tszPath, CSIDL_PERSONAL, FALSE);
1195 szPath = utf_16to8(tszPath);
1196 persdatafile_dir = szPath;
1209 * Returns the user's home directory on Win32.
1214 static const char *home = NULL;
1215 char *homedrive, *homepath;
1219 /* Return the cached value, if available */
1224 * XXX - should we use USERPROFILE anywhere in this process?
1225 * Is there a chance that it might be set but one or more of
1226 * HOMEDRIVE or HOMEPATH isn't set?
1228 homedrive = getenv_utf8("HOMEDRIVE");
1229 if (homedrive != NULL) {
1230 homepath = getenv_utf8("HOMEPATH");
1231 if (homepath != NULL) {
1233 * This is cached, so we don't need to worry about
1234 * allocating multiple ones of them.
1236 homestring = g_strdup_printf("%s%s", homedrive, homepath);
1239 * Trim off any trailing slash or backslash.
1241 lastsep = find_last_pathname_separator(homestring);
1242 if (lastsep != NULL && *(lastsep + 1) == '\0') {
1244 * Last separator is the last character
1245 * in the string. Nuke it.
1254 * Give up and use C:.
1264 * Construct the path name of a personal configuration file, given the
1267 * On Win32, if "for_writing" is FALSE, we check whether the file exists
1268 * and, if not, construct a path name relative to the ".wireshark"
1269 * subdirectory of the user's home directory, and check whether that
1270 * exists; if it does, we return that, so that configuration files
1271 * from earlier versions can be read.
1273 * The returned file name was g_malloc()'d so it must be g_free()d when the
1274 * caller is done with it.
1277 get_persconffile_path(const char *filename, gboolean from_profile, gboolean for_writing
1290 path = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
1291 get_persconffile_dir(persconfprofile), filename);
1293 path = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
1294 get_persconffile_dir(NULL), filename);
1298 if (ws_stat(path, &s_buf) != 0 && errno == ENOENT) {
1300 * OK, it's not in the personal configuration file
1301 * directory; is it in the ".wireshark" subdirectory
1302 * of their home directory?
1304 old_path = g_strdup_printf(
1305 "%s" G_DIR_SEPARATOR_S ".wireshark" G_DIR_SEPARATOR_S "%s",
1306 get_home_dir(), filename);
1307 if (ws_stat(old_path, &s_buf) == 0) {
1309 * OK, it exists; return it instead.
1322 * process command line option belonging to the filesystem settings
1323 * (move this e.g. to main.c and have set_persconffile_dir() instead in this file?)
1326 filesystem_opt(int opt _U_, const char *optstr)
1330 colonp = strchr(optstr, ':');
1331 if (colonp == NULL) {
1339 * Skip over any white space (there probably won't be any, but
1340 * as we allow it in the preferences file, we might as well
1343 while (isspace((guchar)*p))
1347 * Put the colon back, so if our caller uses, in an
1348 * error message, the string they passed us, the message
1355 /* directory should be existing */
1356 /* XXX - is this a requirement? */
1357 if(test_for_directory(p) != EISDIR) {
1359 * Put the colon back, so if our caller uses, in an
1360 * error message, the string they passed us, the message
1367 if (strcmp(optstr,"persconf") == 0) {
1368 persconffile_dir = p;
1369 } else if (strcmp(optstr,"persdata") == 0) {
1370 persdatafile_dir = p;
1371 /* XXX - might need to add the temp file path */
1375 *colonp = ':'; /* put the colon back */
1380 * Construct the path name of a global configuration file, given the
1383 * The returned file name was g_malloc()'d so it must be g_free()d when the
1384 * caller is done with it.
1387 get_datafile_path(const char *filename)
1390 return g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", get_datafile_dir(),
1396 deletefile(const char *path)
1398 return ws_unlink(path) == 0;
1402 * Construct and return the path name of a file in the
1403 * appropriate temporary file directory.
1405 char *get_tempfile_path(const char *filename)
1407 return g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", g_get_tmp_dir(), filename);
1411 * Return an error message for UNIX-style errno indications on open or
1412 * create operations.
1415 file_open_error_message(int err, gboolean for_writing)
1418 static char errmsg_errno[1024+1];
1424 errmsg = "The path to the file \"%s\" doesn't exist.";
1426 errmsg = "The file \"%s\" doesn't exist.";
1431 errmsg = "You don't have permission to create or write to the file \"%s\".";
1433 errmsg = "You don't have permission to read the file \"%s\".";
1437 errmsg = "\"%s\" is a directory (folder), not a file.";
1441 errmsg = "The file \"%s\" could not be created because there is no space left on the file system.";
1446 errmsg = "The file \"%s\" could not be created because you are too close to, or over, your disk quota.";
1451 errmsg = "The file \"%s\" could not be created because an invalid filename was specified.";
1455 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1456 "The file \"%%s\" could not be %s: %s.",
1457 for_writing ? "created" : "opened",
1459 errmsg = errmsg_errno;
1466 * Return an error message for UNIX-style errno indications on write
1470 file_write_error_message(int err)
1473 static char errmsg_errno[1024+1];
1478 errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
1483 errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
1488 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1489 "An error occurred while writing to the file \"%%s\": %s.",
1491 errmsg = errmsg_errno;
1499 file_exists(const char *fname)
1501 struct stat file_stat;
1505 * This is a bit tricky on win32. The st_ino field is documented as:
1506 * "The inode, and therefore st_ino, has no meaning in the FAT, ..."
1507 * but it *is* set to zero if stat() returns without an error,
1508 * so this is working, but maybe not quite the way expected. ULFL
1510 file_stat.st_ino = 1; /* this will make things work if an error occured */
1511 ws_stat(fname, &file_stat);
1512 if (file_stat.st_ino == 0) {
1518 if (ws_stat(fname, &file_stat) != 0 && errno == ENOENT) {
1527 * Check that the from file is not the same as to file
1528 * We do it here so we catch all cases ...
1529 * Unfortunately, the file requester gives us an absolute file
1530 * name and the read file name may be relative (if supplied on
1531 * the command line), so we can't just compare paths. From Joerg Mayer.
1534 files_identical(const char *fname1, const char *fname2)
1536 /* Two different implementations, because:
1538 * - _fullpath is not available on UN*X, so we can't get full
1539 * paths and compare them (which wouldn't work with hard links
1542 * - st_ino isn't filled in with a meaningful value on Windows.
1545 char full1[MAX_PATH], full2[MAX_PATH];
1548 * Get the absolute full paths of the file and compare them.
1549 * That won't work if you have hard links, but those aren't
1550 * much used on Windows, even though NTFS supports them.
1552 * XXX - will _fullpath work with UNC?
1554 if( _fullpath( full1, fname1, MAX_PATH ) == NULL ) {
1558 if( _fullpath( full2, fname2, MAX_PATH ) == NULL ) {
1562 if(strcmp(full1, full2) == 0) {
1568 struct stat filestat1, filestat2;
1571 * Compare st_dev and st_ino.
1573 if (ws_stat(fname1, &filestat1) == -1)
1574 return FALSE; /* can't get info about the first file */
1575 if (ws_stat(fname2, &filestat2) == -1)
1576 return FALSE; /* can't get info about the second file */
1577 return (filestat1.st_dev == filestat2.st_dev &&
1578 filestat1.st_ino == filestat2.st_ino);
1583 * Copy a file in binary mode, for those operating systems that care about
1584 * such things. This should be OK for all files, even text files, as
1585 * we'll copy the raw bytes, and we don't look at the bytes as we copy
1588 * Returns TRUE on success, FALSE on failure. If a failure, it also
1589 * displays a simple dialog window with the error message.
1592 copy_file_binary_mode(const char *from_filename, const char *to_filename)
1594 int from_fd, to_fd, nread, nwritten, err;
1597 /* Copy the raw bytes of the file. */
1598 from_fd = ws_open(from_filename, O_RDONLY | O_BINARY, 0000 /* no creation so don't matter */);
1600 report_open_failure(from_filename, errno, FALSE);
1604 /* Use open() instead of creat() so that we can pass the O_BINARY
1605 flag, which is relevant on Win32; it appears that "creat()"
1606 may open the file in text mode, not binary mode, but we want
1607 to copy the raw bytes of the file, so we need the output file
1608 to be open in binary mode. */
1609 to_fd = ws_open(to_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
1611 report_open_failure(to_filename, errno, TRUE);
1616 while ((nread = ws_read(from_fd, pd, sizeof pd)) > 0) {
1617 nwritten = ws_write(to_fd, pd, nread);
1618 if (nwritten < nread) {
1622 err = WTAP_ERR_SHORT_WRITE;
1623 report_write_failure(to_filename, err);
1631 report_read_failure(from_filename, err);
1637 if (ws_close(to_fd) < 0) {
1638 report_write_failure(to_filename, errno);
1654 * indent-tabs-mode: t
1657 * ex: set shiftwidth=4 tabstop=4 noexpandtab
1658 * :indentSize=4:tabSize=4:noTabs=false: