From fec2a7854e5f29f95e9ba093f671ab9d744ffd67 Mon Sep 17 00:00:00 2001 From: ketmar Date: Sat, 27 Jul 2013 11:33:45 +0000 Subject: [PATCH] added /:/info pseudofile (just a sample) FossilOrigin-Name: fffd7f331a9d3b57e0b9513628cc33dd39a148ec7e8db2ce50a87667acca9568 --- src/fusedrv/fusedrv.c | 117 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 93 insertions(+), 24 deletions(-) diff --git a/src/fusedrv/fusedrv.c b/src/fusedrv/fusedrv.c index 0b6f02f..2cc00d2 100644 --- a/src/fusedrv/fusedrv.c +++ b/src/fusedrv/fusedrv.c @@ -70,6 +70,77 @@ static file_info_t *find_by_short_name (const char *path) { } +//////////////////////////////////////////////////////////////////////////////// +typedef struct { + int fd; // <0: internal file + int size; + char *data; + //UT_hash_handle hh; +} filehandle_t; + + +//static filehandle_t *fhandles = NULL; + + +static filehandle_t *colon_create_info_file (const char *path) { + filehandle_t *fh = NULL; + dlogf("colon_create_info_file: [%s]\n", path); + if (strcmp(path, "/:/info") == 0) { + fh = calloc(1, sizeof(*fh)); + fh->fd = -1; + fh->data = calloc(8192, 1); + snprintf(fh->data, 8192, "files: %d; otags: %d; ntags: %d\n", HASH_COUNT(file_name_hash), HASH_COUNT(tagv_hash_o), HASH_COUNT(tagv_hash_t)); + fh->size = strlen(fh->data); + } + return fh; +} + + +static filehandle_t *fht_open (const char *realpath) { + int fd = open(realpath, O_RDONLY); + if (fd >= 0) { + filehandle_t *fh = calloc(1, sizeof(*fh)); + fh->fd = fd; + return fh; + } + return NULL; +} + + +static void fht_close (filehandle_t *fh) { + if (fh != NULL) { + if (fh->fd >= 0) close(fh->fd); + if (fh->data != NULL) free(fh->data); + free(fh); + } +} + + +static int fht_read (const char *path, char *buf, size_t size, off_t offset, filehandle_t *fh) { + if (fh != NULL) { + if (fh->fd >= 0) { + ssize_t rd; + //dlogf("tfs_read: path=[%s], buf=0x%p, size=%d, offset=%lld, fi=0x%p", path, buf, size, offset, fi); + if (fh->fd < 0) return -EPERM; + if (offset >= 0x7fffffff || size >= 0x7fffffff) return 0;/*-EPERM;*/ //??? + if (lseek(fh->fd, offset, SEEK_SET) == (off_t)-1) return -EPERM; + rd = read(fh->fd, buf, size); + if (rd < 0) return -EPERM; + return rd; + } + if (fh->data != NULL) { + if (offset >= fh->size) return 0; + if ((uint64_t)offset+size > fh->size) size = fh->size-offset; + if (size == 0) return 0; + memcpy(buf, fh->data+offset, size); + return size; + } + } + return -EPERM; +} + + +//////////////////////////////////////////////////////////////////////////////// // this is used in getattr() and readdir() // note that readdir() will call this with 'filename.ext' and getattr() will call this with full path static int do_stat (const char *path, struct stat *statbuf, int do_real_stat) { @@ -85,7 +156,13 @@ static int do_stat (const char *path, struct stat *statbuf, int do_real_stat) { //TODO: set to 2? do we rally want 'find' to work on muffin? statbuf->st_nlink = 1; // actually, this should be set to 'subdir_count+2' (or 1), else 'find' will fail // - if (strcmp(path, "/") == 0 || strcmp(path, "/:otags") == 0) return 0; + if (strcmp(path, "/") == 0 || strcmp(path, "/:otags") == 0 || strcmp(path, "/:") == 0) return 0; + if (strncmp(path, "/:/", 3) == 0) { + // all files are regular ones here + statbuf->st_mode = S_IFREG|0444; + statbuf->st_size = 4096; // arbitrary, but must be bigger than the actual 'info' files + return 0; + } // name = strrchr(path, '/'); if (name == NULL) name = path; else ++name; @@ -260,8 +337,8 @@ static int tfs_utime (const char *path, struct utimbuf *ubuf) { * Changed in version 2.2 */ static int tfs_open (const char *path, struct fuse_file_info *fi) { - int fd; file_info_t *nfo; + filehandle_t *fh = NULL; //dlogf("tfs_open: path=[%s], fi=0x%p; append=%d; trunc=%d\n", path, fi, (fi->flags&O_APPEND ? 1 : 0), (fi->flags&O_TRUNC ? 1 : 0)); if ((fi->flags&O_APPEND) || (fi->flags&O_TRUNC)) { //dlogf(" bad flags!\n"); @@ -275,15 +352,18 @@ static int tfs_open (const char *path, struct fuse_file_info *fi) { return -EPERM; } // - if ((nfo = find_by_short_name(path)) != NULL) { - //dlogf(" found: [%s]\n", nfo->fullname); - fd = open(nfo->fullname, O_RDONLY); - if (fd >= 0) { - //dlogf(" found: [%s]; fd=%d\n", nfo->fullname, fd); - fi->fh = fd; - return 0; + if (strncmp(path, "/:/", 3) == 0) { + fh = colon_create_info_file(path); + } else { + if ((nfo = find_by_short_name(path)) != NULL) { + //dlogf(" found: [%s]\n", nfo->fullname); + fh = fht_open(nfo->fullname); } } + if (fh != NULL) { + fi->fh = (uintptr_t)fh; + return 0; + } //dlogf(" shit!\n"); return -ENOENT; } @@ -301,16 +381,8 @@ static int tfs_open (const char *path, struct fuse_file_info *fi) { * Changed in version 2.2 */ static int tfs_read (const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { - int fd; - ssize_t rd; - //dlogf("tfs_read: path=[%s], buf=0x%p, size=%d, offset=%lld, fi=0x%p", path, buf, size, offset, fi); - fd = fi->fh; - if (fd < 0) return -EPERM; - if (offset >= 0x7fffffff || size >= 0x7fffffff) return -EPERM; - if (lseek(fd, offset, SEEK_SET) == (off_t)-1) return -EPERM; - rd = read(fd, buf, size); - if (rd < 0) return -EPERM; - return rd; + filehandle_t *fh = (filehandle_t *)(uintptr_t)(fi->fh); + return fht_read(path, buf, size, offset, fh); } @@ -390,11 +462,8 @@ static int tfs_flush (const char *path, struct fuse_file_info *fi) { * Changed in version 2.2 */ static int tfs_release (const char *path, struct fuse_file_info *fi) { - int fd; - //dlogf("tfs_release: path=[%s], fi=0x%p", path, fi); - fd = fi->fh; - if (fd < 0) return -EPERM; - close(fd); + filehandle_t *fh = (filehandle_t *)(uintptr_t)(fi->fh); + fht_close(fh); fi->fh = 0; return 0; } -- 2.11.4.GIT