# Makefile.am for bin/megatron/
-INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/sys
-
-bin_PROGRAMS = megatron
-
-megatron_SOURCES = asingle.c hqx.c macbin.c megatron.c nad.c updcrc.c
-megatron_LDADD = $(top_builddir)/libatalk/libatalk.la
-
-noinst_HEADERS = asingle.h megatron.h hqx.h macbin.h nad.h updcrc.h
-
-LINKS = unbin unhex unsingle hqx2bin single2bin macbinary binheader nadheader
-
-install-exec-hook:
- @for LINK in $(LINKS); do \
- rm -f $(DESTDIR)$(bindir)/$$LINK; \
- $(LN_S) megatron $(DESTDIR)$(bindir)/$$LINK; \
- done
-
-uninstall-hook:
- @for LINK in $(LINKS); do \
- rm -f $(DESTDIR)$(bindir)/$$LINK; \
- done
+EXTRADIST = asingle.c hqx.c macbin.c megatron.c nad.c updcrc.c \
+ asingle.h megatron.h hqx.h macbin.h nad.h updcrc.h
struct dirent *dirp;
DIR *dir;
mode_t hf_mode;
- int osx = vol->v_adouble == AD_VERSION2_OSX;
int dropbox = (vol->v_flags & AFPVOL_DROPBOX);
mode |= vol->v_dperm;
for ( dirp = readdir( dir ); dirp != NULL; dirp = readdir( dir )) {
/* FIXME */
- if ( *dirp->d_name == '.' && (!osx || dirp->d_name[1] != '_')) {
+ if (*dirp->d_name == '.') {
continue;
}
if ( lstat( dirp->d_name, &st ) < 0 ) {
}
if (!S_ISDIR(st.st_mode)) {
- int setmode = (osx && *dirp->d_name == '.')?hf_mode:mode;
-
- if (setfilmode(dirp->d_name, setmode, &st, vol->v_umask) < 0) {
+ if (setfilmode(dirp->d_name, mode, &st, vol->v_umask) < 0) {
LOG(log_error, logtype_afpd, "setdirmode: chmod %s: %s",dirp->d_name, strerror(errno) );
return -1;
}
struct stat st;
struct dirent *dirp;
DIR *dir;
- int osx = vol->v_adouble == AD_VERSION2_OSX;
if (( dir = opendir( name )) == NULL ) {
return( -1 );
}
for ( dirp = readdir( dir ); dirp != NULL; dirp = readdir( dir )) {
- if ( *dirp->d_name == '.' && (!osx || dirp->d_name[1] != '_')) {
+ if ( *dirp->d_name == '.') {
continue;
}
if ( lstat( dirp->d_name, &st ) < 0 ) {
else if (strcasecmp(val + 1, "xlateupper") == 0)
options[VOLOPT_CASEFOLD].i_value = AFPVOL_ULOWERMUPPER;
} else if (optionok(tmp, "adouble:", val)) {
- if (strcasecmp(val + 1, "v1") == 0)
- options[VOLOPT_ADOUBLE].i_value = AD_VERSION1;
-#if AD_VERSION == AD_VERSION2
- else if (strcasecmp(val + 1, "v2") == 0)
+ if (strcasecmp(val + 1, "v2") == 0)
options[VOLOPT_ADOUBLE].i_value = AD_VERSION2;
- else if (strcasecmp(val + 1, "osx") == 0)
- options[VOLOPT_ADOUBLE].i_value = AD_VERSION2_OSX;
- else if (strcasecmp(val + 1, "sfm") == 0)
- options[VOLOPT_ADOUBLE].i_value = AD_VERSION1_SFM;
-#endif
+ else if (strcasecmp(val + 1, "ea") == 0)
+ options[VOLOPT_ADOUBLE].i_value = AD_VERSION_EA;
} else if (optionok(tmp, "options:", val)) {
char *p;
#error bad size for AD_DATASZ2
#endif
-#define AD_DATASZ_EA (AD_HEADER_LEN + (ADEID_NUM_EA * AD_ENTRY_LEN) + ADEID_FINDERI + \
- ADEID_COMMENT + ADEID_FILEDATESI + ADEID_AFPFILEI + ADEID_PRIVID)
-#if AD_DATASZ_EA != 352
+#define AD_DATASZ_EA (AD_HEADER_LEN + (ADEID_NUM_EA * AD_ENTRY_LEN) + ADEDLEN_FINDERI + \
+ ADEDLEN_COMMENT + ADEDLEN_FILEDATESI + ADEDLEN_AFPFILEI + ADEDLEN_PRIVID)
+
+#if AD_DATASZ_EA != 342
#error bad size for AD_DATASZ_EA
#endif
#define AD_DATASZ_MAX 1024
+
#if AD_VERSION == AD_VERSION2
#define AD_DATASZ AD_DATASZ2
-#elif AD_VERSION == AD_VERSION2_EA
+#elif AD_VERSION == AD_VERSION_EA
#define AD_DATASZ AD_DATASZ_EA
#endif
} adf_lock_t;
struct ad_fd {
- int adf_fd; /* -1: invalid, -2: symlink, -3: Extended Attribute */
+ int adf_fd; /* -1: invalid, -2: symlink */
#ifndef HAVE_PREAD
off_t adf_off;
#endif
/* some header protection */
#define AD_INITED 0xad494e54 /* ad"INT" */
+struct adouble;
+
struct adouble_fops {
char *(*ad_path)(const char *, int);
int (*ad_mkrf)(char *);
int (*ad_rebuild_header)(struct adouble *);
- int (*ad_check_header)(struct adouble *, struct stat *);
int (*ad_header_read)(struct adouble *, struct stat *);
int (*ad_header_upgrade)(struct adouble *, char *);
};
#define ADVOL_INVDOTS (1 << 3) /* dot files (.DS_Store) are invisible) */
#define ADVOL_NOADOUBLE (1 << 4)
+extern uint32_t adv2_disk_eid[];
+#define DISK_EID(a) (adv2_disk_eid[a])
+
/* lock flags */
#define ADLOCK_CLR (0)
#define ADLOCK_RD (1<<0)
extern uid_t ad_getfuid (void );
extern char *ad_dir (const char *);
extern char *ad_path (const char *, int);
-extern char *ad_path_osx (const char *, int);
-extern char *ad_path_ads (const char *, int);
-extern char *ad_path_sfm (const char *, int);
+extern char *ad_path_ea (const char *, int);
extern int ad_mode (const char *, int);
extern int ad_mkdir (const char *, int);
extern void ad_init (struct adouble *, int, int );
#include <config.h>
#endif
+#if HAVE_ATTR_XATTR_H
+#include <attr/xattr.h>
+#elif HAVE_SYS_XATTR_H
+#include <sys/xattr.h>
+#endif
+
+#ifdef HAVE_SYS_EA_H
+#include <sys/ea.h>
+#endif
+
+#ifdef HAVE_SYS_EXTATTR_H
+#include <sys/extattr.h>
+#endif
+
#ifdef HAVE_SOLARIS_ACLS
#include <sys/acl.h>
#endif
if (xlate)
date = AD_DATE_FROM_UNIX(date);
- if (ad->ad_version == AD_VERSION1) {
-
- if (!ad_getentryoff(ad, ADEID_FILEI))
- return -1;
-
- if (dateoff > AD_DATE_BACKUP)
- return -1;
- memcpy(ad_entry(ad, ADEID_FILEI) + dateoff, &date, sizeof(date));
-
- } else if (ad->ad_version == AD_VERSION2) {
- if (!ad_getentryoff(ad, ADEID_FILEDATESI))
- return -1;
-
- if (dateoff > AD_DATE_ACCESS)
- return -1;
- memcpy(ad_entry(ad, ADEID_FILEDATESI) + dateoff, &date, sizeof(date));
+ if (!ad_getentryoff(ad, ADEID_FILEDATESI))
+ return -1;
- } else
+ if (dateoff > AD_DATE_ACCESS)
return -1;
+ memcpy(ad_entry(ad, ADEID_FILEDATESI) + dateoff, &date, sizeof(date));
return 0;
}
int xlate = (dateoff & AD_DATE_UNIX);
dateoff &= AD_DATE_MASK;
- if (ad->ad_version == AD_VERSION1) {
- if (dateoff > AD_DATE_BACKUP)
- return -1;
- if (!ad_getentryoff(ad, ADEID_FILEI))
- return -1;
- memcpy(date, ad_entry(ad, ADEID_FILEI) + dateoff, sizeof(u_int32_t));
-
- } else if (ad->ad_version == AD_VERSION2) {
- if (!ad_getentryoff(ad, ADEID_FILEDATESI))
- return -1;
-
- if (dateoff > AD_DATE_ACCESS)
- return -1;
- memcpy(date, ad_entry(ad, ADEID_FILEDATESI) + dateoff, sizeof(u_int32_t));
+ if (!ad_getentryoff(ad, ADEID_FILEDATESI))
+ return -1;
- } else
+ if (dateoff > AD_DATE_ACCESS)
return -1;
+ memcpy(date, ad_entry(ad, ADEID_FILEDATESI) + dateoff, sizeof(u_int32_t));
if (xlate)
*date = AD_DATE_TO_UNIX(*date);
/*
* Copyright (c) 1990,1991 Regents of The University of Michigan.
+ * Copyright (c) 2010 Frank Lahm
* All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software and
#endif /* HAVE_CONFIG_H */
#include <string.h>
-#include <atalk/adouble.h>
-
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
-#include "ad_private.h"
-#if AD_VERSION == AD_VERSION1
-
-#define EID_DISK(a) (a)
-
-#else
-
-static const u_int32_t set_eid[] = {
- 0,1,2,3,4,5,6,7,8,
- 9,10,11,12,13,14,15,
- AD_DEV, AD_INO, AD_SYN, AD_ID
-};
+#include <atalk/adouble.h>
+#include <atalk/ea.h>
+#include <atalk/logger.h>
-#define EID_DISK(a) (set_eid[a])
-#endif
+#include "ad_private.h"
-/* rebuild the adouble header
- * XXX should be in a separate file ?
+/*
+ * Rebuild any header information that might have changed.
*/
int ad_rebuild_adouble_header(struct adouble *ad)
{
u_int32_t eid;
u_int32_t temp;
-
u_int16_t nent;
char *buf, *nentp;
+ int len;
- /*
- * Rebuild any header information that might have changed.
- */
buf = ad->ad_data;
temp = htonl( ad->ad_magic );
memcpy(buf, &temp, sizeof( temp ));
buf += sizeof( temp );
- memcpy(buf, ad->ad_filler, sizeof( ad->ad_filler ));
- buf += sizeof( ad->ad_filler );
-
nentp = buf;
buf += sizeof( nent );
for ( eid = 0, nent = 0; eid < ADEID_MAX; eid++ ) {
if ( ad->ad_eid[ eid ].ade_off == 0 ) {
continue;
}
- temp = htonl( EID_DISK(eid) );
+ temp = htonl( DISK_EID(eid) );
memcpy(buf, &temp, sizeof( temp ));
buf += sizeof( temp );
}
nent = htons( nent );
memcpy(nentp, &nent, sizeof( nent ));
- return ad_getentryoff(ad, ADEID_RFORK);
+
+ switch (ad->ad_version) {
+ case AD_VERSION2:
+ len = ad_getentryoff(ad, ADEID_RFORK);
+ break;
+ case AD_VERSION_EA:
+ len = AD_DATASZ_EA;
+ break;
+ default:
+ LOG(log_error, logtype_afpd, "Unexpected adouble version");
+ len = 0;
+ break;
+ }
+
+ return len;
}
/* -------------------
return 0;
}
-/* ------------------- */
-int ad_rebuild_sfm_header(struct adouble *ad)
-{
- u_int32_t temp;
-
- u_int16_t attr;
- char *buf;
-
- /*
- * Rebuild any header information that might have changed.
- */
- buf = ad->ad_data;
- /* FIXME */
-/* temp = htonl( ad->ad_magic ); */
- temp = ad->ad_magic;
- memcpy(buf, &temp, sizeof( temp ));
-
-/* temp = htonl( ad->ad_version ); */
- temp = ad->ad_version;
- memcpy(buf +4, &temp, sizeof( temp ));
-
- /* need to save attrib */
- if (!ad_getattr(ad, &attr)) {
- attr &= ~htons(ATTRBIT_DOPEN | ATTRBIT_ROPEN);
-
- memcpy(buf +48 +4, &attr, sizeof(attr));
-
- }
- return AD_SFM_LEN;
-}
-
-
-int ad_flush( struct adouble *ad)
+int ad_flush(struct adouble *ad)
{
int len;
if (( ad->ad_md->adf_flags & O_RDWR )) {
- /* sync our header */
- if (ad->ad_rlen > 0xffffffff) {
- ad_setentrylen(ad, ADEID_RFORK, 0xffffffff);
- }
- else {
- ad_setentrylen(ad, ADEID_RFORK, ad->ad_rlen);
+ if (ad_getentryoff(ad, ADEID_RFORK)) {
+ if (ad->ad_rlen > 0xffffffff)
+ ad_setentrylen(ad, ADEID_RFORK, 0xffffffff);
+ else
+ ad_setentrylen(ad, ADEID_RFORK, ad->ad_rlen);
}
len = ad->ad_ops->ad_rebuild_header(ad);
- if (adf_pwrite(ad->ad_md, ad->ad_data, len, 0) != len) {
- if ( errno == 0 ) {
- errno = EIO;
+ switch (ad->ad_version) {
+ case AD_VERSION2:
+ if (adf_pwrite(ad->ad_md, ad->ad_data, len, 0) != len) {
+ if (errno == 0)
+ errno = EIO;
+ return( -1 );
+ }
+ break;
+ case AD_VERSION_EA:
+ if (sys_fsetxattr(ad->ad_md->adf_fd, AD_EA_META, ad->ad_data, AD_DATASZ_EA, 0) != 0) {
+ LOG(log_error, logtype_afpd, "Unexpected adouble version");
+ return -1;
}
- return( -1 );
+ break;
+ default:
+ LOG(log_error, logtype_afpd, "Unexpected adouble version");
+ return -1;
}
}
return err;
}
- /* meta /resource fork */
+ /* meta/resource fork */
if ( ad_meta_fileno(ad) != -1 && !(--ad->ad_md->adf_refcount)) {
if ( close( ad_meta_fileno(ad) ) < 0 ) {
adf_lock_free(ad->ad_md);
}
- if (ad->ad_flags != AD_VERSION1_SFM) {
- return err;
- }
-
- if ((adflags & ADFLAGS_DIR)) {
- return err;
- }
-
- if ( ad_reso_fileno(ad) != -1 && !(--ad->ad_resource_fork.adf_refcount)) {
- if ( close( ad_reso_fileno(ad) ) < 0 ) {
- err = -1;
- }
- ad_reso_fileno(ad) = -1;
- adf_lock_free(&ad->ad_resource_fork);
- }
-
return err;
}
adf_unlock(&ad->ad_resource_fork, fork);
}
- if (ad->ad_flags != AD_VERSION1_SFM) {
+ if (ad->ad_flags != AD_VERSION_EA) {
return;
}
if (ad_meta_fileno(ad) != -1) {
#include <atalk/logger.h>
#include <atalk/adouble.h>
#include <atalk/util.h>
+#include <atalk/ea.h>
#include "ad_private.h"
#undef ADEDOFF_FILEI
#endif /* ADEDOFF_FILEI */
-#define ADEDOFF_NAME_V1 (AD_HEADER_LEN + ADEID_NUM_V1*AD_ENTRY_LEN)
-#define ADEDOFF_COMMENT_V1 (ADEDOFF_NAME_V1 + ADEDLEN_NAME)
-#define ADEDOFF_FILEI (ADEDOFF_COMMENT_V1 + ADEDLEN_COMMENT)
-#define ADEDOFF_FINDERI_V1 (ADEDOFF_FILEI + ADEDLEN_FILEI)
-#define ADEDOFF_RFORK_V1 (ADEDOFF_FINDERI_V1 + ADEDLEN_FINDERI)
-
/* i stick things in a slightly different order than their eid order in
* case i ever want to separate RootInfo behaviour from the rest of the
* stuff. */
+
+/* ad:v2 */
#define ADEDOFF_NAME_V2 (AD_HEADER_LEN + ADEID_NUM_V2*AD_ENTRY_LEN)
#define ADEDOFF_COMMENT_V2 (ADEDOFF_NAME_V2 + ADEDLEN_NAME)
#define ADEDOFF_FILEDATESI (ADEDOFF_COMMENT_V2 + ADEDLEN_COMMENT)
#define ADEDOFF_PRIVID (ADEDOFF_PRIVSYN + ADEDLEN_PRIVSYN)
#define ADEDOFF_RFORK_V2 (ADEDOFF_PRIVID + ADEDLEN_PRIVID)
-#define ADEDOFF_FINDERI_OSX (AD_HEADER_LEN + ADEID_NUM_OSX*AD_ENTRY_LEN)
-#define ADEDOFF_RFORK_OSX (ADEDOFF_FINDERI_OSX + ADEDLEN_FINDERI)
-
-/* we keep local copies of a bunch of stuff so that we can initialize things
- * correctly. */
+/* ad:ea */
+#define ADEDOFF_FINDERI_EA (AD_HEADER_LEN + ADEID_NUM_EA * AD_ENTRY_LEN)
+#define ADEDOFF_COMMENT_EA (ADEDOFF_FINDERI_EA + ADEDLEN_FINDERI)
+#define ADEDOFF_FILEDATESI_EA (ADEDOFF_COMMENT_EA + ADEDLEN_COMMENT)
+#define ADEDOFF_AFPFILEI_EA (ADEDOFF_FILEDATESI_EA + ADEDLEN_FILEDATESI)
/* this is to prevent changing timezones from causing problems with
- localtime volumes. the screw-up is 30 years. we use a delta of 5
- years. */
+ localtime volumes. the screw-up is 30 years. we use a delta of 5 years */
#define TIMEWARP_DELTA 157680000
struct entry {
/* --------------------------- */
static uid_t default_uid = -1;
+/* Forward declarations */
+static int ad_mkrf(char *path);
+static int ad_header_read(struct adouble *ad, struct stat *hst);
+static int ad_header_upgrade(struct adouble *ad, char *name);
+
+static int ad_mkrf_ea(char *path);
+static int ad_header_read_ea(struct adouble *ad, struct stat *hst);
+static int ad_header_upgrade_ea(struct adouble *ad, char *name);
+
static struct adouble_fops ad_adouble = {
&ad_path,
&ad_mkrf,
&ad_rebuild_adouble_header,
- &ad_check_size,
&ad_header_read,
&ad_header_upgrade,
};
static struct adouble_fops ad_adouble_ea = {
- &ad_path,
- &ad_mkrf,
+ &ad_path_ea,
+ &ad_mkrf_ea,
&ad_rebuild_adouble_header,
- &ad_check_size,
&ad_header_read_ea,
&ad_header_upgrade_ea,
};
static const struct entry entry_order2[ADEID_NUM_V2 + 1] = {
- {ADEID_NAME, ADEDOFF_NAME_V2, ADEDLEN_INIT},
- {ADEID_COMMENT, ADEDOFF_COMMENT_V2, ADEDLEN_INIT},
- {ADEID_FILEDATESI, ADEDOFF_FILEDATESI, ADEDLEN_FILEDATESI},
- {ADEID_FINDERI, ADEDOFF_FINDERI_V2, ADEDLEN_FINDERI},
- {ADEID_DID, ADEDOFF_DID, ADEDLEN_DID},
- {ADEID_AFPFILEI, ADEDOFF_AFPFILEI, ADEDLEN_AFPFILEI},
- {ADEID_SHORTNAME, ADEDOFF_SHORTNAME, ADEDLEN_INIT},
+ {ADEID_NAME, ADEDOFF_NAME_V2, ADEDLEN_INIT},
+ {ADEID_COMMENT, ADEDOFF_COMMENT_V2, ADEDLEN_INIT},
+ {ADEID_FILEDATESI, ADEDOFF_FILEDATESI, ADEDLEN_FILEDATESI},
+ {ADEID_FINDERI, ADEDOFF_FINDERI_V2, ADEDLEN_FINDERI},
+ {ADEID_DID, ADEDOFF_DID, ADEDLEN_DID},
+ {ADEID_AFPFILEI, ADEDOFF_AFPFILEI, ADEDLEN_AFPFILEI},
+ {ADEID_SHORTNAME, ADEDOFF_SHORTNAME, ADEDLEN_INIT},
{ADEID_PRODOSFILEI, ADEDOFF_PRODOSFILEI, ADEDLEN_PRODOSFILEI},
- {ADEID_PRIVDEV, ADEDOFF_PRIVDEV, ADEDLEN_INIT},
- {ADEID_PRIVINO, ADEDOFF_PRIVINO, ADEDLEN_INIT},
- {ADEID_PRIVSYN, ADEDOFF_PRIVSYN, ADEDLEN_INIT},
- {ADEID_PRIVID, ADEDOFF_PRIVID, ADEDLEN_INIT},
- {ADEID_RFORK, ADEDOFF_RFORK_V2, ADEDLEN_INIT},
+ {ADEID_PRIVDEV, ADEDOFF_PRIVDEV, ADEDLEN_INIT},
+ {ADEID_PRIVINO, ADEDOFF_PRIVINO, ADEDLEN_INIT},
+ {ADEID_PRIVSYN, ADEDOFF_PRIVSYN, ADEDLEN_INIT},
+ {ADEID_PRIVID, ADEDOFF_PRIVID, ADEDLEN_INIT},
+ {ADEID_RFORK, ADEDOFF_RFORK_V2, ADEDLEN_INIT},
{0, 0, 0}
};
/* Using Extended Attributes */
static const struct entry entry_order_ea[ADEID_NUM_EA + 1] = {
- {ADEID_FINDERI, ADEDOFF_FINDERI_OSX, ADEDLEN_FINDERI},
- {ADEID_COMMENT, ADEDOFF_COMMENT_V2, ADEDLEN_INIT},
- {ADEID_FILEDATESI, ADEDOFF_FILEDATESI, ADEDLEN_FILEDATESI},
- {ADEID_AFPFILEI, ADEDOFF_AFPFILEI, ADEDLEN_AFPFILEI},
- {ADEID_PRIVID, ADEDOFF_PRIVID, ADEDLEN_INIT},
+ {ADEID_FINDERI, ADEDOFF_FINDERI_EA, ADEDLEN_FINDERI},
+ {ADEID_COMMENT, ADEDOFF_COMMENT_EA, ADEDLEN_INIT},
+ {ADEID_FILEDATESI, ADEDOFF_FILEDATESI_EA, ADEDLEN_FILEDATESI},
+ {ADEID_AFPFILEI, ADEDOFF_AFPFILEI_EA, ADEDLEN_AFPFILEI},
{0, 0, 0}
};
-#define DISK_EID(ad, a) get_eid(ad, a)
-
-static uint32_t get_eid(struct adouble *ad, u_int32_t eid)
-{
- if (eid <= 15)
- return eid;
- if (eid == AD_DEV)
- return ADEID_PRIVDEV;
- if (eid == AD_INO)
- return ADEID_PRIVINO;
- if (eid == AD_SYN)
- return ADEID_PRIVSYN;
- if (eid == AD_ID)
- return ADEID_PRIVID;
-
- return 0;
-}
+uint32_t adv2_disk_eid[] = {
+ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
+ AD_DEV, AD_INO, AD_SYN, AD_ID
+};
/* ----------------------------------- */
static int new_ad_header(const char *path, struct adouble *ad, int adflags)
}
/* make things invisible */
- if ((ad->ad_options & ADVOL_INVDOTS) && (adflags & ADFLAGS_CREATE) && (*path == '.')) {
+ if ((ad->ad_options & ADVOL_INVDOTS) && (*path == '.')) {
ashort = htons(ATTRBIT_INVISIBLE);
ad_setattr(ad, ashort);
ashort = htons(FINDERINFO_INVISIBLE);
return 0;
}
-/* update a version 2 adouble resource fork with our private entries */
-static int ad_update(struct adouble *ad, const char *path)
-{
- struct stat st;
- u_int16_t nentries = 0;
- off_t off, shiftdata=0;
- const struct entry *eid;
- static off_t entry_len[ADEID_MAX];
- static char databuf[ADEID_MAX][256], *buf;
- int fd;
- int ret = -1;
-
- /* check to see if we should convert this header. */
- if (!path || ad->ad_flags != AD_VERSION2)
- return 0;
-
- LOG(log_maxdebug, logtype_default, "ad_update: checking whether '%s' needs an upgrade.", path);
-
- if (!(ad->ad_md->adf_flags & O_RDWR)) {
- /* we were unable to open the file read write the last time */
- return 0;
- }
-
- if (ad->ad_eid[ADEID_RFORK].ade_off) {
- shiftdata = ADEDOFF_RFORK_V2 -ad->ad_eid[ADEID_RFORK].ade_off;
- }
-
- memcpy(&nentries, ad->ad_data + ADEDOFF_NENTRIES, sizeof( nentries ));
- nentries = ntohs( nentries );
-
- if ( shiftdata == 0 && nentries == ADEID_NUM_V2)
- return 0;
-
- memset(entry_len, 0, sizeof(entry_len));
- memset(databuf, 0, sizeof(databuf));
-
- /* bail if we can't get a lock */
- if (ad_tmplock(ad, ADEID_RFORK, ADLOCK_WR, 0, 0, 0) < 0)
- goto bail_err;
-
- fd = ad->ad_md->adf_fd;
-
- if (fstat(fd, &st)) {
- goto bail_lock;
- }
-
- if (st.st_size > 0x7fffffff) {
- LOG(log_debug, logtype_default, "ad_update: file '%s' too big for update.", path);
- errno = EIO;
- goto bail_lock;
- }
-
- off = ad->ad_eid[ADEID_RFORK].ade_off;
- if (off > st.st_size) {
- LOG(log_error, logtype_default, "ad_update: invalid resource fork offset. (off: %u)", off);
- errno = EIO;
- goto bail_lock;
- }
-
- if (ad->ad_eid[ADEID_RFORK].ade_len > st.st_size - off) {
- LOG(log_error, logtype_default, "ad_update: invalid resource fork length. (rfork len: %u)", ad->ad_eid[ADEID_RFORK].ade_len);
- errno = EIO;
- goto bail_lock;
- }
-
- if ((void *) (buf = (char *)
- mmap(NULL, st.st_size + shiftdata,
- PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) ==
- MAP_FAILED) {
- goto bail_lock;
- }
-
- /* last place for failure. */
- if (sys_ftruncate(fd, st.st_size + shiftdata) < 0) {
- munmap(buf, st.st_size + shiftdata);
- goto bail_lock;
- }
-
- /* move the RFORK. this assumes that the RFORK is at the end */
- if (off) {
- memmove(buf + ADEDOFF_RFORK_V2, buf + off, ad->ad_eid[ADEID_RFORK].ade_len);
- }
-
- munmap(buf, st.st_size + shiftdata);
-
- /* now, fix up our copy of the header */
- memset(ad->ad_filler, 0, sizeof(ad->ad_filler));
-
- /* save the header entries */
- eid = entry_order2;
- while (eid->id) {
- if( ad->ad_eid[eid->id].ade_off != 0) {
- if ( eid->id > 2 && ad->ad_eid[eid->id].ade_len < 256)
- memcpy( databuf[eid->id], ad->ad_data +ad->ad_eid[eid->id].ade_off, ad->ad_eid[eid->id].ade_len);
- entry_len[eid->id] = ad->ad_eid[eid->id].ade_len;
- }
- eid++;
- }
-
- memset(ad->ad_data + AD_HEADER_LEN, 0, AD_DATASZ - AD_HEADER_LEN);
-
- /* copy the saved entries to the new header */
- eid = entry_order2;
- while (eid->id) {
- if ( eid->id > 2 && entry_len[eid->id] > 0) {
- memcpy(ad->ad_data+eid->offset, databuf[eid->id], entry_len[eid->id]);
- }
- ad->ad_eid[eid->id].ade_off = eid->offset;
- ad->ad_eid[eid->id].ade_len = entry_len[eid->id];
- eid++;
- }
-
- /* rebuild the header and cleanup */
- LOG(log_debug, logtype_default, "updated AD2 header %s", path);
- ad_flush(ad );
- ret = 0;
-
-bail_lock:
- ad_tmplock(ad, ADEID_RFORK, ADLOCK_CLR, 0, 0, 0);
-bail_err:
- return ret;
-}
-
-/* ------------------------------------------
- FIXME work only if < 2GB
-*/
-static int ad_convert(struct adouble *ad, const char *path)
-{
- struct stat st;
- u_int16_t attr;
- char *buf;
- int fd, off;
- int ret = -1;
- /* use resource fork offset from file */
- int shiftdata;
- int toV2;
- int toV1;
-
- if (!path) {
- return 0;
- }
-
- if (!(ad->ad_md->adf_flags & ( O_RDWR))) {
- /* we were unable to open the file read write the last time */
- return 0;
- }
-
- /* check to see if we should convert this header. */
- toV2 = ad->ad_version == AD_VERSION1 && ad->ad_flags == AD_VERSION2;
- toV1 = ad->ad_version == AD_VERSION2 && ad->ad_flags == AD_VERSION1;
-
- if (!toV2 && !toV1)
- return 0;
-
- /* convert from v1 to v2. what does this mean?
- * 1) change FILEI into FILEDATESI
- * 2) create space for SHORTNAME, AFPFILEI, DID, and PRODOSI
- * 3) move FILEI attributes into AFPFILEI
- * 4) initialize ACCESS field of FILEDATESI.
- * 5) move the resource fork
- */
-
- /* bail if we can't get a lock */
- if (ad_tmplock(ad, ADEID_RFORK, ADLOCK_WR, 0, 0, 0) < 0)
- goto bail_err;
-
- /* we reuse fd from the resource fork */
- fd = ad->ad_md->adf_fd;
-
- if (ad->ad_eid[ADEID_RFORK].ade_off) {
- shiftdata = ADEDOFF_RFORK_V2 -ad->ad_eid[ADEID_RFORK].ade_off;
- }
- else {
- shiftdata = ADEDOFF_RFORK_V2 -ADEDOFF_RFORK_V1; /* 136 */
- }
-
- if (fstat(fd, &st)) {
- goto bail_lock;
- }
-
- if (st.st_size > 0x7fffffff -shiftdata) {
- LOG(log_debug, logtype_default, "ad_v1tov2: file too big.");
- errno = EIO;
- goto bail_lock;
- }
-
- off = ad->ad_eid[ADEID_RFORK].ade_off;
-
- if (off > st.st_size) {
- LOG(log_error, logtype_default, "ad_v1tov2: invalid resource fork offset. (off: %u)", off);
- errno = EIO;
- goto bail_lock;
- }
-
- if (ad->ad_eid[ADEID_RFORK].ade_len > st.st_size - off) {
- LOG(log_error, logtype_default, "ad_v1tov2: invalid resource fork length. (rfork len: %u)", ad->ad_eid[ADEID_RFORK].ade_len);
- errno = EIO;
- goto bail_lock;
- }
-
- if ((void *) (buf = (char *)
- mmap(NULL, st.st_size + shiftdata,
- PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) ==
- MAP_FAILED) {
- goto bail_lock;
- }
-
- /* last place for failure. */
-
- if (sys_ftruncate(fd, st.st_size + shiftdata) < 0) {
- goto bail_lock;
- }
-
- /* move the RFORK. this assumes that the RFORK is at the end */
- if (off) {
- memmove(buf + ADEDOFF_RFORK_V2, buf + off, ad->ad_eid[ADEID_RFORK].ade_len);
- }
-
- munmap(buf, st.st_size + shiftdata);
-
- /* now, fix up our copy of the header */
- memset(ad->ad_filler, 0, sizeof(ad->ad_filler));
-
- /* replace FILEI with FILEDATESI */
- ad_getattr(ad, &attr);
- ad->ad_eid[ADEID_FILEDATESI].ade_off = ADEDOFF_FILEDATESI;
- ad->ad_eid[ADEID_FILEDATESI].ade_len = ADEDLEN_FILEDATESI;
- ad->ad_eid[ADEID_FILEI].ade_off = 0;
- ad->ad_eid[ADEID_FILEI].ade_len = 0;
-
- /* add in the new entries */
- ad->ad_eid[ADEID_DID].ade_off = ADEDOFF_DID;
- ad->ad_eid[ADEID_DID].ade_len = ADEDLEN_DID;
- ad->ad_eid[ADEID_AFPFILEI].ade_off = ADEDOFF_AFPFILEI;
- ad->ad_eid[ADEID_AFPFILEI].ade_len = ADEDLEN_AFPFILEI;
- ad->ad_eid[ADEID_SHORTNAME].ade_off = ADEDOFF_SHORTNAME;
- ad->ad_eid[ADEID_SHORTNAME].ade_len = ADEDLEN_INIT;
- ad->ad_eid[ADEID_PRODOSFILEI].ade_off = ADEDOFF_PRODOSFILEI;
- ad->ad_eid[ADEID_PRODOSFILEI].ade_len = ADEDLEN_PRODOSFILEI;
-
- ad->ad_eid[ADEID_PRIVDEV].ade_off = ADEDOFF_PRIVDEV;
- ad->ad_eid[ADEID_PRIVDEV].ade_len = ADEDLEN_INIT;
- ad->ad_eid[ADEID_PRIVINO].ade_off = ADEDOFF_PRIVINO;
- ad->ad_eid[ADEID_PRIVINO].ade_len = ADEDLEN_INIT;
- ad->ad_eid[ADEID_PRIVSYN].ade_off = ADEDOFF_PRIVSYN;
- ad->ad_eid[ADEID_PRIVSYN].ade_len = ADEDLEN_INIT;
- ad->ad_eid[ADEID_PRIVID].ade_off = ADEDOFF_PRIVID;
- ad->ad_eid[ADEID_PRIVID].ade_len = ADEDLEN_INIT;
-
- /* shift the old entries (NAME, COMMENT, FINDERI, RFORK) */
- ad->ad_eid[ADEID_NAME].ade_off = ADEDOFF_NAME_V2;
- ad->ad_eid[ADEID_COMMENT].ade_off = ADEDOFF_COMMENT_V2;
- ad->ad_eid[ADEID_FINDERI].ade_off = ADEDOFF_FINDERI_V2;
- ad->ad_eid[ADEID_RFORK].ade_off = ADEDOFF_RFORK_V2;
-
- /* switch to dest version */
- ad->ad_version = (toV2)?AD_VERSION2:AD_VERSION1;
-
- /* move our data buffer to make space for the new entries. */
- memmove(ad->ad_data + ADEDOFF_NAME_V2, ad->ad_data + ADEDOFF_NAME_V1,
- ADEDOFF_RFORK_V1 - ADEDOFF_NAME_V1);
-
- /* now, fill in the space with appropriate stuff. we're
- operating as a v2 file now. */
- ad_setdate(ad, AD_DATE_ACCESS | AD_DATE_UNIX, st.st_mtime);
- memset(ad_entry(ad, ADEID_DID), 0, ADEDLEN_DID);
- memset(ad_entry(ad, ADEID_AFPFILEI), 0, ADEDLEN_AFPFILEI);
- ad_setattr(ad, attr);
- memset(ad_entry(ad, ADEID_SHORTNAME), 0, ADEDLEN_SHORTNAME);
- memset(ad_entry(ad, ADEID_PRODOSFILEI), 0, ADEDLEN_PRODOSFILEI);
-
- /* rebuild the header and cleanup */
- ad_flush(ad );
- ret = 0;
-
-bail_lock:
- ad_tmplock(ad, ADEID_RFORK, ADLOCK_CLR, 0, 0, 0);
-bail_err:
- return ret;
-}
-
/* -------------------------------------
read in the entries
*/
/* now, read in the entry bits */
for (; nentries > 0; nentries-- ) {
memcpy(&eid, buf, sizeof( eid ));
- eid = DISK_EID(ad, ntohl( eid ));
+ eid = DISK_EID(ntohl( eid ));
buf += sizeof( eid );
memcpy(&off, buf, sizeof( off ));
off = ntohl( off );
u_int16_t nentries;
int len;
ssize_t header_len;
- static int warning = 0;
struct stat st;
/* read the header */
memcpy(&ad->ad_magic, buf, sizeof( ad->ad_magic ));
memcpy(&ad->ad_version, buf + ADEDOFF_VERSION, sizeof( ad->ad_version ));
- /* tag broken v1 headers. just assume they're all right.
- * we detect two cases: null magic/version
- * byte swapped magic/version
- * XXX: in the future, you'll need the v1compat flag. */
- if (!ad->ad_magic && !ad->ad_version) {
- if (!warning) {
- LOG(log_debug, logtype_default, "notice: fixing up null v1 magic/version.");
- warning++;
- }
- ad->ad_magic = AD_MAGIC;
- ad->ad_version = AD_VERSION1;
-
- } else if (ad->ad_magic == AD_MAGIC && ad->ad_version == AD_VERSION1) {
- if (!warning) {
- LOG(log_debug, logtype_default, "notice: fixing up byte-swapped v1 magic/version.");
- warning++;
- }
-
- } else {
- ad->ad_magic = ntohl( ad->ad_magic );
- ad->ad_version = ntohl( ad->ad_version );
- }
-
- if ((ad->ad_magic != AD_MAGIC) ||
- ((ad->ad_version != AD_VERSION1) && (ad->ad_version != AD_VERSION2))) {
+ if ((ad->ad_magic != AD_MAGIC) || (ad->ad_version != AD_VERSION2)) {
LOG(log_error, logtype_default, "ad_open: can't parse AppleDouble header.");
errno = EIO;
return -1;
}
- memcpy(ad->ad_filler, buf + ADEDOFF_FILLER, sizeof( ad->ad_filler ));
memcpy(&nentries, buf + ADEDOFF_NENTRIES, sizeof( nentries ));
nentries = ntohs( nentries );
return 0;
}
-static int ad_header_read_ea(struct adouble *ad, struct stat *hst)
+static int ad_header_read_ea(struct adouble *ad, struct stat *hst _U_)
{
- uint16_t nentries;
- int len;
- ssize_t header_len;
- static int warning = 0;
- struct stat st;
-
+ uint16_t nentries;
+ int len;
+ ssize_t header_len;
+ char *buf = ad->ad_data;
/* read the header */
- if ((header_len = sys_lgetxattr(path, AD_EA_META, ad->ad_data, AD_DATASZ_EA)) < 0) {
+ if ((header_len = sys_fgetxattr(ad->ad_md->adf_fd, AD_EA_META, ad->ad_data, AD_DATASZ_EA)) < 0) {
LOG(log_error, logtype_default, "ad_open: can't parse AppleDouble header.");
errno = EIO;
return -1;
/* Now parse entries */
parse_entries(ad, buf + AD_HEADER_LEN, nentries);
+ return 0;
}
static int ad_mkrf(char *path)
return 0;
}
+static int ad_mkrf_ea(char *path _U_)
+{
+ AFP_PANIC("ad_mkrf_ea: dont use");
+ return 0;
+}
/* ----------------
if we are root change path user/ group
return ret;
}
+#define DEFMASK 07700 /* be conservative */
+
/* ----------------
return access right and inode of path parent directory
*/
}
/* --------------------------- */
-static int ad_check_size(struct adouble *ad _U_, struct stat *st)
+static int ad_header_upgrade(struct adouble *ad _U_, char *name _U_)
{
- if (st->st_size > 0 && st->st_size < AD_DATASZ1)
- return 1;
return 0;
}
-/* --------------------------- */
-static int ad_check_size_sfm(struct adouble *ad _U_, struct stat *st)
-{
- if (st->st_size > 0 && st->st_size < AD_SFM_LEN)
- return 1;
- return 0;
-}
-
-/* --------------------------- */
-static int ad_header_upgrade(struct adouble *ad, char *name)
-{
- int ret;
- if ( (ret = ad_convert(ad, name)) < 0 || (ret = ad_update(ad, name) < 0)) {
- return ret;
- }
- return 0;
-}
-
-/* --------------------------- */
-static int ad_header_upgrade_none(struct adouble *ad _U_, char *name _U_)
+static int ad_header_upgrade_ea(struct adouble *ad _U_, char *name _U_)
{
+ AFP_PANIC("ad_header_upgrade_ea: dont use");
return 0;
}
static int ad_open_df(const char *path, int adflags, int oflags, int mode, struct adouble *ad)
{
struct stat st_dir;
- struct stat st_meta;
- struct stat *pst = NULL;
- char *ad_p;
int hoflags, admode;
int st_invalid = -1;
}
AD_SET(ad->ad_md->adf_off);
- ad->ad_md->adf_refcount = 1;
- adf_lock_init(ad->ad_md);
if ((ad->ad_md->adf_flags & ( O_TRUNC | O_CREAT ))) {
/* This is a new adouble header file, create it */
if (new_ad_header(path, ad, adflags) < 0) {
static int ad_open_hf_ea(const char *path, int adflags, int oflags, int mode, struct adouble *ad)
{
- ad->ad_md->adf_fd = -3;
+ int hoflags;
+ ssize_t rforklen;
+
+ hoflags = (oflags & ~(O_CREAT | O_EXCL)) | O_NOFOLLOW;
+ if ((ad->ad_md->adf_fd = open(path, hoflags)) == -1)
+ return -1;
/* Read the adouble header in and parse it.*/
- if (ad->ad_ops->ad_header_read(ad, path) != 0) {
+ if (ad->ad_ops->ad_header_read(ad, NULL) != 0) {
/* It doesnt exist, EPERM or another error */
if (errno != ENOENT)
return -1;
ad_flush(ad);
}
- ssize_t rforklen =
-
+ if ((rforklen = sys_lgetxattr(path, AD_EA_RESO, NULL, 0)) < 0) {
+ rforklen = 0;
+ }
+
+ ad->ad_rlen = rforklen;
+ return 0;
}
static int ad_open_hf(const char *path, int adflags, int oflags, int mode, struct adouble *ad)
ad->ad_rlen = 0;
switch (ad->ad_version) {
- case AD_VERSION_2:
+ case AD_VERSION2:
ret = ad_open_hf_v2(path, adflags, oflags, mode, ad);
break;
case AD_VERSION_EA:
break;
}
+ ad->ad_md->adf_refcount = 1;
+ adf_lock_init(ad->ad_md);
+
return ret;
}
* API functions
********************************************************************************* */
+char *ad_path_ea( const char *path, int adflags _U_)
+{
+ return path;
+}
+
/*
* Put the .AppleDouble where it needs to be:
*
* mode is ANDed with the parent directory's mask value in lieu of "umask",
* and that value is returned.
*/
-
-#define DEFMASK 07700 /* be conservative */
-
char *ad_dir(const char *path)
{
static char modebuf[ MAXPATHLEN + 1];
* @param adflags ADFLAGS_DF: open data fork \n
* ADFLAGS_RF: open ressource fork \n
* ADFLAGS_HF: open header (metadata) file \n
- * ADFLAGS_CREATE: indicate creation \n
* ADFLAGS_NOHF: it's not an error if header file couldn't be created \n
* ADFLAGS_DIR: if path is a directory you MUST or ADFLAGS_DIR to adflags \n
* ADFLAGS_NOADOUBLE: dont create adouble files if not necessary \n
*/
int ad_open(const char *path, int adflags, int oflags, int mode, struct adouble *ad)
{
- struct stat st_dir;
- struct stat st_meta;
- struct stat *pst = NULL;
- char *ad_p;
- int hoflags, admode;
- int st_invalid = -1;
- int open_df = 0;
-
if (ad->ad_inited != AD_INITED) {
ad->ad_inited = AD_INITED;
ad->ad_refcount = 1;
int ad_refresh(struct adouble *ad)
{
- if (ad_meta_fileno(ad) < 0)
+ if (ad_meta_fileno(ad) == -1)
return -1;
return ad->ad_ops->ad_header_read(ad, NULL);
}
break;
case ADOUBLE_VER:
- if (strcasecmp(value, "v1") == 0) {
- vol->v_adouble = AD_VERSION1;
- vol->ad_path = ad_path;
- }
-#if AD_VERSION == AD_VERSION2
- else if (strcasecmp(value, "v2") == 0) {
+ if (strcasecmp(value, "v2") == 0) {
vol->ad_path = ad_path;
vol->v_adouble = AD_VERSION2;
- }
- else if (strcasecmp(value, "osx") == 0) {
- vol->v_adouble = AD_VERSION2_OSX;
- vol->ad_path = ad_path_osx;
- }
-#endif
- else {
+ } else if (strcasecmp(value, "ea") == 0) {
+ vol->ad_path = ad_path_ea;
+ vol->v_adouble = AD_VERSION_EA;
+ } else {
+
fprintf (stderr, "unknown adouble version: %s, %s", buf, value);
return -1;
}
strlcat(buf, item, sizeof(buf));
switch (vol->v_adouble) {
- case AD_VERSION1:
- strlcat(buf, "ADOUBLE_VER:v1\n", sizeof(buf));
- break;
case AD_VERSION2:
strlcat(buf, "ADOUBLE_VER:v2\n", sizeof(buf));
break;
- case AD_VERSION2_OSX:
- strlcat(buf, "ADOUBLE_VER:osx\n", sizeof(buf));
- break;
- case AD_VERSION1_SFM:
- strlcat(buf, "ADOUBLE_VER:sfm\n", sizeof(buf));
+ case AD_VERSION_EA:
+ strlcat(buf, "ADOUBLE_VER:ea\n", sizeof(buf));
break;
}
noinst_LTLIBRARIES = libvfs.la
-libvfs_la_SOURCES = vfs.c unix.c extattr.c ea_ad.c ea_sys.c
+libvfs_la_SOURCES = vfs.c unix.c ea_ad.c ea_sys.c extattr.c
if HAVE_ACLS
libvfs_la_SOURCES += acl.c
#endif
}
+ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
+{
+#if defined(HAVE_FGETXATTR)
+#ifndef XATTR_ADD_OPT
+ return fgetxattr(filedes, name, value, size);
+#else
+ int options = 0;
+ return fgetxattr(filedes, name, value, size, 0, options);
+#endif
+#elif defined(HAVE_FGETEA)
+ return fgetea(filedes, name, value, size);
+#elif defined(HAVE_EXTATTR_GET_FD)
+ char *s;
+ ssize_t retval;
+ int attrnamespace = (strncmp(name, "system", 6) == 0) ?
+ EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
+ const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
+
+ if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
+ if(retval > size) {
+ errno = ERANGE;
+ return -1;
+ }
+ if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
+ return retval;
+ }
+
+ DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
+ return -1;
+#elif defined(HAVE_ATTR_GETF)
+ int retval, flags = 0;
+ int valuelength = (int)size;
+ char *attrname = strchr(name,'.') + 1;
+
+ if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
+
+ retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
+
+ return retval ? retval : valuelength;
+#elif defined(HAVE_ATTROPEN)
+ ssize_t ret = -1;
+ int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
+ if (attrfd >= 0) {
+ ret = solaris_read_xattr(attrfd, value, size);
+ close(attrfd);
+ }
+ return ret;
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
ssize_t sys_lgetxattr (const char *path, const char *uname, void *value, size_t size)
{
const char *name = prefix(uname);
#endif
}
+int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
+{
+#if defined(HAVE_FSETXATTR)
+#ifndef XATTR_ADD_OPT
+ return fsetxattr(filedes, name, value, size, flags);
+#else
+ int options = 0;
+ return fsetxattr(filedes, name, value, size, 0, options);
+#endif
+#elif defined(HAVE_FSETEA)
+ return fsetea(filedes, name, value, size, flags);
+#elif defined(HAVE_EXTATTR_SET_FD)
+ char *s;
+ int retval = 0;
+ int attrnamespace = (strncmp(name, "system", 6) == 0) ?
+ EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
+ const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
+ if (flags) {
+ /* Check attribute existence */
+ retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
+ if (retval < 0) {
+ /* REPLACE attribute, that doesn't exist */
+ if (flags & XATTR_REPLACE && errno == ENOATTR) {
+ errno = ENOATTR;
+ return -1;
+ }
+ /* Ignore other errors */
+ }
+ else {
+ /* CREATE attribute, that already exists */
+ if (flags & XATTR_CREATE) {
+ errno = EEXIST;
+ return -1;
+ }
+ }
+ }
+ retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
+ return (retval < 0) ? -1 : 0;
+#elif defined(HAVE_ATTR_SETF)
+ int myflags = 0;
+ char *attrname = strchr(name,'.') + 1;
+
+ if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
+ if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
+ if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
+
+ return attr_setf(filedes, attrname, (const char *)value, size, myflags);
+#elif defined(HAVE_ATTROPEN)
+ int ret = -1;
+ int myflags = O_RDWR | O_XATTR;
+ int attrfd;
+ if (flags & XATTR_CREATE) myflags |= O_EXCL;
+ if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
+ attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
+ if (attrfd >= 0) {
+ ret = solaris_write_xattr(attrfd, value, size);
+ close(attrfd);
+ }
+ return ret;
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
int sys_lsetxattr (const char *path, const char *uname, const void *value, size_t size, int flags)
{
const char *name = prefix(uname);
}
#endif
-/*********************************************************************************
- * sfm adouble format
- *********************************************************************************/
-static int ads_chown_loop(struct dirent *de _U_, char *name, void *data, int flag _U_, mode_t v_umask _U_)
-{
- struct perm *owner = data;
-
- if (chown( name , owner->uid, owner->gid ) < 0) {
- return -1;
- }
- return 0;
-}
-
-static int RF_chown_ads(VFS_FUNC_ARGS_CHOWN)
-{
- struct stat st;
- char *ad_p;
- struct perm owner;
-
- owner.uid = uid;
- owner.gid = gid;
-
-
- ad_p = ad_dir(vol->ad_path(path, ADFLAGS_HF ));
-
- if ( stat( ad_p, &st ) < 0 ) {
- /* ignore */
- return 0;
- }
-
- if (chown( ad_p, uid, gid ) < 0) {
- return -1;
- }
- return for_each_adouble("chown_ads", ad_p, ads_chown_loop, &owner, 1, vol->v_umask);
-}
-
-/* --------------------------------- */
-static int deletecurdir_ads1_loop(struct dirent *de _U_, char *name, void *data _U_, int flag _U_, mode_t v_umask _U_)
-{
- return netatalk_unlink(name);
-}
-
-static int ads_delete_rf(char *name)
-{
- int err;
-
- if ((err = for_each_adouble("deletecurdir", name, deletecurdir_ads1_loop, NULL, 1, 0)))
- return err;
- /* FIXME
- * it's a problem for a nfs mounted folder, there's .nfsxxx around
- * for linux the following line solve it.
- * but it could fail if rm .nfsxxx create a new .nfsyyy :(
- */
- if ((err = for_each_adouble("deletecurdir", name, deletecurdir_ads1_loop, NULL, 1, 0)))
- return err;
- return netatalk_rmdir(-1, name);
-}
-
-static int deletecurdir_ads_loop(struct dirent *de, char *name, void *data _U_, int flag _U_, mode_t v_umask _U_)
-{
- struct stat st;
-
- /* bail if the file exists in the current directory.
- * note: this will not fail with dangling symlinks */
-
- if (stat(de->d_name, &st) == 0) {
- return AFPERR_DIRNEMPT;
- }
- return ads_delete_rf(name);
-}
-
-static int RF_deletecurdir_ads(VFS_FUNC_ARGS_DELETECURDIR)
-{
- int err;
-
- /* delete stray .AppleDouble files. this happens to get .Parent files as well. */
- if ((err = for_each_adouble("deletecurdir", ".AppleDouble", deletecurdir_ads_loop, NULL, 1, 0)))
- return err;
-
- return netatalk_rmdir(-1, ".AppleDouble" );
-}
-
-/* ------------------- */
-struct set_mode {
- mode_t mode;
- struct stat *st;
-};
-
-static int ads_setfilmode_loop(struct dirent *de _U_, char *name, void *data, int flag _U_, mode_t v_umask)
+/*************************************************************************
+ * EA adouble format
+ ************************************************************************/
+static int validupath_ea(VFS_FUNC_ARGS_VALIDUPATH)
{
- struct set_mode *param = data;
-
- return setfilmode(name, param->mode, param->st, v_umask);
-}
+ return 1;
+}
-static int ads_setfilmode(const char * name, mode_t mode, struct stat *st, mode_t v_umask)
+/* ----------------- */
+static int RF_chown_ea(VFS_FUNC_ARGS_CHOWN)
{
- mode_t file_mode = ad_hf_mode(mode);
- mode_t dir_mode = file_mode;
- struct set_mode param;
-
- if ((dir_mode & (S_IRUSR | S_IWUSR )))
- dir_mode |= S_IXUSR;
- if ((dir_mode & (S_IRGRP | S_IWGRP )))
- dir_mode |= S_IXGRP;
- if ((dir_mode & (S_IROTH | S_IWOTH )))
- dir_mode |= S_IXOTH;
-
- /* change folder */
- dir_mode |= DIRBITS;
- if (dir_rx_set(dir_mode)) {
- if (chmod( name, dir_mode ) < 0)
- return -1;
- }
- param.st = st;
- param.mode = file_mode;
- if (for_each_adouble("setfilmode_ads", name, ads_setfilmode_loop, ¶m, 0, v_umask) < 0)
- return -1;
-
- if (!dir_rx_set(dir_mode)) {
- if (chmod( name, dir_mode ) < 0)
- return -1;
- }
-
return 0;
}
-static int RF_setfilmode_ads(VFS_FUNC_ARGS_SETFILEMODE)
+/* ---------------- */
+static int RF_renamedir_ea(VFS_FUNC_ARGS_RENAMEDIR)
{
- return ads_setfilmode(ad_dir(vol->ad_path(name, ADFLAGS_HF )), mode, st, vol->v_umask);
+ return 0;
}
-/* ------------------- */
-static int RF_setdirunixmode_ads(VFS_FUNC_ARGS_SETDIRUNIXMODE)
+/* ---------------- */
+static int RF_deletecurdir_ea(VFS_FUNC_ARGS_DELETECURDIR)
{
- char *adouble = vol->ad_path(name, ADFLAGS_DIR );
- char ad_p[ MAXPATHLEN + 1];
- int dropbox = vol->v_flags;
-
- strlcpy(ad_p,ad_dir(adouble), MAXPATHLEN + 1);
-
- if (dir_rx_set(mode)) {
-
- /* .AppleDouble */
- if (stickydirmode(ad_dir(ad_p), DIRBITS | mode, dropbox, vol->v_umask) < 0)
- return -1;
-
- /* .AppleDouble/.Parent */
- if (stickydirmode(ad_p, DIRBITS | mode, dropbox, vol->v_umask) < 0)
- return -1;
- }
-
- if (ads_setfilmode(ad_dir(vol->ad_path(name, ADFLAGS_DIR)), mode, st, vol->v_umask) < 0)
- return -1;
-
- if (!dir_rx_set(mode)) {
- if (stickydirmode(ad_p, DIRBITS | mode, dropbox, vol->v_umask) < 0)
- return -1 ;
- if (stickydirmode(ad_dir(ad_p), DIRBITS | mode, dropbox, vol->v_umask) < 0)
- return -1;
- }
return 0;
}
-/* ------------------- */
-struct dir_mode {
- mode_t mode;
- int dropbox;
-};
-
-static int setdirmode_ads_loop(struct dirent *de _U_, char *name, void *data, int flag, mode_t v_umask)
+/* ---------------- */
+static int RF_setdirunixmode_ea(VFS_FUNC_ARGS_SETDIRUNIXMODE)
{
-
- struct dir_mode *param = data;
- int ret = 0; /* 0 ignore error, -1 */
-
- if (dir_rx_set(param->mode)) {
- if (stickydirmode(name, DIRBITS | param->mode, param->dropbox, v_umask) < 0) {
- if (flag) {
- return 0;
- }
- return ret;
- }
- }
- if (ads_setfilmode(name, param->mode, NULL, v_umask) < 0)
- return ret;
-
- if (!dir_rx_set(param->mode)) {
- if (stickydirmode(name, DIRBITS | param->mode, param->dropbox, v_umask) < 0) {
- if (flag) {
- return 0;
- }
- return ret;
- }
- }
return 0;
}
-static int RF_setdirmode_ads(VFS_FUNC_ARGS_SETDIRMODE)
+static int RF_setfilmode_ea(VFS_FUNC_ARGS_SETFILEMODE)
{
- char *adouble = vol->ad_path(name, ADFLAGS_DIR );
- char ad_p[ MAXPATHLEN + 1];
- struct dir_mode param;
-
- param.mode = mode;
- param.dropbox = vol->v_flags;
-
- strlcpy(ad_p,ad_dir(adouble), sizeof(ad_p));
-
- if (dir_rx_set(mode)) {
- /* .AppleDouble */
- if (stickydirmode(ad_dir(ad_p), DIRBITS | mode, param.dropbox, vol->v_umask) < 0)
- return -1;
- }
-
- if (for_each_adouble("setdirmode_ads", ad_dir(ad_p), setdirmode_ads_loop, ¶m, vol_noadouble(vol), vol->v_umask))
- return -1;
-
- if (!dir_rx_set(mode)) {
- if (stickydirmode(ad_dir(ad_p), DIRBITS | mode, param.dropbox, vol->v_umask) < 0 )
- return -1;
- }
return 0;
}
-/* ------------------- */
-static int setdirowner_ads1_loop(struct dirent *de _U_, char *name, void *data, int flag _U_, mode_t v_umask _U_)
+/* ---------------- */
+static int RF_setdirmode_ea(VFS_FUNC_ARGS_SETDIRMODE)
{
- struct perm *owner = data;
-
- if ( chown( name, owner->uid, owner->gid ) < 0 && errno != EPERM ) {
- LOG(log_debug, logtype_afpd, "setdirowner: chown %d/%d %s: %s",
- owner->uid, owner->gid, fullpathname(name), strerror(errno) );
- /* return ( -1 ); Sometimes this is okay */
- }
return 0;
}
-static int setdirowner_ads_loop(struct dirent *de _U_, char *name, void *data, int flag, mode_t v_umask _U_)
+/* ---------------- */
+static int RF_setdirowner_ea(VFS_FUNC_ARGS_SETDIROWNER)
{
- struct perm *owner = data;
-
- if (for_each_adouble("setdirowner", name, setdirowner_ads1_loop, data, flag, 0) < 0)
- return -1;
-
- if ( chown( name, owner->uid, owner->gid ) < 0 && errno != EPERM ) {
- LOG(log_debug, logtype_afpd, "setdirowner: chown %d/%d %s: %s",
- owner->uid, owner->gid, fullpathname(name), strerror(errno) );
- /* return ( -1 ); Sometimes this is okay */
- }
- return 0;
+ return 0;
}
-static int RF_setdirowner_ads(VFS_FUNC_ARGS_SETDIROWNER)
+static int RF_deletefile_ea(VFS_FUNC_ARGS_DELETEFILE)
{
- int noadouble = vol_noadouble(vol);
- char adouble_p[ MAXPATHLEN + 1];
- struct stat st;
- struct perm owner;
-
- owner.uid = uid;
- owner.gid = gid;
-
- strlcpy(adouble_p, ad_dir(vol->ad_path(name, ADFLAGS_DIR )), sizeof(adouble_p));
-
- if (for_each_adouble("setdirowner", ad_dir(adouble_p), setdirowner_ads_loop, &owner, noadouble, 0))
- return -1;
-
- /*
- * We cheat: we know that chown doesn't do anything.
- */
- if ( stat( ".AppleDouble", &st ) < 0) {
- if (errno == ENOENT && noadouble)
- return 0;
- LOG(log_error, logtype_afpd, "setdirowner: stat %s: %s", fullpathname(".AppleDouble"), strerror(errno) );
- return -1;
- }
- if ( gid && gid != st.st_gid && chown( ".AppleDouble", uid, gid ) < 0 && errno != EPERM ) {
- LOG(log_debug, logtype_afpd, "setdirowner: chown %d/%d %s: %s",
- uid, gid,fullpathname(".AppleDouble"), strerror(errno) );
- /* return ( -1 ); Sometimes this is okay */
- }
return 0;
}
-
-/* ------------------- */
-static int RF_deletefile_ads(VFS_FUNC_ARGS_DELETEFILE)
+static int RF_copyfile_ea(VFS_FUNC_ARGS_COPYFILE)
{
- int ret = 0;
- int cwd = -1;
- char *ad_p;
-
- ad_p = ad_dir(vol->ad_path(file, ADFLAGS_HF ));
-
- if (dirfd != -1) {
- if (((cwd = open(".", O_RDONLY)) == -1) || (fchdir(dirfd) != 0)) {
- ret = AFPERR_MISC;
- goto exit;
- }
- }
-
- ret = ads_delete_rf(ad_p);
-
- if (dirfd != -1 && fchdir(cwd) != 0) {
- LOG(log_error, logtype_afpd, "RF_deletefile_ads: cant chdir back. exit!");
- exit(EXITERR_SYS);
- }
-
-exit:
- if (cwd != -1)
- close(cwd);
-
- return ret;
+ return 0;
}
-/* --------------------------- */
-static int RF_renamefile_ads(VFS_FUNC_ARGS_RENAMEFILE)
+/* ---------------- */
+static int RF_renamefile_ea(VFS_FUNC_ARGS_RENAMEFILE)
{
- char adsrc[ MAXPATHLEN + 1];
- int err = 0;
-
- strcpy( adsrc, ad_dir(vol->ad_path(src, 0 )));
- if (unix_rename(dirfd, adsrc, -1, ad_dir(vol->ad_path(dst, 0 ))) < 0) {
- struct stat st;
-
- err = errno;
- if (errno == ENOENT) {
- struct adouble ad;
-
- if (lstatat(dirfd, adsrc, &st)) /* source has no ressource fork, */
- return 0;
-
- /* We are here because :
- * -there's no dest folder.
- * -there's no .AppleDouble in the dest folder.
- * if we use the struct adouble passed in parameter it will not
- * create .AppleDouble if the file is already opened, so we
- * use a diff one, it's not a pb,ie it's not the same file, yet.
- */
- ad_init(&ad, vol->v_adouble, vol->v_ad_options);
- if (!ad_open(dst, ADFLAGS_HF, O_RDWR | O_CREAT, 0666, &ad)) {
- ad_close(&ad, ADFLAGS_HF);
-
- /* We must delete it */
- RF_deletefile_ads(vol, -1, dst );
- if (!unix_rename(dirfd, adsrc, -1, ad_dir(vol->ad_path(dst, 0 ))) )
- err = 0;
- else
- err = errno;
- }
- else { /* it's something else, bail out */
- err = errno;
- }
- }
- }
- if (err) {
- errno = err;
- return -1;
- }
- return 0;
+ return 0;
}
+#if 0
/*************************************************************************
* osx adouble format
************************************************************************/
}
return 0;
}
+#endif
/********************************************************************************************
* VFS chaining
};
/*
- * Primary adouble modules: default, osx, sfm
+ * Primary adouble modules: v2, ea
*/
-static struct vfs_ops netatalk_adouble = {
+static struct vfs_ops netatalk_adouble_v2 = {
/* vfs_validupath: */ validupath_adouble,
/* vfs_chown: */ RF_chown_adouble,
/* vfs_renamedir: */ RF_renamedir_adouble,
NULL
};
-static struct vfs_ops netatalk_adouble_osx = {
- /* vfs_validupath: */ validupath_osx,
- /* vfs_chown: */ RF_chown_adouble,
- /* vfs_renamedir: */ RF_renamedir_osx,
- /* vfs_deletecurdir: */ RF_deletecurdir_osx,
- /* vfs_setfilmode: */ RF_setfilmode_adouble,
- /* vfs_setdirmode: */ RF_setdirmode_osx,
- /* vfs_setdirunixmode:*/ RF_setdirunixmode_osx,
- /* vfs_setdirowner: */ RF_setdirowner_osx,
- /* vfs_deletefile: */ RF_deletefile_adouble,
- /* vfs_renamefile: */ RF_renamefile_osx,
- /* vfs_copyfile: */ NULL,
- NULL
-};
-
-/* samba sfm format. ad_path shouldn't be set her */
-static struct vfs_ops netatalk_adouble_sfm = {
- /* vfs_validupath: */ validupath_adouble,
- /* vfs_chown: */ RF_chown_ads,
- /* vfs_renamedir: */ RF_renamedir_adouble,
- /* vfs_deletecurdir: */ RF_deletecurdir_ads,
- /* vfs_setfilmode: */ RF_setfilmode_ads,
- /* vfs_setdirmode: */ RF_setdirmode_ads,
- /* vfs_setdirunixmode:*/ RF_setdirunixmode_ads,
- /* vfs_setdirowner: */ RF_setdirowner_ads,
- /* vfs_deletefile: */ RF_deletefile_ads,
- /* vfs_renamefile: */ RF_renamefile_ads,
- /* vfs_copyfile: */ NULL,
+static struct vfs_ops netatalk_adouble_ea = {
+ /* vfs_validupath: */ validupath_ea,
+ /* vfs_chown: */ RF_chown_ea,
+ /* vfs_renamedir: */ RF_renamedir_ea,
+ /* vfs_deletecurdir: */ RF_deletecurdir_ea,
+ /* vfs_setfilmode: */ RF_setfilmode_ea,
+ /* vfs_setdirmode: */ RF_setdirmode_ea,
+ /* vfs_setdirunixmode:*/ RF_setdirunixmode_ea,
+ /* vfs_setdirowner: */ RF_setdirowner_ea,
+ /* vfs_deletefile: */ RF_deletefile_ea,
+ /* vfs_renamefile: */ RF_renamefile_ea,
+ /* vfs_copyfile: */ RF_copyfile_ea,
NULL
};
vol->vfs = &vfs_master_funcs;
/* Default adouble stuff */
- if (vol->v_adouble == AD_VERSION2_OSX) {
- vol->vfs_modules[0] = &netatalk_adouble_osx;
- vol->ad_path = ad_path_osx;
- }
- else if (vol->v_adouble == AD_VERSION1_SFM) {
- vol->vfs_modules[0] = &netatalk_adouble_sfm;
- vol->ad_path = ad_path_sfm;
- }
- else {
- vol->vfs_modules[0] = &netatalk_adouble;
+ if (vol->v_adouble == AD_VERSION2) {
+ vol->vfs_modules[0] = &netatalk_adouble_v2;
vol->ad_path = ad_path;
+ } else {
+ vol->vfs_modules[0] = &netatalk_adouble_ea;
+ vol->ad_path = ad_path_ea;
}
/* Extended Attributes */