#include <atalk/util.h>
#include <atalk/cnid.h>
#include <atalk/unix.h>
+#include <atalk/globals.h>
+#include <atalk/fce_api.h>
#include "directory.h"
#include "dircache.h"
#include "fork.h"
#include "file.h"
#include "filedir.h"
-#include "globals.h"
#include "unix.h"
/* the format for the finderinfo fields (from IM: Toolbox Essentials):
memcpy(data, ufinderi, ADEDLEN_FINDERI);
chk_ext = 1;
if (vol_inv_dots(vol) && *upath == '.') { /* make it invisible */
- u_int16_t ashort;
+ uint16_t ashort;
ashort = htons(FINDERINFO_INVISIBLE);
memcpy((char *)data + FINDERINFO_FRFLAGOFF, &ashort, sizeof(ashort));
}
if (islink){
- u_int16_t linkflag;
+ uint16_t linkflag;
memcpy(&linkflag, (char *)data + FINDERINFO_FRFLAGOFF, 2);
linkflag |= htons(FINDERINFO_ISALIAS);
memcpy((char *)data + FINDERINFO_FRFLAGOFF, &linkflag, 2);
/* ---------------------
*/
-char *set_name(const struct vol *vol, char *data, cnid_t pid, char *name, cnid_t id, u_int32_t utf8)
+char *set_name(const struct vol *vol, char *data, cnid_t pid, char *name, cnid_t id, uint32_t utf8)
{
- u_int32_t aint;
+ uint32_t aint;
char *tp = NULL;
char *src = name;
aint = strlen( name );
*data++ = aint;
}
else {
- u_int16_t temp;
+ uint16_t temp;
- if (aint > 255) /* FIXME safeguard, anyway if no ascii char it's game over*/
- aint = 255;
+ if (aint > UTF8FILELEN_EARLY) /* FIXME safeguard, anyway if no ascii char it's game over*/
+ aint = UTF8FILELEN_EARLY;
utf8 = vol->v_kTextEncoding;
memcpy(data, &utf8, sizeof(utf8));
const int len)
{
static int first = 1; /* mark if this func is called the first time */
- u_int32_t adcnid;
- u_int32_t dbcnid = CNID_INVALID;
+ uint32_t adcnid;
+ uint32_t dbcnid = CNID_INVALID;
restart:
if (vol->v_cdb != NULL) {
/* -------------------------- */
int getmetadata(struct vol *vol,
- u_int16_t bitmap,
+ uint16_t bitmap,
struct path *path, struct dir *dir,
char *buf, size_t *buflen, struct adouble *adp)
{
char *data, *l_nameoff = NULL, *upath;
char *utf_nameoff = NULL;
int bit = 0;
- u_int32_t aint;
+ uint32_t aint;
cnid_t id = 0;
- u_int16_t ashort;
+ uint16_t ashort;
u_char achar, fdType[4];
- u_int32_t utf8 = 0;
+ uint32_t utf8 = 0;
struct stat *st;
struct maccess ma;
+ LOG(log_debug, logtype_afpd, "getmetadata(\"%s\")", path->u_name);
+
upath = path->u_name;
st = &path->st;
data = buf;
|| (bitmap & ( (1 << FILPBIT_LNAME) ) && utf8_encoding()) /* FIXME should be m_name utf8 filename */
|| (bitmap & (1 << FILPBIT_FNUM))) {
if (!path->id) {
+ bstring fullpath;
struct dir *cachedfile;
int len = strlen(upath);
- if ((cachedfile = dircache_search_by_name(vol, dir, upath, len, st->st_ctime)) != NULL)
+ if ((cachedfile = dircache_search_by_name(vol, dir, upath, len)) != NULL)
id = cachedfile->d_did;
else {
id = get_id(vol, adp, st, dir->d_did, upath, len);
if (path->m_name == NULL) {
if ((path->m_name = utompath(vol, upath, id, utf8_encoding())) == NULL) {
LOG(log_error, logtype_afpd, "getmetadata: utompath error");
- exit(EXITERR_SYS);
+ return AFPERR_MISC;
}
}
- if ((cachedfile = dir_new(path->m_name, upath, vol, dir->d_did, id, NULL, st->st_ctime)) == NULL) {
+ /* Build fullpath */
+ if (((fullpath = bstrcpy(dir->d_fullpath)) == NULL)
+ || (bconchar(fullpath, '/') != BSTR_OK)
+ || (bcatcstr(fullpath, upath)) != BSTR_OK) {
+ LOG(log_error, logtype_afpd, "getmetadata: fullpath: %s", strerror(errno));
+ return AFPERR_MISC;
+ }
+
+ if ((cachedfile = dir_new(path->m_name, upath, vol, dir->d_did, id, fullpath, st)) == NULL) {
LOG(log_error, logtype_afpd, "getmetadata: error from dir_new");
- exit(EXITERR_SYS);
+ return AFPERR_MISC;
}
- if ((dircache_add(cachedfile)) != 0) {
+ if ((dircache_add(vol, cachedfile)) != 0) {
LOG(log_error, logtype_afpd, "getmetadata: fatal dircache error");
- exit(EXITERR_SYS);
+ return AFPERR_MISC;
}
}
} else {
/* FIXME do we want a visual clue if the file is read only
*/
struct maccess ma;
- accessmode( ".", &ma, dir , NULL);
+ accessmode(vol, ".", &ma, dir , NULL);
if ((ma.ma_user & AR_UWRITE)) {
- accessmode( upath, &ma, dir , st);
+ accessmode(vol, upath, &ma, dir , st);
if (!(ma.ma_user & AR_UWRITE)) {
ashort |= htons(ATTRBIT_NOWRITE);
}
break;
case FILPBIT_PDID :
- memcpy(data, &dir->d_did, sizeof( u_int32_t ));
- data += sizeof( u_int32_t );
+ memcpy(data, &dir->d_did, sizeof( uint32_t ));
+ data += sizeof( uint32_t );
LOG(log_debug, logtype_afpd, "metadata('%s'): Parent DID: %u",
path->u_name, ntohl(dir->d_did));
break;
case FILPBIT_LNAME :
l_nameoff = data;
- data += sizeof( u_int16_t );
+ data += sizeof( uint16_t );
break;
case FILPBIT_SNAME :
- memset(data, 0, sizeof(u_int16_t));
- data += sizeof( u_int16_t );
+ memset(data, 0, sizeof(uint16_t));
+ data += sizeof( uint16_t );
break;
case FILPBIT_FNUM :
if (afp_version >= 30) { /* UTF8 name */
utf8 = kTextEncodingUTF8;
utf_nameoff = data;
- data += sizeof( u_int16_t );
+ data += sizeof( uint16_t );
aint = 0;
memcpy(data, &aint, sizeof( aint ));
data += sizeof( aint );
break;
case FILPBIT_UNIXPR :
/* accessmode may change st_mode with ACLs */
- accessmode( upath, &ma, dir , st);
+ accessmode(vol, upath, &ma, dir , st);
aint = htonl(st->st_uid);
memcpy( data, &aint, sizeof( aint ));
/* ----------------------- */
int getfilparams(struct vol *vol,
- u_int16_t bitmap,
+ uint16_t bitmap,
struct path *path, struct dir *dir,
char *buf, size_t *buflen )
{
int opened = 0;
int rc;
+ LOG(log_debug, logtype_afpd, "getfilparams(\"%s\")", path->u_name);
+
opened = PARAM_NEED_ADP(bitmap);
adp = NULL;
}
}
rc = getmetadata(vol, bitmap, path, dir, buf, buflen, adp);
- ad_close_metadata( adp);
+ ad_close(adp, ADFLAGS_HF);
return( rc );
}
struct ofork *of = NULL;
char *path, *upath;
int creatf, did, openf, retvalue = AFP_OK;
- u_int16_t vid;
+ uint16_t vid;
struct path *s_path;
*rbuflen = 0;
return( AFPERR_BADTYPE );
upath = s_path->u_name;
- ad_init(&ad, vol->v_adouble, vol->v_ad_options);
+ ad_init(&ad, vol);
/* if upath is deleted we already in trouble anyway */
if ((of = of_findname(s_path))) {
return AFPERR_EXIST;
}
- if ( creatf)
- openf = O_RDWR|O_CREAT|O_TRUNC;
+ if (creatf)
+ openf = ADFLAGS_RDWR | ADFLAGS_CREATE | ADFLAGS_TRUNC;
else
/* on a soft create, if the file is open then ad_open won't fail
because open syscall is not called */
- openf = O_RDWR|O_CREAT|O_EXCL;
+ openf = ADFLAGS_RDWR | ADFLAGS_CREATE | ADFLAGS_EXCL;
- if ( ad_open(&ad, upath, ADFLAGS_DF | ADFLAGS_HF | ADFLAGS_NOHF,
- openf, 0666, openf, 0666) < 0 ) {
+ if (ad_open(&ad, upath, ADFLAGS_DF | ADFLAGS_HF | ADFLAGS_NOHF | openf, 0666) < 0) {
switch ( errno ) {
case EROFS:
return AFPERR_VLOCK;
}
}
if ( ad_meta_fileno( &ad ) == -1 ) { /* Hard META / HF */
- /* on noadouble volumes, just creating the data fork is ok */
- if (vol_noadouble(vol)) {
- ad_close( &ad, ADFLAGS_DF );
- goto createfile_done;
- }
/* FIXME with hard create on an existing file, we already
* corrupted the data file.
*/
path = s_path->m_name;
ad_setname(&ad, path);
+
+ struct stat st;
+ if (lstat(upath, &st) != 0) {
+ LOG(log_error, logtype_afpd, "afp_createfile(\"%s\"): stat: %s",
+ upath, strerror(errno));
+ ad_close(&ad, ADFLAGS_DF|ADFLAGS_HF);
+ return AFPERR_MISC;
+ }
+
+ (void)get_id(vol, &ad, &st, dir->d_did, upath, strlen(upath));
+
ad_flush(&ad);
ad_close(&ad, ADFLAGS_DF|ADFLAGS_HF );
+ fce_register_new_file(s_path);
createfile_done:
- curdir->offcnt++;
-
-#ifdef DROPKLUDGE
- if (vol->v_flags & AFPVOL_DROPBOX) {
- retvalue = matchfile2dirperms(upath, vol, did);
- }
-#endif /* DROPKLUDGE */
+ curdir->d_offcnt++;
setvoltime(obj, vol );
struct dir *dir;
struct path *s_path;
int did, rc;
- u_int16_t vid, bitmap;
+ uint16_t vid, bitmap;
*rbuflen = 0;
ibuf += 2;
extern struct path Cur_Path;
int setfilparams(struct vol *vol,
- struct path *path, u_int16_t f_bitmap, char *buf )
+ struct path *path, uint16_t f_bitmap, char *buf )
{
struct adouble ad, *adp;
struct extmap *em;
int bit, isad = 1, err = AFP_OK;
char *upath;
u_char achar, *fdType, xyy[4]; /* uninitialized, OK 310105 */
- u_int16_t ashort, bshort, oshort;
- u_int32_t aint;
- u_int32_t upriv;
- u_int16_t upriv_bit = 0;
-
- struct utimbuf ut;
-
+ uint16_t ashort, bshort, oshort;
+ uint32_t aint;
+ uint32_t upriv;
+ uint16_t upriv_bit = 0;
+ struct utimbuf ut;
int change_mdate = 0;
int change_parent_mdate = 0;
int newdate = 0;
struct timeval tv;
uid_t f_uid;
gid_t f_gid;
- u_int16_t bitmap = f_bitmap;
- u_int32_t cdate,bdate;
+ uint16_t bitmap = f_bitmap;
+ uint32_t cdate,bdate;
u_char finder_buf[32];
+ int symlinked = 0;
#ifdef DEBUG
LOG(log_debug9, logtype_afpd, "begin setfilparams:");
case FILPBIT_FINFO :
change_mdate = 1;
memcpy(finder_buf, buf, 32 );
- if (memcmp(buf,"slnkrhap",8)==0 && !S_ISLNK(path->st.st_mode)){
- // SLFINFO
+ if (memcmp(buf, "slnkrhap", 8) == 0 && !S_ISLNK(path->st.st_mode)) {
int fp;
ssize_t len;
int erc=1;
char buf[PATH_MAX+1];
- if ((fp=open(path->u_name,O_RDONLY))>=0){
- if ((len=read(fp,buf,PATH_MAX+1))){
- if (unlink(path->u_name)==0){
- buf[len]=0;
+ if ((fp = open(path->u_name, O_RDONLY)) >= 0) {
+ if ((len = read(fp, buf, PATH_MAX+1))) {
+ if (unlink(path->u_name) == 0) {
+ buf[len] = 0;
erc = symlink(buf, path->u_name);
if (!erc)
of_stat(path);
}
close(fp);
}
- if (erc!=0){
+ if (erc != 0) {
err=AFPERR_BITMAP;
goto setfilparam_done;
}
+ symlinked = 1;
}
buf += 32;
break;
/* second try with adouble open
*/
- if ( ad_open(adp, upath, ADFLAGS_HF, O_RDWR | O_CREAT, 0666) < 0) {
+ if (ad_open(adp, upath, ADFLAGS_HF | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666) < 0) {
LOG(log_debug, logtype_afpd, "setfilparams: ad_open_metadata error");
/*
* For some things, we don't need an adouble header:
* - change of modification date
* - UNIX privs (Bug-ID #2863424)
*/
- if (!vol_noadouble(vol) && (f_bitmap & ~(1<<FILPBIT_MDATE | 1<<FILPBIT_UNIXPR))) {
+ if (!symlinked && f_bitmap & ~(1<<FILPBIT_MDATE | 1<<FILPBIT_UNIXPR)) {
LOG(log_debug, logtype_afpd, "setfilparams: need adouble access");
return AFPERR_ACCESS;
}
}
if (isad) {
- ad_flush( adp);
- ad_close_metadata( adp);
+ ad_flush(adp);
+ ad_close(adp, ADFLAGS_HF);
}
if (change_parent_mdate && gettimeofday(&tv, NULL) == 0) {
{
int rc;
+ LOG(log_debug, logtype_afpd,
+ "renamefile: src[%d, \"%s\"] -> dst[\"%s\"]", sdir_fd, src, dst);
+
if ( unix_rename( sdir_fd, src, -1, dst ) < 0 ) {
switch ( errno ) {
case ENOENT :
}
/* don't care if we can't open the newly renamed ressource fork */
- if (ad_open(adp, dst, ADFLAGS_HF, O_RDWR) == 0) {
+ if (ad_open(adp, dst, ADFLAGS_HF | ADFLAGS_RDWR) == 0) {
ad_setname(adp, newname);
ad_flush( adp );
ad_close( adp, ADFLAGS_HF );
{
char type = *ibuf;
size_t plen = 0;
-u_int16_t len16;
-u_int32_t hint;
+uint16_t len16;
+uint32_t hint;
if ( type != 2 && !(afp_version >= 30 && type == 3) ) {
return -1;
struct dir *dir;
char *newname, *p, *upath;
struct path *s_path;
- u_int32_t sdid, ddid;
+ uint32_t sdid, ddid;
int err, retvalue = AFP_OK;
- u_int16_t svid, dvid;
+ uint16_t svid, dvid;
struct adouble ad, *adp;
int denyreadset;
adp = of_ad(s_vol, s_path, &ad);
- if (ad_open(adp, s_path->u_name, ADFLAGS_DF | ADFLAGS_HF | ADFLAGS_NOHF, O_RDONLY, O_RDONLY) < 0) {
+ if (ad_open(adp, s_path->u_name, ADFLAGS_DF | ADFLAGS_HF | ADFLAGS_NOHF | ADFLAGS_RDONLY | ADFLAGS_SETSHRMD) < 0) {
return AFPERR_DENYCONF;
}
denyreadset = (ad_testlock(adp, ADEID_DFORK, AD_FILELOCK_DENY_RD) != 0 ||
goto copy_exit;
}
-#ifdef FORCE_UIDGID
- /* FIXME svid != dvid && dvid's user can't read svid */
-#endif
if (NULL == ( d_vol = getvolbyvid( dvid )) ) {
retvalue = AFPERR_PARAM;
goto copy_exit;
retvalue = err;
goto copy_exit;
}
- curdir->offcnt++;
-
-#ifdef DROPKLUDGE
- if (vol->v_flags & AFPVOL_DROPBOX) {
- retvalue=matchfile2dirperms(upath, vol, ddid); /* FIXME sdir or ddid */
- }
-#endif /* DROPKLUDGE */
+ curdir->d_offcnt++;
setvoltime(obj, d_vol );
int err = 0;
char filebuf[8192];
int sfd, dfd;
-
+ off_t soff, doff;
+
if (eid == ADEID_DFORK) {
sfd = ad_data_fileno(ads);
dfd = ad_data_fileno(add);
dfd = ad_reso_fileno(add);
}
- if ((off_t)-1 == lseek(sfd, ad_getentryoff(ads, eid), SEEK_SET))
+ if (add->ad_version == AD_VERSION2)
+ soff = doff = ad_getentryoff(ads, eid);
+ else {
+ if (eid == ADEID_DFORK)
+ soff = doff = ad_getentryoff(ads, eid);
+ else {
+#ifdef HAVE_EAFD
+ soff = doff = 0;
+#else
+ soff = doff = ADEDOFF_RFORK_OSX;
+#endif
+ }
+ }
+
+ if ((off_t)-1 == lseek(sfd, soff, SEEK_SET))
return -1;
- if ((off_t)-1 == lseek(dfd, ad_getentryoff(add, eid), SEEK_SET))
+ if ((off_t)-1 == lseek(dfd, doff, SEEK_SET))
return -1;
#if 0 /* ifdef SENDFILE_FLAVOR_LINUX */
sfd, src, dst, newname);
if (adp == NULL) {
- ad_init(&ads, s_vol->v_adouble, s_vol->v_ad_options);
+ ad_init(&ads, s_vol);
adp = &ads;
}
- adflags = ADFLAGS_DF;
+ adflags = ADFLAGS_DF | ADFLAGS_RF | ADFLAGS_NORF;
if (newname) {
adflags |= ADFLAGS_HF;
}
- if (ad_openat(adp, sfd, src, adflags | ADFLAGS_NOHF, O_RDONLY, O_RDONLY) < 0) {
+ if (ad_openat(adp, sfd, src, adflags | ADFLAGS_NOHF | ADFLAGS_RDONLY) < 0) {
ret_err = errno;
goto done;
}
- if (ad_meta_fileno(adp) == -1 && ad_reso_fileno(adp) == -1) { /* META / HF */
+ if (!AD_RSRC_OPEN(adp))
/* no resource fork, don't create one for dst file */
- adflags &= ~ADFLAGS_HF;
- }
+ adflags &= ~ADFLAGS_RF;
stat_result = fstat(ad_data_fileno(adp), &st); /* saving stat exit code, thus saving us on one more stat later on */
st.st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
}
- ad_init(&add, d_vol->v_adouble, d_vol->v_ad_options);
- if (ad_open(&add, dst, adflags, O_RDWR|O_CREAT|O_EXCL, st.st_mode, O_RDWR|O_CREAT|O_EXCL, st.st_mode) < 0) {
+ ad_init(&add, d_vol);
+ if (ad_open(&add, dst, adflags | ADFLAGS_RDWR | ADFLAGS_CREATE | ADFLAGS_EXCL, st.st_mode) < 0) {
ret_err = errno;
ad_close( adp, adflags );
if (EEXIST != ret_err) {
}
return AFPERR_EXIST;
}
+
+ if (AD_RSRC_OPEN(adp))
+ err = copy_fork(ADEID_RFORK, &add, adp);
- /*
- * XXX if the source and the dest don't use the same resource type it's broken
- */
- if (ad_reso_fileno(adp) == -1 || 0 == (err = copy_fork(ADEID_RFORK, &add, adp))){
- /* copy the data fork */
- if ((err = copy_fork(ADEID_DFORK, &add, adp)) == 0) {
- err = d_vol->vfs->vfs_copyfile(d_vol, sfd, src, dst);
- }
- }
+ if (err == 0)
+ err = copy_fork(ADEID_DFORK, &add, adp);
+
+ if ((err == 0) && (ad_meta_fileno(adp) != -1))
+ err = d_vol->vfs->vfs_copyfile(d_vol, sfd, src, dst);
- if (err < 0) {
+ if (err < 0)
ret_err = errno;
- }
if (!ret_err && newname && (adflags & ADFLAGS_HF)) {
/* set the new name in the resource fork */
static int check_attrib(struct adouble *adp)
{
-u_int16_t bshort = 0;
+uint16_t bshort = 0;
ad_getattr(adp, &bshort);
/*
LOG(log_debug, logtype_afpd, "deletefile('%s')", file);
- ad_init(&ad, vol->v_adouble, vol->v_ad_options);
+ ad_init(&ad, vol);
if (checkAttrib) {
/* was EACCESS error try to get only metadata */
/* we never want to create a resource fork here, we are going to delete it
*/
if ( ad_metadataat(dirfd, file, ADFLAGS_CHECK_OF, &ad) == 0 ) {
if ((err = check_attrib(&ad))) {
- ad_close_metadata(&ad);
+ ad_close(&ad, ADFLAGS_HF);
return err;
}
meta = 1;
/* try to open both forks at once */
adflags = ADFLAGS_DF;
- if ( ad_openat(&ad, dirfd, file, adflags |ADFLAGS_HF|ADFLAGS_NOHF, O_RDONLY, O_RDONLY) < 0 ) {
+ if (ad_openat(&ad, dirfd, file, adflags | ADFLAGS_RF | ADFLAGS_NORF | ADFLAGS_RDONLY) < 0 ) {
switch (errno) {
case ENOENT:
err = AFPERR_NOOBJ;
adp = &ad;
}
- if ( adp && ad_reso_fileno( adp ) != -1 ) { /* there's a resource fork */
- adflags |= ADFLAGS_HF;
+ if ( adp && AD_RSRC_OPEN(adp) != -1 ) { /* there's a resource fork */
+ adflags |= ADFLAGS_RF;
/* FIXME we have a pb here because we want to know if a file is open
* there's a 'priority inversion' if you can't open the ressource fork RW
* you can delete it if it's open because you can't get a write lock.
}
if (adp && ad_tmplock( &ad, ADEID_DFORK, ADLOCK_WR, 0, 0, 0 ) < 0) {
+ LOG(log_error, logtype_afpd, "deletefile('%s'): ad_tmplock error: %s", file, strerror(errno));
err = AFPERR_BUSY;
} else if (!(err = vol->vfs->vfs_deletefile(vol, dirfd, file)) && !(err = netatalk_unlinkat(dirfd, file )) ) {
cnid_t id;
end:
if (meta)
- ad_close_metadata(&ad);
+ ad_close(&ad, ADFLAGS_HF);
if (adp)
ad_close( &ad, adflags ); /* ad_close removes locks if any */
if (dirreenumerate(dir, &st)) {
/* we already did it once and the dir haven't been modified */
- return dir->offcnt;
+ return dir->d_offcnt;
}
data.vol = vol;
int err, retry=0;
size_t buflen;
cnid_t id, cnid;
- u_int16_t vid, bitmap;
+ uint16_t vid, bitmap;
static char buffer[12 + MAXPATHLEN + 1];
int len = 12 + MAXPATHLEN + 1;
adp = (*of)->of_ad;
}
else {
- ret = ad_open(adp, path->u_name, ADFLAGS_HF, O_RDONLY);
+ ret = ad_open(adp, path->u_name, ADFLAGS_HF | ADFLAGS_RDWR);
/* META and HF */
if ( !ret && ad_reso_fileno(adp) != -1 && !(adp->ad_resource_fork.adf_flags & ( O_RDWR | O_WRONLY))) {
/* from AFP spec.
int crossdev;
int slen, dlen;
- u_int32_t sid, did;
- u_int16_t vid;
+ uint32_t sid, did;
+ uint16_t vid;
uid_t uid;
gid_t gid;
return AFPERR_PARAM ;
}
- ad_init(&ads, vol->v_adouble, vol->v_ad_options);
+ ad_init(&ads, vol);
if (!(adsp = find_adouble( path, &s_of, &ads))) {
return afp_errno;
}
goto err_exchangefile;
}
- ad_init(&add, vol->v_adouble, vol->v_ad_options);
+ ad_init(&add, vol);
if (!(addp = find_adouble( path, &d_of, &add))) {
err = afp_errno;
goto err_exchangefile;