/*! \brief Initializes the BNode's file descriptor to the node referred to by the given FD and path combo. \a path must either be \c NULL, an absolute or a relative path. In the first case, \a fd must not be \c NULL; the node it refers to will be opened. If absolute, \a fd is ignored. If relative and \a fd is >= 0, it will be reckoned off the directory identified by \a fd, otherwise off the current working directory. The method will first try to open the node with read and write permission. If that fails due to a read-only FS or because the user has no write permission for the node, it will re-try opening the node read-only. The \a fCStatus member will be set to the return value of this method. \param fd Either a directory FD or a value < 0. In the latter case \a path must be specified. \param path Either \a NULL in which case \a fd must be given, absolute, or relative to the directory specified by \a fd (if given) or to the current working directory. \param traverse If the node identified by \a fd and \a path is a symlink and \a traverse is \c true, the symlink will be resolved recursively. \return \c B_OK, if everything went fine, another error code otherwise. */ status_t BNode::_SetTo(int fd, const char *path, bool traverse) { Unset(); status_t error = (fd >= 0 || path ? B_OK : B_BAD_VALUE); if (error == B_OK) { int traverseFlag = (traverse ? 0 : O_NOTRAVERSE); fFd = _kern_open(fd, path, O_RDWR | traverseFlag, 0); if (fFd < B_OK && fFd != B_ENTRY_NOT_FOUND) { // opening read-write failed, re-try read-only fFd = _kern_open(fd, path, O_RDONLY | traverseFlag, 0); } if (fFd < 0) error = fFd; else fcntl(fFd, F_SETFD, FD_CLOEXEC); } return fCStatus = error; }
int open(char const *path, int omode, ...) { int retval; retval= _kern_open(path, omode); if(retval< 0) { errno = retval; } return retval; }
static int fuse_open(const char* path, struct fuse_file_info* fi) { PRINTD("##open\n"); // TODO: Do we have a syscall similar to the open syscall in linux which // takes only two args: path and flags with no mask/perms? int fd = _kern_open(-1, path, fi->flags, (FSSH_S_IRWXU | FSSH_S_IRWXG | FSSH_S_IRWXO) & ~sUmask); _kern_close(fd); if (fd < FSSH_B_OK) return _ERR(fd); else return 0; }
status_t Session::LoadFromDirectory(int directoryFD) { TRACE(("load session %s\n", Name())); int fd = _kern_open(directoryFD, Name(), O_RDONLY, 0); if (fd < B_OK) return fd; struct stat stat; if (fstat(fd, &stat) != 0) { close(fd); return errno; } if (stat.st_size > 32768) { // for safety reasons // ToDo: make a bit larger later close(fd); return B_BAD_DATA; } char *buffer = (char *)malloc(stat.st_size); if (buffer == NULL) { close(fd); return B_NO_MEMORY; } if (read(fd, buffer, stat.st_size) < stat.st_size) { free(buffer); close(fd); return B_ERROR; } const char *line = buffer; node_ref nodeRef; while (parse_node_ref(line, nodeRef, &line)) { struct node *node = new_node(nodeRef.device, nodeRef.node); if (node != NULL) { // note: this reverses the order of the nodes in the file node->next = fNodes; fNodes = node; } line++; } free(buffer); close(fd); return B_OK; }
static int fuse_mknod(const char* path, mode_t mode, dev_t rdev) { PRINTD("##mknod\n"); if (S_ISREG(mode)) { int fd = _kern_open(-1, path, FSSH_O_CREAT | FSSH_O_EXCL | FSSH_O_WRONLY, mode); if (fd >= FSSH_B_OK) return _ERR(_kern_close(fd)); return _ERR(fd); } else if (S_ISFIFO(mode)) return _ERR(FSSH_EINVAL); else return _ERR(FSSH_EINVAL); }
static int fuse_write(const char* path, const char* buf, size_t size, off_t offset, struct fuse_file_info* fi) { PRINTD("##write\n"); int fd = _kern_open(-1, path, FSSH_O_WRONLY, (FSSH_S_IRWXU | FSSH_S_IRWXG | FSSH_S_IRWXO) & ~sUmask); if (fd < FSSH_B_OK) return _ERR(fd); int res = _kern_write(fd, offset, buf, size); _kern_close(fd); if (res < FSSH_B_OK) res = _ERR(res); return res; }
/*! \brief Re-initializes the BFile to the file referred to by the supplied path name relative to the specified BDirectory and according to the specified open mode. \param dir the BDirectory, relative to which the file's path name is given \param path the file's path name relative to \a dir \param openMode the mode in which the file should be opened - \c B_OK: Everything went fine. - \c B_BAD_VALUE: \c NULL \a dir or \a path or bad \a openMode. - \c B_ENTRY_NOT_FOUND: File not found or failed to create file. - \c B_FILE_EXISTS: File exists and \c B_FAIL_IF_EXISTS was passed. - \c B_PERMISSION_DENIED: File 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. \todo Implemented using SetTo(BEntry*, uint32). Check, if necessary to reimplement! */ status_t BFile::SetTo(const BDirectory *dir, const char *path, uint32 openMode) { Unset(); if (!dir) return (fCStatus = B_BAD_VALUE); openMode |= O_CLOEXEC; int fd = _kern_open(dir->fDirFd, path, openMode, DEFFILEMODE & ~__gUmask); if (fd >= 0) { set_fd(fd); fMode = openMode; fCStatus = B_OK; } else fCStatus = fd; return fCStatus; }
/*! \brief Re-initializes the BFile to the file referred to by the supplied BEntry and according to the specified open mode. \param entry the BEntry referring to the file \param openMode the mode in which the file should be opened \return - \c B_OK: Everything went fine. - \c B_BAD_VALUE: \c NULL \a entry or bad \a openMode. - \c B_ENTRY_NOT_FOUND: File not found or failed to create file. - \c B_FILE_EXISTS: File exists and \c B_FAIL_IF_EXISTS was passed. - \c B_PERMISSION_DENIED: File 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. \todo Implemented using SetTo(entry_ref*, uint32). Check, if necessary to reimplement! */ status_t BFile::SetTo(const BEntry *entry, uint32 openMode) { Unset(); if (!entry) return (fCStatus = B_BAD_VALUE); if (entry->InitCheck() != B_OK) return (fCStatus = entry->InitCheck()); openMode |= O_CLOEXEC; int fd = _kern_open(entry->fDirFd, entry->fName, openMode | O_CLOEXEC, DEFFILEMODE & ~__gUmask); if (fd >= 0) { set_fd(fd); fMode = openMode; fCStatus = B_OK; } else fCStatus = fd; return fCStatus; }
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); }
int open_executable(char *name, image_type type, const char *rpath, const char *programPath, const char *compatibilitySubDir) { char buffer[PATH_MAX]; int fd = B_ENTRY_NOT_FOUND; if (strchr(name, '/')) { // the name already contains a path, we don't have to search for it fd = _kern_open(-1, name, O_RDONLY, 0); if (fd >= 0 || type == B_APP_IMAGE) return fd; // can't search harder an absolute path add-on name! if (type == B_ADD_ON_IMAGE && name[0] == '/') return fd; // Even though ELF specs don't say this, we give shared libraries // and relative path based add-ons another chance and look // them up in the usual search paths - at // least that seems to be what BeOS does, and since it doesn't hurt... if (type == B_LIBRARY_IMAGE) { // For library (but not add-on), strip any path from name. // Relative path of add-on is kept. const char* paths = strrchr(name, '/') + 1; memmove(name, paths, strlen(paths) + 1); } } // try rpath (DT_RPATH) if (rpath != NULL) { // It consists of a colon-separated search path list. Optionally a // second search path list follows, separated from the first by a // semicolon. const char *semicolon = strchr(rpath, ';'); const char *firstList = (semicolon ? rpath : NULL); const char *secondList = (semicolon ? semicolon + 1 : rpath); // If there is no ';', we set only secondList to simplify things. if (firstList) { fd = search_executable_in_path_list(name, firstList, semicolon - firstList, programPath, NULL, buffer, sizeof(buffer)); } if (fd < 0) { fd = search_executable_in_path_list(name, secondList, strlen(secondList), programPath, NULL, buffer, sizeof(buffer)); } } // If not found yet, let's evaluate the system path variables to find the // shared object. if (fd < 0) { if (const char *paths = search_path_for_type(type)) { fd = search_executable_in_path_list(name, paths, strlen(paths), programPath, compatibilitySubDir, buffer, sizeof(buffer)); // If not found and a compatibility sub directory has been // specified, look again in the standard search paths. if (fd == B_ENTRY_NOT_FOUND && compatibilitySubDir != NULL) { fd = search_executable_in_path_list(name, paths, strlen(paths), programPath, NULL, buffer, sizeof(buffer)); } } } if (fd >= 0) { // we found it, copy path! TRACE(("runtime_loader: open_executable(%s): found at %s\n", name, buffer)); strlcpy(name, buffer, PATH_MAX); } return fd; }