libroot_build: Full passthrough to system attributes.
As it turns out, using the xattr emulation layer plus "libgnu" causes some strange mixups at package build time, and so packages built with it were winding up with no attributes at all. So I've just bitten the bullet and written a full passthrough layer to the system attributes. Verified using a full build of haiku.hpkg this time ... after a lot of painful debugging of symlink mixups. Hopefully I am finally rid of this plague...
This commit is contained in:
parent
7d93e79a04
commit
03544bf000
@ -23,6 +23,7 @@ extern "C" {
|
||||
|
||||
/* Since libroot_build is also used on Haiku and linked against the real
|
||||
* libroot which also has the fs*attr functions, these must be shadowed. */
|
||||
#ifndef BUILDING_FS_ATTR_HAIKU
|
||||
#define fs_read_attr build_fs_read_attr
|
||||
#define fs_write_attr build_fs_write_attr
|
||||
#define fs_remove_attr build_fs_remove_attr
|
||||
@ -35,6 +36,7 @@ extern "C" {
|
||||
#define fs_close_attr_dir build_fs_close_attr_dir
|
||||
#define fs_read_attr_dir build_fs_read_attr_dir
|
||||
#define fs_rewind_attr_dir build_fs_rewind_attr_dir
|
||||
#endif
|
||||
|
||||
|
||||
extern ssize_t fs_read_attr(int fd, const char *attribute, uint32 type,
|
||||
|
@ -78,15 +78,10 @@ local librootSources =
|
||||
|
||||
USES_BE_API on [ FGristFiles $(librootSources:S=$(SUFOBJ)) ] = true ;
|
||||
|
||||
local extraLibs ;
|
||||
if $(HOST_PLATFORM) = haiku_host {
|
||||
extraLibs = gnu ;
|
||||
}
|
||||
|
||||
BuildPlatformSharedLibrary libroot_build.so :
|
||||
$(librootSources)
|
||||
:
|
||||
$(HOST_LIBSUPC++) $(HOST_LIBSTDC++) $(extraLibs)
|
||||
$(HOST_LIBSUPC++) $(HOST_LIBSTDC++)
|
||||
;
|
||||
|
||||
# TODO: This doesn't work with the function remapping.
|
||||
|
59
src/build/libroot/LocalFD.h
Normal file
59
src/build/libroot/LocalFD.h
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2005-2008, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
// no header guards: must be included at appropriate part of .cpp
|
||||
|
||||
|
||||
class LocalFD {
|
||||
public:
|
||||
LocalFD()
|
||||
{
|
||||
}
|
||||
|
||||
~LocalFD()
|
||||
{
|
||||
}
|
||||
|
||||
status_t Init(int fd)
|
||||
{
|
||||
#ifndef BUILDING_FS_SHELL
|
||||
Descriptor* descriptor = get_descriptor(fd);
|
||||
if (descriptor && !descriptor->IsSystemFD()) {
|
||||
// we need to get a path
|
||||
fFD = -1;
|
||||
return descriptor->GetPath(fPath);
|
||||
}
|
||||
#endif
|
||||
|
||||
fFD = fd;
|
||||
fPath = "";
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
int FD() const
|
||||
{
|
||||
return fFD;
|
||||
}
|
||||
|
||||
const char* Path() const
|
||||
{
|
||||
return (fFD < 0 ? fPath.c_str() : NULL);
|
||||
}
|
||||
|
||||
bool IsSymlink() const
|
||||
{
|
||||
struct stat st;
|
||||
int result;
|
||||
if (Path())
|
||||
result = lstat(Path(), &st);
|
||||
else
|
||||
result = fstat(fFD, &st);
|
||||
|
||||
return (result == 0 && S_ISLNK(st.st_mode));
|
||||
}
|
||||
|
||||
private:
|
||||
string fPath;
|
||||
int fFD;
|
||||
};
|
@ -1,5 +1,9 @@
|
||||
#ifdef HAIKU_HOST_USE_XATTR
|
||||
# include "fs_attr_untyped.cpp"
|
||||
# ifdef HAIKU_HOST_PLATFORM_HAIKU
|
||||
# include "fs_attr_haiku.cpp"
|
||||
# else
|
||||
# include "fs_attr_untyped.cpp"
|
||||
# endif
|
||||
#else
|
||||
# include "fs_attr_generic.cpp"
|
||||
#endif
|
||||
|
313
src/build/libroot/fs_attr_haiku.cpp
Normal file
313
src/build/libroot/fs_attr_haiku.cpp
Normal file
@ -0,0 +1,313 @@
|
||||
/*
|
||||
* Copyright 2017, Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
/*! Shim over the host Haiku fs_attr API */
|
||||
|
||||
#define BUILDING_FS_ATTR_HAIKU
|
||||
// so build fs_attr.h will not shadow the fs*attr functions
|
||||
|
||||
|
||||
#ifdef BUILDING_FS_SHELL
|
||||
# include "compat.h"
|
||||
# define B_OK 0
|
||||
# define B_BAD_VALUE EINVAL
|
||||
# define B_FILE_ERROR EBADF
|
||||
# define B_ERROR EINVAL
|
||||
# define B_ENTRY_NOT_FOUND ENOENT
|
||||
# define B_NO_MEMORY ENOMEM
|
||||
#else
|
||||
# include <syscalls.h>
|
||||
|
||||
# include "fs_impl.h"
|
||||
# include "fs_descriptors.h"
|
||||
#endif
|
||||
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include <fs_attr.h>
|
||||
|
||||
|
||||
namespace BPrivate {}
|
||||
using namespace BPrivate;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
// LocalFD
|
||||
#include "LocalFD.h"
|
||||
|
||||
} // unnamed namspace
|
||||
|
||||
|
||||
// # pragma mark - Public API
|
||||
|
||||
|
||||
// fs_open_attr_dir
|
||||
extern "C" DIR *
|
||||
build_fs_open_attr_dir(const char *path)
|
||||
{
|
||||
return fs_open_attr_dir(path);
|
||||
}
|
||||
|
||||
// fs_fopen_attr_dir
|
||||
extern "C" DIR* fs_lopen_attr_dir(const char *path);
|
||||
extern "C" DIR*
|
||||
build_fs_fopen_attr_dir(int fd)
|
||||
{
|
||||
LocalFD localFD;
|
||||
status_t error = localFD.Init(fd);
|
||||
if (error != B_OK) {
|
||||
errno = error;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (localFD.FD() < 0) {
|
||||
return fs_lopen_attr_dir(localFD.Path());
|
||||
} else {
|
||||
return fs_fopen_attr_dir(localFD.FD());
|
||||
}
|
||||
}
|
||||
|
||||
// fs_close_attr_dir
|
||||
extern "C" int
|
||||
build_fs_close_attr_dir(DIR *dir)
|
||||
{
|
||||
return fs_close_attr_dir(dir);
|
||||
}
|
||||
|
||||
// fs_read_attr_dir
|
||||
extern "C" struct dirent *
|
||||
build_fs_read_attr_dir(DIR *dir)
|
||||
{
|
||||
return fs_read_attr_dir(dir);
|
||||
}
|
||||
|
||||
// fs_rewind_attr_dir
|
||||
extern "C" void
|
||||
build_fs_rewind_attr_dir(DIR *dir)
|
||||
{
|
||||
return fs_rewind_attr_dir(dir);
|
||||
}
|
||||
|
||||
// fs_fopen_attr
|
||||
extern "C" int
|
||||
build_fs_fopen_attr(int fd, const char *attribute, uint32 type, int openMode)
|
||||
{
|
||||
if (fd < 0) {
|
||||
errno = B_BAD_VALUE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
LocalFD localFD;
|
||||
status_t error = localFD.Init(fd);
|
||||
if (error != B_OK) {
|
||||
errno = error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (localFD.FD() < 0) {
|
||||
return fs_open_attr(localFD.Path(), attribute, type,
|
||||
openMode | O_NOTRAVERSE);
|
||||
} else {
|
||||
return fs_fopen_attr(localFD.FD(), attribute, type, openMode);
|
||||
}
|
||||
}
|
||||
|
||||
// fs_close_attr
|
||||
extern "C" int
|
||||
build_fs_close_attr(int fd)
|
||||
{
|
||||
return fs_close_attr(fd);
|
||||
}
|
||||
|
||||
// fs_read_attr
|
||||
extern "C" ssize_t
|
||||
build_fs_read_attr(int fd, const char* attribute, uint32 type, off_t pos,
|
||||
void *buffer, size_t readBytes)
|
||||
{
|
||||
LocalFD localFD;
|
||||
status_t error = localFD.Init(fd);
|
||||
if (error != B_OK) {
|
||||
errno = error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t bytesRead;
|
||||
if (localFD.FD() < 0) {
|
||||
int fd = open(localFD.Path(), O_RDONLY | O_NOTRAVERSE);
|
||||
bytesRead = fs_read_attr(fd, attribute, type,
|
||||
pos, buffer, readBytes);
|
||||
close(fd);
|
||||
} else {
|
||||
bytesRead = fs_read_attr(localFD.FD(), attribute, type,
|
||||
pos, buffer, readBytes);
|
||||
}
|
||||
if (bytesRead < 0) {
|
||||
// Make sure, the error code is B_ENTRY_NOT_FOUND, if the attribute
|
||||
// doesn't exist.
|
||||
if (errno == ENOATTR || errno == ENODATA)
|
||||
errno = B_ENTRY_NOT_FOUND;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
// fs_write_attr
|
||||
extern "C" ssize_t
|
||||
build_fs_write_attr(int fd, const char* attribute, uint32 type, off_t pos,
|
||||
const void *buffer, size_t writeBytes)
|
||||
{
|
||||
LocalFD localFD;
|
||||
status_t error = localFD.Init(fd);
|
||||
if (error != B_OK) {
|
||||
errno = error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t written;
|
||||
if (localFD.FD() < 0) {
|
||||
int fd = open(localFD.Path(), O_NOTRAVERSE | O_WRONLY);
|
||||
written = fs_write_attr(fd, attribute, type,
|
||||
pos, buffer, writeBytes);
|
||||
close(fd);
|
||||
} else {
|
||||
written = fs_write_attr(localFD.FD(), attribute, type,
|
||||
pos, buffer, writeBytes);
|
||||
}
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
// fs_remove_attr
|
||||
extern "C" int
|
||||
build_fs_remove_attr(int fd, const char* attribute)
|
||||
{
|
||||
LocalFD localFD;
|
||||
status_t error = localFD.Init(fd);
|
||||
if (error != B_OK) {
|
||||
errno = error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// remove attribute
|
||||
int result;
|
||||
if (localFD.FD() < 0) {
|
||||
int fd = open(localFD.Path(), O_NOTRAVERSE | O_WRONLY);
|
||||
result = fs_remove_attr(fd, attribute);
|
||||
close(fd);
|
||||
} else {
|
||||
result = fs_remove_attr(localFD.FD(), attribute);
|
||||
}
|
||||
|
||||
if (result < 0) {
|
||||
// Make sure, the error code is B_ENTRY_NOT_FOUND, if the attribute
|
||||
// doesn't exist.
|
||||
if (errno == ENOATTR || errno == ENODATA)
|
||||
errno = B_ENTRY_NOT_FOUND;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// fs_stat_attr
|
||||
extern "C" int
|
||||
build_fs_stat_attr(int fd, const char *attribute, struct attr_info *attrInfo)
|
||||
{
|
||||
if (!attribute || !attrInfo) {
|
||||
errno = B_BAD_VALUE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
LocalFD localFD;
|
||||
status_t error = localFD.Init(fd);
|
||||
if (error != B_OK) {
|
||||
errno = error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int result;
|
||||
if (localFD.FD() < 0) {
|
||||
int fd = open(localFD.Path(), O_NOTRAVERSE | O_RDONLY);
|
||||
result = fs_stat_attr(fd, attribute, attrInfo);
|
||||
close(fd);
|
||||
} else {
|
||||
result = fs_stat_attr(localFD.FD(), attribute, attrInfo);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - Private Syscalls
|
||||
|
||||
|
||||
#ifndef BUILDING_FS_SHELL
|
||||
|
||||
// _kern_open_attr_dir
|
||||
int
|
||||
_kern_open_attr_dir(int fd, const char *path)
|
||||
{
|
||||
// get node ref for the node
|
||||
struct stat st;
|
||||
status_t error = _kern_read_stat(fd, path, false, &st,
|
||||
sizeof(struct stat));
|
||||
if (error != B_OK) {
|
||||
errno = error;
|
||||
return -1;
|
||||
}
|
||||
NodeRef ref(st);
|
||||
|
||||
DIR* dir;
|
||||
if (path) {
|
||||
// If a path was given, get a usable path.
|
||||
string realPath;
|
||||
status_t error = get_path(fd, path, realPath);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
dir = build_fs_open_attr_dir(realPath.c_str());
|
||||
} else
|
||||
dir = build_fs_fopen_attr_dir(fd);
|
||||
|
||||
if (!dir)
|
||||
return errno;
|
||||
|
||||
// create descriptor
|
||||
AttrDirDescriptor *descriptor = new AttrDirDescriptor(dir, ref);
|
||||
return add_descriptor(descriptor);
|
||||
}
|
||||
|
||||
// _kern_rename_attr
|
||||
status_t
|
||||
_kern_rename_attr(int fromFile, const char *fromName, int toFile,
|
||||
const char *toName)
|
||||
{
|
||||
// not supported ATM
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
// _kern_remove_attr
|
||||
status_t
|
||||
_kern_remove_attr(int fd, const char *name)
|
||||
{
|
||||
if (!name)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if (build_fs_remove_attr(fd, name) < 0)
|
||||
return errno;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
#endif // ! BUILDING_FS_SHELL
|
@ -39,7 +39,7 @@
|
||||
|
||||
|
||||
// Include the interface to the host platform attributes support.
|
||||
#if defined(HAIKU_HOST_PLATFORM_LINUX) || defined(HAIKU_HOST_PLATFORM_HAIKU)
|
||||
#if defined(HAIKU_HOST_PLATFORM_LINUX)
|
||||
# include "fs_attr_xattr.h"
|
||||
#elif defined(HAIKU_HOST_PLATFORM_FREEBSD)
|
||||
# include "fs_attr_extattr.h"
|
||||
@ -315,58 +315,7 @@ private:
|
||||
};
|
||||
|
||||
// LocalFD
|
||||
class LocalFD {
|
||||
public:
|
||||
LocalFD()
|
||||
{
|
||||
}
|
||||
|
||||
~LocalFD()
|
||||
{
|
||||
}
|
||||
|
||||
status_t Init(int fd)
|
||||
{
|
||||
#ifndef BUILDING_FS_SHELL
|
||||
Descriptor* descriptor = get_descriptor(fd);
|
||||
if (descriptor && !descriptor->IsSystemFD()) {
|
||||
// we need to get a path
|
||||
fFD = -1;
|
||||
return descriptor->GetPath(fPath);
|
||||
}
|
||||
#endif
|
||||
|
||||
fFD = fd;
|
||||
fPath = "";
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
int FD() const
|
||||
{
|
||||
return fFD;
|
||||
}
|
||||
|
||||
const char* Path() const
|
||||
{
|
||||
return (fFD < 0 ? fPath.c_str() : NULL);
|
||||
}
|
||||
|
||||
bool IsSymlink() const
|
||||
{
|
||||
struct stat st;
|
||||
int result;
|
||||
if (Path())
|
||||
result = lstat(Path(), &st);
|
||||
else
|
||||
result = fstat(fFD, &st);
|
||||
|
||||
return (result == 0 && S_ISLNK(st.st_mode));
|
||||
}
|
||||
|
||||
private:
|
||||
string fPath;
|
||||
int fFD;
|
||||
};
|
||||
#include "LocalFD.h"
|
||||
|
||||
} // unnamed namspace
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user