Fix st_nlink for directories. Added free_errno() and xfree_errno(). Fix returne… | |
git clone git://git.codemadness.org/susmb | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit bd037226cf4a14330a38b1370ed42b33618edb5c | |
parent 2d2b162d712d698357ae550c630545734f8543fb | |
Author: Geoff Johnstone <[email protected]> | |
Date: Wed, 25 Jun 2008 22:53:53 +0100 | |
Fix st_nlink for directories. | |
Added free_errno() and xfree_errno(). | |
Fix returned errno when free (url) follows the Samba call. | |
Added UNUSED; removed (void)variable. | |
Diffstat: | |
M Makefile | 3 ++- | |
M usmb.c | 13 +++++-------- | |
M usmb_dir.c | 13 ++++--------- | |
M usmb_file.c | 102 ++++++++++++++++++++++-------… | |
M utils.c | 17 +++++++++++++++++ | |
M utils.h | 2 ++ | |
M xml.c | 6 ++++-- | |
7 files changed, 106 insertions(+), 50 deletions(-) | |
--- | |
diff --git a/Makefile b/Makefile | |
@@ -23,7 +23,8 @@ BINDIR = $(PREFIX)/bin | |
CFLAGS += -Wall -Wextra -Werror -std=c99 -pedantic -O \ | |
-I$(SAMBA)/include -D_BSD_SOURCE -DFUSE_USE_VERSION=26 \ | |
- -DHAVE_UTIME_H -DMUSTCHECK='__attribute__ ((warn_unused_result))' | |
+ -DHAVE_UTIME_H -DMUSTCHECK='__attribute__ ((warn_unused_result))' \ | |
+ -DUNUSED='__attribute__ ((unused))' | |
LDLIBS = -lsmbclient | |
LDFLAGS = -L$(SAMBA)/lib | |
diff --git a/usmb.c b/usmb.c | |
@@ -57,11 +57,10 @@ static inline void do_strncpy (char *to, const char *from, … | |
} | |
-static void auth_fn (const char *srv, const char *shr, char *wg, int wglen, | |
- char *un, int unlen, char *pw, int pwlen) | |
+static void auth_fn (const char *srv UNUSED, const char *shr UNUSED, | |
+ char *wg, int wglen, char *un, int unlen, | |
+ char *pw, int pwlen) | |
{ | |
- (void)srv; | |
- (void)shr; | |
DEBUG (fprintf (stderr, "Authenticating for \\\\%s\\%s\n", srv, shr)); | |
DEBUG (fprintf (stderr, "Domain: %s; User: %s; Password:%s\n", | |
domain, username, password)); | |
@@ -118,17 +117,15 @@ static int usmb_statfs (const char *path, struct statvfs … | |
#endif | |
-static void * usmb_init (struct fuse_conn_info *conn) | |
+static void * usmb_init (struct fuse_conn_info *conn UNUSED) | |
{ | |
DEBUG (fputs ("usmb_init()\n", stderr)); | |
- (void)conn; | |
return NULL; | |
} | |
-static void usmb_destroy (void *unused) | |
+static void usmb_destroy (void *unused UNUSED) | |
{ | |
- (void)unused; | |
DEBUG (fputs ("usmb_destroy()\n", stderr)); | |
} | |
diff --git a/usmb_dir.c b/usmb_dir.c | |
@@ -73,12 +73,9 @@ int usmb_opendir (const char *dirname, struct fuse_file_info… | |
} | |
-int usmb_readdir (const char *path, void *h, fuse_fill_dir_t filler, | |
- off_t offset, struct fuse_file_info *fi) | |
+int usmb_readdir (const char *path UNUSED, void *h, fuse_fill_dir_t filler, | |
+ off_t offset UNUSED, struct fuse_file_info *fi) | |
{ | |
- (void)path; | |
- (void)offset; | |
- | |
struct smbc_dirent *dirent; | |
errno = 0; | |
SMBCFILE *file = fd_to_smbcfile (fi->fh); | |
@@ -115,13 +112,11 @@ int usmb_readdir (const char *path, void *h, fuse_fill_di… | |
} | |
-int usmb_releasedir (const char *path, struct fuse_file_info *fi) | |
+int usmb_releasedir (const char *path UNUSED, struct fuse_file_info *fi) | |
{ | |
- (void)path; | |
- | |
SMBCFILE *file = fd_to_smbcfile (fi->fh); | |
DEBUG (fprintf (stderr, "releasedir (%s, %p)\n", path, (void *)file)); | |
- return (ctx->closedir (ctx, file) < 0) ? -errno : 0; | |
+ return (0 > ctx->closedir (ctx, file)) ? -errno : 0; | |
} | |
diff --git a/usmb_file.c b/usmb_file.c | |
@@ -16,9 +16,11 @@ | |
#include <sys/time.h> // struct timeval needed by libsmbclient.h | |
#include <libsmbclient.h> | |
+#include <limits.h> | |
#include <assert.h> | |
#include <fuse.h> | |
#include <errno.h> | |
+#include <stdbool.h> | |
#include <stddef.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
@@ -28,6 +30,34 @@ | |
#include "utils.h" | |
+// Samba gets st_nlink wrong for directories. | |
+static bool fix_nlink (const char *url, struct stat *st) | |
+{ | |
+ assert (NULL != url); | |
+ assert (NULL != st); | |
+ | |
+ if (!S_ISDIR (st->st_mode)) | |
+ return true; | |
+ | |
+ SMBCFILE *file = ctx->opendir (ctx, url); | |
+ if (NULL == file) | |
+ return false; | |
+ | |
+ st->st_nlink = 2; | |
+ errno = ERANGE; | |
+ | |
+ struct smbc_dirent *dirent; | |
+ | |
+ while (NULL != (dirent = ctx->readdir (ctx, file))) | |
+ if (SMBC_DIR == dirent->smbc_type) | |
+ if (INT_MAX == st->st_nlink++) | |
+ break; | |
+ | |
+ (void)ctx->closedir (ctx, file); | |
+ return (NULL == dirent); | |
+} | |
+ | |
+ | |
int usmb_getattr (const char *filename, struct stat *st) | |
{ | |
char *url = make_url (filename); | |
@@ -37,18 +67,38 @@ int usmb_getattr (const char *filename, struct stat *st) | |
DEBUG (fprintf (stderr, "stat (%s)\n", url)); | |
int ret = ctx->stat (ctx, url, st); | |
+ | |
+ if ((0 > ret) || !fix_nlink (url, st)) | |
+ ret = -errno; | |
+ | |
free (url); | |
- return (ret < 0) ? -errno : 0; | |
+ return ret; | |
} | |
-int usmb_fgetattr (const char *filename, struct stat *st, | |
+int usmb_fgetattr (const char *filename UNUSED, struct stat *st, | |
struct fuse_file_info *fi) | |
{ | |
- (void)filename; | |
SMBCFILE *file = fd_to_smbcfile (fi->fh); | |
DEBUG (fprintf (stderr, "fgetattr (%s, %p)\n", filename, (void *)file)); | |
- return (ctx->fstat (ctx, file, st) < 0) ? -errno : 0; | |
+ | |
+ if (0 > ctx->fstat (ctx, file, st)) | |
+ return -errno; | |
+ | |
+ if (S_ISDIR (st->st_mode)) | |
+ { | |
+ char *url = make_url (filename); | |
+ if (NULL == url) | |
+ return -ENOMEM; | |
+ | |
+ bool ok = fix_nlink (url, st); | |
+ free_errno (url); | |
+ | |
+ if (!ok) | |
+ return -errno; | |
+ } | |
+ | |
+ return 0; | |
} | |
@@ -59,7 +109,7 @@ int usmb_unlink (const char *filename) | |
return -ENOMEM; | |
DEBUG (fprintf (stderr, "unlink (%s)\n", url)); | |
- int ret = (ctx->unlink (ctx, url) < 0) ? -errno : 0; | |
+ int ret = (0 > ctx->unlink (ctx, url)) ? -errno : 0; | |
free (url); | |
return ret; | |
} | |
@@ -75,36 +125,32 @@ int usmb_open (const char *filename, struct fuse_file_info… | |
SMBCFILE *file = ctx->open (ctx, url, fi->flags, 0); | |
DEBUG (fprintf (stderr, " = %p\n", (void *)file)); | |
- free (url); | |
int ret = (NULL == file) ? -errno : 0; | |
+ free (url); | |
fi->fh = smbcfile_to_fd (file); | |
return ret; | |
} | |
-int usmb_release (const char *filename, struct fuse_file_info *fi) | |
+int usmb_release (const char *filename UNUSED, struct fuse_file_info *fi) | |
{ | |
- (void)filename; | |
SMBCFILE *file = fd_to_smbcfile (fi->fh); | |
DEBUG (fprintf (stderr, "release (%s, %p)\n", filename, (void *)file)); | |
- return (ctx->close_fn (ctx, file) < 0) ? -errno : 0; | |
+ return (0 > ctx->close_fn (ctx, file)) ? -errno : 0; | |
} | |
-int usmb_read (const char *filename, char *buff, size_t len, off_t off, | |
+int usmb_read (const char *filename UNUSED, char *buff, size_t len, off_t off, | |
struct fuse_file_info *fi) | |
{ | |
- (void)filename; | |
- (void)off; | |
- | |
assert (len <= 32768); | |
SMBCFILE *file = fd_to_smbcfile (fi->fh); | |
DEBUG (fprintf (stderr, "read (%p, %p, %u, %lld) ", | |
(void *)file, buff, len, off)); | |
- if (ctx->lseek (ctx, file, off, SEEK_SET) < 0) | |
+ if (0 > ctx->lseek (ctx, file, off, SEEK_SET)) | |
{ | |
fprintf (stderr, "- seek failed: %d\n", -errno); | |
return -errno; | |
@@ -112,21 +158,18 @@ int usmb_read (const char *filename, char *buff, size_t l… | |
int bytes = ctx->read (ctx, file, buff, len); | |
DEBUG (fprintf (stderr, "= %d\n", bytes)); | |
- return (bytes < 0) ? -errno : (int)bytes; | |
+ return (0 > bytes) ? -errno : (int)bytes; | |
} | |
-int usmb_write (const char *filename, const char *buff, size_t len, off_t off, | |
- struct fuse_file_info *fi) | |
+int usmb_write (const char *filename UNUSED, const char *buff, size_t len, | |
+ off_t off, struct fuse_file_info *fi) | |
{ | |
- (void)filename; | |
- (void)off; | |
- | |
SMBCFILE *file = fd_to_smbcfile (fi->fh); | |
DEBUG (fprintf (stderr, "write (%p, %p, len=%u, off=%lld) ", | |
(void *)file, buff, len, off)); | |
- if (ctx->lseek (ctx, file, off, SEEK_SET) < 0) | |
+ if (0 > ctx->lseek (ctx, file, off, SEEK_SET)) | |
{ | |
fprintf (stderr, "- seek failed: %d\n", -errno); | |
return -errno; | |
@@ -140,8 +183,7 @@ int usmb_write (const char *filename, const char *buff, siz… | |
while (written < len) | |
{ | |
bytes = ctx->write (ctx, file, (char *)buff, (len > 32768) ? 32768 : len); | |
- | |
- if (bytes < 0) | |
+ if (0 > bytes) | |
break; | |
written += bytes; | |
@@ -152,8 +194,8 @@ int usmb_write (const char *filename, const char *buff, siz… | |
break; | |
} | |
- DEBUG (fprintf (stderr, "= %d\n", (bytes < 0) ? -errno : (int)written)); | |
- return (bytes < 0) ? -errno : (int)written; | |
+ DEBUG (fprintf (stderr, "= %d\n", (0 > bytes) ? -errno : (int)written)); | |
+ return (0 > bytes) ? -errno : (int)written; | |
} | |
@@ -189,7 +231,7 @@ int usmb_rename (const char *from, const char *to) | |
} | |
DEBUG (fprintf (stderr, "rename (%s, %s)\n", fromurl, tourl)); | |
- int ret = (ctx->rename (ctx, fromurl, ctx, tourl) < 0) ? -errno : 0; | |
+ int ret = (0 > ctx->rename (ctx, fromurl, ctx, tourl)) ? -errno : 0; | |
free (tourl); | |
free (fromurl); | |
return ret; | |
@@ -228,7 +270,7 @@ int usmb_utime (const char *filename, struct utimbuf *utb) | |
}; | |
DEBUG (fprintf (stderr, "utime (%s)\n", url)); | |
- int ret = (ctx->utimes (ctx, url, tv) < 0) ? -errno : 0; | |
+ int ret = (0 > ctx->utimes (ctx, url, tv)) ? -errno : 0; | |
free (url); | |
return ret; | |
} | |
@@ -243,7 +285,7 @@ int usmb_utimes (const char *filename, const struct timespe… | |
return -ENOMEM; | |
DEBUG (fprintf (stderr, "utimes (%s)\n", url)); | |
- int ret = (ctx->utimes (ctx, url, ts) < 0) ? -errno : 0; | |
+ int ret = (0 > ctx->utimes (ctx, url, ts)) ? -errno : 0; | |
free (url); | |
return ret; | |
} | |
@@ -272,7 +314,7 @@ int usmb_truncate (const char *filename, off_t offset) | |
SMBCFILE *file = ctx->open (ctx, url, O_WRONLY | O_TRUNC, 0); | |
if (NULL == file) | |
{ | |
- free (url); | |
+ free_errno (url); | |
return -errno; | |
} | |
@@ -299,7 +341,7 @@ int usmb_chmod (const char *filename, mode_t mode) | |
return -ENOMEM; | |
DEBUG (fprintf (stderr, "chmod (%s, %u)\n", url, mode)); | |
- int ret = (ctx->chmod (ctx, url, mode) < 0) ? -errno : 0; | |
+ int ret = (0 > ctx->chmod (ctx, url, mode)) ? -errno : 0; | |
free (url); | |
return ret; | |
} | |
diff --git a/utils.c b/utils.c | |
@@ -15,6 +15,7 @@ | |
*/ | |
#include <assert.h> | |
+#include <errno.h> | |
#include <stdarg.h> | |
#include <stddef.h> | |
#include <stdio.h> | |
@@ -122,3 +123,19 @@ void clear_and_free (char *ptr) | |
} | |
} | |
+ | |
+void free_errno (const void *ptr) | |
+{ | |
+ int err = errno; | |
+ free ((void *)ptr); | |
+ errno = err; | |
+} | |
+ | |
+ | |
+void xfree_errno (const void *ptr) | |
+{ | |
+ int err = errno; | |
+ xfree (ptr); | |
+ errno = err; | |
+} | |
+ | |
diff --git a/utils.h b/utils.h | |
@@ -29,5 +29,7 @@ | |
char * xstrdup (const char *in) MUSTCHECK; | |
void xfree (const void *ptr); | |
void clear_and_free (char *ptr); | |
+ void free_errno (const void *ptr); | |
+ void xfree_errno (const void *ptr); | |
#endif | |
diff --git a/xml.c b/xml.c | |
@@ -84,7 +84,8 @@ bool xml_xpath_attr_value (xmlXPathContextPtr ctx, | |
return false; | |
} | |
- do { | |
+ do | |
+ { | |
if (XPATH_NODESET != obj->type) | |
{ | |
DEBUG (fputs ("XPath evaluation didn't return a nodeset\n", stderr)); | |
@@ -142,7 +143,8 @@ bool xml_xpath_text (xmlXPathContextPtr ctx, char *xpath, c… | |
return false; | |
} | |
- do { | |
+ do | |
+ { | |
if (XPATH_NODESET != obj->type) | |
{ | |
DEBUG (fputs ("XPath evaluation didn't return a nodeset\n", stderr)); |