support USERINF, div bug fixes
This commit is contained in:
parent
15455d6130
commit
317e8a19df
30
ChangeLog
30
ChangeLog
@ -1,6 +1,36 @@
|
|||||||
ChangeLog for davfs2
|
ChangeLog for davfs2
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
|
2009-05-31 Werner Baumann (werner.baumann@onlinehome.de)
|
||||||
|
* cache.c, cache.h, dav_coda.c, dav_fuse.c:
|
||||||
|
Cache quota in global variable fs_stat.
|
||||||
|
Update with dir_refresh and when closing or
|
||||||
|
deleting files.
|
||||||
|
Function dav_stafs now returns a pointer.
|
||||||
|
|
||||||
|
2009-05-30 Werner Baumann (werner.baumann@onlinehome.de)
|
||||||
|
* webdav.c, webdav.h, dav_quota:
|
||||||
|
Return total webspace instead of available.
|
||||||
|
Rember support for quota in static flag use_rfc.
|
||||||
|
Add support for method USERINFO.
|
||||||
|
* webdav.c:
|
||||||
|
Rename block_writer into file_reader for consistency
|
||||||
|
with neon naming conventions.
|
||||||
|
* cache.c, dav_open, dav_write:
|
||||||
|
Open directories O_RDWR again, but prevent writing
|
||||||
|
by applications.
|
||||||
|
|
||||||
|
2009-05-29 Werner Baumann (werner.baumann@onlinehome.de)
|
||||||
|
* mount_davfs.c, check_double_mounts:
|
||||||
|
Free temporary string mp.
|
||||||
|
* cache.c, parse_index:
|
||||||
|
Free index.
|
||||||
|
* webdav.c, dav_init_webdav:
|
||||||
|
Make custom_header a global variable to not disturb
|
||||||
|
code test tools.
|
||||||
|
* webdav.c, dav_quota:
|
||||||
|
Initialize ctx to 0; add ctx.error, use strtoull.
|
||||||
|
|
||||||
2009-05-25 Werner Baumann (werner.baumann@onlinehome.de)
|
2009-05-25 Werner Baumann (werner.baumann@onlinehome.de)
|
||||||
* cache.c, mount_davfs.c:
|
* cache.c, mount_davfs.c:
|
||||||
Add missing includes.
|
Add missing includes.
|
||||||
|
92
src/cache.c
92
src/cache.c
@ -128,8 +128,8 @@ static const char* const type[] = {
|
|||||||
/* Private global variables */
|
/* Private global variables */
|
||||||
/*==========================*/
|
/*==========================*/
|
||||||
|
|
||||||
/* Number of nodes. */
|
/* File system statistics. */
|
||||||
static int nnodes;
|
static dav_stat *fs_stat;
|
||||||
|
|
||||||
/* Root node of the directory cache. */
|
/* Root node of the directory cache. */
|
||||||
static dav_node *root;
|
static dav_node *root;
|
||||||
@ -316,6 +316,15 @@ update_node(dav_node *node, dav_props *props);
|
|||||||
static void
|
static void
|
||||||
update_path(dav_node *node, const char *src_path, const char *dst_path);
|
update_path(dav_node *node, const char *src_path, const char *dst_path);
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
update_stat(off_t size, int sign)
|
||||||
|
{
|
||||||
|
if (!fs_stat->utime) return;
|
||||||
|
fs_stat->bfree += sign * (size / fs_stat->bsize);
|
||||||
|
fs_stat->bavail = fs_stat->bfree;
|
||||||
|
fs_stat->ffree = fs_stat->bfree;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get information about node. */
|
/* Get information about node. */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -580,6 +589,9 @@ dav_init_cache(const dav_args *args, const char *mpoint)
|
|||||||
max_retry = args->max_retry;
|
max_retry = args->max_retry;
|
||||||
lock_refresh = args->lock_refresh;
|
lock_refresh = args->lock_refresh;
|
||||||
|
|
||||||
|
fs_stat = (dav_stat *) malloc(sizeof(dav_stat));
|
||||||
|
if (!fs_stat) abort();
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "Checking cache directory");
|
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "Checking cache directory");
|
||||||
max_cache_size = args->cache_size * 0x100000;
|
max_cache_size = args->cache_size * 0x100000;
|
||||||
@ -602,6 +614,19 @@ dav_init_cache(const dav_args *args, const char *mpoint)
|
|||||||
|
|
||||||
clean_cache();
|
clean_cache();
|
||||||
|
|
||||||
|
fs_stat->blocks = 0x65B9AA;
|
||||||
|
fs_stat->bfree = 0x32DCD5;
|
||||||
|
fs_stat->bavail = 0x32DCD5;
|
||||||
|
fs_stat->ffree = 666666;
|
||||||
|
struct stat cache_st;
|
||||||
|
if (stat(cache_dir, &cache_st) == 0) {
|
||||||
|
fs_stat->bsize = cache_st.st_blksize;
|
||||||
|
} else {
|
||||||
|
fs_stat->bsize = 4096;
|
||||||
|
}
|
||||||
|
fs_stat->namelen = 256;
|
||||||
|
fs_stat->utime = 0;
|
||||||
|
|
||||||
int ret = update_directory(root, 0);
|
int ret = update_directory(root, 0);
|
||||||
if (ret == EAGAIN) {
|
if (ret == EAGAIN) {
|
||||||
root->utime = 0;
|
root->utime = 0;
|
||||||
@ -621,6 +646,8 @@ dav_init_cache(const dav_args *args, const char *mpoint)
|
|||||||
} else if (ret) {
|
} else if (ret) {
|
||||||
error(EXIT_FAILURE, 0, _("Mounting failed.\n%s"),
|
error(EXIT_FAILURE, 0, _("Mounting failed.\n%s"),
|
||||||
dav_get_webdav_error());
|
dav_get_webdav_error());
|
||||||
|
} else {
|
||||||
|
dav_statfs();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -681,14 +708,8 @@ dav_register_kernel_interface(dav_write_dir_entry_fn write_fn, int *flush_flag,
|
|||||||
if (flush_flag)
|
if (flush_flag)
|
||||||
flush = flush_flag;
|
flush = flush_flag;
|
||||||
|
|
||||||
if (blksize) {
|
if (blksize)
|
||||||
struct stat st;
|
*blksize = fs_stat->bsize;
|
||||||
if (stat(cache_dir, &st) == 0) {
|
|
||||||
*blksize = st.st_blksize;
|
|
||||||
} else {
|
|
||||||
*blksize = 4096;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return alignment;
|
return alignment;
|
||||||
}
|
}
|
||||||
@ -699,7 +720,7 @@ dav_tidy_cache(void)
|
|||||||
{
|
{
|
||||||
if (debug) {
|
if (debug) {
|
||||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG),
|
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG),
|
||||||
"tidy: %i of %i nodes changed", nchanged, nnodes);
|
"tidy: %i of %llu nodes changed", nchanged, fs_stat->files);
|
||||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "cache-size: %llu MiBytes.",
|
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "cache-size: %llu MiBytes.",
|
||||||
(cache_size + 0x80000) / 0x100000);
|
(cache_size + 0x80000) / 0x100000);
|
||||||
}
|
}
|
||||||
@ -812,8 +833,10 @@ dav_close(dav_node *node, int fd, int flags, pid_t pid, pid_t pgid)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update_stat(node->size, 1);
|
||||||
attr_from_cache_file(node);
|
attr_from_cache_file(node);
|
||||||
set_upload_time(node);
|
set_upload_time(node);
|
||||||
|
update_stat(node->size, -1);
|
||||||
|
|
||||||
if (delay_upload == 0 && (is_dirty(node) || is_created(node))
|
if (delay_upload == 0 && (is_dirty(node) || is_created(node))
|
||||||
&& !is_open_write(node) && !is_backup(node)) {
|
&& !is_open_write(node) && !is_backup(node)) {
|
||||||
@ -1095,7 +1118,7 @@ dav_open(int *fd, dav_node *node, int flags, pid_t pid, pid_t pgid, uid_t uid,
|
|||||||
if (create_dir_cache_file(node) != 0)
|
if (create_dir_cache_file(node) != 0)
|
||||||
return EIO;
|
return EIO;
|
||||||
node->atime = time(NULL);
|
node->atime = time(NULL);
|
||||||
return open_file(fd, node, O_RDONLY, pid, pgid, uid);
|
return open_file(fd, node, O_RDWR, pid, pgid, uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@ -1202,6 +1225,7 @@ dav_remove(dav_node *parent, const char *name, uid_t uid)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
update_stat(node->size, 1);
|
||||||
remove_from_tree(node);
|
remove_from_tree(node);
|
||||||
remove_from_changed(node);
|
remove_from_changed(node);
|
||||||
if (is_open(node)) {
|
if (is_open(node)) {
|
||||||
@ -1486,32 +1510,22 @@ dav_setattr(dav_node *node, uid_t uid, int sm, mode_t mode, int so,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
dav_stat
|
dav_stat *
|
||||||
dav_statfs(void)
|
dav_statfs(void)
|
||||||
{
|
{
|
||||||
dav_stat st;
|
if (time(NULL) > (fs_stat->utime + dir_refresh)) {
|
||||||
st.blocks = 0x65B9AA;
|
off64_t total = 0;
|
||||||
st.bfree = 0x32DCD5;
|
off64_t used = 0;
|
||||||
st.bavail = 0x32DCD5;
|
if (dav_quota(root->path, &total, &used) == 0) {
|
||||||
st.files = nnodes;
|
fs_stat->blocks = total / fs_stat->bsize;
|
||||||
st.ffree = 666666;
|
fs_stat->bfree = fs_stat->blocks - (used / fs_stat->bsize) - 1;
|
||||||
struct stat cache_st;
|
fs_stat->bavail = fs_stat->bfree;
|
||||||
if (stat(cache_dir, &cache_st) == 0) {
|
fs_stat->ffree = fs_stat->bfree;
|
||||||
st.bsize = cache_st.st_blksize;
|
fs_stat->utime = time(NULL);
|
||||||
} else {
|
}
|
||||||
st.bsize = 4096;
|
|
||||||
}
|
|
||||||
st.namelen = 256;
|
|
||||||
|
|
||||||
off_t used = 0;
|
|
||||||
if (dav_quota(root->path, &st.blocks, &used) == 0) {
|
|
||||||
st.blocks /= st.bsize;
|
|
||||||
st.bfree = st.blocks - (used / st.bsize) - 1;
|
|
||||||
st.bavail = st.bfree;
|
|
||||||
st.ffree = st.bfree;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return st;
|
return fs_stat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1538,6 +1552,8 @@ dav_write(size_t *written, dav_node * node, int fd, char *buf, size_t size,
|
|||||||
{
|
{
|
||||||
if (!exists(node))
|
if (!exists(node))
|
||||||
return ENOENT;
|
return ENOENT;
|
||||||
|
if (is_dir(node))
|
||||||
|
return EBADF;
|
||||||
|
|
||||||
dav_handle *fh = get_file_handle(node, fd, 0, 0, 0);
|
dav_handle *fh = get_file_handle(node, fd, 0, 0, 0);
|
||||||
if (!fh)
|
if (!fh)
|
||||||
@ -1770,7 +1786,7 @@ delete_node(dav_node *node)
|
|||||||
free(tofree);
|
free(tofree);
|
||||||
}
|
}
|
||||||
free(node);
|
free(node);
|
||||||
nnodes--;
|
fs_stat->files--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2016,7 +2032,7 @@ new_node(dav_node *parent, mode_t mode)
|
|||||||
if (debug)
|
if (debug)
|
||||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "new node: %p->%p",
|
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "new node: %p->%p",
|
||||||
node->parent, node);
|
node->parent, node);
|
||||||
nnodes++;
|
fs_stat->files++;
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2824,8 +2840,10 @@ parse_index(void)
|
|||||||
{
|
{
|
||||||
char *index = ne_concat(cache_dir, "/", DAV_INDEX, NULL);
|
char *index = ne_concat(cache_dir, "/", DAV_INDEX, NULL);
|
||||||
FILE *idx = fopen(index, "r");
|
FILE *idx = fopen(index, "r");
|
||||||
if (!idx)
|
if (!idx) {
|
||||||
|
free(index);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
char *buf = ne_malloc(DAV_XML_BUF_SIZE);
|
char *buf = ne_malloc(DAV_XML_BUF_SIZE);
|
||||||
size_t len = fread(buf, 1, DAV_XML_BUF_SIZE, idx);
|
size_t len = fread(buf, 1, DAV_XML_BUF_SIZE, idx);
|
||||||
|
26
src/cache.h
26
src/cache.h
@ -147,13 +147,17 @@ struct dav_node_item {
|
|||||||
/* Returned by dav_statfs(). */
|
/* Returned by dav_statfs(). */
|
||||||
typedef struct dav_stat dav_stat;
|
typedef struct dav_stat dav_stat;
|
||||||
struct dav_stat {
|
struct dav_stat {
|
||||||
off_t blocks;
|
off64_t blocks;
|
||||||
off_t bfree;
|
off64_t bfree;
|
||||||
off_t bavail;
|
off64_t bavail;
|
||||||
off_t files;
|
off64_t files;
|
||||||
off_t ffree;
|
off64_t ffree;
|
||||||
off_t bsize;
|
off_t bsize;
|
||||||
off_t namelen;
|
off_t namelen;
|
||||||
|
time_t utime; /* Time when last updated with data from the server.
|
||||||
|
must When 0 this structure contains fake data,
|
||||||
|
that not be changed when a file is changed or
|
||||||
|
deleted. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -409,9 +413,12 @@ dav_setattr(dav_node *node, uid_t uid, int sm, mode_t mode, int so,
|
|||||||
uid_t owner, int sg, gid_t gid, int sat, time_t atime, int smt,
|
uid_t owner, int sg, gid_t gid, int sat, time_t atime, int smt,
|
||||||
time_t mtime, int ssz, off_t size);
|
time_t mtime, int ssz, off_t size);
|
||||||
|
|
||||||
/* Returns struct dav_stat which currently is mainly fake.
|
|
||||||
|
/* Returns struct dav_stat. If the server does not provide theinformation
|
||||||
|
it will contain fake data.
|
||||||
No permissions necessary. */
|
No permissions necessary. */
|
||||||
dav_stat dav_statfs(void);
|
dav_stat *
|
||||||
|
dav_statfs(void);
|
||||||
|
|
||||||
|
|
||||||
/* Calls fsync() for all filedescriptors of node, that are not read only.
|
/* Calls fsync() for all filedescriptors of node, that are not read only.
|
||||||
@ -424,7 +431,6 @@ dav_sync(dav_node *node);
|
|||||||
offset.
|
offset.
|
||||||
The number of bytes written is returned in len.
|
The number of bytes written is returned in len.
|
||||||
The file must be opened writeonly or readwrite. */
|
The file must be opened writeonly or readwrite. */
|
||||||
/* TODO: Remove pid; check flags. */
|
|
||||||
int
|
int
|
||||||
dav_write(size_t *written, dav_node * node, int fd, char *buf, size_t size,
|
dav_write(size_t *written, dav_node * node, int fd, char *buf, size_t size,
|
||||||
off_t offset);
|
off_t offset);
|
||||||
|
@ -684,13 +684,17 @@ coda_statfs(void)
|
|||||||
if (debug)
|
if (debug)
|
||||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "CODA_STATFS:");
|
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "CODA_STATFS:");
|
||||||
|
|
||||||
dav_stat st = dav_statfs();
|
dav_stat *st = dav_statfs();
|
||||||
|
if (!st) {
|
||||||
|
oh->result = EIO;
|
||||||
|
return sizeof(struct coda_out_hdr);
|
||||||
|
}
|
||||||
|
|
||||||
out->stat.f_blocks = st.blocks;
|
out->stat.f_blocks = st->blocks;
|
||||||
out->stat.f_bfree = st.bfree;
|
out->stat.f_bfree = st->bfree;
|
||||||
out->stat.f_bavail = st.bavail;
|
out->stat.f_bavail = st->bavail;
|
||||||
out->stat.f_files = st.files;
|
out->stat.f_files = st->files;
|
||||||
out->stat.f_ffree = st.ffree;
|
out->stat.f_ffree = st->ffree;
|
||||||
|
|
||||||
oh->result = 0;
|
oh->result = 0;
|
||||||
return sizeof(struct coda_statfs_out);
|
return sizeof(struct coda_statfs_out);
|
||||||
|
@ -972,16 +972,20 @@ fuse_stat(void)
|
|||||||
if (debug)
|
if (debug)
|
||||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "FUSE_STATFS:");
|
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "FUSE_STATFS:");
|
||||||
|
|
||||||
dav_stat st = dav_statfs();
|
dav_stat *st = dav_statfs();
|
||||||
|
if (!st) {
|
||||||
|
oh->error = -EIO;
|
||||||
|
return sizeof(struct fuse_out_header);
|
||||||
|
}
|
||||||
|
|
||||||
out->st.blocks = st.blocks;
|
out->st.blocks = st->blocks;
|
||||||
out->st.bfree = st.bfree;
|
out->st.bfree = st->bfree;
|
||||||
out->st.bavail = st.bavail;
|
out->st.bavail = st->bavail;
|
||||||
out->st.files = st.files;
|
out->st.files = st->files;
|
||||||
out->st.ffree = st.ffree;
|
out->st.ffree = st->ffree;
|
||||||
out->st.bsize = (buf_size - sizeof(struct fuse_in_header)
|
out->st.bsize = (buf_size - sizeof(struct fuse_in_header)
|
||||||
- sizeof(struct fuse_write_in) - 4095) & ~4095;
|
- sizeof(struct fuse_write_in) - 4095) & ~4095;
|
||||||
out->st.namelen = st.namelen;
|
out->st.namelen = st->namelen;
|
||||||
out->st.frsize = 0;
|
out->st.frsize = 0;
|
||||||
out->st.padding = 0;
|
out->st.padding = 0;
|
||||||
int i;
|
int i;
|
||||||
|
@ -654,8 +654,8 @@ check_double_mounts(dav_args *args)
|
|||||||
m = strchr(mp, '/');
|
m = strchr(mp, '/');
|
||||||
}
|
}
|
||||||
char *pidf = NULL;
|
char *pidf = NULL;
|
||||||
if (asprintf(&pidf, "%s/%s.pid", DAV_SYS_RUN, mp) < 0)
|
if (asprintf(&pidf, "%s/%s.pid", DAV_SYS_RUN, mp) < 0) abort();
|
||||||
abort();
|
free(mp);
|
||||||
if (args->debug & DAV_DBG_CONFIG)
|
if (args->debug & DAV_DBG_CONFIG)
|
||||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "PID file: %s", pidf);
|
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "PID file: %s", pidf);
|
||||||
|
|
||||||
|
122
src/webdav.c
122
src/webdav.c
@ -90,8 +90,9 @@ typedef struct {
|
|||||||
} get_context;
|
} get_context;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
off_t available; /* Available bytes. */
|
int error;
|
||||||
off_t used; /* Used bytes. */
|
off64_t total; /* Total amount of available bytes. */
|
||||||
|
off64_t used; /* Used bytes. */
|
||||||
} quota_context;
|
} quota_context;
|
||||||
|
|
||||||
|
|
||||||
@ -203,6 +204,9 @@ static iconv_t to_server_enc;
|
|||||||
/* A GNU custom stream, used to redirect neon debug messages to syslog. */
|
/* A GNU custom stream, used to redirect neon debug messages to syslog. */
|
||||||
static FILE *log_stream;
|
static FILE *log_stream;
|
||||||
|
|
||||||
|
/* A user defined header that is added to all requests. */
|
||||||
|
char *custom_header;
|
||||||
|
|
||||||
#if NE_VERSION_MINOR > 25
|
#if NE_VERSION_MINOR > 25
|
||||||
/* Session cookie. */
|
/* Session cookie. */
|
||||||
static char *cookie;
|
static char *cookie;
|
||||||
@ -248,7 +252,7 @@ static int
|
|||||||
auth(void *userdata, const char *realm, int attempt, char *user, char *pwd);
|
auth(void *userdata, const char *realm, int attempt, char *user, char *pwd);
|
||||||
|
|
||||||
static int
|
static int
|
||||||
block_writer(void *userdata, const char *block, size_t length);
|
file_reader(void *userdata, const char *block, size_t length);
|
||||||
|
|
||||||
#if NE_VERSION_MINOR < 26
|
#if NE_VERSION_MINOR < 26
|
||||||
|
|
||||||
@ -276,6 +280,9 @@ quota_result(void *userdata, const ne_uri *uri, const ne_prop_result_set *set);
|
|||||||
|
|
||||||
#endif /* NE_VERSION_MINOR >= 26 */
|
#endif /* NE_VERSION_MINOR >= 26 */
|
||||||
|
|
||||||
|
static int
|
||||||
|
quota_reader(void *userdata, const char *block, size_t length);
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ssl_verify(void *userdata, int failures, const ne_ssl_certificate *cert);
|
ssl_verify(void *userdata, int failures, const ne_ssl_certificate *cert);
|
||||||
|
|
||||||
@ -429,7 +436,7 @@ dav_init_webdav(const dav_args *args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (args->header) {
|
if (args->header) {
|
||||||
char *custom_header = ne_strdup(args->header);
|
custom_header = ne_strdup(args->header);
|
||||||
ne_hook_pre_send(session, add_header, custom_header);
|
ne_hook_pre_send(session, add_header, custom_header);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -674,7 +681,7 @@ dav_get_file(const char *path, const char *cache_path, off_t *size,
|
|||||||
ne_add_request_header(req, "If-Modified-Since", mod_time);
|
ne_add_request_header(req, "If-Modified-Since", mod_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
ne_add_response_body_reader(req, ne_accept_2xx, block_writer, &ctx);
|
ne_add_response_body_reader(req, ne_accept_2xx, file_reader, &ctx);
|
||||||
|
|
||||||
ret = ne_request_dispatch(req);
|
ret = ne_request_dispatch(req);
|
||||||
ret = get_error(ret, "GET");
|
ret = get_error(ret, "GET");
|
||||||
@ -1063,7 +1070,7 @@ dav_put(const char *path, const char *cache_path, int *exists, time_t *expire,
|
|||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
dav_quota(const char *path, off_t *available, off_t *used)
|
dav_quota(const char *path, off64_t *total, off64_t *used)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
@ -1071,26 +1078,52 @@ dav_quota(const char *path, off_t *available, off_t *used)
|
|||||||
if (ret) return ret;
|
if (ret) return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int use_rfc = 1;
|
||||||
|
static int use_userinfo = 1;
|
||||||
|
|
||||||
quota_context ctx;
|
quota_context ctx;
|
||||||
ctx.available = (off_t) -1;
|
ctx.error = 0;
|
||||||
ctx.used = (off_t) -1;
|
ctx.total = 0;
|
||||||
|
ctx.used = 0;
|
||||||
|
ret = EIO;
|
||||||
char *spath = ne_path_escape(path);
|
char *spath = ne_path_escape(path);
|
||||||
ne_propfind_handler *ph = ne_propfind_create(session, spath, NE_DEPTH_ZERO);
|
|
||||||
ret = ne_propfind_named(ph, quota_names, quota_result, &ctx);
|
|
||||||
ret = get_error(ret, "PROPFIND");
|
|
||||||
ne_propfind_destroy(ph);
|
|
||||||
free(spath);
|
|
||||||
|
|
||||||
if (!ret) {
|
if (use_rfc) {
|
||||||
if (ctx.available == (off_t) -1 || ctx.used == (off_t) -1) {
|
ne_propfind_handler *ph = ne_propfind_create(session, spath,
|
||||||
|
NE_DEPTH_ZERO);
|
||||||
|
ret = ne_propfind_named(ph, quota_names, quota_result, &ctx);
|
||||||
|
ret = get_error(ret, "PROPFIND");
|
||||||
|
ne_propfind_destroy(ph);
|
||||||
|
|
||||||
|
if (!ret && ctx.error) {
|
||||||
ret = EIO;
|
ret = EIO;
|
||||||
} else {
|
if (ctx.error == 2)
|
||||||
*available = ctx.available;
|
use_rfc = 0;
|
||||||
*used = ctx.used;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ret && use_userinfo) {
|
||||||
|
ctx.error = 0;
|
||||||
|
ne_request *req = ne_request_create(session, "USERINFO", spath);
|
||||||
|
ne_add_response_body_reader(req, ne_accept_2xx, quota_reader, &ctx);
|
||||||
|
ret = ne_request_dispatch(req);
|
||||||
|
ret = get_error(ret, "USERINFO");
|
||||||
|
ne_request_destroy(req);
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
if (ctx.error)
|
||||||
|
ret = EIO;
|
||||||
|
} else if (ret == EINVAL) {
|
||||||
|
use_userinfo = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
*total = ctx.total;
|
||||||
|
*used = ctx.used;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(spath);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1519,7 +1552,7 @@ auth(void *userdata, const char *realm, int attempt, char *user, char *pwd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Writes data from block to a local file.
|
/* Reads HTTP-data from blockand writes them to a local file.
|
||||||
userdata must be a get_context structure that holds at least the name of
|
userdata must be a get_context structure that holds at least the name of
|
||||||
the local file. If it does not contain a file descriptor, the file is
|
the local file. If it does not contain a file descriptor, the file is
|
||||||
opened for writing and the file descriptor is stored in the get_context
|
opened for writing and the file descriptor is stored in the get_context
|
||||||
@ -1530,7 +1563,7 @@ auth(void *userdata, const char *realm, int attempt, char *user, char *pwd)
|
|||||||
length : Number of bytes in the buffer.
|
length : Number of bytes in the buffer.
|
||||||
return value : 0 on success, EIO otherwise. */
|
return value : 0 on success, EIO otherwise. */
|
||||||
static int
|
static int
|
||||||
block_writer(void *userdata, const char *block, size_t length)
|
file_reader(void *userdata, const char *block, size_t length)
|
||||||
{
|
{
|
||||||
get_context *ctx = (get_context *) userdata;
|
get_context *ctx = (get_context *) userdata;
|
||||||
if (!ctx->fd)
|
if (!ctx->fd)
|
||||||
@ -1733,6 +1766,36 @@ prop_result(void *userdata, const ne_uri *uri, const ne_prop_result_set *set)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
quota_reader(void *userdata, const char *block, size_t length)
|
||||||
|
{
|
||||||
|
if (length < 1) return 0;
|
||||||
|
quota_context *ctx = (quota_context *) userdata;
|
||||||
|
|
||||||
|
char *quota = strndup(block, length);
|
||||||
|
if (!quota) {
|
||||||
|
ctx->error = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *number = strtok(quota, ",");
|
||||||
|
if (number) {
|
||||||
|
ctx->total = strtoull(number, NULL, 10);
|
||||||
|
} else {
|
||||||
|
ctx->error = 1;
|
||||||
|
free(quota);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
number = strtok(NULL, ",");
|
||||||
|
if (number)
|
||||||
|
ctx->used = strtoull(number, NULL, 10);
|
||||||
|
|
||||||
|
free(quota);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Reads available and used bytes from set and stores them in
|
/* Reads available and used bytes from set and stores them in
|
||||||
userdata. */
|
userdata. */
|
||||||
#if NE_VERSION_MINOR < 26
|
#if NE_VERSION_MINOR < 26
|
||||||
@ -1756,12 +1819,23 @@ quota_result(void *userdata, const ne_uri *uri, const ne_prop_result_set *set)
|
|||||||
#endif /* NE_VERSION_MINOR >= 26 */
|
#endif /* NE_VERSION_MINOR >= 26 */
|
||||||
|
|
||||||
const char *data = ne_propset_value(set, "a_names[AVAILABLE]);
|
const char *data = ne_propset_value(set, "a_names[AVAILABLE]);
|
||||||
if (data)
|
if (data) {
|
||||||
ctx->available = strtol(data, NULL, 10);
|
ctx->total = strtoull(data, NULL, 10);
|
||||||
|
} else {
|
||||||
|
const ne_status *st = ne_propset_status(set, "a_names[AVAILABLE]);
|
||||||
|
if (st && st->klass == 4) {
|
||||||
|
ctx->error = 2;
|
||||||
|
} else {
|
||||||
|
ctx->error = 1;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
data = ne_propset_value(set, "a_names[USED]);
|
data = ne_propset_value(set, "a_names[USED]);
|
||||||
if (data)
|
if (data)
|
||||||
ctx->used = strtol(data, NULL, 10);
|
ctx->used = strtoull(data, NULL, 10);
|
||||||
|
|
||||||
|
ctx->total += ctx->used;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -247,10 +247,12 @@ dav_put(const char *path, const char *cache_path, int *exists, time_t *expire,
|
|||||||
char **etag, time_t *mtime, char **mime, int execute);
|
char **etag, time_t *mtime, char **mime, int execute);
|
||||||
|
|
||||||
/* Makes a PROPFIND request for path to get quota information (RFC 4331)
|
/* Makes a PROPFIND request for path to get quota information (RFC 4331)
|
||||||
and places them in available and used. If quota information is not
|
and places them in total and used.
|
||||||
|
toatal is the sum of quota-available-bytes and quota-used-bytes.
|
||||||
|
If quota information is not
|
||||||
available, an error is returned and available and used are not changed. */
|
available, an error is returned and available and used are not changed. */
|
||||||
int
|
int
|
||||||
dav_quota(const char *path, off_t *available, off_t *used);
|
dav_quota(const char *path, off_t *total, off_t *used);
|
||||||
|
|
||||||
|
|
||||||
/* Sets or resets the execute property of file path.
|
/* Sets or resets the execute property of file path.
|
||||||
|
Loading…
Reference in New Issue
Block a user