#include #include #include #include #include #include "pstream.h" extern "C" { #include }; #include const std::string test1=""; //const std::string test2="/store_00010001/DCIM/101CANON"; class Entry; typedef std::string FQName; typedef std::map EntryMap; EntryMap theGlobalEntryMap; std::ostream & operator<<(std::ostream & os, const Entry& fs); class Entry { public: int m_numberInDir; std::string m_baseName; std::string m_fqName; std::string m_pathWith; std::string m_pathWithout; long int m_bytes; std::string m_geom; std::string m_type; bool m_isDir; unsigned int m_hardLinks; public: void addToMap() { theGlobalEntryMap[m_fqName] = this; }; void addHardLink() { ++m_hardLinks; }; void setNamesFrom(const std::string & pathWithout, const std::string & baseName) { if (pathWithout == "/") { // special case m_baseName = baseName; m_pathWithout = ""; m_pathWith = "/"; m_fqName = m_pathWith + m_baseName; } else { m_baseName = baseName; m_pathWithout = pathWithout; m_pathWith = m_pathWithout + "/"; m_fqName = m_pathWith + m_baseName; }; }; void setAsDir(const std::string & pathWithout, const std::string & baseName) { setNamesFrom(pathWithout, baseName); m_numberInDir=0; m_bytes=1; // must be >0 to ensure find unixcmd works! m_geom=""; m_type=""; m_isDir=true; m_hardLinks=2; }; std::istream & readFileFromGPhoto2(const std::string & pathWithout, std::istream & is) { if(is >> m_numberInDir) { // OK } else { // probably passed end record return is; }; is >> m_baseName; setNamesFrom(pathWithout, m_baseName); long int s; is >> s; std::string unit; is >> unit; if (unit!="B") { std::cerr << "You have not modified gphoto2 to report BYTES !!" << std::endl; exit(1); }; m_bytes = s; is >> m_geom; is >> m_type; m_isDir=false; m_hardLinks=0; std::cout << "Just read " << *this << std::endl; return is; }; std::ostream & printMeTo(std::ostream & os) const { return os << "Num[" << m_numberInDir<< "] BaseName[" << m_baseName << "] Size=[" << m_bytes<<"] fqName["<m_fqName; const std::string dirCommand=commandBase+" -l | awk '{if (NR>1){print}}' | colrm 1 3"; const std::string fileCommand=commandBase+" -L | grep '^#' | colrm 1 1"; { std::cerr << "Trying command " << fileCommand << std::endl; redi::pstream ps(fileCommand); Entry * fs = new Entry; while(fs->readFileFromGPhoto2(entry->m_fqName, ps)) { fs->addToMap(); fs = new Entry; }; delete fs; }; { std::cerr << "Trying command " << dirCommand << std::endl; redi::pstream ps(dirCommand); typedef std::list DirNames; DirNames dirNames; { std::string dirName; while(ps>>dirName) { std::cerr << "Found dir name " << dirName << std::endl; dirNames.push_back(dirName); }; }; // Read further dirs in!! for (DirNames::const_iterator it = dirNames.begin(); it!=dirNames.end(); ++it) { const std::string & dirName = *it; Entry * fs = new Entry; fs->setAsDir(entry->m_fqName, dirName); fs->addToMap(); entry->addHardLink(); readEntriesFromCameraForDir(fs); }; }; }; void readAllEntriesFromCamera() { Entry * rootEntry = new Entry; rootEntry->setAsDir("", ""); rootEntry->addToMap(); readEntriesFromCameraForDir(rootEntry); }; class Directory { public: int fuse_getdir(const std::string & fqName, fuse_dirh_t * h, fuse_dirfil_t * filler) const { std::cout << "Asked getdir for [" << fqName << "]" << std::endl; EntryMap::const_iterator fit = theGlobalEntryMap.find(fqName); if (fit==theGlobalEntryMap.end()) { std::cout << "path or filename [" << fqName << "] does not exist!" << std::endl; return -ENOENT; }; const bool isDir = fit->second->m_isDir; if (!isDir) { std::cout << "path or filename [" << fqName << "] exists but is not a directory!" << std::endl; return -ENOENT; }; (*filler)(*h, ".", 0); (*filler)(*h, "..", 0); //std::cout << "Found a dir with name " << dir.name() << " and fullPathWith = " << dir.fullPathWith() << " which looks like " << dir << " which is nice!" << std::endl; //std::cout << "It had size " << dir.m_files.size() << std::endl; for (EntryMap::const_iterator it = theGlobalEntryMap.begin(); it!=theGlobalEntryMap.end(); ++it) { const Entry * entry = it->second; std::string comparison = (fqName=="/")?"":fqName; if (entry->m_pathWithout == comparison && entry->m_fqName!="/") { // We have found a file in this dir! std::cout << "PACKING " << entry->m_baseName << "\n"; (*filler)(*h, entry->m_baseName.c_str(), it->second->m_bytes); }; }; //(*filler)(*h, "hello" , 0); /* for(Directories::const_iterator it = m_directories.begin(); it != m_directories.end(); ++it) { (*filler)(*h, it->name().c_str(), 0); }; */ return 0; }; int fuse_getattr(const std::string & fqName, struct stat *stbuf) { int res = 0; std::cout << "Asked getattr for [" << fqName << "]" << std::endl; memset(stbuf, 0, sizeof(struct stat)); EntryMap::const_iterator it = theGlobalEntryMap.find(fqName); if (it != theGlobalEntryMap.end()) { std::cout << "AA1" << std::endl; const Entry * fs = it->second; if (fs->m_isDir) { std::cout << "AA2" << std::endl; stbuf->st_mode = S_IFDIR | 0555; stbuf->st_nlink = fs->m_hardLinks; stbuf->st_size = fs->m_bytes;//strlen(hello_str); } else { std::cout << "AA3" << std::endl; stbuf->st_mode = S_IFREG | 0444; stbuf->st_nlink = 1; stbuf->st_size = fs->m_bytes;//strlen(hello_str); }; } else { std::cout << "AA4" << std::endl; res = -ENOENT; }; return res; }; int fuse_open(const std::string & fqName, const int flags) { if ((flags & 3) != O_RDONLY) return -EACCES; EntryMap::const_iterator it = theGlobalEntryMap.find(fqName); if (it != theGlobalEntryMap.end()) { std::cout << "BB1" << std::endl; const Entry * fs = it->second; if (fs->m_isDir) { return -EACCES; } else { return 0; }; } else { std::cout << "BB4" << std::endl; return -ENOENT; }; }; int fuse_read(const std::string & fqName, char *buf, size_t size, off_t offset) { static std::string lastFQName; static bool first=true; const bool read = (first || (lastFQName != fqName)); if (first) { first = false; }; EntryMap::const_iterator it = theGlobalEntryMap.find(fqName); if (it == theGlobalEntryMap.end()) { return -ENOENT; }; const Entry * const entry = it->second; if (entry->m_isDir) { return -EACCES; }; static char * BUF = 0; static unsigned int BUFSIZE = 0; if (read) { lastFQName = fqName; std::ostringstream commandBase; commandBase << "gphoto2 --stdout-size --stdout "; commandBase << " -f "; commandBase << entry->m_pathWith; commandBase << " -p "; commandBase << entry->m_numberInDir; const std::string command = commandBase.str(); std::cout << "Opening with command ["<m_fqName<<"]"<m_bytes; { unsigned long sizCheck; ps >> sizCheck; ps.get(); // the get() absorbs the '\n' std::cout << "Read size = " << sizCheck << std::endl; std::cout << "Expected size = " << bytes << std::endl; }; delete[] BUF; BUF = new char[bytes]; BUFSIZE = bytes; std::cout << "Reading ... " << std::flush; char * pos=BUF; for (unsigned int i=0; i BUFSIZE) size = BUFSIZE - offset; memcpy(buf, BUF+offset, size); } else size=0; return size; }; }; Directory rootDir; extern "C" { int really_getdir(const char *path, fuse_dirh_t * h, fuse_dirfil_t * filler) { return rootDir.fuse_getdir(path, h,filler); } int really_getattr(const char *path, struct stat *stdbuf) { return rootDir.fuse_getattr(path, stdbuf); } int really_open(const char *path, int flags) { return rootDir.fuse_open(path, flags); } int really_read(const char *path, char *buf, size_t size, off_t offset) { return rootDir.fuse_read(path, buf, size, offset); }; }; extern "C" { int init_filesystem() { std::cout << "Thank god for C++" << std::endl; //redi::pstream ps("gphoto2 -L | grep ^# | colrm 1 1"); // redi::pstream ps("cat subst | grep ^# | colrm 1 1"); readAllEntriesFromCamera(); //Index * index = new Index(rootDir); // must live longer than this scope! /* FileSummary fs; while(fs.readFileFromGPhoto2(ps)) { std::cout << "[" << fs << "]"<