aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Benjamin Barenblat <bbaren@mit.edu>2016-02-13 20:04:45 -0500
committerGravatar Benjamin Barenblat <bbaren@mit.edu>2016-02-13 20:04:45 -0500
commit6eac94633434f7b84151cec8cf11d35e07e3ff81 (patch)
treef4f02574b83abc078642c672eebf423256f008cd
parent34eb0db1e04cbfc0504c239a151247334f1bb0a8 (diff)
Implement enough to get ls to work
-rw-r--r--src/operations.cc131
-rw-r--r--src/scoville.cc4
2 files changed, 124 insertions, 11 deletions
diff --git a/src/operations.cc b/src/operations.cc
index 17ce2a3..abd2f0c 100644
--- a/src/operations.cc
+++ b/src/operations.cc
@@ -15,12 +15,20 @@
// You should have received a copy of the GNU General Public License along with
// this program. If not, see <http://www.gnu.org/licenses/>.
+#define BSD_SOURCE
+#define _POSIX_C_SOURCE 201602L
+
#include "operations.h"
#include <cerrno>
+#include <cstring>
+#include <memory>
+#include <new>
#define FUSE_USE_VERSION 26
+#include <dirent.h>
#include <fuse.h>
+#include <glog/logging.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
@@ -29,19 +37,117 @@ namespace scoville {
namespace {
-int GetAttr(const char* const path, struct stat* output) {
+struct Directory {
+ DIR* fd;
+ dirent* entry;
+ off_t offset;
+};
+
+Directory* FileInfoDirectory(fuse_file_info* const file_info) {
+ return reinterpret_cast<Directory*>(file_info->fh);
+}
+
+mode_t DirectoryTypeToFileType(const unsigned char type) {
+ switch (type) {
+ case DT_BLK:
+ return S_IFBLK;
+ case DT_CHR:
+ return S_IFCHR;
+ case DT_DIR:
+ return S_IFDIR;
+ case DT_FIFO:
+ return S_IFIFO;
+ case DT_LNK:
+ return S_IFLNK;
+ case DT_REG:
+ return S_IFREG;
+ case DT_SOCK:
+ return S_IFSOCK;
+ default:
+ return 0;
+ }
+}
+
+void* Initialize(fuse_conn_info*) {
+ LOG(INFO) << "initialize";
+ return nullptr;
+}
+
+void Destroy(void*) {
+ LOG(INFO) << "destroy";
+}
+
+int Getattr(const char* const path, struct stat* output) {
+ LOG(INFO) << "getattr(" << path << ")";
if (lstat(path, output) == -1) {
return -errno;
}
return 0;
}
-int ReadLink(const char* const path, char *const output, const size_t output_size) {
- const ssize_t bytes_written = readlink(path, output, output_size);
- if (bytes_written == -1) {
+int Opendir(const char* const path, fuse_file_info* const file_info) {
+ LOG(INFO) << "opendir(" << path << ")";
+
+ std::unique_ptr<Directory> directory;
+ try {
+ directory.reset(new Directory);
+ } catch (std::bad_alloc) {
+ return -ENOMEM;
+ }
+
+ if ((directory->fd = opendir(path)) == nullptr) {
return -errno;
}
- output[bytes_written] = '\0';
+ directory->entry = nullptr;
+ directory->offset = 0;
+
+ static_assert(sizeof(file_info->fh) == sizeof(uintptr_t),
+ "FUSE file handles are a different size than pointers");
+ file_info->fh = reinterpret_cast<uintptr_t>(directory.release());
+ return 0;
+}
+
+int Readdir(const char*, void* const buffer, fuse_fill_dir_t filler,
+ const off_t offset, fuse_file_info* const file_info) {
+ LOG(INFO) << "readdir";
+
+ Directory* const directory = FileInfoDirectory(file_info);
+
+ if (offset != directory->offset) {
+ seekdir(directory->fd, offset);
+ directory->entry = nullptr;
+ directory->offset = offset;
+ }
+
+ while (true) {
+ if (!directory->entry) {
+ directory->entry = readdir(directory->fd);
+ if (!directory->entry) {
+ break;
+ }
+ }
+
+ struct stat stats;
+ std::memset(&stats, 0, sizeof(stats));
+ stats.st_ino = directory->entry->d_ino;
+ stats.st_mode = DirectoryTypeToFileType(directory->entry->d_type);
+ const off_t next_offset = telldir(directory->fd);
+ if (filler(buffer, directory->entry->d_name, &stats, next_offset)) {
+ break;
+ }
+
+ directory->entry = nullptr;
+ directory->offset = next_offset;
+ }
+
+ return 0;
+}
+
+int Releasedir(const char*, fuse_file_info* const file_info) {
+ LOG(INFO) << "releasedir";
+ Directory* const directory = FileInfoDirectory(file_info);
+ closedir(directory->fd);
+ delete directory;
return 0;
}
@@ -49,8 +155,19 @@ int ReadLink(const char* const path, char *const output, const size_t output_siz
fuse_operations FuseOperations() {
fuse_operations result;
- result.getattr = &GetAttr;
- result.readlink = &ReadLink;
+
+ result.flag_nullpath_ok = true;
+ result.flag_nopath = true;
+ result.flag_utime_omit_ok = true;
+
+ result.init = &Initialize;
+ result.destroy = &Destroy;
+
+ result.getattr = &Getattr;
+ result.opendir = &Opendir;
+ result.readdir = &Readdir;
+ result.releasedir = &Releasedir;
+
return result;
}
diff --git a/src/scoville.cc b/src/scoville.cc
index db39ee8..054a6cd 100644
--- a/src/scoville.cc
+++ b/src/scoville.cc
@@ -19,10 +19,6 @@
#include "operations.h"
-namespace {
-
-} // namespace
-
int main(const int argc, char* argv[]) {
FLAGS_logtostderr = true;
google::InstallFailureSignalHandler();