static int cmd_ls(int argc, char **argv) { (void)argc; RootPtr rootInfo = initRootInfo(argv[1]); if (!rootInfo) return EXIT_FAILURE; // show files in directory { DirTraverse dt = rootInfo->root->openDir("/"); if (dt.valid()) { for (string name = dt.nextPlaintextName(); !name.empty(); name = dt.nextPlaintextName()) { shared_ptr<FileNode> fnode = rootInfo->root->lookupNode(name.c_str(), "encfsctl-ls"); struct stat stbuf; fnode->getAttr(&stbuf); struct tm stm; localtime_r(&stbuf.st_mtime, &stm); stm.tm_year += 1900; // TODO: when I add "%s" to the end and name.c_str(), I get a // seg fault from within strlen. Why ??? printf("%11i %4i-%02i-%02i %02i:%02i:%02i %s\n", int(stbuf.st_size), int(stm.tm_year), int(stm.tm_mon), int(stm.tm_mday), int(stm.tm_hour), int(stm.tm_min), int(stm.tm_sec), name.c_str()); } } } return EXIT_SUCCESS; }
static int traverseDirs(const shared_ptr<EncFS_Root> &rootInfo, string volumeDir, string destDir) { if (!endsWith(volumeDir, '/')) volumeDir.append("/"); if (!endsWith(destDir, '/')) destDir.append("/"); // Lookup directory node so we can create a destination directory // with the same permissions { struct stat st; shared_ptr<FileNode> dirNode = rootInfo->root->lookupNode(volumeDir.c_str(), "encfsctl"); if (dirNode->getAttr(&st)) return EXIT_FAILURE; mkdir(destDir.c_str(), st.st_mode); } // show files in directory DirTraverse dt = rootInfo->root->openDir(volumeDir.c_str()); if (dt.valid()) { for (string name = dt.nextPlaintextName(); !name.empty(); name = dt.nextPlaintextName()) { // Recurse to subdirectories if (name != "." && name != "..") { string plainPath = volumeDir + name; string cpath = rootInfo->root->cipherPath(plainPath.c_str()); string destName = destDir + name; int r = EXIT_SUCCESS; struct stat stBuf; if (!lstat(cpath.c_str(), &stBuf)) { if (S_ISDIR(stBuf.st_mode)) { traverseDirs(rootInfo, (plainPath + '/').c_str(), destName + '/'); } else if (S_ISLNK(stBuf.st_mode)) { r = copyLink(stBuf, rootInfo, cpath, destName); } else { r = copyContents(rootInfo, plainPath.c_str(), destName.c_str()); } } else { r = EXIT_FAILURE; } if (r != EXIT_SUCCESS) return r; } } } return EXIT_SUCCESS; }
int encfs_getdir(const char *path, fuse_dirh_t h, fuse_dirfil_t filler) { EncFS_Context *ctx = context(); int res = ESUCCESS; shared_ptr<DirNode> FSRoot = ctx->getRoot(&res); if(!FSRoot) return res; try { DirTraverse dt = FSRoot->openDir( path ); rLog(Info, "getdir on %s", FSRoot->cipherPath(path).c_str()); if(dt.valid()) { int fileType = 0; ino_t inode = 0; std::string name = dt.nextPlaintextName( &fileType, &inode ); while( !name.empty() ) { res = filler( h, name.c_str(), fileType, inode ); if(res != ESUCCESS) break; name = dt.nextPlaintextName( &fileType, &inode ); } } else { rInfo("getdir request invalid, path: '%s'", path); } return res; } catch( rlog::Error &err ) { rError("Error caught in getdir"); err.log( _RLWarningChannel ); return -EIO; } }
int encfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *finfo) { EncFS_Context *ctx = context(); int res = ESUCCESS; std::shared_ptr<DirNode> FSRoot = ctx->getRoot(&res); if (!FSRoot) return res; try { DirTraverse dt = FSRoot->openDir(path); VLOG(1) << "readdir on " << FSRoot->cipherPath(path); if (dt.valid()) { int fileType = 0; ino_t inode = 0; std::string name = dt.nextPlaintextName(&fileType, &inode); while (!name.empty()) { struct stat st; st.st_ino = inode; st.st_mode = fileType << 12; // TODO: add offset support. #if defined(fuse_fill_dir_flags) if (filler(buf, name.c_str(), &st, 0, 0)) break; #else if (filler(buf, name.c_str(), &st, 0)) break; #endif name = dt.nextPlaintextName(&fileType, &inode); } } else { VLOG(1) << "readdir request invalid, path: '" << path << "'"; } return res; } catch (encfs::Error &err) { RLOG(ERROR) << "Error caught in readdir"; return -EIO; } }
int encfs_getdir(const char *path, fuse_dirh_t h, fuse_dirfil_t filler) { EncFS_Context *ctx = context(); int res = ESUCCESS; shared_ptr<DirNode> FSRoot = ctx->getRoot(&res); if(!FSRoot) return res; try { DirTraverse dt = FSRoot->openDir( path ); VLOG(1) << "getdir on " << FSRoot->cipherPath(path); if(dt.valid()) { int fileType = 0; ino_t inode = 0; std::string name = dt.nextPlaintextName( &fileType, &inode ); while( !name.empty() ) { res = filler( h, name.c_str(), fileType, inode ); if(res != ESUCCESS) break; name = dt.nextPlaintextName( &fileType, &inode ); } } else { LOG(INFO) << "getdir request invalid, path: '" << path << "'"; } return res; } catch( Error &err ) { LOG(ERROR) << "error caught in getdir: " << err.what(); return -EIO; } }
int showcruft( const shared_ptr<EncFS_Root> &rootInfo, const char *dirName ) { int found = 0; DirTraverse dt = rootInfo->root->openDir( dirName ); if(dt.valid()) { bool showedDir = false; for(string name = dt.nextInvalid(); !name.empty(); name = dt.nextInvalid()) { string cpath = rootInfo->root->cipherPath( dirName ); cpath += '/'; cpath += name; if(!showedDir) { // just before showing a list of files in a directory cout << autosprintf(_("In directory %s: \n"), dirName); showedDir = true; } ++found; cout << cpath << "\n"; } // now go back and look for directories to recurse into.. dt = rootInfo->root->openDir( dirName ); if(dt.valid()) { for(string name = dt.nextPlaintextName(); !name.empty(); name = dt.nextPlaintextName()) { if( name == "." || name == "..") continue; string plainPath = dirName; plainPath += '/'; plainPath += name; string cpath = rootInfo->root->cipherPath( plainPath.c_str() ); if(isDirectory( cpath.c_str() )) found += showcruft( rootInfo, plainPath.c_str() ); } } } return found; }
static int traverseDirs(const shared_ptr<EncFS_Root> &rootInfo, std::string volumeDir, std::string destDir, const std::set<std::string>& toWrite ) { bool fake = toWrite.empty(); if(!endsWith(volumeDir, '/')) volumeDir.append("/"); if(!endsWith(destDir, '/')) destDir.append("/"); std::string test_string = volumeDir; if (endsWith(test_string, '/') && test_string.length() != 1) { test_string = test_string.substr(0, test_string.length()-1); } /* Abort if we're in export mode and this directory * doesn't need to be written */ if (!toWrite.empty() && toWrite.find(test_string) == toWrite.end()) { return EXIT_SUCCESS; } // Lookup directory node so we can create a destination directory // with the same permissions { struct stat st; shared_ptr<FileNode> dirNode = rootInfo->root->lookupNode( volumeDir.c_str(), "encfsctl" ); if(dirNode->getAttr(&st)) return EXIT_FAILURE; // In fake mode, we always create rw: mode_t srcmode = st.st_mode; if (fake) srcmode = S_IRWXU; if (mkdir(destDir.c_str(), srcmode) == -1) { if (errno == EACCES /* sic! */ || errno == EROFS || errno == ENOSPC) { std::ostringstream out; out << "Not creating " << destDir << ": " << strerror(errno); LOGE(out.str().c_str()); return EXIT_FAILURE; } } } // show files in directory DirTraverse dt = rootInfo->root->openDir(volumeDir.c_str()); if(dt.valid()) { for(std::string name = dt.nextPlaintextName(); !name.empty(); name = dt.nextPlaintextName()) { bool skip = !toWrite.empty() && toWrite.find(volumeDir+name) == toWrite.end(); // Recurse to subdirectories if(name != "." && name != ".." && !skip) { std::string plainPath = volumeDir + name; std::string cpath = rootInfo->root->cipherPath(plainPath.c_str()); std::string destName = destDir + name; /*std::ostringstream out; out << "Decoding " << cpath << " to " << plainPath << " in " << destName; LOGI(out.str().c_str()); */ int r = EXIT_SUCCESS; struct stat stBuf; if( !lstat( cpath.c_str(), &stBuf )) { if( S_ISDIR( stBuf.st_mode ) ) { r = traverseDirs(rootInfo, (plainPath + '/').c_str(), destName + '/', toWrite); } else if( S_ISLNK( stBuf.st_mode )) { r = copyLink( stBuf, rootInfo, cpath, destName ); } else { r = copyContents(rootInfo, plainPath.c_str(), destName.c_str(), fake); } } else { r = EXIT_FAILURE; } if(r != EXIT_SUCCESS) return r; } } } return EXIT_SUCCESS; }