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; }
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; }
/*! \brief Returns the BDirectory's next entries as dirent structures. Unlike GetNextEntry() and GetNextRef(), this method returns also the entries "." and "..". \param buf a pointer to a buffer to be filled with dirent structures of the found entries \param count the maximal number of entries to be returned. \note The iterator used by this method is the same one used by GetNextEntry(), GetNextRef(), Rewind() and CountEntries(). \return - The number of dirent structures stored in the buffer, 0 when there are no more entries to be returned. - \c B_BAD_VALUE: \c NULL \a buf. - \c B_PERMISSION_DENIED: Directory permissions didn't allow operation. - \c B_NO_MEMORY: Insufficient memory for operation. - \c B_NAME_TOO_LONG: The entry's name is too long for the buffer. - \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. */ int32 BDirectory::GetNextDirents(dirent* buf, size_t bufSize, int32 count) { if (!buf) return B_BAD_VALUE; if (InitCheck() != B_OK) return B_FILE_ERROR; return _kern_read_dir(fDirFd, buf, bufSize, count); }
static fssh_status_t command_query(int argc, const char* const* argv) { if (argc != 2) { fprintf(stderr, "Usage: %s <query string>\n", argv[0]); return FSSH_B_BAD_VALUE; } const char* query = argv[1]; // get the volume ID fssh_dev_t volumeID = get_volume_id(); if (volumeID < 0) return volumeID; // open query int fd = _kern_open_query(volumeID, query, strlen(query), 0, -1, -1); if (fd < 0) { fprintf(stderr, "Error: Failed to open query: %s\n", fssh_strerror(fd)); return fd; } // iterate through the entries fssh_status_t error = FSSH_B_OK; 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) { char path[FSSH_B_PATH_NAME_LENGTH]; error = _kern_entry_ref_to_path(volumeID, entry->d_pino, entry->d_name, path, sizeof(path)); if (error == FSSH_B_OK) { printf(" %s\n", path); } else { fprintf(stderr, " failed to resolve entry (%8" FSSH_B_PRIdINO ", \"%s\")\n", entry->d_pino, entry->d_name); } } if (entriesRead < 0) { fprintf(stderr, "Error: reading query failed: %s\n", fssh_strerror(entriesRead)); } // close query error = _kern_close(fd); if (error != FSSH_B_OK) { fprintf(stderr, "Error: Closing query (fd: %d) failed: %s\n", fd, fssh_strerror(error)); } return error; }
int readdir_r(DIR* dir, struct dirent* entry, struct dirent** _result) { ssize_t count = _kern_read_dir(dir->fd, entry, sizeof(struct dirent) + B_FILE_NAME_LENGTH, 1); if (count < B_OK) return count; if (count == 0) { // end of directory *_result = NULL; } else *_result = entry; return 0; }
/*! \brief Returns the next attribute in the node's list of attributes. Every BNode maintains a pointer to its list of attributes. GetNextAttrName() retrieves the name of the attribute that the pointer is currently pointing to, and then bumps the pointer to the next attribute. The name is copied into the buffer, which should be at least B_ATTR_NAME_LENGTH characters long. The copied name is NULL-terminated. When you've asked for every name in the list, GetNextAttrName() returns \c B_ENTRY_NOT_FOUND. \param buffer the buffer the name of the next attribute shall be stored in (must be at least \c B_ATTR_NAME_LENGTH bytes long) \return - \c B_OK: Everything went fine. - \c B_BAD_VALUE: \c NULL \a buffer. - \c B_FILE_ERROR: The object is not initialized. - \c B_ENTRY_NOT_FOUND: There are no more attributes, the last attribute name has already been returned. */ status_t BNode::GetNextAttrName(char *buffer) { // We're allowed to assume buffer is at least // B_ATTR_NAME_LENGTH chars long, but NULLs // are not acceptable. if (buffer == NULL) return B_BAD_VALUE; // /new R5 crashed when passed NULL if (InitAttrDir() != B_OK) return B_FILE_ERROR; BPrivate::Storage::LongDirEntry entry; ssize_t result = _kern_read_dir(fAttrFd, &entry, sizeof(entry), 1); if (result < 0) return result; if (result == 0) return B_ENTRY_NOT_FOUND; strlcpy(buffer, entry.d_name, B_ATTR_NAME_LENGTH); return B_OK; }
struct dirent* readdir(DIR* dir) { ssize_t count; if (dir->seek_position != dir->current_position) { if (do_seek_dir(dir) != 0) return NULL; } if (dir->entries_left > 0) { struct dirent *dirent = (struct dirent *)((uint8 *)&dir->first_entry + dir->next_entry); dir->entries_left--; dir->next_entry += dirent->d_reclen; dir->seek_position++; dir->current_position++; return dirent; } // we need to retrieve new entries count = _kern_read_dir(dir->fd, &dir->first_entry, (char*)dir + DIR_BUFFER_SIZE - (char*)&dir->first_entry, USHRT_MAX); if (count <= 0) { if (count < 0) __set_errno(count); // end of directory return NULL; } dir->entries_left = count - 1; dir->next_entry = dir->first_entry.d_reclen; dir->seek_position++; dir->current_position++; return &dir->first_entry; }
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; }
static int do_seek_dir(DIR* dir) { if (dir->seek_position == dir->current_position) return 0; // If the seek position lies before the current position (the usual case), // rewind to the beginning. if (dir->seek_position < dir->current_position) { status_t status = _kern_rewind_dir(dir->fd); if (status < 0) { __set_errno(status); return -1; } dir->current_position = 0; dir->entries_left = 0; } // Now skip entries until we have reached seek_position. while (dir->seek_position > dir->current_position) { ssize_t count; long toSkip = dir->seek_position - dir->current_position; if (toSkip == dir->entries_left) { // we have to skip exactly all of the currently buffered entries dir->current_position = dir->seek_position; dir->entries_left = 0; return 0; } if (toSkip < dir->entries_left) { // we have to skip only some of the buffered entries for (; toSkip > 0; toSkip--) { struct dirent* entry = (struct dirent*) ((uint8*)&dir->first_entry + dir->next_entry); dir->entries_left--; dir->next_entry += entry->d_reclen; } dir->current_position = dir->seek_position; return 0; } // we have to skip more than the currently buffered entries dir->current_position += dir->entries_left; dir->entries_left = 0; count = _kern_read_dir(dir->fd, &dir->first_entry, (char*)dir + DIR_BUFFER_SIZE - (char*)&dir->first_entry, USHRT_MAX); if (count <= 0) { if (count < 0) __set_errno(count); // end of directory return -1; } dir->next_entry = 0; dir->entries_left = count; } return 0; }