/*
- * $Id: file.c,v 1.120 2009-11-02 14:35:27 didg Exp $
+ * $Id: file.c,v 1.135 2010-02-16 02:43:36 didg Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
}
/* FIXME path : unix or mac name ? (for now it's unix name ) */
-void *get_finderinfo(const struct vol *vol, const char *upath, struct adouble *adp, void *data)
+void *get_finderinfo(const struct vol *vol, const char *upath, struct adouble *adp, void *data, int islink)
{
struct extmap *em;
void *ad_finder = NULL;
memcpy((char *)data + FINDERINFO_FRFLAGOFF, &ashort, sizeof(ashort));
}
}
+
+ if (islink){
+ u_int16_t linkflag;
+ memcpy(&linkflag, (char *)data + FINDERINFO_FRFLAGOFF, 2);
+ linkflag |= htons(FINDERINFO_ISALIAS);
+ memcpy((char *)data + FINDERINFO_FRFLAGOFF, &linkflag, 2);
+ memcpy((char *)data + FINDERINFO_FRTYPEOFF,"slnk",4);
+ memcpy((char *)data + FINDERINFO_FRCREATOFF,"rhap",4);
+ chk_ext = 0;
+ }
+
/** Only enter if no appledouble information and no finder information found. */
if (chk_ext && (em = getextmap( upath ))) {
memcpy(data, em->em_type, sizeof( em->em_type ));
if (aint > 255) /* FIXME safeguard, anyway if no ascii char it's game over*/
aint = 255;
- utf8 = vol->v_mac?htonl(vol->v_mac->kTextEncoding):0; /* htonl(utf8) */
+ utf8 = vol->v_kTextEncoding;
memcpy(data, &utf8, sizeof(utf8));
data += sizeof(utf8);
(1 << FILPBIT_RFLEN) |\
(1 << FILPBIT_EXTRFLEN) |\
(1 << FILPBIT_PDINFO) |\
+ (1 << FILPBIT_FNUM) |\
(1 << FILPBIT_UNIXPR)))
/* -------------------------- */
u_int32_t get_id(struct vol *vol, struct adouble *adp, const struct stat *st,
- const cnid_t did, char *upath, const int len)
+ const cnid_t did, char *upath, const int len)
{
-u_int32_t aint = 0;
-
-#if AD_VERSION > AD_VERSION1
-
- if ((aint = ad_getid(adp, st->st_dev, st->st_ino, did, vol->v_stamp))) {
- return aint;
- }
-#endif
+ u_int32_t adcnid;
+ u_int32_t dbcnid = CNID_INVALID;
if (vol->v_cdb != NULL) {
- aint = cnid_add(vol->v_cdb, st, did, upath, len, aint);
+ /* prime aint with what we think is the cnid, set did to zero for
+ catching moved files */
+ adcnid = ad_getid(adp, st->st_dev, st->st_ino, 0, vol->v_stamp);
+
+ dbcnid = cnid_add(vol->v_cdb, st, did, upath, len, adcnid);
/* Throw errors if cnid_add fails. */
- if (aint == CNID_INVALID) {
+ if (dbcnid == CNID_INVALID) {
switch (errno) {
case CNID_ERR_CLOSE: /* the db is closed */
break;
return CNID_INVALID;
}
}
-#if AD_VERSION > AD_VERSION1
- else if (adp ) {
- /* update the ressource fork
- * for a folder adp is always null
- */
- if (ad_setid(adp, st->st_dev, st->st_ino, aint, did, vol->v_stamp)) {
+ else if (adp && (adcnid != dbcnid)) {
+ /* Update the ressource fork. For a folder adp is always null */
+ LOG(log_debug, logtype_afpd, "get_id: calling ad_setid. adcnid: %u, dbcnid: %u", htonl(adcnid), htonl(dbcnid));
+ if (ad_setid(adp, st->st_dev, st->st_ino, dbcnid, did, vol->v_stamp)) {
ad_flush(adp);
}
}
-#endif
}
- return aint;
+ return dbcnid;
}
/* -------------------------- */
id = get_id(vol, adp, st, dir->d_did, upath, strlen(upath));
else
id = path->id;
- if (id == 0)
+ if (id == CNID_INVALID)
return afp_errno;
if (!path->m_name) {
path->m_name = utompath(vol, upath, id, utf8_encoding());
break;
case FILPBIT_FINFO :
- get_finderinfo(vol, upath, adp, (char *)data);
+ get_finderinfo(vol, upath, adp, (char *)data,S_ISLNK(st->st_mode));
data += ADEDLEN_FINDERI;
break;
adp = of_ad(vol, path, &ad);
upath = path->u_name;
- if ( ad_metadata( upath, flags, adp) < 0 ) {
+ if ( ad_metadata( upath, flags|ADFLAGS_CREATE, adp) < 0 ) {
switch (errno) {
case EACCES:
LOG(log_error, logtype_afpd, "getfilparams(%s): %s: check resource fork permission?",
openf = O_RDWR|O_CREAT|O_EXCL;
}
- if ( ad_open( upath, vol_noadouble(vol)|ADFLAGS_DF|ADFLAGS_HF|ADFLAGS_NOHF|ADFLAGS_CREATE,
+ if ( ad_open( upath, ADFLAGS_DF|ADFLAGS_HF|ADFLAGS_NOHF|ADFLAGS_CREATE,
openf, 0666, adp) < 0 ) {
switch ( errno ) {
case EROFS:
int bit, isad = 1, err = AFP_OK;
char *upath;
u_char achar, *fdType, xyy[4]; /* uninitialized, OK 310105 */
- u_int16_t ashort, bshort;
+ u_int16_t ashort, bshort, oshort;
u_int32_t aint;
u_int32_t upriv;
u_int16_t upriv_bit = 0;
case FILPBIT_FINFO :
change_mdate = 1;
memcpy(finder_buf, buf, 32 );
+ if (memcmp(buf,"slnkrhap",8)==0 && !S_ISLNK(path->st.st_mode)){
+ // SLFINFO
+ 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;
+ erc=symlink(buf,path->u_name);
+ lstat(path->u_name,&(path->st));
+ }
+ }
+ close(fp);
+ }
+ if (erc!=0){
+ err=AFPERR_BITMAP;
+ goto setfilparam_done;
+ }
+ }
buf += 32;
break;
case FILPBIT_UNIXPR :
/* second try with adouble open
*/
- if ( ad_open_metadata( upath, vol_noadouble(vol), O_CREAT, adp) < 0) {
+ if ( ad_open_metadata( upath, 0, O_CREAT, adp) < 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 ( (f_bitmap & ~(1<<FILPBIT_MDATE | 1<<FILPBIT_UNIXPR))) {
+ if (!vol_noadouble(vol) && (f_bitmap & ~(1<<FILPBIT_MDATE | 1<<FILPBIT_UNIXPR))) {
LOG(log_debug, logtype_afpd, "setfilparams: need adouble access");
- return vol_noadouble(vol) ? AFP_OK : AFPERR_ACCESS;
+ return AFPERR_ACCESS;
}
LOG(log_debug, logtype_afpd, "setfilparams: no adouble perms, but only FILPBIT_MDATE and/or FILPBIT_UNIXPR");
isad = 0;
switch( bit ) {
case FILPBIT_ATTR :
ad_getattr(adp, &bshort);
- if ((bshort & htons(ATTRBIT_INVISIBLE)) !=
- (ashort & htons(ATTRBIT_INVISIBLE) & htons(ATTRBIT_SETCLR)) )
- change_parent_mdate = 1;
+ oshort = bshort;
if ( ntohs( ashort ) & ATTRBIT_SETCLR ) {
bshort |= htons( ntohs( ashort ) & ~ATTRBIT_SETCLR );
} else {
bshort &= ~ashort;
}
+ if ((bshort & htons(ATTRBIT_INVISIBLE)) != (oshort & htons(ATTRBIT_INVISIBLE)))
+ change_parent_mdate = 1;
ad_setattr(adp, bshort);
break;
case FILPBIT_CDATE :
if (checkAttrib) {
/* was EACCESS error try to get only metadata */
ad_init(&ad, vol->v_adouble, vol->v_ad_options);
- if ( ad_metadata( file , ADFLAGS_OPENFORKS, &ad) == 0 ) {
+ /* we never want to create a resource fork here, we are going to delete it
+ * moreover sometimes deletefile is called with a no existent file and
+ * ad_open would create a 0 byte resource fork
+ */
+ if ( ad_metadata( file, ADFLAGS_OPENFORKS, &ad) == 0 ) {
ad_close( &ad, adflags );
if ((err = check_attrib(&ad))) {
return err;
cnid_t did = param->did;
cnid_t aint;
- if ( stat(de->d_name, &path.st)<0 )
+ if ( lstat(de->d_name, &path.st)<0 )
return 0;
/* update or add to cnid */
}
/* FIXME use of_statdir ? */
- if (stat(name, &st)) {
+ if (lstat(name, &st)) {
return -1;
}
}
err = AFP_OK;
- if ((movecwd(vol, dir) < 0) || (stat(upath, &st) < 0)) {
+ if ((movecwd(vol, dir) < 0) || (lstat(upath, &st) < 0)) {
switch (errno) {
case EACCES:
case EPERM:
if (did) {
cnid_delete(vol->v_cdb, did);
}
- if ((did && ( (crossdev && stat( upath, &srcst) < 0) ||
+ if ((did && ( (crossdev && lstat( upath, &srcst) < 0) ||
cnid_update(vol->v_cdb, did, &srcst, curdir->d_did,upath, dlen) < 0))
||
- (sid && ( (crossdev && stat(p, &destst) < 0) ||
+ (sid && ( (crossdev && lstat(p, &destst) < 0) ||
cnid_update(vol->v_cdb, sid, &destst, sdir->d_did,supath, slen) < 0))
) {
switch (errno) {