103544bf0SAugustin Cavalier/*
203544bf0SAugustin Cavalier * Copyright 2017, Haiku, Inc. All rights reserved.
303544bf0SAugustin Cavalier * Distributed under the terms of the MIT License.
403544bf0SAugustin Cavalier */
503544bf0SAugustin Cavalier
603544bf0SAugustin Cavalier/*!	Shim over the host Haiku fs_attr API */
703544bf0SAugustin Cavalier
803544bf0SAugustin Cavalier
903544bf0SAugustin Cavalier#ifdef BUILDING_FS_SHELL
1003544bf0SAugustin Cavalier#	include "compat.h"
1103544bf0SAugustin Cavalier#	define B_OK					0
1203544bf0SAugustin Cavalier#	define B_BAD_VALUE			EINVAL
1303544bf0SAugustin Cavalier#	define B_FILE_ERROR			EBADF
1403544bf0SAugustin Cavalier#	define B_ERROR				EINVAL
1503544bf0SAugustin Cavalier#	define B_ENTRY_NOT_FOUND	ENOENT
1603544bf0SAugustin Cavalier#	define B_NO_MEMORY			ENOMEM
1703544bf0SAugustin Cavalier#else
1803544bf0SAugustin Cavalier#	include <syscalls.h>
1903544bf0SAugustin Cavalier
2003544bf0SAugustin Cavalier#	include "fs_impl.h"
2103544bf0SAugustin Cavalier#	include "fs_descriptors.h"
2203544bf0SAugustin Cavalier#endif
2303544bf0SAugustin Cavalier
2403544bf0SAugustin Cavalier#include <dirent.h>
2503544bf0SAugustin Cavalier#include <errno.h>
2603544bf0SAugustin Cavalier#include <fcntl.h>
2703544bf0SAugustin Cavalier#include <stdio.h>
2803544bf0SAugustin Cavalier#include <stdlib.h>
2903544bf0SAugustin Cavalier#include <unistd.h>
3003544bf0SAugustin Cavalier#include <sys/stat.h>
3103544bf0SAugustin Cavalier
3203544bf0SAugustin Cavalier#include <map>
3303544bf0SAugustin Cavalier#include <string>
3403544bf0SAugustin Cavalier
3503544bf0SAugustin Cavalier#include <fs_attr.h>
3603544bf0SAugustin Cavalier
3703544bf0SAugustin Cavalier
3803544bf0SAugustin Cavaliernamespace BPrivate {}
3903544bf0SAugustin Cavalierusing namespace BPrivate;
4003544bf0SAugustin Cavalier
4103544bf0SAugustin Cavalier
4203544bf0SAugustin Cavaliernamespace {
4303544bf0SAugustin Cavalier
4403544bf0SAugustin Cavalier// LocalFD
4503544bf0SAugustin Cavalier#include "LocalFD.h"
4603544bf0SAugustin Cavalier
4703544bf0SAugustin Cavalier} // unnamed namspace
4803544bf0SAugustin Cavalier
4903544bf0SAugustin Cavalier
5003544bf0SAugustin Cavalier// # pragma mark - Public API
5103544bf0SAugustin Cavalier
5203544bf0SAugustin Cavalier
5303544bf0SAugustin Cavalier// fs_open_attr_dir
5403544bf0SAugustin Cavalierextern "C" DIR *
55648f0d5fSAugustin Cavalier_haiku_build_fs_open_attr_dir(const char *path)
5603544bf0SAugustin Cavalier{
5703544bf0SAugustin Cavalier	return fs_open_attr_dir(path);
5803544bf0SAugustin Cavalier}
5903544bf0SAugustin Cavalier
60648f0d5fSAugustin Cavalier// fs_lopen_attr_dir
61648f0d5fSAugustin Cavalierextern "C" DIR*
62648f0d5fSAugustin Cavalier_haiku_build_fs_lopen_attr_dir(const char *path)
63648f0d5fSAugustin Cavalier{
64648f0d5fSAugustin Cavalier	return fs_lopen_attr_dir(path);
65648f0d5fSAugustin Cavalier}
66648f0d5fSAugustin Cavalier
6703544bf0SAugustin Cavalier// fs_fopen_attr_dir
6803544bf0SAugustin Cavalierextern "C" DIR*
69648f0d5fSAugustin Cavalier_haiku_build_fs_fopen_attr_dir(int fd)
7003544bf0SAugustin Cavalier{
7103544bf0SAugustin Cavalier	LocalFD localFD;
7203544bf0SAugustin Cavalier	status_t error = localFD.Init(fd);
7303544bf0SAugustin Cavalier	if (error != B_OK) {
7403544bf0SAugustin Cavalier		errno = error;
7503544bf0SAugustin Cavalier		return NULL;
7603544bf0SAugustin Cavalier	}
7703544bf0SAugustin Cavalier
7803544bf0SAugustin Cavalier	if (localFD.FD() < 0) {
7903544bf0SAugustin Cavalier		return fs_lopen_attr_dir(localFD.Path());
8003544bf0SAugustin Cavalier	} else {
8103544bf0SAugustin Cavalier		return fs_fopen_attr_dir(localFD.FD());
8203544bf0SAugustin Cavalier	}
8303544bf0SAugustin Cavalier}
8403544bf0SAugustin Cavalier
8503544bf0SAugustin Cavalier// fs_close_attr_dir
8603544bf0SAugustin Cavalierextern "C" int
87648f0d5fSAugustin Cavalier_haiku_build_fs_close_attr_dir(DIR *dir)
8803544bf0SAugustin Cavalier{
8903544bf0SAugustin Cavalier	return fs_close_attr_dir(dir);
9003544bf0SAugustin Cavalier}
9103544bf0SAugustin Cavalier
9203544bf0SAugustin Cavalier// fs_read_attr_dir
9303544bf0SAugustin Cavalierextern "C" struct dirent *
94648f0d5fSAugustin Cavalier_haiku_build_fs_read_attr_dir(DIR *dir)
9503544bf0SAugustin Cavalier{
9603544bf0SAugustin Cavalier	return fs_read_attr_dir(dir);
9703544bf0SAugustin Cavalier}
9803544bf0SAugustin Cavalier
9903544bf0SAugustin Cavalier// fs_rewind_attr_dir
10003544bf0SAugustin Cavalierextern "C" void
101648f0d5fSAugustin Cavalier_haiku_build_fs_rewind_attr_dir(DIR *dir)
10203544bf0SAugustin Cavalier{
10303544bf0SAugustin Cavalier	return fs_rewind_attr_dir(dir);
10403544bf0SAugustin Cavalier}
10503544bf0SAugustin Cavalier
10603544bf0SAugustin Cavalier// fs_fopen_attr
10703544bf0SAugustin Cavalierextern "C" int
108648f0d5fSAugustin Cavalier_haiku_build_fs_fopen_attr(int fd, const char *attribute, uint32 type, int openMode)
10903544bf0SAugustin Cavalier{
11003544bf0SAugustin Cavalier	if (fd < 0) {
11103544bf0SAugustin Cavalier		errno = B_BAD_VALUE;
11203544bf0SAugustin Cavalier		return -1;
11303544bf0SAugustin Cavalier	}
11403544bf0SAugustin Cavalier
11503544bf0SAugustin Cavalier	LocalFD localFD;
11603544bf0SAugustin Cavalier	status_t error = localFD.Init(fd);
11703544bf0SAugustin Cavalier	if (error != B_OK) {
11803544bf0SAugustin Cavalier		errno = error;
11903544bf0SAugustin Cavalier		return -1;
12003544bf0SAugustin Cavalier	}
12103544bf0SAugustin Cavalier
12203544bf0SAugustin Cavalier	if (localFD.FD() < 0) {
12303544bf0SAugustin Cavalier		return fs_open_attr(localFD.Path(), attribute, type,
12403544bf0SAugustin Cavalier			openMode | O_NOTRAVERSE);
12503544bf0SAugustin Cavalier	} else {
12603544bf0SAugustin Cavalier		return fs_fopen_attr(localFD.FD(), attribute, type, openMode);
12703544bf0SAugustin Cavalier	}
12803544bf0SAugustin Cavalier}
12903544bf0SAugustin Cavalier
13003544bf0SAugustin Cavalier// fs_close_attr
13103544bf0SAugustin Cavalierextern "C" int
132648f0d5fSAugustin Cavalier_haiku_build_fs_close_attr(int fd)
13303544bf0SAugustin Cavalier{
13403544bf0SAugustin Cavalier	return fs_close_attr(fd);
13503544bf0SAugustin Cavalier}
13603544bf0SAugustin Cavalier
13703544bf0SAugustin Cavalier// fs_read_attr
13803544bf0SAugustin Cavalierextern "C" ssize_t
139648f0d5fSAugustin Cavalier_haiku_build_fs_read_attr(int fd, const char* attribute, uint32 type, off_t pos,
14003544bf0SAugustin Cavalier	void *buffer, size_t readBytes)
14103544bf0SAugustin Cavalier{
14203544bf0SAugustin Cavalier	LocalFD localFD;
14303544bf0SAugustin Cavalier	status_t error = localFD.Init(fd);
14403544bf0SAugustin Cavalier	if (error != B_OK) {
14503544bf0SAugustin Cavalier		errno = error;
14603544bf0SAugustin Cavalier		return -1;
14703544bf0SAugustin Cavalier	}
14803544bf0SAugustin Cavalier
14903544bf0SAugustin Cavalier	ssize_t bytesRead;
15003544bf0SAugustin Cavalier	if (localFD.FD() < 0) {
15103544bf0SAugustin Cavalier		int fd = open(localFD.Path(), O_RDONLY | O_NOTRAVERSE);
15203544bf0SAugustin Cavalier		bytesRead = fs_read_attr(fd, attribute, type,
15303544bf0SAugustin Cavalier			pos, buffer, readBytes);
15403544bf0SAugustin Cavalier		close(fd);
15503544bf0SAugustin Cavalier	} else {
15603544bf0SAugustin Cavalier		bytesRead = fs_read_attr(localFD.FD(), attribute, type,
15703544bf0SAugustin Cavalier			pos, buffer, readBytes);
15803544bf0SAugustin Cavalier	}
15903544bf0SAugustin Cavalier	if (bytesRead < 0) {
16003544bf0SAugustin Cavalier		// Make sure, the error code is B_ENTRY_NOT_FOUND, if the attribute
16103544bf0SAugustin Cavalier		// doesn't exist.
16203544bf0SAugustin Cavalier		if (errno == ENOATTR || errno == ENODATA)
16303544bf0SAugustin Cavalier			errno = B_ENTRY_NOT_FOUND;
16403544bf0SAugustin Cavalier		return -1;
16503544bf0SAugustin Cavalier	}
16603544bf0SAugustin Cavalier
16703544bf0SAugustin Cavalier	return bytesRead;
16803544bf0SAugustin Cavalier}
16903544bf0SAugustin Cavalier
17003544bf0SAugustin Cavalier// fs_write_attr
17103544bf0SAugustin Cavalierextern "C" ssize_t
172648f0d5fSAugustin Cavalier_haiku_build_fs_write_attr(int fd, const char* attribute, uint32 type, off_t pos,
17303544bf0SAugustin Cavalier	const void *buffer, size_t writeBytes)
17403544bf0SAugustin Cavalier{
17503544bf0SAugustin Cavalier	LocalFD localFD;
17603544bf0SAugustin Cavalier	status_t error = localFD.Init(fd);
17703544bf0SAugustin Cavalier	if (error != B_OK) {
17803544bf0SAugustin Cavalier		errno = error;
17903544bf0SAugustin Cavalier		return -1;
18003544bf0SAugustin Cavalier	}
18103544bf0SAugustin Cavalier
18203544bf0SAugustin Cavalier	ssize_t written;
18303544bf0SAugustin Cavalier	if (localFD.FD() < 0) {
18403544bf0SAugustin Cavalier		int fd = open(localFD.Path(), O_NOTRAVERSE | O_WRONLY);
18503544bf0SAugustin Cavalier		written = fs_write_attr(fd, attribute, type,
18603544bf0SAugustin Cavalier			pos, buffer, writeBytes);
18703544bf0SAugustin Cavalier		close(fd);
18803544bf0SAugustin Cavalier	} else {
18903544bf0SAugustin Cavalier		written = fs_write_attr(localFD.FD(), attribute, type,
19003544bf0SAugustin Cavalier			pos, buffer, writeBytes);
19103544bf0SAugustin Cavalier	}
19203544bf0SAugustin Cavalier
19303544bf0SAugustin Cavalier	return written;
19403544bf0SAugustin Cavalier}
19503544bf0SAugustin Cavalier
19603544bf0SAugustin Cavalier// fs_remove_attr
19703544bf0SAugustin Cavalierextern "C" int
198648f0d5fSAugustin Cavalier_haiku_build_fs_remove_attr(int fd, const char* attribute)
19903544bf0SAugustin Cavalier{
20003544bf0SAugustin Cavalier	LocalFD localFD;
20103544bf0SAugustin Cavalier	status_t error = localFD.Init(fd);
20203544bf0SAugustin Cavalier	if (error != B_OK) {
20303544bf0SAugustin Cavalier		errno = error;
20403544bf0SAugustin Cavalier		return -1;
20503544bf0SAugustin Cavalier	}
20603544bf0SAugustin Cavalier
20703544bf0SAugustin Cavalier	// remove attribute
20803544bf0SAugustin Cavalier	int result;
20903544bf0SAugustin Cavalier	if (localFD.FD() < 0) {
21003544bf0SAugustin Cavalier		int fd = open(localFD.Path(), O_NOTRAVERSE | O_WRONLY);
21103544bf0SAugustin Cavalier		result = fs_remove_attr(fd, attribute);
21203544bf0SAugustin Cavalier		close(fd);
21303544bf0SAugustin Cavalier	} else {
21403544bf0SAugustin Cavalier		result = fs_remove_attr(localFD.FD(), attribute);
21503544bf0SAugustin Cavalier	}
21603544bf0SAugustin Cavalier
21703544bf0SAugustin Cavalier	if (result < 0) {
21803544bf0SAugustin Cavalier		// Make sure, the error code is B_ENTRY_NOT_FOUND, if the attribute
21903544bf0SAugustin Cavalier		// doesn't exist.
22003544bf0SAugustin Cavalier		if (errno == ENOATTR || errno == ENODATA)
22103544bf0SAugustin Cavalier			errno = B_ENTRY_NOT_FOUND;
22203544bf0SAugustin Cavalier		return -1;
22303544bf0SAugustin Cavalier	}
22403544bf0SAugustin Cavalier	return 0;
22503544bf0SAugustin Cavalier}
22603544bf0SAugustin Cavalier
22703544bf0SAugustin Cavalier// fs_stat_attr
22803544bf0SAugustin Cavalierextern "C" int
229648f0d5fSAugustin Cavalier_haiku_build_fs_stat_attr(int fd, const char *attribute, struct attr_info *attrInfo)
23003544bf0SAugustin Cavalier{
23103544bf0SAugustin Cavalier	if (!attribute || !attrInfo) {
23203544bf0SAugustin Cavalier		errno = B_BAD_VALUE;
23303544bf0SAugustin Cavalier		return -1;
23403544bf0SAugustin Cavalier	}
23503544bf0SAugustin Cavalier
23603544bf0SAugustin Cavalier	LocalFD localFD;
23703544bf0SAugustin Cavalier	status_t error = localFD.Init(fd);
23803544bf0SAugustin Cavalier	if (error != B_OK) {
23903544bf0SAugustin Cavalier		errno = error;
24003544bf0SAugustin Cavalier		return -1;
24103544bf0SAugustin Cavalier	}
24203544bf0SAugustin Cavalier
24303544bf0SAugustin Cavalier	int result;
24403544bf0SAugustin Cavalier	if (localFD.FD() < 0) {
24503544bf0SAugustin Cavalier		int fd = open(localFD.Path(), O_NOTRAVERSE | O_RDONLY);
24603544bf0SAugustin Cavalier		result = fs_stat_attr(fd, attribute, attrInfo);
24703544bf0SAugustin Cavalier		close(fd);
24803544bf0SAugustin Cavalier	} else {
24903544bf0SAugustin Cavalier		result = fs_stat_attr(localFD.FD(), attribute, attrInfo);
25003544bf0SAugustin Cavalier	}
25103544bf0SAugustin Cavalier
25203544bf0SAugustin Cavalier	return result;
25303544bf0SAugustin Cavalier}
25403544bf0SAugustin Cavalier
25503544bf0SAugustin Cavalier
25603544bf0SAugustin Cavalier// #pragma mark - Private Syscalls
25703544bf0SAugustin Cavalier
25803544bf0SAugustin Cavalier
25903544bf0SAugustin Cavalier#ifndef BUILDING_FS_SHELL
26003544bf0SAugustin Cavalier
26103544bf0SAugustin Cavalier// _kern_open_attr_dir
26203544bf0SAugustin Cavalierint
26303544bf0SAugustin Cavalier_kern_open_attr_dir(int fd, const char *path)
26403544bf0SAugustin Cavalier{
26503544bf0SAugustin Cavalier	// get node ref for the node
26603544bf0SAugustin Cavalier	struct stat st;
26703544bf0SAugustin Cavalier	status_t error = _kern_read_stat(fd, path, false, &st,
26803544bf0SAugustin Cavalier		sizeof(struct stat));
26903544bf0SAugustin Cavalier	if (error != B_OK) {
27003544bf0SAugustin Cavalier		errno = error;
27103544bf0SAugustin Cavalier		return -1;
27203544bf0SAugustin Cavalier	}
27303544bf0SAugustin Cavalier	NodeRef ref(st);
27403544bf0SAugustin Cavalier
27503544bf0SAugustin Cavalier	DIR* dir;
27603544bf0SAugustin Cavalier	if (path) {
27703544bf0SAugustin Cavalier		// If a path was given, get a usable path.
27803544bf0SAugustin Cavalier		string realPath;
27903544bf0SAugustin Cavalier		status_t error = get_path(fd, path, realPath);
28003544bf0SAugustin Cavalier		if (error != B_OK)
28103544bf0SAugustin Cavalier			return error;
28203544bf0SAugustin Cavalier
283648f0d5fSAugustin Cavalier		dir = _haiku_build_fs_open_attr_dir(realPath.c_str());
28403544bf0SAugustin Cavalier	} else
285648f0d5fSAugustin Cavalier		dir = _haiku_build_fs_fopen_attr_dir(fd);
28603544bf0SAugustin Cavalier
28703544bf0SAugustin Cavalier	if (!dir)
28803544bf0SAugustin Cavalier		return errno;
28903544bf0SAugustin Cavalier
29003544bf0SAugustin Cavalier	// create descriptor
29103544bf0SAugustin Cavalier	AttrDirDescriptor *descriptor = new AttrDirDescriptor(dir, ref);
29203544bf0SAugustin Cavalier	return add_descriptor(descriptor);
29303544bf0SAugustin Cavalier}
29403544bf0SAugustin Cavalier
29503544bf0SAugustin Cavalier// _kern_rename_attr
29603544bf0SAugustin Cavalierstatus_t
29703544bf0SAugustin Cavalier_kern_rename_attr(int fromFile, const char *fromName, int toFile,
29803544bf0SAugustin Cavalier	const char *toName)
29903544bf0SAugustin Cavalier{
30003544bf0SAugustin Cavalier	// not supported ATM
30103544bf0SAugustin Cavalier	return B_BAD_VALUE;
30203544bf0SAugustin Cavalier}
30303544bf0SAugustin Cavalier
30403544bf0SAugustin Cavalier// _kern_remove_attr
30503544bf0SAugustin Cavalierstatus_t
30603544bf0SAugustin Cavalier_kern_remove_attr(int fd, const char *name)
30703544bf0SAugustin Cavalier{
30803544bf0SAugustin Cavalier	if (!name)
30903544bf0SAugustin Cavalier		return B_BAD_VALUE;
31003544bf0SAugustin Cavalier
311648f0d5fSAugustin Cavalier	if (_haiku_build_fs_remove_attr(fd, name) < 0)
31203544bf0SAugustin Cavalier		return errno;
31303544bf0SAugustin Cavalier	return B_OK;
31403544bf0SAugustin Cavalier}
31503544bf0SAugustin Cavalier
31603544bf0SAugustin Cavalier#endif	// ! BUILDING_FS_SHELL
317