Beispiel #1
0
/*!	\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;
}
Beispiel #2
0
int
open(char const *path, int omode, ...)
{
	int retval;

	retval= _kern_open(path, omode);

	if(retval< 0) {
		errno = retval;
	}

	return retval;
}
Beispiel #3
0
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;
}
Beispiel #4
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;
}
Beispiel #5
0
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);
}
Beispiel #6
0
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;
}
Beispiel #7
0
/*! \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;
}
Beispiel #8
0
/*! \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;
}
Beispiel #9
0
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);
}
Beispiel #10
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;
}