From: Frank Lahm Date: Thu, 22 Dec 2011 16:07:32 +0000 (+0100) Subject: Redesign ad_open API to only use one arg for all flags, fix locking for adouble:v2 X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=netatalk.git;a=commitdiff_plain;h=3db065fc676b105a36f668df45a5d17d83aebb9b Redesign ad_open API to only use one arg for all flags, fix locking for adouble:v2 --- diff --git a/bin/ad/ad_cp.c b/bin/ad/ad_cp.c index 1020d7d6..49984637 100644 --- a/bin/ad/ad_cp.c +++ b/bin/ad/ad_cp.c @@ -544,7 +544,7 @@ static int copy(const char *path, break; } ad_init(&ad, dvolume.volinfo.v_adouble, dvolume.volinfo.v_ad_options); - if (ad_open(&ad, to.p_path, ADFLAGS_HF | ADFLAGS_DIR, O_RDWR | O_CREAT, 0666) != 0) { + if (ad_open(&ad, to.p_path, ADFLAGS_HF | ADFLAGS_DIR | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666) != 0) { ERROR("Error opening adouble for: %s", to.p_path); } ad_setid( &ad, st.st_dev, st.st_ino, did, pdid, dvolume.db_stamp); @@ -554,7 +554,7 @@ static int copy(const char *path, ad_setdate(&ad, AD_DATE_ACCESS | AD_DATE_UNIX, st.st_mtime); ad_setdate(&ad, AD_DATE_BACKUP, AD_DATE_START); ad_flush(&ad); - ad_close_metadata(&ad); + ad_close(&ad, ADFLAGS_HF); umask(omask); } @@ -611,7 +611,7 @@ static int copy(const char *path, break; } ad_init(&ad, dvolume.volinfo.v_adouble, dvolume.volinfo.v_ad_options); - if (ad_open(&ad, to.p_path, ADFLAGS_HF, O_RDWR | O_CREAT) != 0) { + if (ad_open(&ad, to.p_path, ADFLAGS_HF | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666) != 0) { ERROR("Error opening adouble for: %s", to.p_path); } ad_setid( &ad, st.st_dev, st.st_ino, cnid, did, dvolume.db_stamp); @@ -621,7 +621,7 @@ static int copy(const char *path, ad_setdate(&ad, AD_DATE_ACCESS | AD_DATE_UNIX, st.st_mtime); ad_setdate(&ad, AD_DATE_BACKUP, AD_DATE_START); ad_flush(&ad); - ad_close_metadata(&ad); + ad_close(&ad, ADFLAGS_HF); umask(omask); } break; diff --git a/bin/ad/ad_ls.c b/bin/ad/ad_ls.c index 63226a37..f7ca00e9 100644 --- a/bin/ad/ad_ls.c +++ b/bin/ad/ad_ls.c @@ -381,7 +381,7 @@ static void print_flags(char *path, afpvol_t *vol, const struct stat *st) else printf(" !ADVOL_CACHE "); - ad_close_metadata(&ad); + ad_close(&ad, ADFLAGS_HF); } #define TYPE(b) ((st->st_mode & (S_IFMT)) == (b)) diff --git a/bin/ad/ad_mv.c b/bin/ad/ad_mv.c index 156d648b..9d5f5c22 100644 --- a/bin/ad/ad_mv.c +++ b/bin/ad/ad_mv.c @@ -374,13 +374,13 @@ static int do_move(const char *from, const char *to) struct adouble ad; ad_init(&ad, dvolume.volinfo.v_adouble, dvolume.volinfo.v_ad_options); - if (ad_open(&ad, to, S_ISDIR(sb.st_mode) ? (ADFLAGS_DIR | ADFLAGS_HF) : ADFLAGS_HF, O_RDWR) != 0) { + if (ad_open(&ad, to, S_ISDIR(sb.st_mode) ? (ADFLAGS_DIR | ADFLAGS_HF | ADFLAGS_RDWR) : ADFLAGS_HF | ADFLAGS_RDWR) != 0) { SLOG("Error opening adouble for: %s", to); return 1; } ad_setid(&ad, sb.st_dev, sb.st_ino, cnid, newdid, dvolume.db_stamp); ad_flush(&ad); - ad_close_metadata(&ad); + ad_close(&ad, ADFLAGS_HF); if (vflg) printf("%s -> %s\n", from, to); diff --git a/etc/afpd/catsearch.c b/etc/afpd/catsearch.c index 1c913a0a..68d28664 100644 --- a/etc/afpd/catsearch.c +++ b/etc/afpd/catsearch.c @@ -418,7 +418,7 @@ static int crit_check(struct vol *vol, struct path *path) { result |= 1; crit_check_ret: if (adp != NULL) - ad_close_metadata(adp); + ad_close(adp, ADFLAGS_HF); return result; } diff --git a/etc/afpd/desktop.c b/etc/afpd/desktop.c index 96e2fccf..a8e71a81 100644 --- a/etc/afpd/desktop.c +++ b/etc/afpd/desktop.c @@ -650,8 +650,7 @@ static int ad_addcomment(struct vol *vol, struct path *path, char *ibuf) adp = of->of_ad; if (ad_open(adp, upath, - ADFLAGS_HF | ( (isadir) ? ADFLAGS_DIR : 0), - O_CREAT | O_RDWR, + ADFLAGS_HF | ( (isadir) ? ADFLAGS_DIR : 0) | ADFLAGS_CREATE | ADFLAGS_RDWR, 0666) < 0 ) { return( AFPERR_ACCESS ); } @@ -669,7 +668,7 @@ static int ad_addcomment(struct vol *vol, struct path *path, char *ibuf) memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen ); ad_flush( adp ); } - ad_close_metadata( adp); + ad_close(adp, ADFLAGS_HF); return( AFP_OK ); } @@ -730,7 +729,7 @@ static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, size_t } if (!ad_getentryoff(adp, ADEID_COMMENT)) { - ad_close_metadata( adp ); + ad_close(adp, ADFLAGS_HF); return AFPERR_NOITEM; } /* @@ -738,7 +737,7 @@ static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, size_t */ if ( ad_getentrylen( adp, ADEID_COMMENT ) <= 0 || ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) { - ad_close_metadata( adp ); + ad_close(adp, ADFLAGS_HF); return( AFPERR_NOITEM ); } @@ -746,7 +745,7 @@ static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, size_t *rbuf++ = clen; memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ), clen); *rbuflen = clen + 1; - ad_close_metadata( adp); + ad_close(adp, ADFLAGS_HF); return( AFP_OK ); } @@ -802,7 +801,7 @@ static int ad_rmvcomment(struct vol *vol, struct path *path) } else adp = of->of_ad; - if ( ad_open(adp, upath, ADFLAGS_HF | (isadir) ? ADFLAGS_DIR : 0, 0) < 0 ) { + if ( ad_open(adp, upath, ADFLAGS_HF | ADFLAGS_RDWR | (isadir) ? ADFLAGS_DIR : 0) < 0 ) { switch ( errno ) { case ENOENT : return( AFPERR_NOITEM ); @@ -817,7 +816,7 @@ static int ad_rmvcomment(struct vol *vol, struct path *path) ad_setentrylen( adp, ADEID_COMMENT, 0 ); ad_flush( adp ); } - ad_close_metadata( adp); + ad_close(adp, ADFLAGS_HF); return( AFP_OK ); } diff --git a/etc/afpd/directory.c b/etc/afpd/directory.c index dd922103..5c8f6e9f 100644 --- a/etc/afpd/directory.c +++ b/etc/afpd/directory.c @@ -913,7 +913,7 @@ struct dir *dir_add(struct vol *vol, const struct dir *dir, struct path *path, i /* get_id needs adp for reading CNID from adouble file */ ad_init(&ad, vol->v_adouble, vol->v_ad_options); - if ((ad_open(&ad, path->u_name, ADFLAGS_HF | ADFLAGS_DIR)) == 0) /* 1 */ + if ((ad_open(&ad, path->u_name, ADFLAGS_HF | ADFLAGS_DIR | ADFLAGS_RDONLY)) == 0) /* 1 */ adp = &ad; /* Get CNID */ @@ -923,7 +923,7 @@ struct dir *dir_add(struct vol *vol, const struct dir *dir, struct path *path, i } if (adp) - ad_close_metadata(adp); + ad_close(adp, ADFLAGS_HF); /* Get macname from unixname */ if (path->m_name == NULL) { @@ -966,7 +966,7 @@ exit: cfrombstr(dir->d_u_name), path->u_name, err); if (adp) - ad_close_metadata(adp); + ad_close(adp, ADFLAGS_HF); if (!cdir && fullpath) bdestroy(fullpath); if (cdir) @@ -1503,7 +1503,7 @@ int getdirparams(const struct vol *vol, ad_init(&ad, vol->v_adouble, vol->v_ad_options); if ( !ad_metadata( upath, ADFLAGS_DIR, &ad) ) { isad = 1; - if (ad.ad_md->adf_flags & O_CREAT) { + if (ad.ad_mdp->adf_flags & O_CREAT) { /* We just created it */ if (s_path->m_name == NULL) { if ((s_path->m_name = utompath(vol, @@ -1700,7 +1700,7 @@ int getdirparams(const struct vol *vol, default : if ( isad ) { - ad_close_metadata( &ad ); + ad_close(&ad, ADFLAGS_HF); } return( AFPERR_BITMAP ); } @@ -1718,7 +1718,7 @@ int getdirparams(const struct vol *vol, data = set_name(vol, data, pdid, cfrombstr(dir->d_m_name), dir->d_did, utf8); } if ( isad ) { - ad_close_metadata( &ad ); + ad_close(&ad, ADFLAGS_HF); } *buflen = data - buf; return( AFP_OK ); @@ -1929,7 +1929,7 @@ int setdirparams(struct vol *vol, struct path *path, uint16_t d_bitmap, char *bu } ad_init(&ad, vol->v_adouble, vol->v_ad_options); - if (ad_open(&ad, upath, ADFLAGS_HF | ADFLAGS_DIR, O_CREAT, 0777) != 0) { + if (ad_open(&ad, upath, ADFLAGS_HF | ADFLAGS_DIR | ADFLAGS_CREATE | ADFLAGS_RDWR, 0777) != 0) { /* * Check to see what we're trying to set. If it's anything * but ACCESS, UID, or GID, give an error. If it's any of those @@ -2113,8 +2113,8 @@ setdirparam_done: ad_setid(&ad, st->st_dev, st->st_ino, dir->d_did, dir->d_pdid, vol->v_stamp); } } - ad_flush( &ad); - ad_close_metadata( &ad); + ad_flush(&ad); + ad_close(&ad, ADFLAGS_HF); } if (change_parent_mdate && dir->d_did != DIRDID_ROOT @@ -2282,7 +2282,7 @@ int afp_createdir(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_ } ad_init(&ad, vol->v_adouble, vol->v_ad_options); - if (ad_open(&ad, ".", ADFLAGS_HF | ADFLAGS_DIR, O_CREAT, 0777) < 0) { + if (ad_open(&ad, ".", ADFLAGS_HF | ADFLAGS_DIR | ADFLAGS_CREATE | ADFLAGS_RDWR, 0777) < 0) { if (vol_noadouble(vol)) goto createdir_done; return( AFPERR_ACCESS ); @@ -2292,8 +2292,8 @@ int afp_createdir(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_ fce_register_new_dir(s_path); - ad_flush( &ad); - ad_close_metadata( &ad); + ad_flush(&ad); + ad_close(&ad, ADFLAGS_HF); createdir_done: memcpy( rbuf, &dir->d_did, sizeof( uint32_t )); @@ -2350,10 +2350,10 @@ int renamedir(const struct vol *vol, ad_init(&ad, vol->v_adouble, vol->v_ad_options); - if (ad_open(&ad, dst, ADFLAGS_HF | ADFLAGS_DIR) == 0) { + if (ad_open(&ad, dst, ADFLAGS_HF | ADFLAGS_DIR | ADFLAGS_RDWR) == 0) { ad_setname(&ad, newname); - ad_flush( &ad); - ad_close_metadata( &ad); + ad_flush(&ad); + ad_close(&ad, ADFLAGS_HF); } return( AFP_OK ); @@ -2381,7 +2381,7 @@ int deletecurdir(struct vol *vol) if ( ad_metadata( ".", ADFLAGS_DIR, &ad) == 0 ) { ad_getattr(&ad, &ashort); - ad_close_metadata(&ad); + ad_close(&ad, ADFLAGS_HF); if ((ashort & htons(ATTRBIT_NODELETE))) { return AFPERR_OLOCK; } diff --git a/etc/afpd/extattrs.c b/etc/afpd/extattrs.c index 3be452ed..2a5214e5 100644 --- a/etc/afpd/extattrs.c +++ b/etc/afpd/extattrs.c @@ -234,7 +234,7 @@ exit: buf_valid = 0; if (adp) - ad_close_metadata(adp); + ad_close(adp, ADFLAGS_HF); return ret; } diff --git a/etc/afpd/file.c b/etc/afpd/file.c index 4c954e4e..41462d19 100644 --- a/etc/afpd/file.c +++ b/etc/afpd/file.c @@ -639,7 +639,7 @@ int getfilparams(struct vol *vol, } } rc = getmetadata(vol, bitmap, path, dir, buf, buflen, adp); - ad_close_metadata( adp); + ad_close(adp, ADFLAGS_HF); return( rc ); } @@ -692,15 +692,14 @@ int afp_createfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, 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; @@ -965,7 +964,7 @@ int setfilparams(struct vol *vol, /* 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: @@ -1057,8 +1056,8 @@ setfilparam_done: } 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) { @@ -1145,7 +1144,7 @@ int renamefile(const struct vol *vol, int sdir_fd, char *src, char *dst, char *n } /* 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 ); @@ -1273,7 +1272,7 @@ int afp_copyfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, si 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) < 0) { return AFPERR_DENYCONF; } denyreadset = (ad_testlock(adp, ADEID_DFORK, AD_FILELOCK_DENY_RD) != 0 || @@ -1475,7 +1474,7 @@ int copyfile(const struct vol *s_vol, 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; } @@ -1493,7 +1492,7 @@ int copyfile(const struct vol *s_vol, } 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) { + 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) { @@ -1611,7 +1610,7 @@ int deletefile(const struct vol *vol, int dirfd, char *file, int checkAttrib) */ 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; @@ -1620,7 +1619,7 @@ int deletefile(const struct vol *vol, int dirfd, char *file, int checkAttrib) /* 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_HF | ADFLAGS_NOHF | ADFLAGS_RDONLY) < 0 ) { switch (errno) { case ENOENT: err = AFPERR_NOOBJ; @@ -1667,7 +1666,7 @@ int deletefile(const struct vol *vol, int dirfd, char *file, int checkAttrib) end: if (meta) - ad_close_metadata(&ad); + ad_close(&ad, ADFLAGS_HF); if (adp) ad_close( &ad, adflags ); /* ad_close removes locks if any */ @@ -2030,7 +2029,7 @@ static struct adouble *find_adouble(struct path *path, struct ofork **of, struct 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_RDONLY); /* META and HF */ if ( !ret && ad_reso_fileno(adp) != -1 && !(adp->ad_resource_fork.adf_flags & ( O_RDWR | O_WRONLY))) { /* from AFP spec. diff --git a/etc/afpd/filedir.c b/etc/afpd/filedir.c index 61386d66..f98f79c7 100644 --- a/etc/afpd/filedir.c +++ b/etc/afpd/filedir.c @@ -305,7 +305,7 @@ static int moveandrename(const struct vol *vol, ad_getattr(adp, &bshort); - ad_close_metadata( adp); + ad_close(adp, ADFLAGS_HF); if ((bshort & htons(ATTRBIT_NORENAME))) { rc = AFPERR_OLOCK; goto exit; @@ -380,7 +380,7 @@ static int moveandrename(const struct vol *vol, if (!ad_metadata(upath, adflags, adp)) { ad_setid(adp, st->st_dev, st->st_ino, id, curdir->d_did, vol->v_stamp); ad_flush(adp); - ad_close_metadata(adp); + ad_close(adp, ADFLAGS_HF); } /* fix up the catalog entry */ diff --git a/etc/afpd/fork.c b/etc/afpd/fork.c index ad92ff4a..1273e4aa 100644 --- a/etc/afpd/fork.c +++ b/etc/afpd/fork.c @@ -834,9 +834,8 @@ static int read_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, si reqcount = get_off_t(&ibuf, is64); LOG(log_debug, logtype_afpd, - "afp_read(\"%s\", off: %" PRIu64 ", size: %" PRIu64 ", fork: %s)", - cfrombstr(ofork->of_ad->ad_fullpath), offset, reqcount, - (ofork->of_flags & AFPFORK_DATA) ? "d" : "r"); + "afp_read(off: %" PRIu64 ", size: %" PRIu64 ", fork: %s)", offset, reqcount, + (ofork->of_flags & AFPFORK_DATA) ? "d" : "r"); if (is64) { nlmask = nlchar = 0; @@ -1013,9 +1012,7 @@ int afp_flushfork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U return( AFPERR_PARAM ); } - LOG(log_debug, logtype_afpd, - "afp_flushfork(\"%s\", fork: %s)", - cfrombstr(ofork->of_ad->ad_fullpath), + LOG(log_debug, logtype_afpd, "afp_flushfork(fork: %s)", (ofork->of_flags & AFPFORK_DATA) ? "d" : "r"); if ( flushfork( ofork ) < 0 ) { @@ -1047,9 +1044,7 @@ int afp_syncfork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_ return( AFPERR_PARAM ); } - LOG(log_debug, logtype_afpd, - "afp_syncfork(\"%s\", fork: %s)", - cfrombstr(ofork->of_ad->ad_fullpath), + LOG(log_debug, logtype_afpd, "afp_syncfork(fork: %s)", (ofork->of_flags & AFPFORK_DATA) ? "d" : "r"); if ( flushfork( ofork ) < 0 ) { @@ -1116,9 +1111,7 @@ int afp_closefork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U return( AFPERR_PARAM ); } - LOG(log_debug, logtype_afpd, - "afp_closefork(\"%s\", fork: %s)", - cfrombstr(ofork->of_ad->ad_fullpath), + LOG(log_debug, logtype_afpd, "afp_closefork(fork: %s)", (ofork->of_flags & AFPFORK_DATA) ? "d" : "r"); if ( of_closefork( ofork ) < 0 ) { @@ -1196,10 +1189,8 @@ static int write_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, s goto afp_write_err; } - LOG(log_debug, logtype_afpd, - "afp_write(\"%s\", off: %" PRIu64 ", size: %" PRIu64 ", fork: %s)", - cfrombstr(ofork->of_ad->ad_fullpath), offset, reqcount, - (ofork->of_flags & AFPFORK_DATA) ? "d" : "r"); + LOG(log_debug, logtype_afpd, "afp_write(off: %" PRIu64 ", size: %" PRIu64 ", fork: %s)", + offset, reqcount, (ofork->of_flags & AFPFORK_DATA) ? "d" : "r"); if ((ofork->of_flags & AFPFORK_ACCWR) == 0) { err = AFPERR_ACCESS; diff --git a/etc/afpd/volume.c b/etc/afpd/volume.c index 7437f58b..0d2bf061 100644 --- a/etc/afpd/volume.c +++ b/etc/afpd/volume.c @@ -1620,7 +1620,7 @@ static int getvolparams( uint16_t bitmap, struct vol *vol, struct stat *st, char * .Parent file here if it doesn't exist. */ ad_init(&ad, vol->v_adouble, vol->v_ad_options); - if (ad_open(&ad, vol->v_path, ADFLAGS_HF | ADFLAGS_DIR, O_RDWR | O_CREAT, 0666) != 0 ) { + if (ad_open(&ad, vol->v_path, ADFLAGS_HF | ADFLAGS_DIR | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666) != 0 ) { isad = 0; vol->v_ctime = AD_DATE_FROM_UNIX(st->st_mtime); @@ -1797,7 +1797,7 @@ static int getvolparams( uint16_t bitmap, struct vol *vol, struct stat *st, char data += aint; } if ( isad ) { - ad_close_metadata( &ad); + ad_close(&ad, ADFLAGS_HF); } *buflen = data - buf; return( AFP_OK ); @@ -2605,7 +2605,7 @@ int afp_setvolparams(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf return AFPERR_BITMAP; ad_init(&ad, vol->v_adouble, vol->v_ad_options); - if ( ad_open(&ad, vol->v_path, ADFLAGS_HF|ADFLAGS_DIR, O_RDWR) < 0 ) { + if ( ad_open(&ad, vol->v_path, ADFLAGS_HF | ADFLAGS_DIR | ADFLAGS_RDWR) < 0 ) { if (errno == EROFS) return AFPERR_VLOCK; @@ -2700,7 +2700,7 @@ static int create_special_folder (const struct vol *vol, const struct _special_f if ( !ret && folder->hide) { /* Hide it */ ad_init(&ad, vol->v_adouble, vol->v_ad_options); - if (ad_open(&ad, p, ADFLAGS_HF | ADFLAGS_DIR, O_RDWR | O_CREAT, 0666) != 0) { + if (ad_open(&ad, p, ADFLAGS_HF | ADFLAGS_DIR | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666) != 0) { free(p); free(q); return (-1); @@ -2719,8 +2719,8 @@ static int create_special_folder (const struct vol *vol, const struct _special_f memcpy(ad_entry(&ad, ADEID_FINDERI) + FINDERINFO_FRFLAGOFF,&attr, sizeof(attr)); } - ad_flush( &ad ); - ad_close_metadata( &ad); + ad_flush(&ad); + ad_close(&ad, ADFLAGS_HF); } free(p); free(q); diff --git a/etc/cnid_dbd/cmd_dbd_scanvol.c b/etc/cnid_dbd/cmd_dbd_scanvol.c index 75f51fa6..3061c2fb 100644 --- a/etc/cnid_dbd/cmd_dbd_scanvol.c +++ b/etc/cnid_dbd/cmd_dbd_scanvol.c @@ -322,7 +322,7 @@ static int check_adfile(const char *fname, const struct stat *st) /* Create ad file */ ad_init(&ad, myvolinfo->v_adouble, myvolinfo->v_ad_options); - if ((ret = ad_open(&ad, fname, adflags, O_CREAT | O_RDWR, 0666)) != 0) { + if ((ret = ad_open(&ad, fname, adflags | ADFLAGS_CREATE | ADFLAGS_RDWR, 0666)) != 0) { dbd_log( LOGSTD, "Error creating AppleDouble file '%s/%s': %s", cwdbuf, adname, strerror(errno)); @@ -332,7 +332,7 @@ static int check_adfile(const char *fname, const struct stat *st) /* Set name in ad-file */ ad_setname(&ad, utompath((char *)fname)); ad_flush(&ad); - ad_close_metadata(&ad); + ad_close(&ad, ADFLAGS_HF); chown(adname, st->st_uid, st->st_gid); /* FIXME: should we inherit mode too here ? */ @@ -341,11 +341,11 @@ static int check_adfile(const char *fname, const struct stat *st) #endif } else { ad_init(&ad, myvolinfo->v_adouble, myvolinfo->v_ad_options); - if (ad_open(&ad, fname, adflags, O_RDONLY) != 0) { + if (ad_open(&ad, fname, adflags | ADFLAGS_RDONLY) != 0) { dbd_log( LOGSTD, "Error opening AppleDouble file for '%s/%s'", cwdbuf, fname); return -1; } - ad_close_metadata(&ad); + ad_close(&ad, ADFLAGS_HF); } return 0; } @@ -499,7 +499,7 @@ static int check_addir(int volroot) /* Create ad dir and set name */ ad_init(&ad, myvolinfo->v_adouble, myvolinfo->v_ad_options); - if (ad_open(&ad, ".", ADFLAGS_HF | ADFLAGS_DIR, O_CREAT | O_RDWR, 0777) != 0) { + if (ad_open(&ad, ".", ADFLAGS_HF | ADFLAGS_DIR | ADFLAGS_CREATE | ADFLAGS_RDWR, 0777) != 0) { dbd_log( LOGSTD, "Error creating AppleDouble dir in %s: %s", cwdbuf, strerror(errno)); return -1; } @@ -510,7 +510,7 @@ static int check_addir(int volroot) /* Update name in ad file */ ad_setname(&ad, mname); ad_flush(&ad); - ad_close_metadata(&ad); + ad_close(&ad, ADFLAGS_HF); /* Inherit owner/group from "." to ".AppleDouble" and ".Parent" */ if ((lstat(".", &st)) != 0) { @@ -695,7 +695,7 @@ static cnid_t check_cnid(const char *name, cnid_t did, struct stat *st, int adfi ad_cnid = 0; if ( (myvolinfo->v_flags & AFPVOL_CACHE) && ADFILE_OK) { ad_init(&ad, myvolinfo->v_adouble, myvolinfo->v_ad_options); - if (ad_open(&ad, name, adflags, O_RDWR) != 0) { + if (ad_open(&ad, name, adflags | ADFLAGS_RDWR) != 0) { if (dbd_flags & DBD_FLAGS_CLEANUP) return CNID_INVALID; @@ -718,7 +718,7 @@ static cnid_t check_cnid(const char *name, cnid_t did, struct stat *st, int adfi else dbd_log( LOGDEBUG, "CNID from .AppleDouble file for '%s/%s': %u", cwdbuf, name, ntohl(ad_cnid)); - ad_close_metadata(&ad); + ad_close(&ad, ADFLAGS_HF); } /* Get CNID from database */ @@ -761,14 +761,14 @@ static cnid_t check_cnid(const char *name, cnid_t did, struct stat *st, int adfi dbd_log(LOGSTD, "Updating AppleDouble file for '%s/%s' with CNID: %u from database", cwdbuf, name, ntohl(db_cnid)); ad_init(&ad, myvolinfo->v_adouble, myvolinfo->v_ad_options); - if (ad_open(&ad, name, adflags | ADFLAGS_HF, O_RDWR, 0666, &ad) != 0) { + if (ad_open(&ad, name, adflags | ADFLAGS_HF | ADFLAGS_RDWR) != 0) { dbd_log(LOGSTD, "Error opening AppleDouble file for '%s/%s': %s", cwdbuf, name, strerror(errno)); return CNID_INVALID; } ad_setid( &ad, st->st_dev, st->st_ino, db_cnid, did, stamp); ad_flush(&ad); - ad_close_metadata(&ad); + ad_close(&ad, ADFLAGS_HF); } return db_cnid; } else if (ad_cnid && (db_cnid == 0)) { @@ -794,14 +794,14 @@ static cnid_t check_cnid(const char *name, cnid_t did, struct stat *st, int adfi dbd_log(LOGSTD, "Writing CNID data for '%s/%s' to AppleDouble file", cwdbuf, name, ntohl(db_cnid)); ad_init(&ad, myvolinfo->v_adouble, myvolinfo->v_ad_options); - if (ad_open(&ad, name, adflags, O_RDWR) != 0) { + if (ad_open(&ad, name, adflags | ADFLAGS_RDWR) != 0) { dbd_log(LOGSTD, "Error opening AppleDouble file for '%s/%s': %s", cwdbuf, name, strerror(errno)); return CNID_INVALID; } ad_setid( &ad, st->st_dev, st->st_ino, db_cnid, did, stamp); ad_flush(&ad); - ad_close_metadata(&ad); + ad_close(&ad, ADFLAGS_HF); } return db_cnid; } @@ -834,14 +834,14 @@ static cnid_t check_cnid(const char *name, cnid_t did, struct stat *st, int adfi dbd_log(LOGSTD, "Writing CNID data for '%s/%s' to AppleDouble file", cwdbuf, name, ntohl(db_cnid)); ad_init(&ad, myvolinfo->v_adouble, myvolinfo->v_ad_options); - if (ad_open(&ad, name, adflags, O_RDWR) != 0) { + if (ad_open(&ad, name, adflags | ADFLAGS_RDWR) != 0) { dbd_log(LOGSTD, "Error opening AppleDouble file for '%s/%s': %s", cwdbuf, name, strerror(errno)); return CNID_INVALID; } ad_setid( &ad, st->st_dev, st->st_ino, db_cnid, did, stamp); ad_flush(&ad); - ad_close_metadata(&ad); + ad_close(&ad, ADFLAGS_HF); } } return db_cnid; diff --git a/include/atalk/adouble.h b/include/atalk/adouble.h index fd466b2f..bf8152fb 100644 --- a/include/atalk/adouble.h +++ b/include/atalk/adouble.h @@ -159,16 +159,11 @@ typedef struct adf_lock_t { struct ad_fd { int adf_fd; /* -1: invalid, -2: symlink */ -#ifndef HAVE_PREAD - off_t adf_off; -#endif char *adf_syml; int adf_flags; int adf_excl; -#if 0 adf_lock_t *adf_lock; int adf_refcount, adf_lockcount, adf_lockmax; -#endif }; /* some header protection */ @@ -192,10 +187,11 @@ struct adouble { struct ad_entry ad_eid[ADEID_MAX]; struct ad_fd ad_data_fork; /* the data fork */ struct ad_fd ad_resource_fork; /* adouble:v2 -> the adouble file * - * adouble:ea -> the rfork EA */ - struct ad_fd ad_metadata_fork; /* adouble:v2 -> unused * - * adouble:ea -> the metadata EA */ - struct ad_fd *ad_md; /* either ad_resource or ad_metadata */ + * adouble:ea -> unused */ + struct ad_fd *ad_rfp; /* adouble:v2 -> ad_resource_fork * + * adouble:ea -> ad_data_fork */ + struct ad_fd *ad_mdp; /* adouble:v2 -> ad_resource_fork * + * adouble:ea -> ad_data_fork */ int ad_flags; /* Our adouble version info (AD_VERSION*) */ int ad_adflags; /* ad_open flags adflags like ADFLAGS_DIR */ uint32_t ad_inited; @@ -207,7 +203,6 @@ struct adouble { * the header parameter size is too small. */ char *ad_m_name; /* mac name for open fork */ int ad_m_namelen; - bstring ad_fullpath; /* fullpath of file, adouble:ea need this */ struct adouble_fops *ad_ops; uint16_t ad_open_forks; /* open forks (by others) */ char ad_data[AD_DATASZ_MAX]; @@ -220,6 +215,12 @@ struct adouble { #define ADFLAGS_NOHF (1<<4) /* not an error if no ressource fork */ #define ADFLAGS_CHECK_OF (1<<6) /* check for open forks from us and other afpd's */ +#define ADFLAGS_RDWR (1<<7) /* open read/write */ +#define ADFLAGS_RDONLY (1<<7) /* open read only */ +#define ADFLAGS_CREATE (1<<8) /* create file, open called with O_CREAT */ +#define ADFLAGS_EXCL (1<<9) /* exclusive open, open called with O_EXCL */ +#define ADFLAGS_TRUNC (1<<10) /* truncate, open called with O_TRUNC */ + #define ADVOL_NODEV (1 << 0) #define ADVOL_CACHE (1 << 1) #define ADVOL_UNIXPRIV (1 << 2) /* adouble unix priv */ @@ -235,33 +236,14 @@ struct adouble { #define ADLOCK_FILELOCK (1<<3) /* we use this so that we can use the same mechanism for both byte - * locks and file synchronization locks. i do this by co-opting either - * first bits on 32-bit machines or shifting above the last bit on - * 64-bit machines. this only matters for the data fork. */ -#if defined(TRY_64BITOFF_T) && (~0UL > 0xFFFFFFFFU) -/* synchronization locks */ -#define AD_FILELOCK_BASE (0x80000000) -#else + * locks and file synchronization locks. */ #if _FILE_OFFSET_BITS == 64 -#define AD_FILELOCK_BASE (0x7FFFFFFFFFFFFFFFULL - 9) +#define AD_FILELOCK_BASE (UINT64_C(0x7FFFFFFFFFFFFFFF) - 9) #else -#define AD_FILELOCK_BASE (0x7FFFFFFF -9) -#endif +#define AD_FILELOCK_BASE (UINT32_C(0x7FFFFFFF) - 9) #endif -/* FIXME: - * AD_FILELOCK_BASE case - */ -#if _FILE_OFFSET_BITS == 64 -#define BYTELOCK_MAX (0x7FFFFFFFFFFFFFFFULL) -#else -/* Tru64 is an always-64-bit OS; version 4.0 does not set _FILE_OFFSET_BITS */ -#if defined(TRU64) -#define BYTELOCK_MAX (0x7FFFFFFFFFFFFFFFULL) -#else -#define BYTELOCK_MAX (0x7FFFFFFFU) -#endif -#endif +#define BYTELOCK_MAX (AD_FILELOCK_BASE - 1) #define AD_FILELOCK_OPEN_WR (AD_FILELOCK_BASE + 0) #define AD_FILELOCK_OPEN_RD (AD_FILELOCK_BASE + 1) @@ -336,8 +318,8 @@ struct adouble { #define AD_AFPFILEI_BLANKACCESS (1 << 2) /* blank access permissions */ #define ad_data_fileno(ad) ((ad)->ad_data_fork.adf_fd) -#define ad_reso_fileno(ad) ((ad)->ad_resource_fork.adf_fd) -#define ad_meta_fileno(ad) ((ad)->ad_md->adf_fd) +#define ad_reso_fileno(ad) ((ad)->ad_rfp->adf_fd) +#define ad_meta_fileno(ad) ((ad)->ad_mdp->adf_fd) #define ad_getversion(ad) ((ad)->ad_version) @@ -346,8 +328,8 @@ struct adouble { #define ad_getentryoff(ad,eid) ((ad)->ad_eid[(eid)].ade_off) #define ad_entry(ad,eid) ((caddr_t)(ad)->ad_data + (ad)->ad_eid[(eid)].ade_off) -#define ad_get_RF_flags(ad) ((ad)->ad_resource_fork.adf_flags) -#define ad_get_MD_flags(ad) ((ad)->ad_md->adf_flags) +#define ad_get_RF_flags(ad) ((ad)->ad_rfp->adf_flags) +#define ad_get_MD_flags(ad) ((ad)->ad_mdp->adf_flags) /* Refcounting open forks using one struct adouble */ #define ad_ref(ad) (ad)->ad_refcount++ @@ -370,7 +352,6 @@ extern void ad_unlock(struct adouble *, int user); extern int ad_tmplock(struct adouble *, uint32_t eid, int type, off_t off, off_t len, int user); /* ad_open.c */ -extern const char *oflags2logstr(int oflags); extern const char *adflags2logstr(int adflags); extern int ad_setfuid (const uid_t ); extern uid_t ad_getfuid (void ); @@ -387,13 +368,6 @@ extern int ad_stat (const char *, struct stat *); extern int ad_metadata (const char *, int, struct adouble *); extern int ad_metadataat (int, const char *, int, struct adouble *); -#if 0 -#define ad_open_metadata(name, flags, mode, adp)\ - ad_open(name, ADFLAGS_HF | (flags), O_RDWR |(mode), 0666, (adp)) -#endif - -#define ad_close_metadata(adp) ad_close( (adp), ADFLAGS_HF) - /* build a resource fork mode from the data fork mode: * remove X mode and extend header to RW if R or W (W if R for locking), */ @@ -453,10 +427,4 @@ extern uint32_t ad_forcegetid(struct adouble *adp); extern int ad_readfile_init(const struct adouble *ad, int eid, off_t *off, int end); #endif -#if 0 -#ifdef HAVE_SENDFILE_WRITE -extern ssize_t ad_writefile(struct adouble *, int, int, off_t, int, size_t); -#endif /* HAVE_SENDFILE_WRITE */ -#endif /* 0 */ - #endif /* _ATALK_ADOUBLE_H */ diff --git a/libatalk/adouble/ad_attr.c b/libatalk/adouble/ad_attr.c index 6579f0de..e005577f 100644 --- a/libatalk/adouble/ad_attr.c +++ b/libatalk/adouble/ad_attr.c @@ -133,7 +133,7 @@ uint32_t ad_getid (struct adouble *adp, const dev_t st_dev, const ino_t st_ino , */ if (adp && (adp->ad_options & ADVOL_CACHE) - && (adp->ad_md->adf_flags & O_RDWR ) + && (adp->ad_mdp->adf_flags & O_RDWR ) && (sizeof(dev_t) == ad_getentrylen(adp, ADEID_PRIVDEV)) /* One check to ensure ALL values are there */ ) { memcpy(&dev, ad_entry(adp, ADEID_PRIVDEV), sizeof(dev_t)); diff --git a/libatalk/adouble/ad_flush.c b/libatalk/adouble/ad_flush.c index ed9aa95d..e1fd54ed 100644 --- a/libatalk/adouble/ad_flush.c +++ b/libatalk/adouble/ad_flush.c @@ -148,7 +148,7 @@ int ad_flush(struct adouble *ad) { int len; - if (( ad->ad_md->adf_flags & O_RDWR )) { + if (( ad->ad_mdp->adf_flags & O_RDWR )) { if (ad_getentryoff(ad, ADEID_RFORK)) { if (ad->ad_rlen > 0xffffffff) ad_setentrylen(ad, ADEID_RFORK, 0xffffffff); @@ -159,14 +159,14 @@ int ad_flush(struct adouble *ad) switch (ad->ad_flags) { case AD_VERSION2: - if (adf_pwrite(ad->ad_md, ad->ad_data, len, 0) != len) { + if (adf_pwrite(ad->ad_mdp, ad->ad_data, len, 0) != len) { if (errno == 0) errno = EIO; return( -1 ); } break; case AD_VERSION_EA: - if (sys_lsetxattr(cfrombstr(ad->ad_fullpath), AD_EA_META, ad->ad_data, AD_DATASZ_EA, 0) != 0) { + if (sys_fsetxattr(ad_data_fileno(ad), AD_EA_META, ad->ad_data, AD_DATASZ_EA, 0) != 0) { LOG(log_error, logtype_afpd, "ad_flush: sys_fsetxattr error: %s", strerror(errno)); return -1; @@ -183,27 +183,15 @@ int ad_flush(struct adouble *ad) /*! * Close a struct adouble freeing all resources - * - * This close the whole thing, regardless of what you pass in adflags! - * When open forks are using this struct adouble (ad_refcount>0) the close - * request is ignored. */ -int ad_close( struct adouble *ad, int adflags) +int ad_close(struct adouble *ad, int adflags) { int err = 0; if (ad == NULL) return 0; - LOG(log_debug, logtype_default, "ad_close(\"%s\", %s)", - cfrombstr(ad->ad_fullpath), - adflags2logstr(adflags)); - - if (ad->ad_refcount) { - LOG(log_debug, logtype_default, "ad_close(\"%s\"): adouble in use by fork, not closing", - cfrombstr(ad->ad_fullpath)); - return 0; - } + LOG(log_debug, logtype_default, "ad_close(%s)", adflags2logstr(adflags)); if (ad_data_fileno(ad) != -1) { if ((ad_data_fileno(ad) == -2) && (ad->ad_data_fork.adf_syml != NULL)) { @@ -222,7 +210,7 @@ int ad_close( struct adouble *ad, int adflags) if ( close( ad_meta_fileno(ad) ) < 0 ) err = -1; ad_meta_fileno(ad) = -1; - adf_lock_free(ad->ad_md); + adf_lock_free(ad->ad_mdp); ad->ad_adflags &= ~ADFLAGS_HF; } @@ -232,10 +220,5 @@ int ad_close( struct adouble *ad, int adflags) ad->ad_adflags &= ~ADFLAGS_RF; } - if (ad->ad_fullpath) { - bdestroy(ad->ad_fullpath); - ad->ad_fullpath = NULL; - } - return err; } diff --git a/libatalk/adouble/ad_lock.c b/libatalk/adouble/ad_lock.c index 38d2226e..28d7bde8 100644 --- a/libatalk/adouble/ad_lock.c +++ b/libatalk/adouble/ad_lock.c @@ -530,13 +530,6 @@ static void ad_fcntl_unlock(struct adouble *ad, const int fork) if (ad_reso_fileno(ad) != -1) { adf_unlock(&ad->ad_resource_fork, fork); } - - if (ad->ad_flags != AD_VERSION_EA) { - return; - } - if (ad_meta_fileno(ad) != -1) { - adf_unlock(&ad->ad_metadata_fork, fork); - } } /****************************************************************************** diff --git a/libatalk/adouble/ad_lock.h b/libatalk/adouble/ad_lock.h index 8e7860d2..7552f241 100644 --- a/libatalk/adouble/ad_lock.h +++ b/libatalk/adouble/ad_lock.h @@ -3,13 +3,25 @@ #include -/* this is so that we can keep lists of fds referencing the same file - * around. that way, we can honor locks created by the same process +/* this is so that we can keep lists of fds referencing the same file + * around. that way, we can honor locks created by the same process * with the same file. */ -#define adf_lock_free(a) \ - do { \ - ; \ +#define adf_lock_init(a) do { \ + (a)->adf_lockmax = (a)->adf_lockcount = 0; \ + (a)->adf_excl = 0;(a)->adf_lock = NULL; \ + } while (0) + +#define adf_lock_free(a) do { \ + int i;\ + if (!(a)->adf_lock) \ + break; \ + for (i = 0; i < (a)->adf_lockcount; i++) {\ + adf_lock_t *lock = (a)->adf_lock + i;\ + if (--(*lock->refcount) < 1)free(lock->refcount); \ + }\ + free((a)->adf_lock); \ + adf_lock_init(a); \ } while (0) #endif /* libatalk/adouble/ad_private.h */ diff --git a/libatalk/adouble/ad_open.c b/libatalk/adouble/ad_open.c index ffb188ea..8a67960a 100644 --- a/libatalk/adouble/ad_open.c +++ b/libatalk/adouble/ad_open.c @@ -28,8 +28,6 @@ /*! * @file * Part of Netatalk's AppleDouble implementatation - * @note We don't use inlines because a good compiler should be - * able to optimize all the static funcs below. * @sa include/atalk/adouble.h */ @@ -51,6 +49,7 @@ #include #include #include +#include #include "ad_lock.h" @@ -58,12 +57,6 @@ #define MAX(a, b) ((a) < (b) ? (b) : (a)) #endif /* ! MAX */ -#ifdef HAVE_PREAD -# define AD_SET(a) -#else -# define AD_SET(a) a = 0 -#endif - #define ADEDOFF_MAGIC (0) #define ADEDOFF_VERSION (ADEDOFF_MAGIC + ADEDLEN_MAGIC) #define ADEDOFF_FILLER (ADEDOFF_VERSION + ADEDLEN_VERSION) @@ -159,6 +152,50 @@ static const struct entry entry_order_ea[ADEID_NUM_EA + 1] = { {0, 0, 0} }; +const char *adflags2logstr(int adflags) +{ + int first = 1; + static char buf[64]; + + buf[0] = 0; + + if (adflags & ADFLAGS_DF) { + strlcat(buf, "DF", 64); + first = 0; + } + if (adflags & ADFLAGS_RF) { + if (!first) + strlcat(buf, "|", 64); + strlcat(buf, "RF", 64); + first = 0; + } + if (adflags & ADFLAGS_HF) { + if (!first) + strlcat(buf, "|", 64); + strlcat(buf, "HF", 64); + first = 0; + } + if (adflags & ADFLAGS_NOHF) { + if (!first) + strlcat(buf, "|", 64); + strlcat(buf, "NOHF", 64); + first = 0; + } + if (adflags & ADFLAGS_DIR) { + if (!first) + strlcat(buf, "|", 64); + strlcat(buf, "DIR", 64); + first = 0; + } + if (adflags & ADFLAGS_CHECK_OF) { + if (!first) + strlcat(buf, "|", 64); + strlcat(buf, "OF", 64); + first = 0; + } + return buf; +} + static uint32_t get_eid(uint32_t eid) { if (eid <= 15) @@ -282,7 +319,7 @@ static int ad_header_read(struct adouble *ad, struct stat *hst) struct stat st; /* read the header */ - if ((header_len = adf_pread( ad->ad_md, buf, sizeof(ad->ad_data), 0)) < 0) { + if ((header_len = adf_pread( ad->ad_mdp, buf, sizeof(ad->ad_data), 0)) < 0) { return -1; } if (header_len < AD_HEADER_LEN) { @@ -338,7 +375,7 @@ static int ad_header_read(struct adouble *ad, struct stat *hst) if (hst == NULL) { hst = &st; - if (fstat(ad->ad_md->adf_fd, &st) < 0) { + if (fstat(ad->ad_mdp->adf_fd, &st) < 0) { return 1; /* fail silently */ } } @@ -356,7 +393,7 @@ static int ad_header_read_ea(struct adouble *ad, struct stat *hst _U_) char *buf = ad->ad_data; /* read the header */ - if ((header_len = sys_lgetxattr(cfrombstr(ad->ad_fullpath), AD_EA_META, ad->ad_data, AD_DATASZ_EA)) < 1) { + if ((header_len = sys_fgetxattr(ad_data_fileno(ad), AD_EA_META, ad->ad_data, AD_DATASZ_EA)) < 1) { LOG(log_debug, logtype_default, "ad_header_read_ea: %s (%u)", strerror(errno), errno); return -1; } @@ -499,148 +536,170 @@ static int ad_error(struct adouble *ad, int adflags) return -1 ; } -static int ad_open_df(const char *path, int adflags, int oflags, int mode, struct adouble *ad) +/* Map ADFLAGS to open() flags */ +static int ad2openflags(int adflags) +{ + int oflags = 0; + + if (adflags & ADFLAGS_RDWR) + oflags |= O_RDWR; + if (adflags & ADFLAGS_RDONLY) + oflags |= O_RDONLY; + if (adflags & ADFLAGS_CREATE) + oflags |= O_CREAT; + if (adflags & ADFLAGS_EXCL) + oflags |= O_EXCL; + if (adflags & ADFLAGS_TRUNC) + oflags |= O_TRUNC; + + return oflags; +} + +static int ad_open_df(const char *path, int adflags, mode_t mode, struct adouble *ad) { struct stat st_dir; - int hoflags, admode; + int oflags; + mode_t admode; int st_invalid = -1; + ssize_t lsz; LOG(log_debug, logtype_default, "ad_open_df(\"%s\", %s, %04o)", - fullpathname(path), oflags2logstr(oflags), mode); + fullpathname(path), mode); - if (ad_data_fileno(ad) == -1) { - hoflags = (oflags & ~(O_RDONLY | O_WRONLY)) | O_RDWR; - admode = mode; - if ((oflags & O_CREAT)) { - st_invalid = ad_mode_st(path, &admode, &st_dir); - if ((ad->ad_options & ADVOL_UNIXPRIV)) { - admode = mode; + + if (ad_data_fileno(ad) != -1) { + /* the file is already open, but we want write access: */ + if ((adflags & ADFLAGS_RDWR) + /* and it was denied the first time: */ + && (ad->ad_data_fork.adf_flags & O_RDONLY)) { + errno = EACCES; + return -1; } - } + /* it's not new anymore */ + ad->ad_mdp->adf_flags &= ~( O_TRUNC | O_CREAT ); + ad->ad_data_fork.adf_refcount++; + return 0; + } - ad->ad_data_fork.adf_fd = open(path, hoflags | O_NOFOLLOW, admode); + oflags = O_NOFOLLOW | ad2openflags(adflags); - if (ad->ad_data_fork.adf_fd == -1) { - if ((errno == EACCES || errno == EROFS) && !(oflags & O_RDWR)) { - hoflags = oflags; - ad->ad_data_fork.adf_fd = open( path, hoflags | O_NOFOLLOW, admode ); - } - if (ad->ad_data_fork.adf_fd == -1 && errno == OPEN_NOFOLLOW_ERRNO) { - int lsz; - - ad->ad_data_fork.adf_syml = malloc(MAXPATHLEN+1); - lsz = readlink(path, ad->ad_data_fork.adf_syml, MAXPATHLEN); - if (lsz <= 0) { - free(ad->ad_data_fork.adf_syml); - return -1; - } - ad->ad_data_fork.adf_syml[lsz] = 0; - ad->ad_data_fork.adf_fd = -2; /* -2 means its a symlink */ - } - } + admode = mode; + if ((adflags & ADFLAGS_CREATE)) { + st_invalid = ad_mode_st(path, &admode, &st_dir); + if ((ad->ad_options & ADVOL_UNIXPRIV)) + admode = mode; + } - if ( ad->ad_data_fork.adf_fd == -1 ) + ad->ad_data_fork.adf_fd = open(path, oflags, admode); + + if (ad->ad_data_fork.adf_fd == -1) { + if (errno != OPEN_NOFOLLOW_ERRNO) return -1; - AD_SET(ad->ad_data_fork.adf_off); - ad->ad_data_fork.adf_flags = hoflags; - if (!st_invalid) { - /* just created, set owner if admin (root) */ - ad_chown(path, &st_dir); - } - } else { - /* the file is already open... but */ - if ((oflags & ( O_RDWR | O_WRONLY)) - /* we want write access */ - && !(ad->ad_data_fork.adf_flags & ( O_RDWR | O_WRONLY))) { - /* and it was denied the first time */ - errno = EACCES; + ad->ad_data_fork.adf_syml = malloc(MAXPATHLEN+1); + if ((lsz = readlink(path, ad->ad_data_fork.adf_syml, MAXPATHLEN)) <= 0) { + free(ad->ad_data_fork.adf_syml); return -1; } - /* FIXME - * for now ad_open is never called with O_TRUNC or O_EXCL if the file is - * already open. Should we check for it? ie - * O_EXCL --> error - * O_TRUNC --> truncate the fork. - * idem for ressource fork. - */ + ad->ad_data_fork.adf_syml[lsz] = 0; + ad->ad_data_fork.adf_fd = -2; /* -2 means its a symlink */ } + if (!st_invalid) + ad_chown(path, &st_dir); /* just created, set owner if admin (root) */ + + ad->ad_data_fork.adf_flags = oflags; + adf_lock_init(&ad->ad_data_fork); + ad->ad_data_fork.adf_refcount++; + return 0; } -static int ad_open_hf_v2(const char *path, int adflags, int oflags, int mode, struct adouble *ad) +static int ad_open_hf_v2(const char *path, int adflags, mode_t mode, struct adouble *ad) { struct stat st_dir; struct stat st_meta; struct stat *pst = NULL; const char *ad_p; - int hoflags, admode; + int oflags, nocreatflags; + mode_t admode; int st_invalid = -1; - ad_p = ad->ad_ops->ad_path( path, adflags ); - - hoflags = (oflags & ~(O_CREAT | O_EXCL)) | O_NOFOLLOW; + if (ad_meta_fileno(ad) != -1) { + /* the file is already open, but we want write access: */ + if (!(adflags & ADFLAGS_RDONLY) && + /* and it was already denied: */ + !(ad->ad_mdp->adf_flags & O_RDWR)) { + errno = EACCES; + return -1; + } + ad_refresh(ad); + /* it's not new anymore */ + ad->ad_mdp->adf_flags &= ~( O_TRUNC | O_CREAT ); + ad->ad_mdp->adf_refcount++; + return 0; + } - ad->ad_md->adf_fd = open(ad_p, hoflags, 0); + ad_p = ad->ad_ops->ad_path(path, adflags); + oflags = O_NOFOLLOW | ad2openflags(adflags); + nocreatflags = oflags & ~(O_CREAT | O_EXCL); + ad->ad_mdp->adf_fd = open(ad_p, nocreatflags); - if ( ad->ad_md->adf_fd < 0 ) { - if (errno == ENOENT && (oflags & O_CREAT) ) { - /* - * We're expecting to create a new adouble header file here - * if ((oflags & O_CREAT) ==> (oflags & O_RDWR) - */ - LOG(log_debug, logtype_default, "ad_open(\"%s\"): creating adouble file", - fullpathname(path)); + if ( ad->ad_mdp->adf_fd < 0 ) { + if (!(errno == ENOENT && (oflags & O_CREAT))) + return ad_error(ad, adflags); + /* + * We're expecting to create a new adouble header file here + * if ((oflags & O_CREAT) ==> (oflags & O_RDWR) + */ + LOG(log_debug, logtype_default, "ad_open(\"%s\"): creating adouble file", + fullpathname(path)); + admode = mode; + errno = 0; + st_invalid = ad_mode_st(ad_p, &admode, &st_dir); + if ((ad->ad_options & ADVOL_UNIXPRIV)) + admode = mode; + admode = ad_hf_mode(admode); + if (errno == ENOENT) { + if (ad->ad_ops->ad_mkrf( ad_p) < 0) { + return ad_error(ad, adflags); + } admode = mode; - errno = 0; st_invalid = ad_mode_st(ad_p, &admode, &st_dir); - if ((ad->ad_options & ADVOL_UNIXPRIV)) { + if ((ad->ad_options & ADVOL_UNIXPRIV)) admode = mode; - } admode = ad_hf_mode(admode); - if ((errno == ENOENT)) { - if (ad->ad_ops->ad_mkrf( ad_p) < 0) { - return ad_error(ad, adflags); - } - admode = mode; - st_invalid = ad_mode_st(ad_p, &admode, &st_dir); - if ((ad->ad_options & ADVOL_UNIXPRIV)) { - admode = mode; - } - admode = ad_hf_mode(admode); - } - /* retry with O_CREAT */ - ad->ad_md->adf_fd = open(ad_p, oflags, admode); - if ( ad->ad_md->adf_fd < 0 ) { - return ad_error(ad, adflags); - } - ad->ad_md->adf_flags = oflags; - /* just created, set owner if admin owner (root) */ - if (!st_invalid) { - ad_chown(ad_p, &st_dir); - } - } else { - return ad_error(ad, adflags); } + + /* retry with O_CREAT */ + ad->ad_mdp->adf_fd = open(ad_p, oflags, admode); + if ( ad->ad_mdp->adf_fd < 0 ) + return ad_error(ad, adflags); + + ad->ad_mdp->adf_flags = oflags; + /* just created, set owner if admin owner (root) */ + if (!st_invalid) + ad_chown(ad_p, &st_dir); } else { - ad->ad_md->adf_flags = hoflags; - if (fstat(ad->ad_md->adf_fd, &st_meta) == 0 && st_meta.st_size == 0) { + ad->ad_mdp->adf_flags = nocreatflags; + if (fstat(ad->ad_mdp->adf_fd, &st_meta) == 0 && st_meta.st_size == 0) { /* for 0 length files, treat them as new. */ - ad->ad_md->adf_flags |= O_TRUNC; + ad->ad_mdp->adf_flags |= O_TRUNC; } else { /* we have valid data in st_meta stat structure, reused it in ad_header_read */ pst = &st_meta; } } - AD_SET(ad->ad_md->adf_off); + ad->ad_mdp->adf_refcount = 1; + adf_lock_init(ad->ad_mdp); - if ((ad->ad_md->adf_flags & ( O_TRUNC | O_CREAT ))) { + if ((ad->ad_mdp->adf_flags & ( O_TRUNC | O_CREAT ))) { /* This is a new adouble header file, create it */ if (new_ad_header(path, ad, adflags) < 0) { int err = errno; /* the file is already deleted, perm, whatever, so return an error */ + ad_close(ad, adflags); errno = err; return -1; } @@ -650,6 +709,7 @@ static int ad_open_hf_v2(const char *path, int adflags, int oflags, int mode, st if (ad->ad_ops->ad_header_read( ad , pst) < 0 || ad->ad_ops->ad_header_upgrade(ad, ad_p) < 0) { int err = errno; + ad_close(ad, adflags); errno = err; return -1; } @@ -658,21 +718,28 @@ static int ad_open_hf_v2(const char *path, int adflags, int oflags, int mode, st return 0; } -static int ad_open_hf_ea(const char *path, int adflags, int oflags, int mode, struct adouble *ad) +static int ad_open_hf_ea(const char *path, int adflags, int mode, struct adouble *ad) { ssize_t rforklen; + int oflags = O_NOFOLLOW; + + oflags = ad2openflags(adflags) & ~(O_CREAT | O_TRUNC); - /* we dont use this fd, but open it anyway, maybe we need it sometimes */ - if ((ad->ad_md->adf_fd = open(path, O_RDONLY | O_NOFOLLOW)) == -1) - goto error; + if (ad_meta_fileno(ad) == -1) { + if ((ad_meta_fileno(ad) = open(path, oflags)) == -1) + goto error; + ad->ad_mdp->adf_flags = oflags; + ad->ad_mdp->adf_refcount = 1; + adf_lock_init(ad->ad_mdp); + } /* Read the adouble header in and parse it.*/ if (ad->ad_ops->ad_header_read(ad, NULL) != 0) { - if (!(oflags & O_CREAT)) + if (!(adflags & ADFLAGS_CREATE)) goto error; /* It doesnt exist, EPERM or another error */ - if (errno != ENOATTR && errno != ENOENT) { + if (!(errno == ENOATTR || errno == ENOENT)) { LOG(log_error, logtype_default, "ad_open_hf_ea: unexpected: %s", strerror(errno)); goto error; } @@ -683,43 +750,41 @@ static int ad_open_hf_ea(const char *path, int adflags, int oflags, int mode, st fullpathname(path)); goto error; } - ad->ad_md->adf_flags |= O_CREAT; /* mark as just created */ + ad->ad_mdp->adf_flags |= O_CREAT; /* mark as just created */ ad_flush(ad); - LOG(log_debug, logtype_default, "ad_open_hf_ea(\"%s\"): created metadata EA", - cfrombstr(ad->ad_fullpath)); + LOG(log_debug, logtype_default, "ad_open_hf_ea(\"%s\"): created metadata EA", path); } - ad->ad_md->adf_flags |= oflags & (O_RDONLY|O_WRONLY|O_RDWR); /* store current flags */ + ad->ad_mdp->adf_refcount++; - if ((rforklen = sys_lgetxattr(cfrombstr(ad->ad_fullpath), AD_EA_RESO, NULL, 0)) > 0) + if ((rforklen = sys_fgetxattr(ad_meta_fileno(ad), AD_EA_RESO, NULL, 0)) > 0) ad->ad_rlen = rforklen; return 0; error: - if (ad->ad_md->adf_fd != -1) { - close(ad->ad_md->adf_fd); - ad->ad_md->adf_fd = -1; + if (ad_meta_fileno(ad) != -1) { + close(ad_meta_fileno(ad)); + ad_meta_fileno(ad) = -1; } return ad_error(ad, adflags); } -static int ad_open_hf(const char *path, int adflags, int oflags, int mode, struct adouble *ad) +static int ad_open_hf(const char *path, int adflags, int mode, struct adouble *ad) { int ret = 0; - LOG(log_debug, logtype_default, "ad_open_hf(\"%s\", %s, %04o)", - cfrombstr(ad->ad_fullpath), oflags2logstr(oflags), mode); + LOG(log_debug, logtype_default, "ad_open_hf(\"%s\", %04o)", path, mode); memset(ad->ad_eid, 0, sizeof( ad->ad_eid )); ad->ad_rlen = 0; switch (ad->ad_flags) { case AD_VERSION2: - ret = ad_open_hf_v2(path, adflags, oflags, mode, ad); + ret = ad_open_hf_v2(path, adflags, mode, ad); break; case AD_VERSION_EA: - ret = ad_open_hf_ea(path, adflags, oflags, mode, ad); + ret = ad_open_hf_ea(path, adflags, mode, ad); break; default: ret = -1; @@ -735,17 +800,17 @@ static int ad_open_hf(const char *path, int adflags, int oflags, int mode, struc * Only for adouble:ea, a nullop otherwise because adouble:v2 has the ressource fork as part * of the adouble file which is openend by ADFLAGS_HF. */ -static int ad_open_rf(const char *path, int adflags, int oflags, int mode, struct adouble *ad) +static int ad_open_rf(const char *path, int adflags, int mode, struct adouble *ad) { int ret = 0; if (ad->ad_flags != AD_VERSION_EA) return 0; - LOG(log_debug, logtype_default, "ad_open_rf(\"%s\", %s, %04o)", - cfrombstr(ad->ad_fullpath), oflags2logstr(oflags), mode); + LOG(log_debug, logtype_default, "ad_open_rf(\"%s\", %04o)", + path, mode); - if ((ad->ad_rlen = sys_lgetxattr(cfrombstr(ad->ad_fullpath), AD_EA_RESO, NULL, 0)) <= 0) { + if ((ad->ad_rlen = sys_fgetxattr(ad_meta_fileno(ad), AD_EA_RESO, NULL, 0)) <= 0) { switch (errno) { case ENOATTR: ad->ad_rlen = 0; @@ -769,7 +834,7 @@ static int ad_open_rf(const char *path, int adflags, int oflags, int mode, struc /* Read the EA into the buffer */ if (ad->ad_rlen > 0) { - if (sys_lgetxattr(cfrombstr(ad->ad_fullpath), AD_EA_RESO, ad->ad_resforkbuf, ad->ad_rlen) == -1) { + if (sys_fgetxattr(ad_meta_fileno(ad), AD_EA_RESO, ad->ad_resforkbuf, ad->ad_rlen) == -1) { ret = -1; goto exit; } @@ -946,16 +1011,18 @@ int ad_mkdir( const char *path, int mode) void ad_init(struct adouble *ad, int flags, int options) { - memset(ad, 0, sizeof(struct adouble)); - - if (flags == AD_VERSION2) { + switch (flags) { + case AD_VERSION2: ad->ad_ops = &ad_adouble; - ad->ad_md = &ad->ad_resource_fork; - } - else if (flags == AD_VERSION_EA) { + ad->ad_rfp = &ad->ad_resource_fork; + ad->ad_mdp = &ad->ad_resource_fork; + break; + case AD_VERSION_EA: ad->ad_ops = &ad_adouble_ea; - ad->ad_md = &ad->ad_metadata_fork; - } else { + ad->ad_rfp = &ad->ad_data_fork; + ad->ad_mdp = &ad->ad_data_fork; + break; + default: LOG(log_error, logtype_default, "ad_init: unknown AD version"); errno = EIO; return; @@ -966,88 +1033,22 @@ void ad_init(struct adouble *ad, int flags, int options) ad_data_fileno(ad) = -1; ad_reso_fileno(ad) = -1; ad_meta_fileno(ad) = -1; - ad->ad_inited = AD_INITED; -} - -const char *adflags2logstr(int adflags) -{ - int first = 1; - static char buf[64]; - - buf[0] = 0; - - if (adflags & ADFLAGS_DF) { - strlcat(buf, "DF", 64); - first = 0; - } - if (adflags & ADFLAGS_RF) { - if (!first) - strlcat(buf, "|", 64); - strlcat(buf, "RF", 64); - first = 0; - } - if (adflags & ADFLAGS_HF) { - if (!first) - strlcat(buf, "|", 64); - strlcat(buf, "HF", 64); - first = 0; - } - if (adflags & ADFLAGS_NOHF) { - if (!first) - strlcat(buf, "|", 64); - strlcat(buf, "NOHF", 64); - first = 0; - } - if (adflags & ADFLAGS_DIR) { - if (!first) - strlcat(buf, "|", 64); - strlcat(buf, "DIR", 64); - first = 0; - } - if (adflags & ADFLAGS_CHECK_OF) { - if (!first) - strlcat(buf, "|", 64); - strlcat(buf, "OF", 64); - first = 0; - } - return buf; -} - -const char *oflags2logstr(int oflags) -{ - int first = 1; - static char buf[64]; - - buf[0] = 0; - - if (oflags == O_RDONLY) { - strlcat(buf, "O_RDONLY", 64); - first = 0; - } - if (oflags & O_RDWR) { - if (!first) - strlcat(buf, "|", 64); - strlcat(buf, "O_RDWR", 64); - first = 0; - } - if (oflags & O_CREAT) { - if (!first) - strlcat(buf, "|", 64); - strlcat(buf, "O_CREAT", 64); - first = 0; - } - if (oflags & O_EXCL) { - if (!first) - strlcat(buf, "|", 64); - strlcat(buf, "O_EXCL", 64); - first = 0; - } - return buf; + memset(ad->ad_eid, 0, sizeof( ad->ad_eid )); + ad->ad_rlen = 0; + ad->ad_refcount = 1; + ad->ad_open_forks = 0; + ad->ad_resource_fork.adf_refcount = 0; + ad->ad_data_fork.adf_refcount = 0; + ad->ad_data_fork.adf_syml=0; + ad->ad_inited = 0; } /*! * Open data-, metadata(header)- or ressource fork * + * ad_open(struct adouble *ad, const char *path, int adflags, int flags) + * ad_open(struct adouble *ad, const char *path, int adflags, int flags, mode_t mode) + * * You must call ad_init() before ad_open, usually you'll just call it like this: \n * @code * struct adoube ad; @@ -1056,22 +1057,6 @@ const char *oflags2logstr(int oflags) * * Open a files data fork, metadata fork or ressource fork. * - * For each fork to be opened specify the open flags and mode in case you want to create it - * (O_CREAT in open flags). The order in which forks are opened is: - * 1) ADFLAGS_DF, 2) ADFLAGS_HF, 3) ADFLAGS_RF. - * It is possible to call ad_open subsequently opening ADFLAGS_DF first and ADFLAGS_HF in - * another ad_open call. Already openend forks are uneffected in subsequent calls (3). - * The variable arguments must be passed according to this order. Then: - * 1. Ensure the adouble struct has been initialized. - * 2. Store the full path to the object the first time ad_open is called for it. - * 3. Check if the fork has already been opened. - * - * ad_close accompanies ad_open and closes a struct adouble. In order to tigh together the - * semantics of struct adouble/ad_open/ad_close and versus forks, which use and keep a ref to - * the according struct adouble for the fork, open forks refcount their struct adouble - * in struct adouble.ad_refcount. An ad_close is ignored when ad_refcount != 0, because - * ad_refcount != 0 means an open fork is using this very struct adouble. - * * @param ad (rw) pointer to struct adouble * @param path (r) Path to file or directory * @param adflags (r) ADFLAGS_DF: open data fork \n @@ -1079,85 +1064,53 @@ const char *oflags2logstr(int oflags) * ADFLAGS_HF: open header (metadata) file \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_RDONLY: dont upgrade mode from r to rw with adouble:v2 headerfile \n + * The open mode flags (rw vs ro) have to take into account all the following requirements: + * - we remember open fds for files because me must avoid a single close releasing fcntl locks for other + * fds of the same file + * - a file may be opened first ro, then rw and theres no way to upgrade this -> fork.c always opens rw * ADFLAGS_CHECK_OF: check for open forks from us and other afpd's + * @param mode (r) mode used with O_CREATE * * @returns 0 on success, any other value indicates an error */ -static int vad_open(struct adouble *ad, const char *path, int adflags, va_list args) +int ad_open(struct adouble *ad, const char *path, int adflags, ...) { - int ret = 0; - int oflags; - int mode = 0; - - LOG(log_debug, logtype_default, "ad_open(\"%s\", %s)", - fullpathname(path), adflags2logstr(adflags)); + EC_INIT; + va_list args; + mode_t mode = 0; - if (ad->ad_inited != AD_INITED) /* 1 */ - AFP_PANIC("ad_open: not initialized"); + LOG(log_debug, logtype_default, "ad_open(\"%s\", %s, %s)", + fullpathname(path), adflags2logstr(adflags)); - if (ad->ad_fullpath == NULL) { /* 2 */ - if ((ad->ad_fullpath = bfromcstr(fullpathname(path))) == NULL) { - ret = -1; - goto exit; - } + if (ad->ad_inited != AD_INITED) { + ad->ad_adflags = adflags; + } else { + ad->ad_open_forks = ((ad->ad_data_fork.adf_refcount > 0) ? ATTRBIT_DOPEN : 0); + if (ad->ad_resource_fork.adf_refcount > 0) + ad->ad_open_forks |= ATTRBIT_ROPEN; } + va_start(args, adflags); + if (adflags & ADFLAGS_CREATE) + mode = va_arg(args, mode_t); + va_end(args); + if ((adflags & ADFLAGS_DF) && !(ad->ad_adflags & ADFLAGS_DF)) { /* 3 */ - oflags = va_arg(args, int); - if (oflags & O_CREAT) - mode = va_arg(args, int); - if (ad_open_df(path, adflags, oflags, mode, ad) != 0) { - ret = -1; - goto exit; - } + EC_ZERO( ad_open_df(path, adflags, mode, ad) ); ad->ad_adflags |= ADFLAGS_DF; } if ((adflags & ADFLAGS_HF) && !(ad->ad_adflags & ADFLAGS_HF)) { /* 3 */ - oflags = va_arg(args, int); - if (oflags & O_CREAT) - mode = va_arg(args, int); - if (ad_open_hf(path, adflags, oflags, mode, ad) != 0) { - ret = -1; - goto exit; - } + EC_ZERO( ad_open_hf(path, adflags, mode, ad) ); ad->ad_adflags |= ADFLAGS_HF; } if ((adflags & ADFLAGS_RF) && !(ad->ad_adflags & ADFLAGS_RF)) { /* 3 */ - oflags = va_arg(args, int); - if (oflags & O_CREAT) - mode = va_arg(args, int); - if (ad_open_rf(path, adflags, oflags, mode, ad) != 0) { - ret = -1; - goto exit; - } + EC_ZERO( ad_open_rf(path, adflags, mode, ad) ); ad->ad_adflags |= ADFLAGS_RF; } -exit: - if (ret != 0) { - /* FIXME: ad_close stuff we opened before hitting an error */ - /* Dont forget ADFLAGS_NOHF !!! */ - - if (ad->ad_fullpath) { - bdestroy(ad->ad_fullpath); - ad->ad_fullpath = NULL; - } - } - - return ret; -} - -int ad_open(struct adouble *ad, const char *path, int adflags, ...) -{ - int ret; - va_list args; - - va_start(args, adflags); - ret = vad_open(ad, path, adflags, args); - va_end(args); +EC_CLEANUP: return ret; } @@ -1175,11 +1128,12 @@ int ad_open(struct adouble *ad, const char *path, int adflags, ...) int ad_metadata(const char *name, int flags, struct adouble *adp) { uid_t uid; - int ret, err, dir; + int ret, err, oflags; - dir = flags & ADFLAGS_DIR; + oflags = (flags & ADFLAGS_DIR) | ADFLAGS_HF | ADFLAGS_RDONLY; - if ((ret = ad_open(adp, name, ADFLAGS_HF | dir, O_RDONLY)) < 0 && errno == EACCES) { +// if ((ret = ad_open(adp, name, oflags)) < 0 && errno == EACCES) { + if ((ret = ad_open(adp, name, oflags, 0)) < 0 && errno == EACCES) { uid = geteuid(); if (seteuid(0)) { LOG(log_error, logtype_default, "ad_metadata(%s): seteuid failed %s", name, strerror(errno)); @@ -1187,7 +1141,8 @@ int ad_metadata(const char *name, int flags, struct adouble *adp) return -1; } /* we are root open read only */ - ret = ad_open(adp, name, ADFLAGS_HF | dir, O_RDONLY); +// ret = ad_open(adp, name, oflags); + ret = ad_open(adp, name, oflags, 0); err = errno; if ( seteuid(uid) < 0) { LOG(log_error, logtype_default, "ad_metadata: can't seteuid back"); @@ -1196,7 +1151,7 @@ int ad_metadata(const char *name, int flags, struct adouble *adp) errno = err; } - if (!ret && (ADFLAGS_CHECK_OF & flags)) { + if ((ret == 0) && (ADFLAGS_CHECK_OF & flags)) { /* we need to check if the file is open by another process. it's slow so we only do it if we have to: @@ -1257,33 +1212,30 @@ int ad_openat(struct adouble *ad, const char *path, int adflags, ...) { - int ret = 0; + EC_INIT; int cwdfd = -1; va_list args; + mode_t mode; if (dirfd != -1) { - if ((cwdfd = open(".", O_RDONLY) == -1) || (fchdir(dirfd) != 0)) { - ret = -1; - goto exit; - } + if ((cwdfd = open(".", O_RDONLY) == -1) || (fchdir(dirfd) != 0)) + EC_FAIL; } va_start(args, adflags); - - if (vad_open(ad, path, adflags, args) < 0) { - ret = -1; - goto exit; - } - + if (adflags & ADFLAGS_CREATE) + mode = va_arg(args, mode_t); va_end(args); + EC_NEG1( ad_open(ad, path, adflags, mode) ); + if (dirfd != -1) { if (fchdir(cwdfd) != 0) { AFP_PANIC("ad_openat: cant chdir back"); } } -exit: +EC_CLEANUP: if (cwdfd != -1) close(cwdfd); diff --git a/libatalk/adouble/ad_write.c b/libatalk/adouble/ad_write.c index 65e3ca2d..b316fa89 100644 --- a/libatalk/adouble/ad_write.c +++ b/libatalk/adouble/ad_write.c @@ -94,7 +94,7 @@ ssize_t ad_write(struct adouble *ad, uint32_t eid, off_t off, int end, const cha if ((off + buflen) > ad->ad_rlen) ad->ad_rlen = off + buflen; - if (sys_lsetxattr(cfrombstr(ad->ad_fullpath), AD_EA_RESO, ad->ad_resforkbuf, ad->ad_rlen, 0) == -1) + if (sys_fsetxattr(ad_meta_fileno(ad), AD_EA_RESO, ad->ad_resforkbuf, ad->ad_rlen, 0) == -1) return -1; cc = buflen; } diff --git a/libatalk/vfs/ea_ad.c b/libatalk/vfs/ea_ad.c index 9f369ea4..7394e84c 100644 --- a/libatalk/vfs/ea_ad.c +++ b/libatalk/vfs/ea_ad.c @@ -1398,7 +1398,7 @@ int ea_renamefile(VFS_FUNC_ARGS_RENAMEFILE) if (errno == ENOENT) { /* Possibly the .AppleDouble folder didn't exist, we create it and try again */ ad_init(&ad, vol->v_adouble, vol->v_ad_options); - if ((ad_open(&ad, dst, ADFLAGS_HF, O_RDWR | O_CREAT, 0666)) != 0) { + if ((ad_open(&ad, dst, ADFLAGS_HF | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666)) != 0) { LOG(log_error, logtype_afpd, "ea_renamefile('%s/%s'): ad_open error: '%s'", src, dst, dst); ret = AFPERR_MISC; goto exit; @@ -1495,7 +1495,7 @@ int ea_copyfile(VFS_FUNC_ARGS_COPYFILE) if (errno == ENOENT) { /* Possibly the .AppleDouble folder didn't exist, we create it and try again */ ad_init(&ad, vol->v_adouble, vol->v_ad_options); - if ((ad_open(&ad, dst, ADFLAGS_HF, O_RDWR | O_CREAT, 0666)) != 0) { + if ((ad_open(&ad, dst, ADFLAGS_HF | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666)) != 0) { LOG(log_error, logtype_afpd, "ea_copyfile('%s/%s'): ad_open error: '%s'", src, dst, dst); ret = AFPERR_MISC; goto exit; diff --git a/libatalk/vfs/vfs.c b/libatalk/vfs/vfs.c index 0eaacfae..ca37885d 100644 --- a/libatalk/vfs/vfs.c +++ b/libatalk/vfs/vfs.c @@ -309,7 +309,7 @@ static int RF_renamefile_adouble(VFS_FUNC_ARGS_RENAMEFILE) * 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(&ad, dst, ADFLAGS_HF, O_RDWR | O_CREAT, 0666) == 0) { + if (ad_open(&ad, dst, ADFLAGS_HF | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666) == 0) { ad_close(&ad, ADFLAGS_HF); if (!unix_rename(dirfd, adsrc, -1, vol->ad_path(dst, 0 )) ) err = 0;