Index: appfsd.c ================================================================== --- appfsd.c +++ appfsd.c @@ -52,10 +52,14 @@ struct { int executable; off_t size; char sha1[41]; } file; + struct { + off_t size; + char source[256]; + } symlink; } typeinfo; }; struct appfs_sqlite3_query_cb_handle { struct appfs_children *head; @@ -207,11 +211,10 @@ return; } return; } - #define appfs_free_list_type(id, type) static void appfs_free_list_ ## id(type *head) { \ type *obj, *next; \ for (obj = head; obj; obj = next) { \ next = obj->_next; \ @@ -436,10 +439,24 @@ if (strcmp(type, "directory") == 0) { pathinfo->type = APPFS_PATHTYPE_DIRECTORY; pathinfo->typeinfo.dir.childcount = 0; + return(0); + } + + if (strcmp(type, "symlink") == 0) { + pathinfo->type = APPFS_PATHTYPE_SYMLINK; + pathinfo->typeinfo.dir.childcount = 0; + + if (!source) { + source = ".BADLINK"; + } + + pathinfo->typeinfo.symlink.size = strlen(source); + snprintf(pathinfo->typeinfo.symlink.source, sizeof(pathinfo->typeinfo.symlink.source), "%s", source); + return(0); } return(0); @@ -685,16 +702,44 @@ free(path_s); return(0); } + +static int appfs_fuse_readlink(const char *path, char *buf, size_t size) { + struct appfs_pathinfo pathinfo; + int res = 0; + + APPFS_DEBUG("Enter (path = %s, ...)", path); + + pathinfo.type = APPFS_PATHTYPE_INVALID; + + res = appfs_get_path_info(path, &pathinfo, NULL); + if (res != 0) { + return(res); + } + + if (pathinfo.type != APPFS_PATHTYPE_SYMLINK) { + return(-EINVAL); + } + + if ((strlen(pathinfo.typeinfo.symlink.source) + 1) > size) { + return(-ENAMETOOLONG); + } + + memcpy(buf, pathinfo.typeinfo.symlink.source, strlen(pathinfo.typeinfo.symlink.source) + 1); + + return(0); +} static int appfs_fuse_getattr(const char *path, struct stat *stbuf) { struct appfs_pathinfo pathinfo; int res = 0; APPFS_DEBUG("Enter (path = %s, ...)", path); + + pathinfo.type = APPFS_PATHTYPE_INVALID; res = appfs_get_path_info(path, &pathinfo, NULL); if (res != 0) { return(res); } @@ -703,22 +748,34 @@ stbuf->st_mtime = pathinfo.time; stbuf->st_ctime = pathinfo.time; stbuf->st_atime = pathinfo.time; - if (pathinfo.type == APPFS_PATHTYPE_DIRECTORY) { - stbuf->st_mode = S_IFDIR | 0555; - stbuf->st_nlink = 2 + pathinfo.typeinfo.dir.childcount; - } else { - if (pathinfo.typeinfo.file.executable) { - stbuf->st_mode = S_IFREG | 0555; - } else { - stbuf->st_mode = S_IFREG | 0444; - } - - stbuf->st_nlink = 1; - stbuf->st_size = pathinfo.typeinfo.file.size; + switch (pathinfo.type) { + case APPFS_PATHTYPE_DIRECTORY: + stbuf->st_mode = S_IFDIR | 0555; + stbuf->st_nlink = 2 + pathinfo.typeinfo.dir.childcount; + break; + case APPFS_PATHTYPE_FILE: + if (pathinfo.typeinfo.file.executable) { + stbuf->st_mode = S_IFREG | 0555; + } else { + stbuf->st_mode = S_IFREG | 0444; + } + + stbuf->st_nlink = 1; + stbuf->st_size = pathinfo.typeinfo.file.size; + break; + case APPFS_PATHTYPE_SYMLINK: + stbuf->st_mode = S_IFLNK | 0555; + stbuf->st_nlink = 1; + stbuf->st_size = pathinfo.typeinfo.symlink.size; + break; + case APPFS_PATHTYPE_INVALID: + res = -EIO; + + break; } return res; } @@ -811,10 +868,11 @@ } static struct fuse_operations appfs_oper = { .getattr = appfs_fuse_getattr, .readdir = appfs_fuse_readdir, + .readlink = appfs_fuse_readlink, .open = appfs_fuse_open, .release = appfs_fuse_close, .read = appfs_fuse_read };