@@ -383,19 +383,19 @@ static __thread Tcl_Obj *attr_key_type = NULL, *attr_key_perms = NULL, *attr_key_size = NULL, *attr_key_time = NULL, *attr_key_source = NULL, *attr_key_childcount = NULL; int tcl_ret; interp = appfs_TclInterp(); if (interp == NULL) { - return(1); + return(-EIO); } tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::getattr", path); if (tcl_ret != TCL_OK) { APPFS_DEBUG("::appfs::getattr(%s) failed.", path); APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); - return(1); + return(-ENOENT); } if (attr_key_type == NULL) { attr_key_type = Tcl_NewStringObj("type", -1); attr_key_perms = Tcl_NewStringObj("perms", -1); @@ -409,18 +409,19 @@ tcl_ret = Tcl_DictObjGet(interp, attrs_dict, attr_key_type, &attr_value); if (tcl_ret != TCL_OK) { APPFS_DEBUG("[dict get \"type\"] failed"); APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); - return(1); + return(-EIO); } if (attr_value == NULL) { - return(1); + return(-EIO); } pathinfo->packaged = 0; + pathinfo->inode = appfs_get_path_inode(path); attr_value_str = Tcl_GetString(attr_value); switch (attr_value_str[0]) { case 'd': /* directory */ pathinfo->type = APPFS_PATHTYPE_DIRECTORY; @@ -472,11 +473,11 @@ memcpy(pathinfo->typeinfo.symlink.source, attr_value_str, attr_value_int); } } break; default: - return(1); + return(-EIO); } Tcl_DictObjGet(interp, attrs_dict, attr_key_time, &attr_value); if (attr_value != NULL) { tcl_ret = Tcl_GetWideIntFromObj(NULL, attr_value, &attr_value_wide); @@ -577,11 +578,10 @@ static int appfs_fuse_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) { Tcl_Interp *interp; Tcl_Obj **children; int children_count, idx; int tcl_ret; - int retval; APPFS_DEBUG("Enter (path = %s, ...)", path); interp = appfs_TclInterp(); if (interp == NULL) { @@ -593,19 +593,19 @@ tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::getchildren", path); if (tcl_ret != TCL_OK) { APPFS_DEBUG("::appfs::getchildren(%s) failed.", path); APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); - + return(0); } tcl_ret = Tcl_ListObjGetElements(interp, Tcl_GetObjResult(interp), &children_count, &children); if (tcl_ret != TCL_OK) { APPFS_DEBUG("Parsing list of children on path %s failed.", path); APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); - + return(0); } for (idx = 0; idx < children_count; idx++) { filler(buf, Tcl_GetString(children[idx]), NULL, 0); @@ -613,45 +613,66 @@ return(0); } static int appfs_fuse_open(const char *path, struct fuse_file_info *fi) { + Tcl_Interp *interp; struct appfs_pathinfo pathinfo; - const char *real_path; + const char *real_path, *mode; + int gpi_ret, tcl_ret; int fh; - int gpi_ret; APPFS_DEBUG("Enter (path = %s, ...)", path); -#if 0 - - if ((fi->flags & 3) != O_RDONLY) { - return(-EACCES); - } - - gpi_ret = appfs_get_path_info(path, &pathinfo, NULL); - if (gpi_ret != 0) { - return(gpi_ret); + gpi_ret = appfs_get_path_info(path, &pathinfo); + + if ((fi->flags & (O_WRONLY|O_CREAT)) == (O_CREAT|O_WRONLY)) { + /* The file will be created if it does not exist */ + if (gpi_ret != 0 && gpi_ret != -ENOENT) { + return(gpi_ret); + } + + mode = "create"; + } else { + /* The file must already exist */ + if (gpi_ret != 0) { + return(gpi_ret); + } + + mode = ""; } if (pathinfo.type == APPFS_PATHTYPE_DIRECTORY) { return(-EISDIR); } - real_path = appfs_getfile(pathinfo.hostname, pathinfo.typeinfo.file.sha1); + interp = appfs_TclInterp(); + if (interp == NULL) { + return(-EIO); + } + + tcl_ret = appfs_Tcl_Eval(interp, 3, "::appfs::openpath", path, mode); + if (tcl_ret != TCL_OK) { + APPFS_DEBUG("::appfs::openpath(%s, %s) failed.", path, mode); + APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); + + return(-EIO); + } + + real_path = Tcl_GetStringResult(interp); if (real_path == NULL) { return(-EIO); } - fh = open(real_path, O_RDONLY); - free((void *) real_path); + APPFS_DEBUG("Translated request to open %s to opening %s (mode = \"%s\")", path, real_path, mode); + + fh = open(real_path, fi->flags, 0600); if (fh < 0) { return(-EIO); } fi->fh = fh; -#endif return(0); } static int appfs_fuse_close(const char *path, struct fuse_file_info *fi) { @@ -776,11 +797,11 @@ /* * FUSE option parsing callback */ static int appfs_fuse_opt_cb(void *data, const char *arg, int key, struct fuse_args *outargs) { - static seen_cachedir = 0; + static int seen_cachedir = 0; if (key == FUSE_OPT_KEY_NONOPT && seen_cachedir == 0) { seen_cachedir = 1; appfs_cachedir = strdup(arg);