static int fuse_readdir(const char* path, void* buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info* fi) { PRINTD("##readdir\n"); int dfp = _kern_open_dir(-1, path); if (dfp < FSSH_B_OK) return _ERR(dfp); fssh_ssize_t entriesRead = 0; struct fssh_stat f_st; struct stat st; char buffer[sizeof(fssh_dirent) + FSSH_B_FILE_NAME_LENGTH]; fssh_dirent* dirEntry = (fssh_dirent*)buffer; while ((entriesRead = _kern_read_dir(dfp, dirEntry, sizeof(buffer), 1)) == 1) { fssh_memset(&st, 0, sizeof(st)); fssh_memset(&f_st, 0, sizeof(f_st)); fssh_status_t status = _kern_read_stat(dfp, dirEntry->d_name, false, &f_st, sizeof(f_st)); if (status >= FSSH_B_OK) { fromFsshStatToStat(&f_st, &st); if (filler(buf, dirEntry->d_name, &st, 0)) break; } } _kern_close(dfp); //TODO: check _kern_close return 0; }
static fssh_status_t command_ls(int argc, const char* const* argv) { const char* const currentDirFiles[] = { ".", NULL }; const char* const* files; if (argc >= 2) files = argv + 1; else files = currentDirFiles; for (; *files; files++) { const char* file = *files; // stat file struct fssh_stat st; fssh_status_t error = _kern_read_stat(-1, file, false, &st, sizeof(st)); if (error != FSSH_B_OK) { fprintf(stderr, "Error: Failed to stat() \"%s\": %s\n", file, fssh_strerror(error)); continue; } // if it is a directory, print its entries if (FSSH_S_ISDIR(st.fssh_st_mode)) { printf("%s:\n", file); // open dir int fd = _kern_open_dir(-1, file); if (fd < 0) { fprintf(stderr, "Error: Failed to open dir \"%s\": %s\n", file, fssh_strerror(fd)); continue; } // iterate through the entries char buffer[sizeof(fssh_dirent) + FSSH_B_FILE_NAME_LENGTH]; fssh_dirent* entry = (fssh_dirent*)buffer; fssh_ssize_t entriesRead = 0; while ((entriesRead = _kern_read_dir(fd, entry, sizeof(buffer), 1)) == 1) { list_entry(file, entry->d_name); } if (entriesRead < 0) { fprintf(stderr, "Error: reading dir \"%s\" failed: %s\n", file, fssh_strerror(entriesRead)); } // close dir error = _kern_close(fd); if (error != FSSH_B_OK) { fprintf(stderr, "Error: Closing dir \"%s\" (fd: %d) failed: " "%s\n", file, fd, fssh_strerror(error)); continue; } } else list_entry(file); } return FSSH_B_OK; }
/*! \brief Re-initializes the BDirectory to the directory referred to by the supplied BEntry. \param entry the BEntry referring to the directory \return - \c B_OK: Everything went fine. - \c B_BAD_VALUE: \c NULL \a entry. - \c B_ENTRY_NOT_FOUND: Directory not found. - \c B_PERMISSION_DENIED: Directory permissions didn't allow operation. - \c B_NO_MEMORY: Insufficient memory for operation. - \c B_LINK_LIMIT: Indicates a cyclic loop within the file system. - \c B_BUSY: A node was busy. - \c B_FILE_ERROR: A general file error. - \c B_NO_MORE_FDS: The application has run out of file descriptors. */ status_t BDirectory::SetTo(const BEntry* entry) { if (!entry) { Unset(); return (fCStatus = B_BAD_VALUE); } // open node status_t error = _SetTo(entry->fDirFd, entry->fName, true); if (error != B_OK) return error; // open dir fDirFd = _kern_open_dir(entry->fDirFd, entry->fName); if (fDirFd < 0) { status_t error = fDirFd; Unset(); return (fCStatus = error); } // set close on exec flag on dir FD fcntl(fDirFd, F_SETFD, FD_CLOEXEC); return B_OK; }
DIR* fdopendir(int fd) { DIR* dir; // Since our standard file descriptors can't be used as directory file // descriptors, we have to open a fresh one explicitly. int dirFD = _kern_open_dir(fd, NULL); if (dirFD < 0) { __set_errno(dirFD); return NULL; } // Since applications are allowed to use the file descriptor after a call // to fdopendir() without changing its state (like for other *at() // functions), we cannot close it now. // We dup2() the new FD to the previous location instead. if (dup2(dirFD, fd) == -1) close(fd); else { close(dirFD); dirFD = fd; fcntl(dirFD, F_SETFD, FD_CLOEXEC); // reset close-on-exec which is cleared by dup() } dir = __create_dir_struct(dirFD); if (dir == NULL) { close(dirFD); return NULL; } return dir; }
DIR* opendir(const char* path) { DIR* dir; int fd = _kern_open_dir(-1, path); if (fd < 0) { __set_errno(fd); return NULL; } // allocate the DIR structure if ((dir = __create_dir_struct(fd)) == NULL) { _kern_close(fd); return NULL; } return dir; }
static fssh_status_t command_ioctl(int argc, const char* const* argv) { if (argc != 2) { fprintf(stderr, "Usage: %s <opcode>\n", argv[0]); return FSSH_B_BAD_VALUE; } int rootDir = _kern_open_dir(-1, "/myfs"); if (rootDir < 0) return rootDir; fssh_status_t status = _kern_ioctl(rootDir, atoi(argv[1]), NULL, 0); if (status != FSSH_B_OK) { fprintf(stderr, "Error: ioctl failed: %s\n", fssh_strerror(status)); return status; } return FSSH_B_OK; }
/*! \brief Re-initializes the BDirectory to the directory referred to by the supplied path name. \param path the directory's path name \return - \c B_OK: Everything went fine. - \c B_BAD_VALUE: \c NULL \a path. - \c B_ENTRY_NOT_FOUND: Directory not found. - \c B_PERMISSION_DENIED: Directory permissions didn't allow operation. - \c B_NO_MEMORY: Insufficient memory for operation. - \c B_NAME_TOO_LONG: The supplied path name (\a path) is too long. - \c B_LINK_LIMIT: Indicates a cyclic loop within the file system. - \c B_BUSY: A node was busy. - \c B_FILE_ERROR: A general file error. - \c B_NO_MORE_FDS: The application has run out of file descriptors. - \c B_NOT_A_DIRECTORY: \a path includes a non-directory. */ status_t BDirectory::SetTo(const char* path) { // open node status_t error = _SetTo(-1, path, true); if (error != B_OK) return error; // open dir fDirFd = _kern_open_dir(-1, path); if (fDirFd < 0) { status_t error = fDirFd; Unset(); return (fCStatus = error); } // set close on exec flag on dir FD fcntl(fDirFd, F_SETFD, FD_CLOEXEC); return B_OK; }
static fssh_status_t remove_dir_contents(int parentDir, const char *name, bool force) { // open the dir int dir = _kern_open_dir(parentDir, name); if (dir < 0) { fprintf(stderr, "Error: Failed to open dir \"%s\": %s\n", name, fssh_strerror(dir)); return dir; } fssh_status_t error = FSSH_B_OK; // iterate through the entries fssh_ssize_t numRead; char buffer[sizeof(fssh_dirent) + FSSH_B_FILE_NAME_LENGTH]; fssh_dirent *entry = (fssh_dirent*)buffer; while ((numRead = _kern_read_dir(dir, entry, sizeof(buffer), 1)) > 0) { // skip "." and ".." if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; error = remove_entry(dir, entry->d_name, true, force); if (error != FSSH_B_OK) break; } if (numRead < 0) { fprintf(stderr, "Error: Failed to read directory \"%s\": %s\n", name, fssh_strerror(numRead)); error = numRead; } // close _kern_close(dir); return error; }
/*! \brief Re-initializes the BDirectory to the directory referred to by the supplied path name relative to the specified BDirectory. \param dir the BDirectory, relative to which the directory's path name is given \param path the directory's path name relative to \a dir \return - \c B_OK: Everything went fine. - \c B_BAD_VALUE: \c NULL \a dir or \a path, or \a path is absolute. - \c B_ENTRY_NOT_FOUND: Directory not found. - \c B_PERMISSION_DENIED: Directory permissions didn't allow operation. - \c B_NO_MEMORY: Insufficient memory for operation. - \c B_NAME_TOO_LONG: The supplied path name (\a path) is too long. - \c B_LINK_LIMIT: Indicates a cyclic loop within the file system. - \c B_BUSY: A node was busy. - \c B_FILE_ERROR: A general file error. - \c B_NO_MORE_FDS: The application has run out of file descriptors. - \c B_NOT_A_DIRECTORY: \a path includes a non-directory. */ status_t BDirectory::SetTo(const BDirectory* dir, const char* path) { if (!dir || !path || BPrivate::Storage::is_absolute_path(path)) { Unset(); return (fCStatus = B_BAD_VALUE); } int dirFD = dir->fDirFd; if (dir == this) { // prevent that our file descriptor goes away in _SetTo() fDirFd = -1; } // open node status_t error = _SetTo(dirFD, path, true); if (error != B_OK) return error; // open dir fDirFd = _kern_open_dir(dirFD, path); if (fDirFd < 0) { status_t error = fDirFd; Unset(); return (fCStatus = error); } if (dir == this) { // cleanup after _SetTo() _kern_close(dirFD); } // set close on exec flag on dir FD fcntl(fDirFd, F_SETFD, FD_CLOEXEC); return B_OK; }
static fssh_status_t command_mv(int argc, const char* const* argv) { bool force = false; // parse parameters int argi = 1; for (argi = 1; argi < argc; argi++) { const char *arg = argv[argi]; if (arg[0] != '-') break; if (arg[1] == '\0') { fprintf(stderr, "Error: Invalid option \"-\"\n"); return FSSH_B_BAD_VALUE; } for (int i = 1; arg[i]; i++) { switch (arg[i]) { case 'f': force = true; break; default: fprintf(stderr, "Error: Unknown option \"-%c\"\n", arg[i]); return FSSH_B_BAD_VALUE; } } } // check params int count = argc - 1 - argi; if (count <= 0) { fprintf(stderr, "Usage: %s [-f] <file>... <target>\n", argv[0]); return FSSH_B_BAD_VALUE; } const char* target = argv[argc - 1]; // stat the target struct fssh_stat st; fssh_status_t status = _kern_read_stat(-1, target, true, &st, sizeof(st)); if (status != FSSH_B_OK && count != 1) { fprintf(stderr, "Error: Failed to stat target \"%s\": %s\n", target, fssh_strerror(status)); return status; } if (status == FSSH_B_OK && FSSH_S_ISDIR(st.fssh_st_mode)) { // move several entries int targetDir = _kern_open_dir(-1, target); if (targetDir < 0) { fprintf(stderr, "Error: Failed to open dir \"%s\": %s\n", target, fssh_strerror(targetDir)); return targetDir; } // move loop for (; argi < argc - 1; argi++) { status = move_entry(-1, argv[argi], targetDir, argv[argi], force); if (status != FSSH_B_OK) { _kern_close(targetDir); return status; } } _kern_close(targetDir); return FSSH_B_OK; } // rename single entry return move_entry(-1, argv[argi], -1, target, force); }