mirror of https://github.com/djcb/mu.git
* dont't require direntry->d_type; this should help the Solaris build.
also, some cleanups
This commit is contained in:
parent
a0069702ba
commit
d14727c7a8
49
configure.ac
49
configure.ac
|
@ -25,6 +25,7 @@ AC_CONFIG_MACRO_DIR([m4])
|
||||||
# silent build
|
# silent build
|
||||||
AM_SILENT_RULES([yes])
|
AM_SILENT_RULES([yes])
|
||||||
|
|
||||||
|
|
||||||
LT_INIT # don't use AC_PROG_LIBTOOL anymore
|
LT_INIT # don't use AC_PROG_LIBTOOL anymore
|
||||||
|
|
||||||
AS_IF([test x$prefix = xNONE],[
|
AS_IF([test x$prefix = xNONE],[
|
||||||
|
@ -38,24 +39,33 @@ AC_PROG_CXX
|
||||||
AC_HEADER_STDC
|
AC_HEADER_STDC
|
||||||
|
|
||||||
|
|
||||||
# currently, we don't support systems without d_type in their struct
|
# we need some special tricks for filesystems that don't have d_type;
|
||||||
# dirent (Solaris 10); but we do support FSs for which d_type is always
|
# e.g. Solaris. See mu-maildir.c. Explicitly disabling it is for
|
||||||
# DT_UNKNOWN (Like ReiserFS, XFS on Linux)
|
# testing purposes only
|
||||||
#
|
AC_ARG_ENABLE([dirent-d-type],
|
||||||
# note, we could work around this if there are many people for which
|
AC_HELP_STRING([--disable-dirent-d-type],
|
||||||
# this breaks
|
[Don't use dirent->d_type, even if you have it]),
|
||||||
AC_STRUCT_DIRENT_D_TYPE
|
[], [AC_STRUCT_DIRENT_D_TYPE]
|
||||||
AS_IF([test "x$ac_cv_member_struct_dirent_d_type" != "xyes"],[
|
)
|
||||||
AC_MSG_ERROR([
|
AS_IF([test "x$ac_cv_member_struct_dirent_d_type" != "xyes"],
|
||||||
*** We need the d_type member in struct dirent, but it seems
|
[use_dirent_d_type="no"], [use_dirent_d_type="yes"])
|
||||||
*** your system does not have it])
|
|
||||||
])
|
|
||||||
# support for d_ino in struct dirent is optional
|
# support for d_ino (inode) in struct dirent is optional; if it's
|
||||||
AC_STRUCT_DIRENT_D_INO
|
# available we can sort direntries by inode and access them in that
|
||||||
|
# order; this is much faster on some file systems (such as extfs3).
|
||||||
|
# Explicity disabling it is for testing purposes only.
|
||||||
|
AC_ARG_ENABLE([dirent-d-ino],
|
||||||
|
AC_HELP_STRING([--disable-dirent-d-ino],
|
||||||
|
[Don't use dirent->d_ino, even if you have it]),
|
||||||
|
[], [AC_STRUCT_DIRENT_D_INO]
|
||||||
|
)
|
||||||
|
AS_IF([test "x$ac_cv_member_struct_dirent_d_ino" != "xyes"],
|
||||||
|
[use_dirent_d_ino="no"], [use_dirent_d_ino="yes"])
|
||||||
|
|
||||||
|
|
||||||
# we need these
|
# we need these
|
||||||
AC_CHECK_FUNCS([memset realpath setlocale strerror])
|
AC_CHECK_FUNCS([memset memcpy realpath setlocale strerror])
|
||||||
|
|
||||||
|
|
||||||
# require pkg-config
|
# require pkg-config
|
||||||
AC_PATH_PROG([PKG_CONFIG], [pkg-config], [no])
|
AC_PATH_PROG([PKG_CONFIG], [pkg-config], [no])
|
||||||
|
@ -170,7 +180,7 @@ AS_IF([test "x$PMCCABE" = "xno"],[
|
||||||
|
|
||||||
if test "x$PMCCABE" = "xno"; then
|
if test "x$PMCCABE" = "xno"; then
|
||||||
have_pmccabe="no"
|
have_pmccabe="no"
|
||||||
else
|
lselse
|
||||||
have_pmccabe="yes"
|
have_pmccabe="yes"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -198,10 +208,15 @@ if test -e ~/.mu/xapian-0.6; then
|
||||||
echo "remove the old <muhome>/xapian-0.6 directory to save some disk space"
|
echo "remove the old <muhome>/xapian-0.6 directory to save some disk space"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
echo "Xapian version : $xapian_version"
|
echo "Xapian version : $xapian_version"
|
||||||
echo "Build unit tests (glib >= 2.16) : $have_gtest"
|
echo "Build unit tests (glib >= 2.16) : $have_gtest"
|
||||||
echo "Build 'mug' (requires GTK+) : $have_gtk"
|
echo "Build 'mug' (requires GTK+) : $have_gtk"
|
||||||
echo "McCabe's Cyclomatic Complexity tool : $have_pmccabe"
|
echo "McCabe's Cyclomatic Complexity tool : $have_pmccabe"
|
||||||
|
echo
|
||||||
|
echo "Use direntry->d_ino : $use_dirent_d_ino"
|
||||||
|
echo "Use direntry->d_type : $use_dirent_d_type"
|
||||||
|
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "type 'make' to build mu, or 'make check' to run the unit tests."
|
echo "type 'make' to build mu, or 'make check' to run the unit tests."
|
||||||
|
|
173
src/mu-maildir.c
173
src/mu-maildir.c
|
@ -25,7 +25,6 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <dirent.h>
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
@ -33,22 +32,24 @@
|
||||||
|
|
||||||
#include "mu-util.h"
|
#include "mu-util.h"
|
||||||
#include "mu-maildir.h"
|
#include "mu-maildir.h"
|
||||||
|
#include "mu-str.h"
|
||||||
|
|
||||||
#define MU_MAILDIR_WALK_MAX_FILE_SIZE (32*1000*1000)
|
#define MU_MAILDIR_WALK_MAX_FILE_SIZE (32*1000*1000)
|
||||||
#define MU_MAILDIR_NOINDEX_FILE ".noindex"
|
#define MU_MAILDIR_NOINDEX_FILE ".noindex"
|
||||||
|
|
||||||
/* note: this function is *not* re-entrant, it returns a static buffer */
|
/* On Linux (and some BSD), we have entry->d_type, but some file
|
||||||
static const char*
|
* systems (XFS, ReiserFS) do not support it, and set it DT_UNKNOWN.
|
||||||
fullpath_s (const char* path, const char* name)
|
* On other OSs, notably Solaris, entry->d_type is not present at all.
|
||||||
{
|
* For these cases, we use lstat (in get_dtype) as a slower fallback,
|
||||||
static char buf[4096];
|
* and return it in the d_type parameter
|
||||||
|
*/
|
||||||
snprintf (buf, sizeof(buf), "%s%c%s",
|
#ifdef HAVE_STRUCT_DIRENT_D_TYPE
|
||||||
path, G_DIR_SEPARATOR,
|
#define GET_DTYPE(DE,FP) \
|
||||||
name ? name : "");
|
((DE)->d_type == DT_UNKNOWN ? mu_util_get_dtype_with_lstat((FP)) : (DE)->d_type)
|
||||||
|
#else
|
||||||
return buf;
|
#define GET_DTYPE(DE,FP) \
|
||||||
}
|
mu_util_get_dtype_with_lstat((FP))
|
||||||
|
#endif /*HAVE_STRUCT_DIRENT_D_TYPE*/
|
||||||
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -71,7 +72,7 @@ create_maildir (const char *path, mode_t mode, GError **err)
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
/* static buffer */
|
/* static buffer */
|
||||||
fullpath = fullpath_s (path, subdirs[i]);
|
fullpath = mu_str_fullpath_s (path, subdirs[i]);
|
||||||
rv = g_mkdir_with_parents (fullpath, (int)mode);
|
rv = g_mkdir_with_parents (fullpath, (int)mode);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
g_set_error (err, 0, MU_FILE_ERROR_CANNOT_MKDIR,
|
g_set_error (err, 0, MU_FILE_ERROR_CANNOT_MKDIR,
|
||||||
|
@ -92,7 +93,7 @@ create_noindex (const char *path, GError **err)
|
||||||
const char *noindexpath;
|
const char *noindexpath;
|
||||||
|
|
||||||
/* static buffer */
|
/* static buffer */
|
||||||
noindexpath = fullpath_s (path, MU_MAILDIR_NOINDEX_FILE);
|
noindexpath = mu_str_fullpath_s (path, MU_MAILDIR_NOINDEX_FILE);
|
||||||
|
|
||||||
fd = creat (noindexpath, 0644);
|
fd = creat (noindexpath, 0644);
|
||||||
|
|
||||||
|
@ -288,7 +289,7 @@ has_noindex_file (const char *path)
|
||||||
const char* noindexpath;
|
const char* noindexpath;
|
||||||
|
|
||||||
/* static buffer */
|
/* static buffer */
|
||||||
noindexpath = fullpath_s (path, MU_MAILDIR_NOINDEX_FILE);
|
noindexpath = mu_str_fullpath_s (path, MU_MAILDIR_NOINDEX_FILE);
|
||||||
|
|
||||||
if (access (noindexpath, F_OK) == 0)
|
if (access (noindexpath, F_OK) == 0)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -301,62 +302,15 @@ has_noindex_file (const char *path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* do readdir, and of file systems that do not support ->_dtype, fill it
|
|
||||||
* using stat -- much slower, but it works.
|
|
||||||
*/
|
|
||||||
static struct dirent*
|
|
||||||
readdir_with_stat_fallback (DIR* dir, const char* path)
|
|
||||||
{
|
|
||||||
struct dirent *entry;
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
entry = readdir (dir);
|
|
||||||
|
|
||||||
if (G_UNLIKELY(!entry)) {
|
|
||||||
if (errno != 0)
|
|
||||||
g_warning ("readdir failed in %s: %s",
|
|
||||||
path, strerror (errno));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XFS, ReiserFS and some other FSs don't support d_type, and
|
|
||||||
* always set it to NULL; we use (slow) lstat instead then */
|
|
||||||
if (G_UNLIKELY(entry->d_type == DT_UNKNOWN)) {
|
|
||||||
|
|
||||||
struct stat statbuf;
|
|
||||||
const char* fullpath;
|
|
||||||
|
|
||||||
/* note, fullpath_s returns a static buffer */
|
|
||||||
fullpath = fullpath_s (path, entry->d_name);
|
|
||||||
if G_UNLIKELY(lstat (fullpath, &statbuf) != 0) {
|
|
||||||
g_warning ("stat failed on %s: %s", fullpath, strerror(errno));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we only care about dirs, regular files and links */
|
|
||||||
if (S_ISREG (statbuf.st_mode))
|
|
||||||
entry->d_type = DT_REG;
|
|
||||||
else if (S_ISDIR (statbuf.st_mode))
|
|
||||||
entry->d_type = DT_DIR;
|
|
||||||
else if (S_ISLNK (statbuf.st_mode))
|
|
||||||
entry->d_type = DT_LNK;
|
|
||||||
}
|
|
||||||
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
ignore_dir_entry (struct dirent *entry)
|
ignore_dir_entry (struct dirent *entry, unsigned char d_type)
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
/* if it's not a dir and not a file, ignore it.
|
/* if it's not a dir and not a file, ignore it.
|
||||||
* note, this means also symlinks (DT_LNK) are ignored,
|
* note, this means also symlinks (DT_LNK) are ignored,
|
||||||
* maybe make this optional. Also note that entry->d_type is
|
* maybe make this optional */
|
||||||
* defined on Linux, BSDs is not part of POSIX; this needs a
|
if (d_type != DT_REG && d_type != DT_DIR)
|
||||||
* configure check */
|
|
||||||
if (entry->d_type != DT_REG &&
|
|
||||||
entry->d_type != DT_DIR)
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
name = entry->d_name;
|
name = entry->d_name;
|
||||||
|
@ -399,22 +353,24 @@ process_dir_entry (const char* path, const char* mdir, struct dirent *entry,
|
||||||
{
|
{
|
||||||
const char *fp;
|
const char *fp;
|
||||||
char* fullpath;
|
char* fullpath;
|
||||||
|
unsigned char d_type;
|
||||||
/* ignore special dirs: */
|
|
||||||
if (ignore_dir_entry (entry))
|
|
||||||
return MU_OK;
|
|
||||||
|
|
||||||
/* we have to copy the buffer from fullpath_s, because it
|
/* we have to copy the buffer from fullpath_s, because it
|
||||||
* returns a static buffer */
|
* returns a static buffer */
|
||||||
fp = fullpath_s (path, entry->d_name);
|
fp = mu_str_fullpath_s (path, entry->d_name);
|
||||||
fullpath = g_newa (char, strlen(fp) + 1);
|
fullpath = g_newa (char, strlen(fp) + 1);
|
||||||
strcpy (fullpath, fp);
|
strcpy (fullpath, fp);
|
||||||
|
|
||||||
switch (entry->d_type) {
|
d_type = GET_DTYPE(entry, fullpath);
|
||||||
case DT_REG:
|
|
||||||
/* we only want files in cur/ and new/ */
|
/* ignore special files/dirs */
|
||||||
|
if (ignore_dir_entry (entry, d_type))
|
||||||
|
return MU_OK;
|
||||||
|
|
||||||
|
switch (d_type) {
|
||||||
|
case DT_REG: /* we only want files in cur/ and new/ */
|
||||||
if (!is_maildir_new_or_cur (path))
|
if (!is_maildir_new_or_cur (path))
|
||||||
return MU_OK;
|
return MU_OK;
|
||||||
|
|
||||||
return process_file (fullpath, mdir, cb_msg, data);
|
return process_file (fullpath, mdir, cb_msg, data);
|
||||||
|
|
||||||
|
@ -425,6 +381,7 @@ process_dir_entry (const char* path, const char* mdir, struct dirent *entry,
|
||||||
my_mdir = get_mdir_for_path (mdir, entry->d_name);
|
my_mdir = get_mdir_for_path (mdir, entry->d_name);
|
||||||
rv = process_dir (fullpath, my_mdir, cb_msg, cb_dir, data);
|
rv = process_dir (fullpath, my_mdir, cb_msg, cb_dir, data);
|
||||||
g_free (my_mdir);
|
g_free (my_mdir);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -437,13 +394,12 @@ process_dir_entry (const char* path, const char* mdir, struct dirent *entry,
|
||||||
static struct dirent*
|
static struct dirent*
|
||||||
dirent_copy (struct dirent *entry)
|
dirent_copy (struct dirent *entry)
|
||||||
{
|
{
|
||||||
struct dirent *d;
|
struct dirent *d;
|
||||||
|
|
||||||
|
d = g_slice_new (struct dirent);
|
||||||
|
|
||||||
/* NOTE: simply memcpy'ing sizeof(struct dirent) bytes will
|
/* NOTE: simply memcpy'ing sizeof(struct dirent) bytes will
|
||||||
* give memory errors. Also note, g_slice_new has been known to
|
* give memory errors. */
|
||||||
* crash on FreeBSD */
|
|
||||||
d = g_slice_new (struct dirent);
|
|
||||||
|
|
||||||
return (struct dirent*) memcpy (d, entry, entry->d_reclen);
|
return (struct dirent*) memcpy (d, entry, entry->d_reclen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -469,32 +425,28 @@ dirent_cmp (struct dirent *d1, struct dirent *d2)
|
||||||
}
|
}
|
||||||
#endif /*HAVE_STRUCT_DIRENT_D_INO*/
|
#endif /*HAVE_STRUCT_DIRENT_D_INO*/
|
||||||
|
|
||||||
|
|
||||||
/* we sort the inodes if the FS's dirent has them. It makes
|
|
||||||
* file-access much faster on some filesystems, such as ext3,4.
|
|
||||||
*
|
|
||||||
* readdir_with_stat_fallback is a wrapper for readdir that falls back
|
|
||||||
* to (slow) lstats if the FS does not support entry->d_type
|
|
||||||
*/
|
|
||||||
static MuResult
|
static MuResult
|
||||||
process_dir_entries_sorted (DIR *dir, const char* path, const char* mdir,
|
process_dir_entries (DIR *dir, const char* path, const char* mdir,
|
||||||
MuMaildirWalkMsgCallback msg_cb,
|
MuMaildirWalkMsgCallback msg_cb,
|
||||||
MuMaildirWalkDirCallback dir_cb, void *data)
|
MuMaildirWalkDirCallback dir_cb, void *data)
|
||||||
{
|
{
|
||||||
MuResult result;
|
MuResult result;
|
||||||
GList *lst, *c;
|
GList *lst, *c;
|
||||||
struct dirent *entry;
|
struct dirent *entry;
|
||||||
|
|
||||||
lst = NULL;
|
lst = NULL;
|
||||||
while ((entry = readdir_with_stat_fallback (dir, path)))
|
while ((entry = readdir (dir)))
|
||||||
lst = g_list_prepend (lst, dirent_copy(entry));
|
lst = g_list_prepend (lst, dirent_copy(entry));
|
||||||
|
|
||||||
|
/* we sort by inode; this makes things much faster on
|
||||||
|
* extfs2,3 */
|
||||||
#if HAVE_STRUCT_DIRENT_D_INO
|
#if HAVE_STRUCT_DIRENT_D_INO
|
||||||
c = lst = g_list_sort (lst, (GCompareFunc)dirent_cmp);
|
c = lst = g_list_sort (lst, (GCompareFunc)dirent_cmp);
|
||||||
#endif /*HAVE_STRUCT_DIRENT_D_INO*/
|
#endif /*HAVE_STRUCT_DIRENT_D_INO*/
|
||||||
|
|
||||||
for (c = lst, result = MU_OK; c && result == MU_OK; c = c->next) {
|
for (c = lst, result = MU_OK; c && result == MU_OK; c = c->next) {
|
||||||
result = process_dir_entry (path, mdir, (struct dirent*)c->data,
|
result = process_dir_entry (path, mdir,
|
||||||
|
(struct dirent*)c->data,
|
||||||
msg_cb, dir_cb, data);
|
msg_cb, dir_cb, data);
|
||||||
/* hmmm, break on MU_ERROR as well? */
|
/* hmmm, break on MU_ERROR as well? */
|
||||||
if (result == MU_STOP)
|
if (result == MU_STOP)
|
||||||
|
@ -538,8 +490,7 @@ process_dir (const char* path, const char* mdir,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result = process_dir_entries_sorted (dir, path, mdir, msg_cb, dir_cb,
|
result = process_dir_entries (dir, path, mdir, msg_cb, dir_cb, data);
|
||||||
data);
|
|
||||||
closedir (dir);
|
closedir (dir);
|
||||||
|
|
||||||
/* only run dir_cb if it exists and so far, things went ok */
|
/* only run dir_cb if it exists and so far, things went ok */
|
||||||
|
@ -567,8 +518,7 @@ mu_maildir_walk (const char *path, MuMaildirWalkMsgCallback cb_msg,
|
||||||
if (mypath[strlen(mypath)-1] == G_DIR_SEPARATOR)
|
if (mypath[strlen(mypath)-1] == G_DIR_SEPARATOR)
|
||||||
mypath[strlen(mypath)-1] = '\0';
|
mypath[strlen(mypath)-1] = '\0';
|
||||||
|
|
||||||
rv = process_dir (mypath, NULL, cb_msg,
|
rv = process_dir (mypath, NULL, cb_msg, cb_dir, data);
|
||||||
cb_dir, data);
|
|
||||||
g_free (mypath);
|
g_free (mypath);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
|
@ -582,27 +532,31 @@ clear_links (const gchar* dirname, DIR *dir, GError **err)
|
||||||
gboolean rv;
|
gboolean rv;
|
||||||
|
|
||||||
rv = TRUE;
|
rv = TRUE;
|
||||||
while ((entry = readdir_with_stat_fallback (dir, dirname))) {
|
errno = 0;
|
||||||
|
while ((entry = readdir (dir))) {
|
||||||
|
|
||||||
const char *fp;
|
const char *fp;
|
||||||
char *fullpath;
|
char *fullpath;
|
||||||
|
unsigned char d_type;
|
||||||
|
|
||||||
/* ignore empty, dot thingies */
|
/* ignore empty, dot thingies */
|
||||||
if (!entry->d_name || entry->d_name[0] == '.')
|
if (!entry->d_name || entry->d_name[0] == '.')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* ignore non-links / non-dirs */
|
|
||||||
if (entry->d_type != DT_LNK && entry->d_type != DT_DIR)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* we have to copy the buffer from fullpath_s, because
|
/* we have to copy the buffer from fullpath_s, because
|
||||||
* it returns a static buffer and we are
|
* it returns a static buffer and we are
|
||||||
* recursive*/
|
* recursive*/
|
||||||
fp = fullpath_s (dirname, entry->d_name);
|
fp = mu_str_fullpath_s (dirname, entry->d_name);
|
||||||
fullpath = g_newa (char, strlen(fp) + 1);
|
fullpath = g_newa (char, strlen(fp) + 1);
|
||||||
strcpy (fullpath, fp);
|
strcpy (fullpath, fp);
|
||||||
|
|
||||||
|
d_type = GET_DTYPE (entry, fullpath);
|
||||||
|
|
||||||
|
/* ignore non-links / non-dirs */
|
||||||
|
if (d_type != DT_LNK && d_type != DT_DIR)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (entry->d_type == DT_LNK) {
|
if (d_type == DT_LNK) {
|
||||||
if (unlink (fullpath) != 0) {
|
if (unlink (fullpath) != 0) {
|
||||||
/* don't use err */
|
/* don't use err */
|
||||||
g_warning ("error unlinking %s: %s",
|
g_warning ("error unlinking %s: %s",
|
||||||
|
@ -612,8 +566,11 @@ clear_links (const gchar* dirname, DIR *dir, GError **err)
|
||||||
} else /* DT_DIR, see check before*/
|
} else /* DT_DIR, see check before*/
|
||||||
rv = mu_maildir_clear_links (fullpath, err);
|
rv = mu_maildir_clear_links (fullpath, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (errno != 0)
|
||||||
|
g_set_error (err, 0, MU_ERROR_FILE,"file error: %s", strerror(errno));
|
||||||
|
|
||||||
return rv;
|
return (rv == FALSE && errno == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
26
src/mu-str.c
26
src/mu-str.c
|
@ -27,6 +27,17 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* hopefully, this should get us a sane PATH_MAX */
|
||||||
|
#include <limits.h>
|
||||||
|
/* not all systems provide PATH_MAX in limits.h */
|
||||||
|
#ifndef PATH_MAX
|
||||||
|
#include <sys/param.h>
|
||||||
|
#ifndef PATH_MAX
|
||||||
|
#define PATH_MAX MAXPATHLEN
|
||||||
|
#endif /*!PATH_MAX*/
|
||||||
|
#endif /*PATH_MAX*/
|
||||||
|
|
||||||
#include "mu-str.h"
|
#include "mu-str.h"
|
||||||
#include "mu-msg-flags.h"
|
#include "mu-msg-flags.h"
|
||||||
|
@ -342,3 +353,18 @@ mu_str_ascii_xapian_escape (const char *query)
|
||||||
|
|
||||||
return mu_str_ascii_xapian_escape_in_place (g_strdup(query));
|
return mu_str_ascii_xapian_escape_in_place (g_strdup(query));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* note: this function is *not* re-entrant, it returns a static buffer */
|
||||||
|
const char*
|
||||||
|
mu_str_fullpath_s (const char* path, const char* name)
|
||||||
|
{
|
||||||
|
static char buf[PATH_MAX + 1];
|
||||||
|
|
||||||
|
g_return_val_if_fail (path, NULL);
|
||||||
|
|
||||||
|
snprintf (buf, sizeof(buf), "%s%c%s", path, G_DIR_SEPARATOR,
|
||||||
|
name ? name : "");
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
11
src/mu-str.h
11
src/mu-str.h
|
@ -209,6 +209,17 @@ char* mu_str_ascii_xapian_escape (const char *query);
|
||||||
time_t mu_str_date_parse_hdwmy (const char* str);
|
time_t mu_str_date_parse_hdwmy (const char* str);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create a full path from a path + a filename. function is _not_
|
||||||
|
* reentrant.
|
||||||
|
*
|
||||||
|
* @param path a path (!= NULL)
|
||||||
|
* @param name a name (may be NULL)
|
||||||
|
*
|
||||||
|
* @return the path as a statically allocated buffer. don't free.
|
||||||
|
*/
|
||||||
|
const char* mu_str_fullpath_s (const char* path, const char* name);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /*__MU_STR_H__*/
|
#endif /*__MU_STR_H__*/
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
#include <wordexp.h> /* for shell-style globbing */
|
#include <wordexp.h> /* for shell-style globbing */
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
/* hopefully, the should get us a sane PATH_MAX */
|
/* hopefully, this should get us a sane PATH_MAX */
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
/* not all systems provide PATH_MAX in limits.h */
|
/* not all systems provide PATH_MAX in limits.h */
|
||||||
#ifndef PATH_MAX
|
#ifndef PATH_MAX
|
||||||
|
@ -274,4 +274,28 @@ mu_util_create_writeable_fd (const char* filename, const char* dir,
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned char
|
||||||
|
mu_util_get_dtype_with_lstat (const char *path)
|
||||||
|
{
|
||||||
|
struct stat statbuf;
|
||||||
|
|
||||||
|
g_return_val_if_fail (path, DT_UNKNOWN);
|
||||||
|
|
||||||
|
if (lstat (path, &statbuf) != 0) {
|
||||||
|
g_warning ("stat failed on %s: %s",
|
||||||
|
path, strerror(errno));
|
||||||
|
return DT_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we only care about dirs, regular files and links */
|
||||||
|
if (S_ISREG (statbuf.st_mode))
|
||||||
|
return DT_REG;
|
||||||
|
else if (S_ISDIR (statbuf.st_mode))
|
||||||
|
return DT_DIR;
|
||||||
|
else if (S_ISLNK (statbuf.st_mode))
|
||||||
|
return DT_LNK;
|
||||||
|
|
||||||
|
return DT_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,12 +21,14 @@
|
||||||
#define __MU_UTIL_H__
|
#define __MU_UTIL_H__
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* do system-specific initialization. should be called before anything
|
* do system-specific initialization. should be called before anything
|
||||||
* else. Initializes the locale and Gtype
|
* else. Initializes the locale and Gtype. Note: this function is
|
||||||
|
* called by mu_runtime_init.
|
||||||
*
|
*
|
||||||
* @return TRUE if is succeeds, FALSE otherwise
|
* @return TRUE if is succeeds, FALSE otherwise
|
||||||
*/
|
*/
|
||||||
|
@ -121,12 +123,50 @@ int mu_util_create_writeable_fd (const char* filename, const char* dir,
|
||||||
gchar* mu_util_str_from_strv (const gchar **params)
|
gchar* mu_util_str_from_strv (const gchar **params)
|
||||||
G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
|
G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* for OSs with out support for direntry->d_type, like Solaris
|
||||||
|
*/
|
||||||
|
#ifndef DT_UNKNOWN
|
||||||
|
enum {
|
||||||
|
DT_UNKNOWN = 0,
|
||||||
|
# define DT_UNKNOWN DT_UNKNOWN
|
||||||
|
DT_FIFO = 1,
|
||||||
|
# define DT_FIFO DT_FIFO
|
||||||
|
DT_CHR = 2,
|
||||||
|
# define DT_CHR DT_CHR
|
||||||
|
DT_DIR = 4,
|
||||||
|
# define DT_DIR DT_DIR
|
||||||
|
DT_BLK = 6,
|
||||||
|
# define DT_BLK DT_BLK
|
||||||
|
DT_REG = 8,
|
||||||
|
# define DT_REG DT_REG
|
||||||
|
DT_LNK = 10,
|
||||||
|
# define DT_LNK DT_LNK
|
||||||
|
DT_SOCK = 12,
|
||||||
|
# define DT_SOCK DT_SOCK
|
||||||
|
DT_WHT = 14
|
||||||
|
# define DT_WHT DT_WHT
|
||||||
|
};
|
||||||
|
#endif /*DT_UNKNOWN*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the d_type (as in direntry->d_type) for the file at path, using
|
||||||
|
* lstat(3)
|
||||||
|
*
|
||||||
|
* @param path full path
|
||||||
|
*
|
||||||
|
* @return DT_REG, DT_DIR, DT_LNK, or DT_UNKNOWN (other values are not
|
||||||
|
* supported currently )
|
||||||
|
*/
|
||||||
|
unsigned char mu_util_get_dtype_with_lstat (const char *path);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* don't repeat these catch blocks everywhere...
|
* don't repeat these catch blocks everywhere...
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define MU_XAPIAN_CATCH_BLOCK \
|
#define MU_XAPIAN_CATCH_BLOCK \
|
||||||
catch (const Xapian::Error &xerr) { \
|
catch (const Xapian::Error &xerr) { \
|
||||||
g_critical ("%s: caught xapian exception '%s'", \
|
g_critical ("%s: caught xapian exception '%s'", \
|
||||||
|
|
Loading…
Reference in New Issue