Index: Makefile ================================================================== --- Makefile +++ Makefile @@ -1,8 +1,8 @@ CC = gcc PKG_CONFIG = pkg-config -CFLAGS = -Wall $(shell $(PKG_CONFIG) --cflags fuse) $(shell $(PKG_CONFIG) --cflags sqlite3) $(TCL_CFLAGS) +CFLAGS = -Wall -g3 -ggdb3 $(shell $(PKG_CONFIG) --cflags fuse) $(shell $(PKG_CONFIG) --cflags sqlite3) $(TCL_CFLAGS) LDFLAGS = $(TCL_LDFLAGS) LIBS = $(shell $(PKG_CONFIG) --libs fuse) $(shell $(PKG_CONFIG) --libs sqlite3) $(TCL_LIBS) PREFIX = /usr/local prefix = $(PREFIX) bindir = $(prefix)/bin Index: appfsd.c ================================================================== --- appfsd.c +++ appfsd.c @@ -46,10 +46,11 @@ struct appfs_pathinfo { appfs_pathtype_t type; time_t time; char hostname[256]; + unsigned long long inode; union { struct { int childcount; } dir; struct { @@ -273,10 +274,12 @@ sqlite3_free(sql); if (sqlite_ret != SQLITE_OK) { APPFS_DEBUG("Call to sqlite3_exec failed."); + appfs_free_list_children(head); + return(NULL); } if (head != NULL) { *children_count_p = head->counter + 1; @@ -400,20 +403,24 @@ return(retval); } static int appfs_getfileinfo_cb(void *_pathinfo, int columns, char **values, char **names) { struct appfs_pathinfo *pathinfo = _pathinfo; - const char *type, *time, *source, *size, *perms, *sha1; + const char *type, *time, *source, *size, *perms, *sha1, *rowid; type = values[0]; time = values[1]; source = values[2]; size = values[3]; perms = values[4]; sha1 = values[5]; + rowid = values[6]; pathinfo->time = strtoull(time, NULL, 10); + + /* Package file inodes start at 2^32, fake inodes are before then */ + pathinfo->inode = strtoull(rowid, NULL, 10) + 4294967296ULL; if (strcmp(type, "file") == 0) { pathinfo->type = APPFS_PATHTYPE_FILE; if (!size) { @@ -488,11 +495,11 @@ } else { *file = '\0'; file++; } - sql = sqlite3_mprintf("SELECT type, time, source, size, perms, file_sha1 FROM files WHERE package_sha1 = %Q AND file_directory = %Q AND file_name = %Q;", package_hash, directory, file); + sql = sqlite3_mprintf("SELECT type, time, source, size, perms, file_sha1, rowid FROM files WHERE package_sha1 = %Q AND file_directory = %Q AND file_name = %Q;", package_hash, directory, file); if (sql == NULL) { APPFS_DEBUG("Call to sqlite3_mprintf failed."); free(path); @@ -563,10 +570,29 @@ *children = new_child; } return(0); } + +/* Generate an inode for a given path */ +static long long appfs_get_path_inode(const char *path) { + long long retval; + const char *p; + + retval = 10; + + for (p = path; *p; p++) { + retval %= 4290960290ULL; + retval += *p; + retval <<= 7; + } + + retval += 10; + retval %= 4294967296ULL; + + return(retval); +} /* Get information about a path, and optionally list children */ static int appfs_get_path_info(const char *_path, struct appfs_pathinfo *pathinfo, struct appfs_children **children) { struct appfs_children *dir_children; char *hostname, *packagename, *os_cpuArch, *os, *cpuArch, *version; @@ -589,10 +615,11 @@ } if (_path[1] == '\0') { /* Request for the root directory */ pathinfo->hostname[0] = '\0'; + pathinfo->inode = 1; sql = sqlite3_mprintf("SELECT DISTINCT hostname FROM packages;"); retval = appfs_get_path_info_sql(sql, 1, NULL, pathinfo, children); @@ -608,10 +635,12 @@ return(retval); } path = strdup(_path); path_s = path; + + pathinfo->inode = appfs_get_path_inode(path); hostname = path + 1; packagename = strchr(hostname, '/'); if (packagename != NULL) { @@ -739,10 +768,12 @@ pathinfo->typeinfo.dir.childcount = files_count; } if (children) { *children = dir_children; + } else { + appfs_free_list_children(dir_children); } } free(path_s); @@ -791,10 +822,11 @@ memset(stbuf, 0, sizeof(struct stat)); stbuf->st_mtime = pathinfo.time; stbuf->st_ctime = pathinfo.time; stbuf->st_atime = pathinfo.time; + stbuf->st_ino = pathinfo.inode; switch (pathinfo.type) { case APPFS_PATHTYPE_DIRECTORY: stbuf->st_mode = S_IFDIR | 0555; stbuf->st_nlink = 2 + pathinfo.typeinfo.dir.childcount;