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; }
int _lstat_current(const char* path, struct stat* stat) { int status = _kern_read_stat(-1, path, false, stat, sizeof(struct stat)); RETURN_AND_SET_ERRNO(status); }
int _fstat_current(int fd, struct stat* stat) { int status = _kern_read_stat(fd, NULL, false, stat, sizeof(struct stat)); RETURN_AND_SET_ERRNO(status); }
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 Fills in the given stat structure with \code stat() \endcode information for this object. \param st a pointer to a stat structure to be filled in \return - \c B_OK: Everything went fine. - \c B_BAD_VALUE: \c NULL \a st. - another error code, e.g., if the object wasn't properly initialized */ status_t BNode::GetStat(struct stat *st) const { return (fCStatus != B_OK) ? fCStatus : _kern_read_stat(fFd, NULL, false, st, sizeof(struct stat)); }
int fstatat(int fd, const char *path, struct stat *st, int flag) { int status = _kern_read_stat(fd, path, (flag & AT_SYMLINK_NOFOLLOW) == 0, st, sizeof(struct stat)); RETURN_AND_SET_ERRNO(status); }
static fssh_dev_t get_volume_id() { struct fssh_stat st; fssh_status_t error = _kern_read_stat(-1, kMountPoint, false, &st, sizeof(st)); if (error != FSSH_B_OK) return error; return st.fssh_st_dev; }
dev_t dev_for_path(const char *path) { struct stat stat; int status = _kern_read_stat(-1, path, true, &stat, sizeof(struct stat)); if (status == B_OK) return stat.st_dev; RETURN_AND_SET_ERRNO(status); }
int fuse_getattr(const char* path, struct stat* stbuf) { PRINTD("##getattr\n"); struct fssh_stat f_stbuf; fssh_status_t status = _kern_read_stat(-1, path, false, &f_stbuf, sizeof(f_stbuf)); fromFsshStatToStat(&f_stbuf, stbuf); if (gIsDebug) printf("GETATTR returned: %d\n", status); return _ERR(status); }
static fssh_dev_t get_volume_id() { struct fssh_stat st; fssh_status_t error = _kern_read_stat(-1, kMountPoint, false, &st, sizeof(st)); if (error != FSSH_B_OK) { fprintf(stderr, "Error: Failed to stat() mount point: %s\n", fssh_strerror(error)); return error; } return st.fssh_st_dev; }
status_t BDirectory::_GetStatFor(const char* path, struct stat* st) const { if (!st) return B_BAD_VALUE; if (InitCheck() != B_OK) return B_NO_INIT; if (path != NULL) { if (path[0] == '\0') return B_ENTRY_NOT_FOUND; return _kern_read_stat(fDirFd, path, false, st, sizeof(struct stat)); } return GetStat(st); }
static fssh_status_t remove_entry(int dir, const char *entry, bool recursive, bool force) { // stat the file struct fssh_stat st; fssh_status_t error = _kern_read_stat(dir, entry, false, &st, sizeof(st)); if (error != FSSH_B_OK) { if (force && error == FSSH_B_ENTRY_NOT_FOUND) return FSSH_B_OK; fprintf(stderr, "Error: Failed to remove \"%s\": %s\n", entry, fssh_strerror(error)); return error; } if (FSSH_S_ISDIR(st.fssh_st_mode)) { if (!recursive) { fprintf(stderr, "Error: \"%s\" is a directory.\n", entry); // TODO: get the full path return FSSH_EISDIR; } // remove the contents error = remove_dir_contents(dir, entry, force); if (error != FSSH_B_OK) return error; // remove the directory error = _kern_remove_dir(dir, entry); if (error != FSSH_B_OK) { fprintf(stderr, "Error: Failed to remove directory \"%s\": %s\n", entry, fssh_strerror(error)); return error; } } else { // remove the entry error = _kern_unlink(dir, entry); if (error != FSSH_B_OK) { fprintf(stderr, "Error: Failed to remove entry \"%s\": %s\n", entry, fssh_strerror(error)); return error; } } return FSSH_B_OK; }
static fssh_status_t move_entry(int dir, const char *entry, int targetDir, const char* target, bool force) { // stat the file struct fssh_stat st; fssh_status_t status = _kern_read_stat(dir, entry, false, &st, sizeof(st)); if (status != FSSH_B_OK) { if (force && status == FSSH_B_ENTRY_NOT_FOUND) return FSSH_B_OK; fprintf(stderr, "Error: Failed to move \"%s\": %s\n", entry, fssh_strerror(status)); return status; } return _kern_rename(dir, entry, targetDir, target); }
static int search_executable_in_path_list(const char *name, const char *pathList, int pathListLen, const char *programPath, const char *compatibilitySubDir, char *pathBuffer, size_t pathBufferLength) { const char *pathListEnd = pathList + pathListLen; status_t status = B_ENTRY_NOT_FOUND; TRACE(("runtime_loader: search_container_in_path_list() %s in %.*s\n", name, pathListLen, pathList)); while (pathListLen > 0) { const char *pathEnd = pathList; int fd; // find the next ':' or run till the end of the string while (pathEnd < pathListEnd && *pathEnd != ':') pathEnd++; fd = try_open_executable(pathList, pathEnd - pathList, name, programPath, compatibilitySubDir, pathBuffer, pathBufferLength); if (fd >= 0) { // see if it's a dir struct stat stat; status = _kern_read_stat(fd, NULL, true, &stat, sizeof(struct stat)); if (status == B_OK) { if (!S_ISDIR(stat.st_mode)) return fd; status = B_IS_A_DIRECTORY; } _kern_close(fd); } pathListLen = pathListEnd - pathEnd - 1; pathList = pathEnd + 1; } return status; }
static fssh_status_t command_ln(int argc, const char* const* argv) { bool force = false; bool symbolic = false; bool dereference = true; // 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; case 's': symbolic = true; break; case 'n': dereference = false; break; default: fprintf(stderr, "Error: Unknown option \"-%c\"\n", arg[i]); return FSSH_B_BAD_VALUE; } } } if (argc - argi != 2) { fprintf(stderr, "Usage: %s [Options] <source> <target>\n", argv[0]); return FSSH_B_BAD_VALUE; } const char *source = argv[argi]; const char *target = argv[argi + 1]; // check, if the the target is an existing directory struct fssh_stat st; char targetBuffer[FSSH_B_PATH_NAME_LENGTH]; fssh_status_t error = _kern_read_stat(-1, target, dereference, &st, sizeof(st)); if (error == FSSH_B_OK) { if (FSSH_S_ISDIR(st.fssh_st_mode)) { // get source leaf char leaf[FSSH_B_FILE_NAME_LENGTH]; error = get_last_path_component(source, leaf, sizeof(leaf)); if (error != FSSH_B_OK) { fprintf(stderr, "Error: Failed to get leaf name of source " "path: %s\n", fssh_strerror(error)); return error; } // compose a new path int len = strlen(target) + 1 + strlen(leaf); if (len > (int)sizeof(targetBuffer)) { fprintf(stderr, "Error: Resulting target path is too long.\n"); return FSSH_B_BAD_VALUE; } strcpy(targetBuffer, target); strcat(targetBuffer, "/"); strcat(targetBuffer, leaf); target = targetBuffer; } } // check, if the target exists error = _kern_read_stat(-1, target, false, &st, sizeof(st)); if (error == FSSH_B_OK) { if (!force) { fprintf(stderr, "Error: Can't create link. \"%s\" is in the way.\n", target); return FSSH_B_FILE_EXISTS; } // unlink the entry error = _kern_unlink(-1, target); if (error != FSSH_B_OK) { fprintf(stderr, "Error: Failed to remove \"%s\" to make way for " "link: %s\n", target, fssh_strerror(error)); return error; } } // finally create the link if (symbolic) { error = _kern_create_symlink(-1, target, source, FSSH_S_IRWXU | FSSH_S_IRWXG | FSSH_S_IRWXO); } else error = _kern_create_link(target, source); if (error != FSSH_B_OK) { fprintf(stderr, "Error: Failed to create link: %s\n", fssh_strerror(error)); } return error; }
void register_image(image_t* image, int fd, const char* path) { struct stat stat; image_info info; // TODO: set these correctly info.id = 0; info.type = image->type; info.sequence = 0; info.init_order = 0; info.init_routine = (void (*)())image->init_routine; info.term_routine = (void (*)())image->term_routine; if (_kern_read_stat(fd, NULL, false, &stat, sizeof(struct stat)) == B_OK) { info.device = stat.st_dev; info.node = stat.st_ino; } else { info.device = -1; info.node = -1; } // We may have split segments into separate regions. Compute the correct // segments for the image info. addr_t textBase = 0; addr_t textEnd = 0; addr_t dataBase = 0; addr_t dataEnd = 0; for (uint32 i= 0; i < image->num_regions; i++) { addr_t base = image->regions[i].vmstart; addr_t end = base + image->regions[i].vmsize; if (image->regions[i].flags & RFLAG_RW) { // data if (dataBase == 0) { dataBase = base; dataEnd = end; } else { dataBase = std::min(dataBase, base); dataEnd = std::max(dataEnd, end); } } else { // text if (textBase == 0) { textBase = base; textEnd = end; } else { textBase = std::min(textBase, base); textEnd = std::max(textEnd, end); } } } strlcpy(info.name, path, sizeof(info.name)); info.text = (void*)textBase; info.text_size = textEnd - textBase; info.data = (void*)dataBase; info.data_size = dataEnd - dataBase; info.api_version = image->api_version; info.abi = image->abi; image->id = _kern_register_image(&info, sizeof(image_info)); }
static int try_open_executable(const char *dir, int dirLength, const char *name, const char *programPath, const char *compatibilitySubDir, char *path, size_t pathLength) { size_t nameLength = strlen(name); struct stat stat; status_t status; // construct the path if (dirLength > 0) { char *buffer = path; size_t subDirLen = 0; if (programPath == NULL) programPath = gProgramArgs->program_path; if (dirLength >= 2 && strncmp(dir, "%A", 2) == 0) { // Replace %A with current app folder path (of course, // this must be the first part of the path) char *lastSlash = strrchr(programPath, '/'); int bytesCopied; // copy what's left (when the application name is removed) if (lastSlash != NULL) { strlcpy(buffer, programPath, std::min((long)pathLength, lastSlash + 1 - programPath)); } else strlcpy(buffer, ".", pathLength); bytesCopied = strlen(buffer); buffer += bytesCopied; pathLength -= bytesCopied; dir += 2; dirLength -= 2; } else if (compatibilitySubDir != NULL) { // We're looking for a library or an add-on and the executable has // not been compiled with a compiler compatible with the one the // OS has been built with. Thus we only look in specific subdirs. subDirLen = strlen(compatibilitySubDir) + 1; } if (dirLength + 1 + subDirLen + nameLength >= pathLength) return B_NAME_TOO_LONG; memcpy(buffer, dir, dirLength); buffer[dirLength] = '/'; if (subDirLen > 0) { memcpy(buffer + dirLength + 1, compatibilitySubDir, subDirLen - 1); buffer[dirLength + subDirLen] = '/'; } strcpy(buffer + dirLength + 1 + subDirLen, name); } else { if (nameLength >= pathLength) return B_NAME_TOO_LONG; strcpy(path + dirLength + 1, name); } TRACE(("runtime_loader: try_open_container(): %s\n", path)); // Test if the target is a symbolic link, and correct the path in this case status = _kern_read_stat(-1, path, false, &stat, sizeof(struct stat)); if (status < B_OK) return status; if (S_ISLNK(stat.st_mode)) { char buffer[PATH_MAX]; size_t length = PATH_MAX - 1; char *lastSlash; // it's a link, indeed status = _kern_read_link(-1, path, buffer, &length); if (status < B_OK) return status; buffer[length] = '\0'; lastSlash = strrchr(path, '/'); if (buffer[0] != '/' && lastSlash != NULL) { // relative path strlcpy(lastSlash + 1, buffer, lastSlash + 1 - path + pathLength); } else strlcpy(path, buffer, pathLength); } return _kern_open(-1, path, O_RDONLY, 0); }
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); }
static void list_entry(const char* file, const char* name = NULL) { // construct path, if a leaf name is given std::string path; if (name) { path = file; path += '/'; path += name; file = path.c_str(); } else name = file; // stat the 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)); return; } // get time struct tm time; time_t fileTime = st.fssh_st_mtime; localtime_r(&fileTime, &time); // get permissions std::string permissions; fssh_mode_t mode = st.fssh_st_mode; // user permissions += ((mode & FSSH_S_IRUSR) ? 'r' : '-'); permissions += ((mode & FSSH_S_IWUSR) ? 'w' : '-'); if (mode & FSSH_S_ISUID) permissions += 's'; else permissions += ((mode & FSSH_S_IXUSR) ? 'x' : '-'); // group permissions += ((mode & FSSH_S_IRGRP) ? 'r' : '-'); permissions += ((mode & FSSH_S_IWGRP) ? 'w' : '-'); if (mode & FSSH_S_ISGID) permissions += 's'; else permissions += ((mode & FSSH_S_IXGRP) ? 'x' : '-'); // others permissions += ((mode & FSSH_S_IROTH) ? 'r' : '-'); permissions += ((mode & FSSH_S_IWOTH) ? 'w' : '-'); permissions += ((mode & FSSH_S_IXOTH) ? 'x' : '-'); // get file type char fileType = '?'; if (FSSH_S_ISREG(mode)) { fileType = '-'; } else if (FSSH_S_ISLNK(mode)) { fileType = 'l'; } else if (FSSH_S_ISBLK(mode)) { fileType = 'b'; } else if (FSSH_S_ISDIR(mode)) { fileType = 'd'; } else if (FSSH_S_ISCHR(mode)) { fileType = 'c'; } else if (FSSH_S_ISFIFO(mode)) { fileType = 'f'; } else if (FSSH_S_ISINDEX(mode)) { fileType = 'i'; } // get link target std::string nameSuffix; if (FSSH_S_ISLNK(mode)) { char buffer[FSSH_B_PATH_NAME_LENGTH]; fssh_size_t size = sizeof(buffer) - 1; error = _kern_read_link(-1, file, buffer, &size); if (error != FSSH_B_OK) snprintf(buffer, sizeof(buffer), "(%s)", fssh_strerror(error)); buffer[size] = '\0'; nameSuffix += " -> "; nameSuffix += buffer; } printf("%c%s %2d %2d %10" FSSH_B_PRIdOFF " %d-%02d-%02d %02d:%02d:%02d %s%s\n", fileType, permissions.c_str(), (int)st.fssh_st_uid, (int)st.fssh_st_gid, st.fssh_st_size, 1900 + time.tm_year, 1 + time.tm_mon, time.tm_mday, time.tm_hour, time.tm_min, time.tm_sec, name, nameSuffix.c_str()); }
static fssh_status_t create_dir(const char *path, bool createParents) { // stat the entry struct fssh_stat st; fssh_status_t error = _kern_read_stat(-1, path, false, &st, sizeof(st)); if (error == FSSH_B_OK) { if (createParents && FSSH_S_ISDIR(st.fssh_st_mode)) return FSSH_B_OK; fprintf(stderr, "Error: Cannot make dir, entry \"%s\" is in the way.\n", path); return FSSH_B_FILE_EXISTS; } // the dir doesn't exist yet // if we shall create all parents, do that first if (createParents) { // create the parent dir path // eat the trailing '/'s int len = strlen(path); while (len > 0 && path[len - 1] == '/') len--; // eat the last path component while (len > 0 && path[len - 1] != '/') len--; // eat the trailing '/'s while (len > 0 && path[len - 1] == '/') len--; // Now either nothing remains, which means we had a single component, // a root subdir -- in those cases we can just fall through (we should // actually never be here in case of the root dir, but anyway) -- or // there is something left, which we can call a parent directory and // try to create it. if (len > 0) { char *parentPath = (char*)malloc(len + 1); if (!parentPath) { fprintf(stderr, "Error: Failed to allocate memory for parent " "path.\n"); return FSSH_B_NO_MEMORY; } memcpy(parentPath, path, len); parentPath[len] = '\0'; error = create_dir(parentPath, createParents); free(parentPath); if (error != FSSH_B_OK) return error; } } // make the directory error = _kern_create_dir(-1, path, (FSSH_S_IRWXU | FSSH_S_IRWXG | FSSH_S_IRWXO) & ~sUmask); if (error != FSSH_B_OK) { fprintf(stderr, "Error: Failed to make directory \"%s\": %s\n", path, fssh_strerror(error)); return error; } return FSSH_B_OK; }