From a03a613265c54c687dbc3408c70c24b267c3a685 Mon Sep 17 00:00:00 2001 From: Frank Lahm Date: Wed, 4 Jan 2012 16:48:56 +0100 Subject: [PATCH 1/1] Fixes --- etc/afpd/fork.c | 4 +- include/atalk/adouble.h | 4 +- libatalk/adouble/ad_attr.c | 2 +- libatalk/adouble/ad_flush.c | 10 ++-- libatalk/adouble/ad_lock.c | 6 +-- libatalk/adouble/ad_open.c | 91 ++++++++++++++++--------------------- libatalk/adouble/ad_read.c | 60 ++++++++++++++++++------ libatalk/adouble/ad_write.c | 20 ++++---- libatalk/vfs/extattr.c | 6 ++- 9 files changed, 116 insertions(+), 87 deletions(-) diff --git a/etc/afpd/fork.c b/etc/afpd/fork.c index 4b5a9a26..40ae7cda 100644 --- a/etc/afpd/fork.c +++ b/etc/afpd/fork.c @@ -54,7 +54,7 @@ static int getforkparams(struct ofork *ofork, uint16_t bitmap, char *buf, size_t return( AFPERR_BITMAP ); } - if ( ad_reso_fileno( ofork->of_ad ) == -1 ) { /* META ? */ + if (! AD_META_OPEN(ofork->of_ad)) { adp = NULL; } else { adp = ofork->of_ad; @@ -1353,7 +1353,7 @@ int afp_getforkparams(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbu return( AFPERR_PARAM ); } - if (AD_META_OPEN(ofork->of_ad))) { + if (AD_META_OPEN(ofork->of_ad)) { if ( ad_refresh( ofork->of_ad ) < 0 ) { LOG(log_error, logtype_afpd, "getforkparams(%s): ad_refresh: %s", of_name(ofork), strerror(errno) ); return( AFPERR_PARAM ); diff --git a/include/atalk/adouble.h b/include/atalk/adouble.h index d3466518..4539bed8 100644 --- a/include/atalk/adouble.h +++ b/include/atalk/adouble.h @@ -374,8 +374,8 @@ extern uid_t ad_getfuid (void ); extern char *ad_dir (const char *); extern const char *ad_path (const char *, int); extern const char *ad_path_ea (const char *, int); -extern int ad_mode (const char *, int); -extern int ad_mkdir (const char *, int); +extern int ad_mode (const char *, mode_t); +extern int ad_mkdir (const char *, mode_t); struct vol; extern void ad_init (struct adouble *, const struct vol * restrict); extern void ad_init_old (struct adouble *ad, int flags, int options); diff --git a/libatalk/adouble/ad_attr.c b/libatalk/adouble/ad_attr.c index e005577f..47e6f37c 100644 --- a/libatalk/adouble/ad_attr.c +++ b/libatalk/adouble/ad_attr.c @@ -92,7 +92,7 @@ int ad_setattr(const struct adouble *ad, const uint16_t attribute) */ int ad_setid (struct adouble *adp, const dev_t dev, const ino_t ino , const uint32_t id, const cnid_t did, const void *stamp) { - if ((adp->ad_flags == AD_VERSION2) && (adp->ad_options & ADVOL_CACHE)) { + if ((adp->ad_vers == AD_VERSION2) && (adp->ad_options & ADVOL_CACHE)) { /* ad_getid depends on this to detect presence of ALL entries */ ad_setentrylen( adp, ADEID_PRIVID, sizeof(id)); diff --git a/libatalk/adouble/ad_flush.c b/libatalk/adouble/ad_flush.c index abc697bd..06856466 100644 --- a/libatalk/adouble/ad_flush.c +++ b/libatalk/adouble/ad_flush.c @@ -93,7 +93,7 @@ int ad_rebuild_adouble_header(struct adouble *ad) nent = htons( nent ); memcpy(nentp, &nent, sizeof( nent )); - switch (ad->ad_flags) { + switch (ad->ad_vers) { case AD_VERSION2: len = ad_getentryoff(ad, ADEID_RFORK); break; @@ -149,7 +149,7 @@ int ad_flush(struct adouble *ad) int len; struct ad_fd *adf; - switch (ad->ad_flags) { + switch (ad->ad_vers) { case AD_VERSION2: adf = ad->ad_mdp; break; @@ -170,7 +170,7 @@ int ad_flush(struct adouble *ad) } len = ad->ad_ops->ad_rebuild_header(ad); - switch (ad->ad_flags) { + switch (ad->ad_vers) { case AD_VERSION2: if (adf_pwrite(ad->ad_mdp, ad->ad_data, len, 0) != len) { if (errno == 0) @@ -221,7 +221,7 @@ int ad_close(struct adouble *ad, int adflags) } if ((adflags & ADFLAGS_HF)) { - switch (ad->ad_flags) { + switch (ad->ad_vers) { case AD_VERSION2: if ((ad_meta_fileno(ad) != -1) && !(--ad->ad_mdp->adf_refcount)) { if (close( ad_meta_fileno(ad) ) < 0) @@ -249,7 +249,7 @@ int ad_close(struct adouble *ad, int adflags) } if ((adflags & ADFLAGS_RF)) { - switch (ad->ad_flags) { + switch (ad->ad_vers) { case AD_VERSION2: /* Do nothing as ADFLAGS_RF == ADFLAGS_HF */ break; diff --git a/libatalk/adouble/ad_lock.c b/libatalk/adouble/ad_lock.c index b78e22de..6961930d 100644 --- a/libatalk/adouble/ad_lock.c +++ b/libatalk/adouble/ad_lock.c @@ -462,7 +462,7 @@ int ad_lock(struct adouble *ad, uint32_t eid, int locktype, off_t off, off_t len } } } else { /* rfork */ - switch (ad->ad_flags) { + switch (ad->ad_vers) { case AD_VERSION2: if (ad_meta_fileno(ad) == -1 || ad_reso_fileno(ad) == -1) { /* there's no meta data. return a lock error @@ -682,7 +682,7 @@ void ad_unlock(struct adouble *ad, const int fork) */ int ad_testlock(struct adouble *ad, int eid, const off_t off) { - switch (ad->ad_flags) { + switch (ad->ad_vers) { case AD_VERSION2: return ad_testlock_v2(ad, eid, off); case AD_VERSION_EA: @@ -706,7 +706,7 @@ int ad_testlock(struct adouble *ad, int eid, const off_t off) */ uint16_t ad_openforks(struct adouble *ad, uint16_t attrbits) { - switch (ad->ad_flags) { + switch (ad->ad_vers) { case AD_VERSION2: return ad_openforks_v2(ad, attrbits); case AD_VERSION_EA: diff --git a/libatalk/adouble/ad_open.c b/libatalk/adouble/ad_open.c index c906e07b..2223029b 100644 --- a/libatalk/adouble/ad_open.c +++ b/libatalk/adouble/ad_open.c @@ -253,7 +253,7 @@ static int new_ad_header(const char *path, struct adouble *ad, int adflags) struct stat st; ad->ad_magic = AD_MAGIC; - ad->ad_version = ad->ad_flags & 0x0f0000; + ad->ad_version = ad->ad_vers & 0x0f0000; if (!ad->ad_version) { ad->ad_version = AD_VERSION; } @@ -261,9 +261,9 @@ static int new_ad_header(const char *path, struct adouble *ad, int adflags) memset(ad->ad_data, 0, sizeof(ad->ad_data)); - if (ad->ad_flags == AD_VERSION2) + if (ad->ad_vers == AD_VERSION2) eid = entry_order2; - else if (ad->ad_flags == AD_VERSION_EA) + else if (ad->ad_vers == AD_VERSION_EA) eid = entry_order_ea; else { return -1; @@ -465,6 +465,27 @@ static int ad_header_read_ea(struct adouble *ad, struct stat *hst _U_) /* Now parse entries */ parse_entries(ad, buf + AD_HEADER_LEN, nentries); + + return 0; +} + +static int ad_rsrc_len_ea(struct adouble *ad) +{ + ssize_t rlen; + + if ((rlen = sys_fgetxattr(ad_data_fileno(ad), AD_EA_RESO, NULL, 0)) <= 0) { + switch (errno) { + case ENOATTR: + case ENOENT: + ad->ad_rlen = 0; + break; + default: + LOG(log_error, logtype_default, "ad_refresh_rsrc_len_ea: %s", strerror(errno)); + ad->ad_rlen = 0; + return -1; + } + } + ad->ad_rlen = rlen; return 0; } @@ -522,7 +543,7 @@ static int ad_chown(const char *path, struct stat *stbuf) /* ---------------- return access right and inode of path parent directory */ -static int ad_mode_st(const char *path, int *mode, struct stat *stbuf) +static int ad_mode_st(const char *path, mode_t *mode, struct stat *stbuf) { if (*mode == 0) { return -1; @@ -558,11 +579,11 @@ static int ad_header_upgrade_ea(struct adouble *ad _U_, const char *name _U_) static int ad_error(struct adouble *ad, int adflags) { int err = errno; - if ((adflags & ADFLAGS_NOHF)) { /* 1 */ + if (adflags & ADFLAGS_NOHF) { /* 1 */ ad->ad_adflags &= ~ADFLAGS_HF; return 0; } - if ((adflags & ADFLAGS_DF) { /* 2 */ + if (adflags & ADFLAGS_DF) { /* 2 */ ad_close( ad, ADFLAGS_DF ); err = errno; } @@ -864,7 +885,7 @@ static int ad_open_hf(const char *path, int adflags, int mode, struct adouble *a memset(ad->ad_eid, 0, sizeof( ad->ad_eid )); ad->ad_rlen = 0; - switch (ad->ad_flags) { + switch (ad->ad_vers) { case AD_VERSION2: ret = ad_open_hf_v2(path, adflags, mode, ad); break; @@ -879,6 +900,7 @@ static int ad_open_hf(const char *path, int adflags, int mode, struct adouble *a return ret; } + /*! * Open ressource fork * @@ -889,8 +911,9 @@ static int ad_open_rf(const char *path, int adflags, int mode, struct adouble *a { int ret = 0; int oflags; + ssize_t rlen; - if (ad->ad_flags != AD_VERSION_EA) + if (ad->ad_vers != AD_VERSION_EA) return 0; LOG(log_debug, logtype_default, "ad_open_rf(\"%s\", %04o)", path, mode); @@ -914,47 +937,12 @@ static int ad_open_rf(const char *path, int adflags, int mode, struct adouble *a adf_lock_init(&ad->ad_data_fork); } - if ((ad->ad_rlen = sys_fgetxattr(ad_data_fileno(ad), AD_EA_RESO, NULL, 0)) <= 0) { - switch (errno) { - case ENOATTR: - ad->ad_rlen = 0; - break; - default: - LOG(log_warning, logtype_default, "ad_open_rf(\"%s\"): %s", - fullpathname(path), strerror(errno)); - ret = -1; - goto exit; - } - } - - /* Round up and allocate buffer */ - size_t roundup = ((ad->ad_rlen / RFORK_EA_ALLOCSIZE) + 1) * RFORK_EA_ALLOCSIZE; - if ((ad->ad_resforkbuf = malloc(roundup)) == NULL) { - ret = -1; + if ((ret = ad_rsrc_len_ea(ad)) != 0) goto exit; - } - - ad->ad_resforkbufsize = roundup; - - /* Read the EA into the buffer */ - if (ad->ad_rlen > 0) { - if (sys_fgetxattr(ad_data_fileno(ad), AD_EA_RESO, ad->ad_resforkbuf, ad->ad_rlen) == -1) { - ret = -1; - goto exit; - } - } ad->ad_data_fork.adf_refcount++; exit: - if (ret != 0) { - if (ad->ad_resforkbuf) - free(ad->ad_resforkbuf); - ad->ad_resforkbuf = NULL; - ad->ad_rlen = 0; - ad->ad_resforkbufsize = 0; - } - return ret; } @@ -1088,7 +1076,7 @@ int ad_stat(const char *path, struct stat *stbuf) /* ---------------- return access right of path parent directory */ -int ad_mode( const char *path, int mode) +int ad_mode( const char *path, mode_t mode) { struct stat stbuf; ad_mode_st(path, &mode, &stbuf); @@ -1098,7 +1086,7 @@ int ad_mode( const char *path, int mode) /* * Use mkdir() with mode bits taken from ad_mode(). */ -int ad_mkdir( const char *path, int mode) +int ad_mkdir( const char *path, mode_t mode) { int ret; int st_invalid; @@ -1118,7 +1106,7 @@ int ad_mkdir( const char *path, int mode) static void ad_init_func(struct adouble *ad) { - switch (ad->ad_flags) { + switch (ad->ad_vers) { case AD_VERSION2: ad->ad_ops = &ad_adouble; ad->ad_rfp = &ad->ad_resource_fork; @@ -1150,14 +1138,14 @@ static void ad_init_func(struct adouble *ad) void ad_init_old(struct adouble *ad, int flags, int options) { - ad->ad_flags = flags; + ad->ad_vers = flags; ad->ad_options = options; ad_init_func(ad); } void ad_init(struct adouble *ad, const struct vol * restrict vol) { - ad->ad_flags = vol->v_adouble; + ad->ad_vers = vol->v_adouble; ad->ad_options = vol->v_ad_options; ad->ad_maxeafssize = 3500; /* FIXME: option from vol */ ad_init_func(ad); @@ -1316,8 +1304,7 @@ exit: int ad_refresh(struct adouble *ad) { - - switch (ad->ad_flags) { + switch (ad->ad_vers) { case AD_VERSION2: if (ad_meta_fileno(ad) == -1) return -1; @@ -1326,6 +1313,8 @@ int ad_refresh(struct adouble *ad) case AD_VERSION_EA: if (ad_data_fileno(ad) == -1) return -1; + if (ad_rsrc_len_ea(ad) != 0) + return -1; return ad->ad_ops->ad_header_read(ad, NULL); break; default: diff --git a/libatalk/adouble/ad_read.c b/libatalk/adouble/ad_read.c index 224c72d9..7b8841bb 100644 --- a/libatalk/adouble/ad_read.c +++ b/libatalk/adouble/ad_read.c @@ -28,13 +28,12 @@ #include #include #include +#include #include #include - -#ifndef MIN -#define MIN(a,b) ((a)<(b)?(a):(b)) -#endif /* ! MIN */ +#include +#include ssize_t adf_pread(struct ad_fd *ad_fd, void *buf, size_t count, off_t offset) { @@ -63,6 +62,8 @@ ssize_t adf_pread(struct ad_fd *ad_fd, void *buf, size_t count, off_t offset) ssize_t ad_read( struct adouble *ad, const uint32_t eid, off_t off, char *buf, const size_t buflen) { ssize_t cc; + ssize_t rlen; + off_t r_off; /* We're either reading the data fork (and thus the data file) * or we're reading anything else (and thus the header file). */ @@ -78,11 +79,12 @@ ssize_t ad_read( struct adouble *ad, const uint32_t eid, off_t off, char *buf, c cc = adf_pread(&ad->ad_data_fork, buf, buflen, off); } } else { - if (ad->ad_flags != AD_VERSION_EA) { - off_t r_off; - if ( ad_reso_fileno( ad ) == -1 ) - /* resource fork is not open ( cf etc/afp/fork.c) */ - return 0; + if (! AD_RSRC_OPEN(ad)) + /* resource fork is not open ( cf etc/afp/fork.c) */ + return 0; + + switch (ad->ad_vers) { + case AD_VERSION2: r_off = ad_getentryoff(ad, eid) + off; if (( cc = adf_pread( &ad->ad_resource_fork, buf, buflen, r_off )) < 0 ) return( -1 ); @@ -101,17 +103,49 @@ ssize_t ad_read( struct adouble *ad, const uint32_t eid, off_t off, char *buf, c MIN(sizeof( ad->ad_data ) - r_off, cc)); } } - } else { /* AD_VERSION_EA */ + break; + + case AD_VERSION_EA: + if ((rlen = sys_fgetxattr(ad_data_fileno(ad), AD_EA_RESO, NULL, 0)) <= 0) { + switch (errno) { + case ENOATTR: + case ENOENT: + cc = ad->ad_rlen = 0; + break; + default: + LOG(log_error, logtype_default, "ad_read: %s", strerror(errno)); + return -1; + } + } + ad->ad_rlen = rlen; + if (off > ad->ad_rlen) { errno = ERANGE; return -1; } - if (ad->ad_rlen == 0) - return 0; + + if (ad->ad_resforkbuf == NULL) { + if ((ad->ad_resforkbuf = malloc(ad->ad_rlen)) == NULL) { + ad->ad_rlen = 0; + return -1; + } + } else { + if ((ad->ad_resforkbuf = realloc(ad->ad_resforkbuf, ad->ad_rlen)) == NULL) { + ad->ad_rlen = 0; + return -1; + } + } + + if (sys_fgetxattr(ad_data_fileno(ad), AD_EA_RESO, ad->ad_resforkbuf, ad->ad_rlen) == -1) { + ad->ad_rlen = 0; + return -1; + } + if ((off + buflen) > ad->ad_rlen) cc = ad->ad_rlen; memcpy(buf, ad->ad_resforkbuf + off, cc); - } + break; + } /* switch (ad->ad_vers) */ } return( cc ); diff --git a/libatalk/adouble/ad_write.c b/libatalk/adouble/ad_write.c index dd66796c..5762d18f 100644 --- a/libatalk/adouble/ad_write.c +++ b/libatalk/adouble/ad_write.c @@ -112,7 +112,7 @@ ssize_t ad_write(struct adouble *ad, uint32_t eid, off_t off, int end, const cha } cc = adf_pwrite(&ad->ad_data_fork, buf, buflen, off); } else if ( eid == ADEID_RFORK ) { - switch (ad->ad_flags) { + switch (ad->ad_vers) { case AD_VERSION2: if ( end ) { @@ -131,15 +131,19 @@ ssize_t ad_write(struct adouble *ad, uint32_t eid, off_t off, int end, const cha break; case AD_VERSION_EA: - if ((off + buflen) > ad->ad_resforkbufsize) { - roundup = (((off + buflen) / RFORK_EA_ALLOCSIZE) + 1) * RFORK_EA_ALLOCSIZE; - if ((ad->ad_resforkbuf = realloc(ad->ad_resforkbuf, roundup)) == NULL) + if (ad->ad_resforkbuf == NULL) { + ad->ad_rlen = off + buflen; + if ((ad->ad_resforkbuf = malloc(ad->ad_rlen)) == NULL) { + ad->ad_rlen = 0; return -1; - ad->ad_resforkbufsize = roundup; + } } - memcpy(ad->ad_resforkbuf + off, buf, buflen); - if ((off + buflen) > ad->ad_rlen) + if ((off + buflen) > ad->ad_rlen) { + if ((ad->ad_resforkbuf = realloc(ad->ad_resforkbuf, off + buflen)) == NULL) + return -1; ad->ad_rlen = off + buflen; + } + memcpy(ad->ad_resforkbuf + off, buf, buflen); if (fsetrsrcea(ad, ad_data_fileno(ad), AD_EA_RESO, ad->ad_resforkbuf, ad->ad_rlen, 0) == -1) return -1; @@ -217,7 +221,7 @@ char c = 0; /* ------------------------ */ int ad_rtruncate( struct adouble *ad, const off_t size) { - if (ad->ad_flags != AD_VERSION_EA) + if (ad->ad_vers != AD_VERSION_EA) if (sys_ftruncate(ad_reso_fileno(ad), size + ad->ad_eid[ ADEID_RFORK ].ade_off ) < 0 ) return -1; diff --git a/libatalk/vfs/extattr.c b/libatalk/vfs/extattr.c index bdae873e..853b7f2f 100644 --- a/libatalk/vfs/extattr.c +++ b/libatalk/vfs/extattr.c @@ -855,8 +855,10 @@ static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode) { int filedes = openat(fildes, path, oflag, mode); if (filedes == -1) { - LOG(log_error, logtype_default, "openat(\"%s\"): %s", - path, strerror(errno)); + if (errno != ENOENT) + LOG(log_error, logtype_default, "openat(\"%s\"): %s", + path, strerror(errno)); + errno = ENOATTR; } return filedes; } -- 2.39.2