X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=netatalk.git;a=blobdiff_plain;f=etc%2Fafpd%2Ffile.c;h=915219f595d11d7ea53876adc269a26a8b484b0b;hp=198b155e78899bc6b076189e2655ada4f4bf399f;hb=2bf71d3ccf20c072bc67a9d075b6ac8b0798021e;hpb=b3a6997615d13c9986e0aad330a03502582577e0 diff --git a/etc/afpd/file.c b/etc/afpd/file.c index 198b155e..915219f5 100644 --- a/etc/afpd/file.c +++ b/etc/afpd/file.c @@ -1,5 +1,5 @@ /* - * $Id: file.c,v 1.125 2009-11-27 15:45:40 franklahm Exp $ + * $Id: file.c,v 1.134 2010-02-10 14:05:37 franklahm Exp $ * * Copyright (c) 1990,1993 Regents of The University of Michigan. * All Rights Reserved. See COPYRIGHT. @@ -89,7 +89,7 @@ static int default_type(void *finder) } /* 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; @@ -114,6 +114,17 @@ void *get_finderinfo(const struct vol *vol, const char *upath, struct adouble *a 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 )); @@ -187,18 +198,24 @@ char *set_name(const struct vol *vol, char *data, cnid_t pid, char *name, cnid_t (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) { - u_int32_t aint = 0; + 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; @@ -214,16 +231,15 @@ u_int32_t get_id(struct vol *vol, struct adouble *adp, const struct stat *st, return CNID_INVALID; } } - 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); } } } - return aint; + return dbcnid; } /* -------------------------- */ @@ -259,7 +275,7 @@ int getmetadata(struct vol *vol, 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()); @@ -327,7 +343,7 @@ int getmetadata(struct vol *vol, 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; @@ -522,7 +538,7 @@ int getfilparams(struct vol *vol, adp = of_ad(vol, path, &ad); upath = path->u_name; - if ( ad_metadata( upath, vol_noadouble(vol) | 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?", @@ -614,7 +630,7 @@ int afp_createfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, 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: @@ -732,7 +748,7 @@ int setfilparams(struct vol *vol, 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; @@ -790,6 +806,27 @@ int setfilparams(struct vol *vol, 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 : @@ -852,7 +889,7 @@ int setfilparams(struct vol *vol, /* 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: @@ -880,14 +917,14 @@ int setfilparams(struct vol *vol, 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 : @@ -1493,7 +1530,7 @@ int deletefile(const struct vol *vol, char *file, int checkAttrib) * 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_NOADOUBLE | ADFLAGS_OPENFORKS, &ad) == 0 ) { + if ( ad_metadata( file, ADFLAGS_OPENFORKS, &ad) == 0 ) { ad_close( &ad, adflags ); if ((err = check_attrib(&ad))) { return err; @@ -1649,7 +1686,7 @@ static int reenumerate_loop(struct dirent *de, char *mname _U_, void *data) 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 */ @@ -1694,7 +1731,7 @@ reenumerate_id(struct vol *vol, char *name, struct dir *dir) } /* FIXME use of_statdir ? */ - if (stat(name, &st)) { + if (lstat(name, &st)) { return -1; } @@ -1864,7 +1901,7 @@ int afp_deleteid(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_ } 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: @@ -2109,10 +2146,10 @@ int afp_exchangefiles(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U 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) {