/*
- * $Id: file.c,v 1.109 2009-07-20 18:31:04 didg Exp $
+ * $Id: file.c,v 1.126.2.1 2010-01-02 10:22:32 franklahm Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
#endif /* ! HAVE_MEMCPY */
#endif /* STDC_HEADERS */
-#include <atalk/adouble.h>
#include <utime.h>
-#include <dirent.h>
#include <errno.h>
-
-#include <atalk/logger.h>
#include <sys/param.h>
-
+#include <atalk/adouble.h>
+#include <atalk/vfs.h>
+#include <atalk/logger.h>
#include <atalk/afp.h>
#include <atalk/util.h>
#include <atalk/cnid.h>
+#include <atalk/unix.h>
+
#include "directory.h"
#include "desktop.h"
#include "volume.h"
}
/* 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;
+ linkflag=htons(FINDERINFO_ISALIAS);
+ memcpy((char *)data + FINDERINFO_FRTYPEOFF,"slnk",4);
+ memcpy((char *)data + FINDERINFO_FRCREATOFF,"rhap",4);
+ *((u_int16_t*)((char *)data+FINDERINFO_FRFLAGOFF))|=linkflag;
+ 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 aint = 0;
if (vol->v_cdb != NULL) {
+ /* prime aint with what we think is the cnid, set did to zero for
+ catching moved files */
+ aint = ad_getid(adp, st->st_dev, st->st_ino, 0, vol->v_stamp);
+
aint = cnid_add(vol->v_cdb, st, did, upath, len, aint);
/* Throw errors if cnid_add fails. */
if (aint == CNID_INVALID) {
return CNID_INVALID;
}
}
-#if AD_VERSION > AD_VERSION1
else if (adp ) {
/* update the ressource fork
* for a folder adp is always null
ad_flush(adp);
}
}
-#endif
}
return aint;
}
int getmetadata(struct vol *vol,
u_int16_t bitmap,
struct path *path, struct dir *dir,
- char *buf, int *buflen, struct adouble *adp)
+ char *buf, size_t *buflen, struct adouble *adp)
{
char *data, *l_nameoff = NULL, *upath;
char *utf_nameoff = NULL;
struct maccess ma;
#ifdef DEBUG
- LOG(log_info, logtype_afpd, "begin getmetadata:");
+ LOG(log_debug9, logtype_afpd, "begin getmetadata:");
#endif /* DEBUG */
upath = path->u_name;
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;
int getfilparams(struct vol *vol,
u_int16_t bitmap,
struct path *path, struct dir *dir,
- char *buf, int *buflen )
+ char *buf, size_t *buflen )
{
struct adouble ad, *adp;
- struct ofork *of;
- char *upath;
int opened = 0;
int rc;
#ifdef DEBUG
- LOG(log_info, logtype_default, "begin getfilparams:");
+ LOG(log_debug9, logtype_default, "begin getfilparams:");
#endif /* DEBUG */
opened = PARAM_NEED_ADP(bitmap);
adp = NULL;
if (opened) {
- int flags = (bitmap & (1 << FILPBIT_ATTR))?ADFLAGS_OPENFORKS:0;
+ char *upath;
+ int flags = (bitmap & (1 << FILPBIT_ATTR))?ADFLAGS_OPENFORKS:0;
+
+ adp = of_ad(vol, path, &ad);
upath = path->u_name;
- if ((of = of_findname(path))) {
- adp = of->of_ad;
- } else {
- ad_init(&ad, vol->v_adouble, vol->v_ad_options);
- adp = &ad;
- }
- if ( ad_metadata( upath, flags, adp) < 0 ) {
+ if ( ad_metadata( upath, vol_noadouble(vol) | flags, adp) < 0 ) {
switch (errno) {
case EACCES:
LOG(log_error, logtype_afpd, "getfilparams(%s): %s: check resource fork permission?",
ad_close_metadata( adp);
}
#ifdef DEBUG
- LOG(log_info, logtype_afpd, "end getfilparams:");
+ LOG(log_debug9, logtype_afpd, "end getfilparams:");
#endif /* DEBUG */
return( rc );
}
/* ----------------------------- */
-int afp_createfile(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj *obj;
-char *ibuf, *rbuf _U_;
-int ibuflen _U_, *rbuflen;
+int afp_createfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
{
struct adouble ad, *adp;
struct vol *vol;
u_int16_t vid;
struct path *s_path;
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "begin afp_createfile:");
-#endif /* DEBUG */
-
*rbuflen = 0;
ibuf++;
creatf = (unsigned char) *ibuf++;
setvoltime(obj, vol );
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "end afp_createfile");
-#endif /* DEBUG */
-
return (retvalue);
}
-int afp_setfilparams(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj *obj;
-char *ibuf, *rbuf _U_;
-int ibuflen _U_, *rbuflen;
+int afp_setfilparams(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
{
struct vol *vol;
struct dir *dir;
int did, rc;
u_int16_t vid, bitmap;
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "begin afp_setfilparams:");
-#endif /* DEBUG */
-
*rbuflen = 0;
ibuf += 2;
setvoltime(obj, vol );
}
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "end afp_setfilparams:");
-#endif /* DEBUG */
-
return( rc );
}
u_char finder_buf[32];
#ifdef DEBUG
- LOG(log_info, logtype_afpd, "begin setfilparams:");
+ LOG(log_debug9, logtype_afpd, "begin setfilparams:");
#endif /* DEBUG */
- upath = path->u_name;
adp = of_ad(vol, path, &ad);
-
+ upath = path->u_name;
if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
return AFPERR_ACCESS;
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) {
- /* for some things, we don't need an adouble header */
- if (f_bitmap & ~(1<<FILPBIT_MDATE)) {
+ 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))) {
+ LOG(log_debug, logtype_afpd, "setfilparams: need adouble access");
return vol_noadouble(vol) ? AFP_OK : AFPERR_ACCESS;
}
+ LOG(log_debug, logtype_afpd, "setfilparams: no adouble perms, but only FILPBIT_MDATE and/or FILPBIT_UNIXPR");
isad = 0;
} else if ((ad_get_HF_flags( adp ) & O_CREAT) ) {
ad_setname(adp, path->m_name);
}
#ifdef DEBUG
- LOG(log_info, logtype_afpd, "end setfilparams:");
+ LOG(log_debug9, logtype_afpd, "end setfilparams:");
#endif /* DEBUG */
return err;
}
* adp adouble struct of src file, if open, or & zeroed one
*
*/
-int renamefile(vol, src, dst, newname, adp )
-const struct vol *vol;
-char *src, *dst, *newname;
-struct adouble *adp;
+int renamefile(const struct vol *vol, char *src, char *dst, char *newname, struct adouble *adp)
{
int rc;
#ifdef DEBUG
- LOG(log_info, logtype_afpd, "begin renamefile:");
+ LOG(log_debug9, logtype_afpd, "begin renamefile:");
#endif /* DEBUG */
if ( unix_rename( src, dst ) < 0 ) {
}
}
- if (vol->vfs->rf_renamefile(vol, src, dst) < 0 ) {
+ if (vol->vfs->vfs_renamefile(vol, src, dst) < 0 ) {
int err;
err = errno;
ad_close( adp, ADFLAGS_HF );
}
#ifdef DEBUG
- LOG(log_info, logtype_afpd, "end renamefile:");
+ LOG(log_debug9, logtype_afpd, "end renamefile:");
#endif /* DEBUG */
return( AFP_OK );
/* -----------------------------------
*/
-int afp_copyfile(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj *obj;
-char *ibuf, *rbuf _U_;
-int ibuflen _U_, *rbuflen;
+int afp_copyfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
{
struct vol *s_vol, *d_vol;
struct dir *dir;
struct adouble ad, *adp;
int denyreadset;
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "begin afp_copyfile:");
-#endif /* DEBUG */
-
*rbuflen = 0;
ibuf += 2;
setvoltime(obj, d_vol );
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "end afp_copyfile:");
-#endif /* DEBUG */
-
return( retvalue );
}
ssize_t cc;
#ifdef DEBUG
- LOG(log_info, logtype_afpd, "begin copy_all:");
+ LOG(log_debug9, logtype_afpd, "begin copy_all:");
#endif /* DEBUG */
while (buflen > 0) {
}
#ifdef DEBUG
- LOG(log_info, logtype_afpd, "end copy_all:");
+ LOG(log_debug9, logtype_afpd, "end copy_all:");
#endif /* DEBUG */
return 0;
* because we are doing it elsewhere.
* currently if newname is NULL then adp is NULL.
*/
-int copyfile(s_vol, d_vol, src, dst, newname, adp )
-const struct vol *s_vol, *d_vol;
-char *src, *dst, *newname;
-struct adouble *adp;
+int copyfile(const struct vol *s_vol, const struct vol*d_vol,
+ char *src, char *dst, char *newname, struct adouble *adp)
{
struct adouble ads, add;
int err = 0;
struct stat st;
#ifdef DEBUG
- LOG(log_info, logtype_afpd, "begin copyfile:");
+ LOG(log_debug9, logtype_afpd, "begin copyfile:");
#endif /* DEBUG */
if (adp == NULL) {
}
return AFPERR_EXIST;
}
- /* XXX if the source and the dest don't use the same resource type it's broken
- */
+
+ /*
+ * 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 */
- err = copy_fork(ADEID_DFORK, &add, adp);
+ if ((err = copy_fork(ADEID_DFORK, &add, adp)) == 0) {
+ err = d_vol->vfs->vfs_copyfile(d_vol, src, dst);
+ }
}
if (err < 0) {
}
#ifdef DEBUG
- LOG(log_info, logtype_afpd, "end copyfile:");
+ LOG(log_debug9, logtype_afpd, "end copyfile:");
#endif /* DEBUG */
done:
return 0;
}
-int deletefile( vol, file, checkAttrib )
-const struct vol *vol;
-char *file;
-int checkAttrib;
+int deletefile(const struct vol *vol, char *file, int checkAttrib)
{
struct adouble ad;
struct adouble *adp = &ad;
int adflags, err = AFP_OK;
#ifdef DEBUG
- LOG(log_info, logtype_afpd, "begin deletefile:");
+ LOG(log_debug9, logtype_afpd, "begin deletefile:");
#endif /* DEBUG */
/* try to open both forks at once */
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_NOADOUBLE | ADFLAGS_OPENFORKS, &ad) == 0 ) {
ad_close( &ad, adflags );
if ((err = check_attrib(&ad))) {
return err;
if (adp && ad_tmplock( &ad, ADEID_DFORK, ADLOCK_WR, 0, 0, 0 ) < 0) {
err = AFPERR_BUSY;
}
- else if (!(err = vol->vfs->rf_deletefile(vol, file)) && !(err = netatalk_unlink( file )) ) {
+ else if (!(err = vol->vfs->vfs_deletefile(vol, file)) && !(err = netatalk_unlink( file )) ) {
cnid_t id;
if (checkAttrib && (id = cnid_get(vol->v_cdb, curdir->d_did, file, strlen(file))))
{
ad_close( &ad, adflags ); /* ad_close removes locks if any */
#ifdef DEBUG
- LOG(log_info, logtype_afpd, "end deletefile:");
+ LOG(log_debug9, logtype_afpd, "end deletefile:");
#endif /* DEBUG */
return err;
/* ------------------------------------ */
/* return a file id */
-int afp_createid(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj *obj _U_;
-char *ibuf, *rbuf;
-int ibuflen _U_, *rbuflen;
+int afp_createid(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
{
struct stat *st;
struct vol *vol;
u_short vid;
struct path *s_path;
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "begin afp_createid:");
-#endif /* DEBUG */
-
*rbuflen = 0;
ibuf += 2;
return AFP_OK;
}
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "ending afp_createid...:");
-#endif /* DEBUG */
return afp_errno;
}
cnid_t did = param->did;
cnid_t aint;
- memset(&path, 0, sizeof(path));
-
- 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;
}
/* ------------------------------
resolve a file id */
-int afp_resolveid(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj *obj _U_;
-char *ibuf, *rbuf;
-int ibuflen _U_, *rbuflen;
+int afp_resolveid(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
{
struct vol *vol;
struct dir *dir;
char *upath;
struct path path;
- int err, buflen, retry=0;
+ int err, retry=0;
+ size_t buflen;
cnid_t id, cnid;
u_int16_t vid, bitmap;
static char buffer[12 + MAXPATHLEN + 1];
int len = 12 + MAXPATHLEN + 1;
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "begin afp_resolveid:");
-#endif /* DEBUG */
-
*rbuflen = 0;
ibuf += 2;
return AFPERR_NOID;
}
retry:
- memset(&path, 0, sizeof(path));
if (NULL == (upath = cnid_resolve(vol->v_cdb, &id, buffer, len)) ) {
return AFPERR_NOID; /* was AFPERR_BADID, but help older Macs */
}
if (NULL == ( dir = dirlookup( vol, id )) ) {
return AFPERR_NOID; /* idem AFPERR_PARAM */
}
- path.u_name = upath;
if (movecwd(vol, dir) < 0) {
switch (errno) {
case EACCES:
}
}
+ memset(&path, 0, sizeof(path));
+ path.u_name = upath;
if ( of_stat(&path) < 0 ) {
#ifdef ESTALE
/* with nfs and our working directory is deleted */
*rbuflen = buflen + sizeof(bitmap);
memcpy(rbuf, ibuf, sizeof(bitmap));
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "end afp_resolveid:");
-#endif /* DEBUG */
-
return AFP_OK;
}
/* ------------------------------ */
-int afp_deleteid(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj *obj _U_;
-char *ibuf, *rbuf _U_;
-int ibuflen _U_, *rbuflen;
+int afp_deleteid(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
{
struct stat st;
struct vol *vol;
static char buffer[12 + MAXPATHLEN + 1];
int len = 12 + MAXPATHLEN + 1;
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "begin afp_deleteid:");
-#endif /* DEBUG */
-
*rbuflen = 0;
ibuf += 2;
}
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:
}
}
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "end afp_deleteid:");
-#endif /* DEBUG */
-
return err;
}
#define APPLETEMP ".AppleTempXXXXXX"
-int afp_exchangefiles(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj *obj;
-char *ibuf, *rbuf _U_ ;
-int ibuflen _U_, *rbuflen;
+int afp_exchangefiles(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
{
struct stat srcst, destst;
struct vol *vol;
uid_t uid;
gid_t gid;
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "begin afp_exchangefiles:");
-#endif /* DEBUG */
-
*rbuflen = 0;
ibuf += 2;
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) {
exit(EXITERR_SYS);
}
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "ending afp_exchangefiles:");
-#endif /* DEBUG */
-
err = AFP_OK;
goto err_exchangefile;