/* filesystem.c
* Filesystem utility routines
*
- * $Id: filesystem.c,v 1.24 2003/09/15 19:04:59 guy Exp $
+ * $Id$
*
- * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@ethereal.com>
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* This program is free software; you can redistribute it and/or
#include <sys/stat.h>
#endif
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
#include <windows.h>
-#endif
-
-#ifdef HAVE_DIRECT_H
-#include <direct.h> /* to declare "mkdir()" on Windows */
-#endif
-
-#ifndef WIN32
+#include <tchar.h>
+#include "epan/strutil.h"
+#else
#include <pwd.h>
#endif
#include "filesystem.h"
+#include <wiretap/file_util.h>
/*
* Given a pathname, return a pointer to the last pathname separator
* character in the pathname, or NULL if the pathname contains no
* separators.
*/
-char *
-find_last_pathname_separator(char *path)
+static char *
+find_last_pathname_separator(const char *path)
{
char *separator;
-#ifdef WIN32
+#ifdef _WIN32
char c;
/*
* We have to scan for '\' or '/'.
* Get to the end of the string.
*/
- separator = path + strlen(path); /* points to ending '\0' */
+ separator = strchr(path, '\0'); /* points to ending '\0' */
while (separator > path) {
c = *--separator;
if (c == '\\' || c == '/')
/*
* Given a pathname, return the last component.
*/
-char *
-get_basename(char *path)
+const char *
+get_basename(const char *path)
{
- char *filename;
+ const char *filename;
g_assert(path != NULL);
filename = find_last_pathname_separator(path);
{
struct stat statb;
- if (stat(path, &statb) < 0)
+ if (eth_stat(path, &statb) < 0)
return errno;
if (S_ISDIR(statb.st_mode))
{
struct stat statb;
- if (stat(path, &statb) < 0)
+ if (eth_stat(path, &statb) < 0)
return errno;
if (S_ISFIFO(statb.st_mode))
return 0;
}
+static char *progfile_dir;
+
+/*
+ * Get the pathname of the directory from which the executable came,
+ * and save it for future use. Returns NULL on success, and a
+ * g_mallocated string containing an error on failure.
+ */
+char *
+init_progfile_dir(const char *arg0
+#ifdef _WIN32
+ _U_
+#endif
+)
+{
+ char *dir_end;
+ char *path;
+#ifdef _WIN32
+ TCHAR prog_pathname_w[_MAX_PATH+2];
+ size_t progfile_dir_len;
+ char *prog_pathname;
+ DWORD error;
+ TCHAR *msg_w;
+ guchar *msg;
+ size_t msglen;
+
+ /*
+ * Attempt to get the full pathname of the currently running
+ * program.
+ */
+ if (GetModuleFileName(NULL, prog_pathname_w, sizeof prog_pathname_w) != 0) {
+ /*
+ * XXX - Should we use g_utf16_to_utf8(), as in
+ * getenv_utf8()?
+ */
+ prog_pathname = utf_16to8(prog_pathname_w);
+ /*
+ * We got it; strip off the last component, which would be
+ * the file name of the executable, giving us the pathname
+ * of the directory where the executable resies
+ *
+ * First, find the last "\" in the directory, as that
+ * marks the end of the directory pathname.
+ *
+ * XXX - Can the pathname be something such as
+ * "C:wireshark.exe"? Or is it always a full pathname
+ * beginning with "\" after the drive letter?
+ */
+ dir_end = strrchr(prog_pathname, '\\');
+ if (dir_end != NULL) {
+ /*
+ * Found it - now figure out how long the program
+ * directory pathname will be.
+ */
+ progfile_dir_len = (dir_end - prog_pathname);
+
+ /*
+ * Allocate a buffer for the program directory
+ * pathname, and construct it.
+ */
+ path = g_malloc(progfile_dir_len + 1);
+ strncpy(path, prog_pathname, progfile_dir_len);
+ path[progfile_dir_len] = '\0';
+ progfile_dir = path;
+
+ return NULL; /* we succeeded */
+ } else {
+ /*
+ * OK, no \ - what do we do now?
+ */
+ return g_strdup_printf("No \\ in executable pathname \"%s\"",
+ prog_pathname);
+ }
+ } else {
+ /*
+ * Oh, well. Return an indication of the error.
+ */
+ error = GetLastError();
+ if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, error, 0, (LPTSTR) &msg_w, 0, NULL) == 0) {
+ /*
+ * Gak. We can't format the message.
+ */
+ return g_strdup_printf("GetModuleFileName failed: %u (FormatMessage failed: %u)",
+ error, GetLastError());
+ }
+ msg = utf_16to8(msg_w);
+ LocalFree(msg_w);
+ /*
+ * "FormatMessage()" "helpfully" sticks CR/LF at the
+ * end of the message. Get rid of it.
+ */
+ msglen = strlen(msg);
+ if (msglen >= 2) {
+ msg[msglen - 1] = '\0';
+ msg[msglen - 2] = '\0';
+ }
+ return g_strdup_printf("GetModuleFileName failed: %s (%u)",
+ msg, error);
+ }
+#else
+ char *prog_pathname;
+ char *curdir;
+ long path_max;
+ char *pathstr;
+ char *path_start, *path_end;
+ size_t path_component_len;
+ char *retstr;
+
+ /*
+ * Try to figure out the directory in which the currently running
+ * program resides, given the argv[0] it was started with. That
+ * might be the absolute path of the program, or a path relative
+ * to the current directory of the process that started it, or
+ * just a name for the program if it was started from the command
+ * line and was searched for in $PATH. It's not guaranteed to be
+ * any of those, however, so there are no guarantees....
+ */
+ if (arg0[0] == '/') {
+ /*
+ * It's an absolute path.
+ */
+ prog_pathname = g_strdup(arg0);
+ } else if (strchr(arg0, '/') != NULL) {
+ /*
+ * It's a relative path, with a directory in it.
+ * Get the current directory, and combine it
+ * with that directory.
+ */
+ path_max = pathconf(".", _PC_PATH_MAX);
+ if (path_max == -1) {
+ /*
+ * We have no idea how big a buffer to
+ * allocate for the current directory.
+ */
+ return g_strdup_printf("pathconf failed: %s\n",
+ strerror(errno));
+ }
+ curdir = g_malloc(path_max);
+ if (getcwd(curdir, path_max) == NULL) {
+ /*
+ * It failed - give up, and just stick
+ * with DATAFILE_DIR.
+ */
+ g_free(curdir);
+ return g_strdup_printf("getcwd failed: %s\n",
+ strerror(errno));
+ }
+ path = g_malloc(strlen(curdir) + 1 + strlen(arg0) + 1);
+ strcpy(path, curdir);
+ strcat(path, "/");
+ strcat(path, arg0);
+ g_free(curdir);
+ prog_pathname = path;
+ } else {
+ /*
+ * It's just a file name.
+ * Search the path for a file with that name
+ * that's executable.
+ */
+ prog_pathname = NULL; /* haven't found it yet */
+ pathstr = getenv("PATH");
+ path_start = pathstr;
+ if (path_start != NULL) {
+ while (*path_start != '\0') {
+ path_end = strchr(path_start, ':');
+ if (path_end == NULL)
+ path_end = path_start + strlen(path_start);
+ path_component_len = path_end - path_start;
+ path = g_malloc(path_component_len + 1
+ + strlen(arg0) + 1);
+ memcpy(path, path_start, path_component_len);
+ path[path_component_len] = '\0';
+ strcat(path, "/");
+ strcat(path, arg0);
+ if (access(path, X_OK) == 0) {
+ /*
+ * Found it!
+ */
+ prog_pathname = path;
+ break;
+ }
+
+ /*
+ * That's not it. If there are more
+ * path components to test, try them.
+ */
+ if (*path_end == '\0') {
+ /*
+ * There's nothing more to try.
+ */
+ break;
+ }
+ if (*path_end == ':')
+ path_end++;
+ path_start = path_end;
+ g_free(path);
+ }
+ if (prog_pathname == NULL) {
+ /*
+ * Program not found in path.
+ */
+ return g_strdup_printf("\"%s\" not found in \"%s\"",
+ arg0, pathstr);
+ }
+ } else {
+ /*
+ * PATH isn't set.
+ * XXX - should we pick a default?
+ */
+ return g_strdup("PATH isn't set");
+ }
+ }
+
+ /*
+ * OK, we have what we think is the pathname
+ * of the program.
+ *
+ * First, find the last "/" in the directory,
+ * as that marks the end of the directory pathname.
+ */
+ dir_end = strrchr(prog_pathname, '/');
+ if (dir_end != NULL) {
+ /*
+ * Found it. Strip off the last component,
+ * as that's the path of the program.
+ */
+ *dir_end = '\0';
+
+ /*
+ * Is there a "/.libs" at the end?
+ */
+ dir_end = strrchr(prog_pathname, '/');
+ if (dir_end != NULL) {
+ if (strcmp(dir_end, "/.libs") == 0) {
+ /*
+ * Yup, it's ".libs".
+ * Strip that off; it's an
+ * artifact of libtool.
+ */
+ *dir_end = '\0';
+ }
+ }
+
+ /*
+ * OK, we have the path we want.
+ */
+ progfile_dir = prog_pathname;
+ return NULL;
+ } else {
+ /*
+ * This "shouldn't happen"; we apparently
+ * have no "/" in the pathname.
+ * Just free up prog_pathname.
+ */
+ retstr = g_strdup_printf("No / found in \"%s\"", prog_pathname);
+ g_free(prog_pathname);
+ return retstr;
+ }
+#endif
+}
+
+/*
+ * Get the directory in which the program resides.
+ */
+const char *
+get_progfile_dir(void)
+{
+ return progfile_dir;
+}
+
/*
- * Get the directory in which Ethereal's global configuration and data
- * files are stored.
+ * Get the directory in which the global configuration and data files are
+ * stored.
*
- * XXX - if we ever make libethereal a real library, used by multiple
- * applications (more than just Tethereal and versions of Ethereal with
+ * XXX - if we ever make libwireshark a real library, used by multiple
+ * applications (more than just TShark and versions of Wireshark with
* various UIs), should the configuration files belong to the library
* (and be shared by all those applications) or to the applications?
*
* passed in as an argument, in some call, on UNIX.
*
* Note that some of those configuration files might be used by code in
- * libethereal, some of them might be used by dissectors (would they
- * belong to libethereal, the application, or a separate library?),
- * and some of them might be used by other code (the Ethereal preferences
+ * libwireshark, some of them might be used by dissectors (would they
+ * belong to libwireshark, the application, or a separate library?),
+ * and some of them might be used by other code (the Wireshark preferences
* file includes resolver preferences that control the behavior of code
- * in libethereal, dissector preferences, and UI preferences, for
+ * in libwireshark, dissector preferences, and UI preferences, for
* example).
*/
const char *
get_datafile_dir(void)
{
-#ifdef WIN32
- char prog_pathname[_MAX_PATH+2];
- char *dir_end;
- size_t datafile_dir_len;
- static char *datafile_dir;
+#ifdef _WIN32
+ char *u3deviceexecpath;
+#endif
+ static char *datafile_dir = NULL;
- /*
- * Have we already gotten the pathname?
- * If so, just return it.
- */
- if (datafile_dir != NULL)
+ if(datafile_dir != NULL)
return datafile_dir;
- /*
- * No, we haven't.
- * Start out by assuming it's the default installation directory.
- */
- datafile_dir = "C:\\Program Files\\Ethereal\\";
+#ifdef _WIN32
+
+ u3deviceexecpath = getenv_utf8("U3_DEVICE_EXEC_PATH");
+
+ if(u3deviceexecpath != NULL) {
+ datafile_dir = u3deviceexecpath;
+ } else {
- /*
- * Now we attempt to get the full pathname of the currently running
- * program, under the assumption that we're running an installed
- * version of the program. If we fail, we don't change "datafile_dir",
- * and thus end up using the default.
- *
- * XXX - does NSIS put the installation directory into
- * "\HKEY_LOCAL_MACHINE\SOFTWARE\Ethereal\InstallDir"?
- * If so, perhaps we should read that from the registry,
- * instead.
- */
- if (GetModuleFileName(NULL, prog_pathname, sizeof prog_pathname) != 0) {
/*
- * If the program is an installed version, the full pathname
- * includes the pathname of the directory in which it was
- * installed; get that directory's pathname, and construct
- * from it the pathname of the directory in which the
- * plugins were installed.
+ * Do we have the pathname of the program? If so, assume we're
+ * running an installed version of the program. If we fail,
+ * we don't change "datafile_dir", and thus end up using the
+ * default.
*
- * First, find the last "\\" in the directory, as that
- * marks the end of the directory pathname.
- *
- * XXX - Can the pathname be something such as
- * "C:ethereal.exe"? Or is it always a full pathname
- * beginning with "\\" after the drive letter?
+ * XXX - does NSIS put the installation directory into
+ * "\HKEY_LOCAL_MACHINE\SOFTWARE\Wireshark\InstallDir"?
+ * If so, perhaps we should read that from the registry,
+ * instead.
*/
- dir_end = strrchr(prog_pathname, '\\');
- if (dir_end != NULL) {
- /*
- * Found it - now figure out how long the datafile
- * directory pathname will be.
- */
- datafile_dir_len = (dir_end - prog_pathname);
-
+ if (progfile_dir != NULL)
+ datafile_dir = progfile_dir;
+ else
/*
- * Allocate a buffer for the plugin directory
- * pathname, and construct it.
- */
- datafile_dir = g_malloc(datafile_dir_len + 1);
- strncpy(datafile_dir, prog_pathname, datafile_dir_len);
- datafile_dir[datafile_dir_len] = '\0';
- }
+ * No, we don't.
+ * Fall back on the default installation directory.
+ */
+ datafile_dir = "C:\\Program Files\\Wireshark\\";
}
- return datafile_dir;
#else
/*
* Just use DATAFILE_DIR, as that's what the configure script
* set it to be.
*/
- return DATAFILE_DIR;
+ datafile_dir = DATAFILE_DIR;
#endif
+ return datafile_dir;
}
/*
* Get the directory in which files that, at least on UNIX, are
* system files (such as "/etc/ethers") are stored; on Windows,
- * there's no "/etc" directory, so we get them from the Ethereal
- * global configuration and data file directory.
+ * there's no "/etc" directory, so we get them from the global
+ * configuration and data file directory.
*/
const char *
get_systemfile_dir(void)
{
-#ifdef WIN32
+#ifdef _WIN32
return get_datafile_dir();
#else
return "/etc";
* Name of directory, under the user's home directory, in which
* personal configuration files are stored.
*/
-#ifdef WIN32
-#define PF_DIR "Ethereal"
+#ifdef _WIN32
+#define PF_DIR "Wireshark"
#else
/*
* XXX - should this be ".libepan"? For backwards-compatibility, I'll keep
- * it ".ethereal" for now.
+ * it ".wireshark" for now.
*/
-#define PF_DIR ".ethereal"
+#define PF_DIR ".wireshark"
+#endif
+
+#ifdef WIN32
+/* utf8 version of getenv, needed to get win32 filename paths */
+char *getenv_utf8(const char *varname)
+{
+ char *envvar;
+ wchar_t *envvarw;
+ wchar_t *varnamew;
+
+ envvar = getenv(varname);
+
+ /* since GLib 2.6 we need an utf8 version of the filename */
+#if GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 6)
+ if (!G_WIN32_HAVE_WIDECHAR_API ()) {
+ /* Windows OT (9x, ME), convert from current code page to utf8 */
+ /* it's the best we can do here ... */
+ envvar = g_locale_to_utf8(envvar, -1, NULL, NULL, NULL);
+ /* XXX - memleak */
+ return envvar;
+ }
+
+ /* Windows NT, 2000, XP, ... */
+ /* using the wide char version of getenv should work under all circumstances */
+
+ /* convert given varname to utf16, needed by _wgetenv */
+ varnamew = g_utf8_to_utf16(varname, -1, NULL, NULL, NULL);
+ if (varnamew == NULL) {
+ return envvar;
+ }
+
+ /* use wide char version of getenv */
+ envvarw = _wgetenv(varnamew);
+ g_free(varnamew);
+ if (envvarw == NULL) {
+ return envvar;
+ }
+
+ /* convert value to utf8 */
+ envvar = g_utf16_to_utf8(envvarw, -1, NULL, NULL, NULL);
+ /* XXX - memleak */
+#endif
+
+ return envvar;
+}
#endif
/*
* Get the directory in which personal configuration files reside;
- * in UNIX-compatible systems, it's ".ethereal", under the user's home
- * directory, and on Windows systems, it's "Ethereal", under %APPDATA%
+ * in UNIX-compatible systems, it's ".wireshark", under the user's home
+ * directory, and on Windows systems, it's "Wireshark", under %APPDATA%
* or, if %APPDATA% isn't set, it's "%USERPROFILE%\Application Data"
* (which is what %APPDATA% normally is on Windows 2000).
*/
static const char *
get_persconffile_dir(void)
{
-#ifdef WIN32
+#ifdef _WIN32
char *appdatadir;
char *userprofiledir;
+ char *u3appdatapath;
#else
- char *homedir;
+ const char *homedir;
struct passwd *pwd;
#endif
static char *pf_dir = NULL;
if (pf_dir != NULL)
return pf_dir;
-#ifdef WIN32
+#ifdef _WIN32
+
/*
- * Use %APPDATA% or %USERPROFILE%, so that configuration files are
- * stored in the user profile, rather than in the home directory.
- * The Windows convention is to store configuration information
- * in the user profile, and doing so means you can use
- * Ethereal even if the home directory is an inaccessible
- * network drive.
+ * See if we are running in a U3 environment
*/
- appdatadir = getenv("APPDATA");
- if (appdatadir != NULL) {
- /*
- * Concatenate %APPDATA% with "\Ethereal".
- */
- pf_dir = g_malloc(strlen(appdatadir) + strlen(PF_DIR) + 2);
- sprintf(pf_dir, "%s" G_DIR_SEPARATOR_S "%s", appdatadir,
- PF_DIR);
+
+ u3appdatapath = getenv_utf8("U3_APP_DATA_PATH");
+
+ if(u3appdatapath != NULL) {
+
+ pf_dir = u3appdatapath;
+
} else {
+
/*
- * OK, %APPDATA% wasn't set, so use
- * %USERPROFILE%\Application Data.
+ * Use %APPDATA% or %USERPROFILE%, so that configuration files are
+ * stored in the user profile, rather than in the home directory.
+ * The Windows convention is to store configuration information
+ * in the user profile, and doing so means you can use
+ * Wireshark even if the home directory is an inaccessible
+ * network drive.
*/
- userprofiledir = getenv("USERPROFILE");
- if (userprofiledir != NULL) {
- pf_dir = g_malloc(strlen(userprofiledir) +
- strlen("Application Data") + strlen(PF_DIR) + 3);
- sprintf(pf_dir,
- "%s" G_DIR_SEPARATOR_S "Application Data" G_DIR_SEPARATOR_S "%s",
- userprofiledir, PF_DIR);
+ appdatadir = getenv_utf8("APPDATA");
+ if (appdatadir != NULL) {
+ /*
+ * Concatenate %APPDATA% with "\Wireshark".
+ */
+ pf_dir = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
+ appdatadir, PF_DIR);
} else {
/*
- * Give up and use "C:".
+ * OK, %APPDATA% wasn't set, so use
+ * %USERPROFILE%\Application Data.
*/
- pf_dir = g_malloc(strlen("C:") + strlen(PF_DIR) + 2);
- sprintf(pf_dir, "C:" G_DIR_SEPARATOR_S "%s", PF_DIR);
+ userprofiledir = getenv_utf8("USERPROFILE");
+ if (userprofiledir != NULL) {
+ pf_dir = g_strdup_printf(
+ "%s" G_DIR_SEPARATOR_S "Application Data" G_DIR_SEPARATOR_S "%s",
+ userprofiledir, PF_DIR);
+ } else {
+ /*
+ * Give up and use "C:".
+ */
+ pf_dir = g_strdup_printf("C:" G_DIR_SEPARATOR_S "%s", PF_DIR);
+ }
}
}
#else
} else
homedir = "/tmp";
}
- pf_dir = g_malloc(strlen(homedir) + strlen(PF_DIR) + 2);
- sprintf(pf_dir, "%s" G_DIR_SEPARATOR_S "%s", homedir, PF_DIR);
+ pf_dir = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", homedir, PF_DIR);
#endif
return pf_dir;
create_persconffile_dir(char **pf_dir_path_return)
{
const char *pf_dir_path;
-#ifdef WIN32
+#ifdef _WIN32
char *pf_dir_path_copy, *pf_dir_parent_path;
size_t pf_dir_parent_path_len;
#endif
int ret;
pf_dir_path = get_persconffile_dir();
- if (stat(pf_dir_path, &s_buf) != 0 && errno == ENOENT) {
-#ifdef WIN32
+ if (eth_stat(pf_dir_path, &s_buf) != 0 && errno == ENOENT) {
+#ifdef _WIN32
/*
* Does the parent directory of that directory
* exist? %APPDATA% may not exist even though
pf_dir_parent_path_len = strlen(pf_dir_parent_path);
if (pf_dir_parent_path_len > 0
&& pf_dir_parent_path[pf_dir_parent_path_len - 1] != ':'
- && stat(pf_dir_parent_path, &s_buf) != 0) {
+ && eth_stat(pf_dir_parent_path, &s_buf) != 0) {
/*
* No, it doesn't exist - make it first.
*/
- ret = mkdir(pf_dir_parent_path);
+ ret = eth_mkdir(pf_dir_parent_path, 0755);
if (ret == -1) {
*pf_dir_path_return = pf_dir_parent_path;
return -1;
}
}
g_free(pf_dir_path_copy);
- ret = mkdir(pf_dir_path);
+ ret = eth_mkdir(pf_dir_path, 0755);
#else
- ret = mkdir(pf_dir_path, 0755);
+ ret = eth_mkdir(pf_dir_path, 0755);
#endif
} else {
/*
return ret;
}
-#ifdef WIN32
+#ifdef _WIN32
/*
* Returns the user's home directory on Win32.
*/
* Is there a chance that it might be set but one or more of
* HOMEDRIVE or HOMEPATH isn't set?
*/
- homedrive = getenv("HOMEDRIVE");
+ homedrive = getenv_utf8("HOMEDRIVE");
if (homedrive != NULL) {
- homepath = getenv("HOMEPATH");
+ homepath = getenv_utf8("HOMEPATH");
if (homepath != NULL) {
/*
* This is cached, so we don't need to worry about
* file name.
*
* On Win32, if "for_writing" is FALSE, we check whether the file exists
- * and, if not, construct a path name relative to the ".ethereal"
+ * and, if not, construct a path name relative to the ".wireshark"
* subdirectory of the user's home directory, and check whether that
* exists; if it does, we return that, so that configuration files
* from earlier versions can be read.
*/
char *
get_persconffile_path(const char *filename, gboolean for_writing
-#ifndef WIN32
+#ifndef _WIN32
_U_
#endif
)
{
char *path;
-#ifdef WIN32
+#ifdef _WIN32
struct stat s_buf;
char *old_path;
#endif
- path = (gchar *) g_malloc(strlen(get_persconffile_dir()) +
- strlen(filename) + 2);
- sprintf(path, "%s" G_DIR_SEPARATOR_S "%s", get_persconffile_dir(),
+ path = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", get_persconffile_dir(),
filename);
-#ifdef WIN32
+#ifdef _WIN32
if (!for_writing) {
- if (stat(path, &s_buf) != 0 && errno == ENOENT) {
+ if (eth_stat(path, &s_buf) != 0 && errno == ENOENT) {
/*
* OK, it's not in the personal configuration file
- * directory; is it in the ".ethereal" subdirectory
+ * directory; is it in the ".wireshark" subdirectory
* of their home directory?
*/
- old_path = (gchar *) g_malloc(strlen(get_home_dir()) +
- strlen(".ethereal") + strlen(filename) + 3);
- sprintf(old_path,
- "%s" G_DIR_SEPARATOR_S ".ethereal" G_DIR_SEPARATOR_S "%s",
+ old_path = g_strdup_printf(
+ "%s" G_DIR_SEPARATOR_S ".wireshark" G_DIR_SEPARATOR_S "%s",
get_home_dir(), filename);
- if (stat(old_path, &s_buf) == 0) {
+ if (eth_stat(old_path, &s_buf) == 0) {
/*
* OK, it exists; return it instead.
*/
char *
get_datafile_path(const char *filename)
{
- char *path;
- path = (gchar *) g_malloc(strlen(get_datafile_dir()) +
- strlen(filename) + 2);
- sprintf(path, "%s" G_DIR_SEPARATOR_S "%s", get_datafile_dir(),
+ return g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", get_datafile_dir(),
filename);
-
- return path;
}
/* Delete a file */
gboolean
deletefile(const char *path)
{
- return unlink(path) == 0;
+ return eth_unlink(path) == 0;
+}
+
+/*
+ * Construct and return the path name of a file in the
+ * appropriate temporary file directory.
+ */
+char *get_tempfile_path(const char *filename)
+{
+
+ return g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", g_get_tmp_dir(), filename);
+}
+
+/*
+ * Return an error message for UNIX-style errno indications on open or
+ * create operations.
+ */
+const char *
+file_open_error_message(int err, gboolean for_writing)
+{
+ const char *errmsg;
+ static char errmsg_errno[1024+1];
+
+ switch (err) {
+
+ case ENOENT:
+ if (for_writing)
+ errmsg = "The path to the file \"%s\" doesn't exist.";
+ else
+ errmsg = "The file \"%s\" doesn't exist.";
+ break;
+
+ case EACCES:
+ if (for_writing)
+ errmsg = "You don't have permission to create or write to the file \"%s\".";
+ else
+ errmsg = "You don't have permission to read the file \"%s\".";
+ break;
+
+ case EISDIR:
+ errmsg = "\"%s\" is a directory (folder), not a file.";
+ break;
+
+ case ENOSPC:
+ errmsg = "The file \"%s\" could not be created because there is no space left on the file system.";
+ break;
+
+#ifdef EDQUOT
+ case EDQUOT:
+ errmsg = "The file \"%s\" could not be created because you are too close to, or over, your disk quota.";
+ break;
+#endif
+
+ default:
+ g_snprintf(errmsg_errno, sizeof(errmsg_errno),
+ "The file \"%%s\" could not be %s: %s.",
+ for_writing ? "created" : "opened",
+ strerror(err));
+ errmsg = errmsg_errno;
+ break;
+ }
+ return errmsg;
+}
+
+/*
+ * Return an error message for UNIX-style errno indications on write
+ * operations.
+ */
+const char *
+file_write_error_message(int err)
+{
+ const char *errmsg;
+ static char errmsg_errno[1024+1];
+
+ switch (err) {
+
+ case ENOSPC:
+ errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
+ break;
+
+#ifdef EDQUOT
+ case EDQUOT:
+ errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
+ break;
+#endif
+
+ default:
+ g_snprintf(errmsg_errno, sizeof(errmsg_errno),
+ "An error occurred while writing to the file \"%%s\": %s.",
+ strerror(err));
+ errmsg = errmsg_errno;
+ break;
+ }
+ return errmsg;
}
+
+
+gboolean
+file_exists(const char *fname)
+{
+ struct stat file_stat;
+
+
+#ifdef _WIN32
+ /*
+ * This is a bit tricky on win32. The st_ino field is documented as:
+ * "The inode, and therefore st_ino, has no meaning in the FAT, ..."
+ * but it *is* set to zero if stat() returns without an error,
+ * so this is working, but maybe not quite the way expected. ULFL
+ */
+ file_stat.st_ino = 1; /* this will make things work if an error occured */
+ eth_stat(fname, &file_stat);
+ if (file_stat.st_ino == 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+#else
+ if (eth_stat(fname, &file_stat) != 0 && errno == ENOENT) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+#endif
+
+}
+
+/*
+ * Check that the from file is not the same as to file
+ * We do it here so we catch all cases ...
+ * Unfortunately, the file requester gives us an absolute file
+ * name and the read file name may be relative (if supplied on
+ * the command line), so we can't just compare paths. From Joerg Mayer.
+ */
+gboolean
+files_identical(const char *fname1, const char *fname2)
+{
+ /* Two different implementations, because:
+ *
+ * - _fullpath is not available on UN*X, so we can't get full
+ * paths and compare them (which wouldn't work with hard links
+ * in any case);
+ *
+ * - st_ino isn't filled in with a meaningful value on Windows.
+ */
+#ifdef _WIN32
+ char full1[MAX_PATH], full2[MAX_PATH];
+
+ /*
+ * Get the absolute full paths of the file and compare them.
+ * That won't work if you have hard links, but those aren't
+ * much used on Windows, even though NTFS supports them.
+ *
+ * XXX - will _fullpath work with UNC?
+ */
+ if( _fullpath( full1, fname1, MAX_PATH ) == NULL ) {
+ return FALSE;
+ }
+
+ if( _fullpath( full2, fname2, MAX_PATH ) == NULL ) {
+ return FALSE;
+ }
+
+ if(strcmp(full1, full2) == 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+#else
+ struct stat filestat1, filestat2;
+
+ /*
+ * Compare st_dev and st_ino.
+ */
+ if (eth_stat(fname1, &filestat1) == -1)
+ return FALSE; /* can't get info about the first file */
+ if (eth_stat(fname2, &filestat2) == -1)
+ return FALSE; /* can't get info about the second file */
+ return (filestat1.st_dev == filestat2.st_dev &&
+ filestat1.st_ino == filestat2.st_ino);
+#endif
+}
+