static int fuse_readlink(const char* path, char* buffer, size_t size) { PRINTD("##readlink\n"); fssh_size_t n_size = size - 1; fssh_status_t st = _kern_read_link(-1, path, buffer, &n_size); if (st >= FSSH_B_OK) buffer[n_size] = '\0'; return _ERR(st); }
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 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()); }