mirror of
https://github.com/openharmony/third_party_libfuse.git
synced 2026-07-18 10:34:54 -04:00
fix
This commit is contained in:
@@ -1,3 +1,9 @@
|
||||
2006-02-17 Miklos Szeredi <miklos@szeredi.hu>
|
||||
|
||||
* Lowlevel lib: Unify fuse_dirent_size() and fuse_add_dirent()
|
||||
into a single function fuse_add_direntry(). This cleans up the
|
||||
interface and makes it possible to do stacking.
|
||||
|
||||
2006-02-16 Miklos Szeredi <miklos@szeredi.hu>
|
||||
|
||||
* Fix rare race betweeen abort and release caused by failed iget()
|
||||
|
||||
+8
-6
@@ -75,15 +75,17 @@ struct dirbuf {
|
||||
size_t size;
|
||||
};
|
||||
|
||||
static void dirbuf_add(struct dirbuf *b, const char *name, fuse_ino_t ino)
|
||||
static void dirbuf_add(fuse_req_t req, struct dirbuf *b, const char *name,
|
||||
fuse_ino_t ino)
|
||||
{
|
||||
struct stat stbuf;
|
||||
size_t oldsize = b->size;
|
||||
b->size += fuse_dirent_size(strlen(name));
|
||||
b->size += fuse_add_direntry(req, NULL, 0, name, NULL, 0);
|
||||
b->p = (char *) realloc(b->p, b->size);
|
||||
memset(&stbuf, 0, sizeof(stbuf));
|
||||
stbuf.st_ino = ino;
|
||||
fuse_add_dirent(b->p + oldsize, name, &stbuf, b->size);
|
||||
fuse_add_direntry(req, b->p + oldsize, b->size - oldsize, name, &stbuf,
|
||||
b->size);
|
||||
}
|
||||
|
||||
#define min(x, y) ((x) < (y) ? (x) : (y))
|
||||
@@ -108,9 +110,9 @@ static void hello_ll_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
|
||||
struct dirbuf b;
|
||||
|
||||
memset(&b, 0, sizeof(b));
|
||||
dirbuf_add(&b, ".", 1);
|
||||
dirbuf_add(&b, "..", 1);
|
||||
dirbuf_add(&b, hello_name, 2);
|
||||
dirbuf_add(req, &b, ".", 1);
|
||||
dirbuf_add(req, &b, "..", 1);
|
||||
dirbuf_add(req, &b, hello_name, 2);
|
||||
reply_buf_limited(req, b.p, b.size, off, size);
|
||||
free(b.p);
|
||||
}
|
||||
|
||||
+12
-13
@@ -525,7 +525,7 @@ struct fuse_lowlevel_ops {
|
||||
/**
|
||||
* Read directory
|
||||
*
|
||||
* Send a buffer filled using fuse_add_dirent(), with size not
|
||||
* Send a buffer filled using fuse_add_direntry(), with size not
|
||||
* exceeding the requested size. Send an empty buffer on end of
|
||||
* stream.
|
||||
*
|
||||
@@ -872,18 +872,14 @@ int fuse_reply_xattr(fuse_req_t req, size_t count);
|
||||
* Filling a buffer in readdir *
|
||||
* ----------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Calculate the number of bytes a directory entry takes up
|
||||
*
|
||||
* @param namelen the length of the entry name
|
||||
* @return the number of bytes needed
|
||||
*/
|
||||
size_t fuse_dirent_size(size_t namelen);
|
||||
|
||||
/**
|
||||
* Add a directory entry to the buffer
|
||||
*
|
||||
* Buffer needs to be large enough to hold the entry
|
||||
* Buffer needs to be large enough to hold the entry. Of it's not,
|
||||
* then the entry is not filled in but the size of the entry is still
|
||||
* returned. The caller can check this by comparing the bufsize
|
||||
* parameter with the returned entry size. If the entry size is
|
||||
* larger than the buffer size, the operation failed.
|
||||
*
|
||||
* From the 'stbuf' argument the st_ino field and bits 12-15 of the
|
||||
* st_mode field are used. The other fields are ignored.
|
||||
@@ -892,14 +888,17 @@ size_t fuse_dirent_size(size_t namelen);
|
||||
* could be any marker, that enables the implementation to find a
|
||||
* specific point in the directory stream.
|
||||
*
|
||||
* @param req request handle
|
||||
* @param buf the point where the new entry will be added to the buffer
|
||||
* @param bufsize remaining size of the buffer
|
||||
* @param the name of the entry
|
||||
* @param stbuf the file attributes
|
||||
* @param off the offset of the next entry
|
||||
* @return a pointer to the start of the next entry in the buffer
|
||||
* @return the space needed for the entry
|
||||
*/
|
||||
char *fuse_add_dirent(char *buf, const char *name, const struct stat *stbuf,
|
||||
off_t off);
|
||||
size_t fuse_add_direntry(fuse_req_t req, char *buf, size_t bufsize,
|
||||
const char *name, const struct stat *stbuf,
|
||||
off_t off);
|
||||
|
||||
/* ----------------------------------------------------------- *
|
||||
* Utility functions *
|
||||
|
||||
@@ -62,6 +62,11 @@ struct fuse_session *fuse_lowlevel_new_compat25(struct fuse_args *args,
|
||||
const struct fuse_lowlevel_ops_compat25 *op,
|
||||
size_t op_size, void *userdata);
|
||||
|
||||
size_t fuse_dirent_size(size_t namelen);
|
||||
|
||||
char *fuse_add_dirent(char *buf, const char *name, const struct stat *stbuf,
|
||||
off_t off);
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
|
||||
#include <sys/statfs.h>
|
||||
|
||||
+40
-25
@@ -90,6 +90,7 @@ struct node {
|
||||
struct fuse_dirhandle {
|
||||
pthread_mutex_t lock;
|
||||
struct fuse *fuse;
|
||||
fuse_req_t req;
|
||||
char *contents;
|
||||
int allocated;
|
||||
unsigned len;
|
||||
@@ -1446,13 +1447,32 @@ static void fuse_opendir(fuse_req_t req, fuse_ino_t ino,
|
||||
fuse_reply_open(req, llfi);
|
||||
}
|
||||
|
||||
static int extend_contents(struct fuse_dirhandle *dh, unsigned minsize)
|
||||
{
|
||||
if (minsize > dh->size) {
|
||||
char *newptr;
|
||||
unsigned newsize = dh->size;
|
||||
if (!newsize)
|
||||
newsize = 1024;
|
||||
while (newsize < minsize)
|
||||
newsize *= 2;
|
||||
|
||||
newptr = (char *) realloc(dh->contents, newsize);
|
||||
if (!newptr) {
|
||||
dh->error = -ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
dh->contents = newptr;
|
||||
dh->size = newsize;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fill_dir_common(struct fuse_dirhandle *dh, const char *name,
|
||||
const struct stat *statp, off_t off)
|
||||
{
|
||||
struct stat stbuf;
|
||||
unsigned namelen = strlen(name);
|
||||
unsigned entsize;
|
||||
unsigned newlen;
|
||||
size_t newlen;
|
||||
|
||||
if (statp)
|
||||
stbuf = *statp;
|
||||
@@ -1473,31 +1493,24 @@ static int fill_dir_common(struct fuse_dirhandle *dh, const char *name,
|
||||
}
|
||||
}
|
||||
|
||||
entsize = fuse_dirent_size(namelen);
|
||||
newlen = dh->len + entsize;
|
||||
|
||||
if (off) {
|
||||
if (extend_contents(dh, dh->needlen) == -1)
|
||||
return 1;
|
||||
|
||||
dh->filled = 0;
|
||||
newlen = dh->len + fuse_add_direntry(dh->req, dh->contents + dh->len,
|
||||
dh->needlen - dh->len, name,
|
||||
&stbuf, off);
|
||||
if (newlen > dh->needlen)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (newlen > dh->size) {
|
||||
char *newptr;
|
||||
|
||||
if (!dh->size)
|
||||
dh->size = 1024;
|
||||
while (newlen > dh->size)
|
||||
dh->size *= 2;
|
||||
|
||||
newptr = (char *) realloc(dh->contents, dh->size);
|
||||
if (!newptr) {
|
||||
dh->error = -ENOMEM;
|
||||
} else {
|
||||
newlen = dh->len + fuse_add_direntry(dh->req, NULL, 0, name, NULL, 0);
|
||||
if (extend_contents(dh, newlen) == -1)
|
||||
return 1;
|
||||
}
|
||||
dh->contents = newptr;
|
||||
|
||||
fuse_add_direntry(dh->req, dh->contents + dh->len, dh->size - dh->len,
|
||||
name, &stbuf, newlen);
|
||||
}
|
||||
fuse_add_dirent(dh->contents + dh->len, name, &stbuf, off ? off : newlen);
|
||||
dh->len = newlen;
|
||||
return 0;
|
||||
}
|
||||
@@ -1521,8 +1534,8 @@ static int fill_dir_old(struct fuse_dirhandle *dh, const char *name, int type,
|
||||
return dh->error;
|
||||
}
|
||||
|
||||
static int readdir_fill(struct fuse *f, fuse_ino_t ino, size_t size,
|
||||
off_t off, struct fuse_dirhandle *dh,
|
||||
static int readdir_fill(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
|
||||
size_t size, off_t off, struct fuse_dirhandle *dh,
|
||||
struct fuse_file_info *fi)
|
||||
{
|
||||
int err = -ENOENT;
|
||||
@@ -1534,11 +1547,13 @@ static int readdir_fill(struct fuse *f, fuse_ino_t ino, size_t size,
|
||||
dh->error = 0;
|
||||
dh->needlen = size;
|
||||
dh->filled = 1;
|
||||
dh->req = req;
|
||||
err = -ENOSYS;
|
||||
if (f->op.readdir)
|
||||
err = f->op.readdir(path, dh, fill_dir, off, fi);
|
||||
else if (f->op.getdir)
|
||||
err = f->op.getdir(path, dh, fill_dir_old);
|
||||
dh->req = NULL;
|
||||
if (!err)
|
||||
err = dh->error;
|
||||
if (err)
|
||||
@@ -1563,7 +1578,7 @@ static void fuse_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
|
||||
dh->filled = 0;
|
||||
|
||||
if (!dh->filled) {
|
||||
int err = readdir_fill(f, ino, size, off, dh, &fi);
|
||||
int err = readdir_fill(f, req, ino, size, off, dh, &fi);
|
||||
if (err) {
|
||||
reply_err(req, err);
|
||||
goto out;
|
||||
|
||||
+14
-3
@@ -186,6 +186,18 @@ char *fuse_add_dirent(char *buf, const char *name, const struct stat *stbuf,
|
||||
return buf + entsize;
|
||||
}
|
||||
|
||||
size_t fuse_add_direntry(fuse_req_t req, char *buf, size_t bufsize,
|
||||
const char *name, const struct stat *stbuf, off_t off)
|
||||
{
|
||||
size_t entsize;
|
||||
|
||||
(void) req;
|
||||
entsize = fuse_dirent_size(strlen(name));
|
||||
if (entsize <= bufsize && buf)
|
||||
fuse_add_dirent(buf, name, stbuf, off);
|
||||
return entsize;
|
||||
}
|
||||
|
||||
static void convert_statfs(const struct statvfs *stbuf,
|
||||
struct fuse_kstatfs *kstatfs)
|
||||
{
|
||||
@@ -526,8 +538,7 @@ static void do_write(fuse_req_t req, fuse_ino_t nodeid,
|
||||
fi.writepage = arg->write_flags & 1;
|
||||
|
||||
if (req->f->op.write)
|
||||
req->f->op.write(req, nodeid, PARAM(arg), arg->size,
|
||||
arg->offset, &fi);
|
||||
req->f->op.write(req, nodeid, PARAM(arg), arg->size, arg->offset, &fi);
|
||||
else
|
||||
fuse_reply_err(req, ENOSYS);
|
||||
}
|
||||
@@ -654,7 +665,7 @@ static void do_setxattr(fuse_req_t req, fuse_ino_t nodeid,
|
||||
|
||||
if (req->f->op.setxattr)
|
||||
req->f->op.setxattr(req, nodeid, name, value, arg->size,
|
||||
arg->flags);
|
||||
arg->flags);
|
||||
else
|
||||
fuse_reply_err(req, ENOSYS);
|
||||
}
|
||||
|
||||
@@ -85,6 +85,7 @@ FUSE_2.5 {
|
||||
|
||||
FUSE_2.6 {
|
||||
global:
|
||||
fuse_add_direntry;
|
||||
fuse_lowlevel_new;
|
||||
fuse_lowlevel_new_compat25;
|
||||
fuse_main_real;
|
||||
@@ -94,4 +95,7 @@ FUSE_2.6 {
|
||||
fuse_opt_insert_arg;
|
||||
fuse_setup;
|
||||
fuse_setup_compat25;
|
||||
|
||||
local:
|
||||
*;
|
||||
} FUSE_2.5;
|
||||
|
||||
Reference in New Issue
Block a user