242 lines
5.8 KiB
C
242 lines
5.8 KiB
C
/* mars_nwe AFP xattr metadata backend helpers. */
|
|
#include "net.h"
|
|
#include "config.h"
|
|
#include "nwatalk.h"
|
|
#include "nwxattr.h"
|
|
#include "tools.h"
|
|
|
|
#include <string.h>
|
|
|
|
#if XATTR_SUPPORT
|
|
#include <errno.h>
|
|
#endif
|
|
|
|
#define MARS_NWE_AFP_ENTRY_ID_XATTR "org.mars-nwe.afp.entry-id"
|
|
#define MARS_NWE_AFP_FINDER_INFO_XATTR "org.mars-nwe.afp.finder-info"
|
|
#define MARS_NWE_AFP_ATTRIBUTES_XATTR "org.mars-nwe.afp.attributes"
|
|
#define MARS_NWE_AFP_ENTRY_ID_VERSION 1
|
|
#define MARS_NWE_AFP_ATTRIBUTES_VERSION 1
|
|
|
|
#define NWATALK_AFP_ATTR_HIDDEN 0x0200
|
|
#define NWATALK_AFP_ATTR_SYSTEM 0x0400
|
|
#define NWATALK_AFP_ATTR_SETCLR 0x8000
|
|
#define NWATALK_AFP_ATTR_STORED_MASK \
|
|
(NWATALK_AFP_ATTR_HIDDEN | NWATALK_AFP_ATTR_SYSTEM)
|
|
|
|
typedef struct {
|
|
uint8 version;
|
|
uint8 reserved[3];
|
|
uint8 entry_id[4];
|
|
} MARS_NWE_AFP_ENTRY_ID_XATTR_DATA;
|
|
|
|
typedef struct {
|
|
uint8 version;
|
|
uint8 reserved;
|
|
uint8 attributes[2];
|
|
} MARS_NWE_AFP_ATTRIBUTES_XATTR_DATA;
|
|
|
|
int nwatalk_backend_available(void)
|
|
{
|
|
#if XATTR_SUPPORT
|
|
return(1);
|
|
#else
|
|
return(0);
|
|
#endif
|
|
}
|
|
|
|
#if XATTR_SUPPORT
|
|
static int nwatalk_get_mars_entry_id_xattr(const char *path, uint32 *entry_id)
|
|
{
|
|
MARS_NWE_AFP_ENTRY_ID_XATTR_DATA d;
|
|
ssize_t len;
|
|
uint32 id;
|
|
|
|
if (!entry_id) return(-0x9c);
|
|
*entry_id = 0;
|
|
if (!path || !*path) return(-0x9c);
|
|
|
|
memset(&d, 0, sizeof(d));
|
|
len = mars_nwe_getxattr(path, MARS_NWE_AFP_ENTRY_ID_XATTR, &d, sizeof(d));
|
|
if (len != sizeof(d) || d.version != MARS_NWE_AFP_ENTRY_ID_VERSION)
|
|
return(-0x9c);
|
|
|
|
id = GET_BE32(d.entry_id);
|
|
id &= 0x7fffffffU;
|
|
if (!id) return(-0x9c);
|
|
|
|
*entry_id = id;
|
|
return(0);
|
|
}
|
|
#else
|
|
static int nwatalk_get_mars_entry_id_xattr(const char *path, uint32 *entry_id)
|
|
{
|
|
(void)path;
|
|
if (entry_id) *entry_id = 0;
|
|
return(-0xbf);
|
|
}
|
|
#endif
|
|
|
|
int nwatalk_get_finder_info(const char *path, uint8 *finder_info,
|
|
int finder_info_len)
|
|
{
|
|
#if XATTR_SUPPORT
|
|
ssize_t len;
|
|
#endif
|
|
|
|
if (!finder_info || finder_info_len < NWATALK_FINDER_INFO_LEN) {
|
|
return(-0x9c);
|
|
}
|
|
|
|
memset(finder_info, 0, finder_info_len);
|
|
|
|
#if XATTR_SUPPORT
|
|
if (path && *path) {
|
|
len = mars_nwe_getxattr(path, MARS_NWE_AFP_FINDER_INFO_XATTR,
|
|
finder_info, NWATALK_FINDER_INFO_LEN);
|
|
if (len == NWATALK_FINDER_INFO_LEN)
|
|
return(0);
|
|
memset(finder_info, 0, finder_info_len);
|
|
}
|
|
#else
|
|
(void)path;
|
|
#endif
|
|
|
|
/* Missing FinderInfo is a valid AFP state; absent metadata reads as zeroes. */
|
|
return(0);
|
|
}
|
|
|
|
int nwatalk_set_finder_info(const char *path, const uint8 *finder_info,
|
|
int finder_info_len)
|
|
{
|
|
#if XATTR_SUPPORT
|
|
if (!path || !*path || !finder_info || finder_info_len < NWATALK_FINDER_INFO_LEN)
|
|
return(-0x9c);
|
|
|
|
if (mars_nwe_setxattr(path, MARS_NWE_AFP_FINDER_INFO_XATTR,
|
|
finder_info, NWATALK_FINDER_INFO_LEN, 0)) {
|
|
int err = errno;
|
|
XDPRINTF((3,0,"AFP FinderInfo xattr write failed for %s errno=%d", path, err));
|
|
return(-0x8c); /* no write privileges / cannot persist metadata */
|
|
}
|
|
|
|
return(0);
|
|
#else
|
|
(void)path;
|
|
(void)finder_info;
|
|
(void)finder_info_len;
|
|
return(-0xbf); /* invalid namespace / xattrs unavailable */
|
|
#endif
|
|
}
|
|
|
|
int nwatalk_get_afp_attributes(const char *path, uint16 *attributes)
|
|
{
|
|
#if XATTR_SUPPORT
|
|
MARS_NWE_AFP_ATTRIBUTES_XATTR_DATA d;
|
|
ssize_t len;
|
|
#endif
|
|
|
|
if (!attributes) return(-0x9c);
|
|
*attributes = 0;
|
|
if (!path || !*path) return(-0x9c);
|
|
|
|
#if XATTR_SUPPORT
|
|
memset(&d, 0, sizeof(d));
|
|
len = mars_nwe_getxattr(path, MARS_NWE_AFP_ATTRIBUTES_XATTR,
|
|
&d, sizeof(d));
|
|
if (len == sizeof(d) && d.version == MARS_NWE_AFP_ATTRIBUTES_VERSION) {
|
|
*attributes = GET_BE16(d.attributes) & NWATALK_AFP_ATTR_STORED_MASK;
|
|
return(0);
|
|
}
|
|
#else
|
|
(void)path;
|
|
#endif
|
|
|
|
return(-0x9c);
|
|
}
|
|
|
|
int nwatalk_set_afp_attributes(const char *path, uint16 attributes)
|
|
{
|
|
#if XATTR_SUPPORT
|
|
MARS_NWE_AFP_ATTRIBUTES_XATTR_DATA d;
|
|
uint16 stored = 0;
|
|
uint16 requested = attributes & ~NWATALK_AFP_ATTR_SETCLR;
|
|
uint16 current = 0;
|
|
|
|
if (!path || !*path) return(-0x9c);
|
|
|
|
if (requested & ~NWATALK_AFP_ATTR_STORED_MASK) {
|
|
XDPRINTF((3,0,"AFP attributes xattr write rejected for %s attrs=0x%04x", path, attributes));
|
|
return(-0x9c);
|
|
}
|
|
|
|
(void)nwatalk_get_afp_attributes(path, ¤t);
|
|
if (attributes & NWATALK_AFP_ATTR_SETCLR)
|
|
stored = current | requested;
|
|
else
|
|
stored = current & ~requested;
|
|
|
|
memset(&d, 0, sizeof(d));
|
|
d.version = MARS_NWE_AFP_ATTRIBUTES_VERSION;
|
|
U16_TO_BE16(stored, d.attributes);
|
|
|
|
if (mars_nwe_setxattr(path, MARS_NWE_AFP_ATTRIBUTES_XATTR,
|
|
&d, sizeof(d), 0)) {
|
|
int err = errno;
|
|
XDPRINTF((3,0,"AFP attributes xattr write failed for %s attrs=0x%04x errno=%d", path, stored, err));
|
|
return(-0x8c);
|
|
}
|
|
|
|
return(0);
|
|
#else
|
|
(void)path;
|
|
(void)attributes;
|
|
return(-0xbf);
|
|
#endif
|
|
}
|
|
|
|
int nwatalk_set_entry_id(const char *path, uint32 entry_id)
|
|
{
|
|
#if XATTR_SUPPORT
|
|
MARS_NWE_AFP_ENTRY_ID_XATTR_DATA d;
|
|
|
|
if (!path || !*path) return(-0x9c);
|
|
entry_id &= 0x7fffffffU;
|
|
if (!entry_id) return(-0x9c);
|
|
|
|
memset(&d, 0, sizeof(d));
|
|
d.version = MARS_NWE_AFP_ENTRY_ID_VERSION;
|
|
U32_TO_BE32(entry_id, d.entry_id);
|
|
|
|
if (mars_nwe_setxattr(path, MARS_NWE_AFP_ENTRY_ID_XATTR,
|
|
&d, sizeof(d), 0)) {
|
|
int err = errno;
|
|
XDPRINTF((5,0,"AFP entry-id xattr write ignored for %s entry=0x%08x errno=%d",
|
|
path, entry_id, err));
|
|
return(-0x8c);
|
|
}
|
|
|
|
return(0);
|
|
#else
|
|
(void)path;
|
|
(void)entry_id;
|
|
return(-0xbf);
|
|
#endif
|
|
}
|
|
|
|
int nwatalk_get_resource_fork_size(const char *path, uint32 *resource_size)
|
|
{
|
|
(void)path;
|
|
if (!resource_size) return(-0x9c);
|
|
*resource_size = 0;
|
|
return(0);
|
|
}
|
|
|
|
int nwatalk_get_entry_id(const char *path, uint32 *entry_id)
|
|
{
|
|
if (!entry_id) return(-0x9c);
|
|
*entry_id = 0;
|
|
if (!path || !*path) return(-0x9c);
|
|
|
|
return(nwatalk_get_mars_entry_id_xattr(path, entry_id));
|
|
}
|