X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=netatalk.git;a=blobdiff_plain;f=etc%2Fafpd%2Ffile.c;h=881640da3871fa0824792fce47b578201b014da2;hp=71c248a450a50dea658b5836a9bd0675023fce4c;hb=d3dff4ba4b8db3131a16641d35a6554be5fb5160;hpb=40c614d84ae5bf7c1808a30a2ccac8db12228519 diff --git a/etc/afpd/file.c b/etc/afpd/file.c index 71c248a4..881640da 100644 --- a/etc/afpd/file.c +++ b/etc/afpd/file.c @@ -93,6 +93,7 @@ void *get_finderinfo(const struct vol *vol, const char *upath, struct adouble *a } else { memcpy(data, ufinderi, ADEDLEN_FINDERI); + chk_ext = 1; if (vol_inv_dots(vol) && *upath == '.') { /* make it invisible */ uint16_t ashort; @@ -219,7 +220,10 @@ restart: catching moved files */ adcnid = ad_getid(adp, st->st_dev, st->st_ino, 0, vol->v_stamp); /* (1) */ + AFP_CNID_START("cnid_add"); dbcnid = cnid_add(vol->v_cdb, st, did, upath, len, adcnid); /* (2) */ + AFP_CNID_DONE(); + /* Throw errors if cnid_add fails. */ if (dbcnid == CNID_INVALID) { switch (errno) { @@ -248,7 +252,7 @@ restart: } LOG(log_error, logtype_afpd, "Reopen volume %s using in memory temporary CNID DB.", vol->v_path); - vol->v_cdb = cnid_open(vol->v_path, vol->v_umask, "tdb", flags, NULL, NULL); + vol->v_cdb = cnid_open(vol, "tdb", flags); if (vol->v_cdb) { if (!(vol->v_flags & AFPVOL_TM)) { vol->v_flags |= AFPVOL_RO; @@ -335,6 +339,7 @@ int getmetadata(const AFPObj *obj, || (bconchar(fullpath, '/') != BSTR_OK) || (bcatcstr(fullpath, upath)) != BSTR_OK) { LOG(log_error, logtype_afpd, "getmetadata: fullpath: %s", strerror(errno)); + bdestroy(fullpath); return AFPERR_MISC; } @@ -373,6 +378,7 @@ int getmetadata(const AFPObj *obj, ashort = htons(ATTRBIT_INVISIBLE); } else ashort = 0; + ashort &= ~htons(vol->v_ignattr); #if 0 /* FIXME do we want a visual clue if the file is read only */ @@ -455,18 +461,23 @@ int getmetadata(const AFPObj *obj, data += sizeof( aint ); break; - case FILPBIT_RFLEN : - if ( adp ) { + case FILPBIT_RFLEN: { + off_t rlen; + if (adp) { if (adp->ad_rlen > 0xffffffff) aint = 0xffffffff; else aint = htonl( adp->ad_rlen); } else { - aint = 0; + rlen = ad_reso_size(path->u_name, 0, NULL); + if (rlen > 0xffffffff) + rlen = 0xffffffff; + aint = htonl(rlen); } memcpy(data, &aint, sizeof( aint )); data += sizeof( aint ); break; + } /* Current client needs ProDOS info block for this file. Use simple heuristic and let the Mac "type" string tell @@ -534,15 +545,18 @@ int getmetadata(const AFPObj *obj, data += sizeof( aint ); break; case FILPBIT_EXTRFLEN: - aint = 0; - if (adp) + if (adp) { aint = htonl(adp->ad_rlen >> 32); - memcpy(data, &aint, sizeof( aint )); - data += sizeof( aint ); - if (adp) + memcpy(data, &aint, sizeof( aint )); + data += sizeof( aint ); aint = htonl(adp->ad_rlen); - memcpy(data, &aint, sizeof( aint )); - data += sizeof( aint ); + memcpy(data, &aint, sizeof( aint )); + data += sizeof( aint ); + } else { + int64_t rlen = hton64(ad_reso_size(path->u_name, 0, NULL)); + memcpy(data, &rlen, sizeof(rlen)); + data += sizeof(rlen); + } break; case FILPBIT_UNIXPR : /* accessmode may change st_mode with ACLs */ @@ -750,7 +764,7 @@ int afp_createfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, createfile_iderr: ad_flush(&ad); ad_close(&ad, ADFLAGS_DF|ADFLAGS_HF ); - fce_register(FCE_FILE_CREATE, fullpathname(upath), NULL, fce_file); + fce_register(obj, FCE_FILE_CREATE, fullpathname(upath), NULL); sl_index_file(path); curdir->d_offcnt++; @@ -1010,6 +1024,7 @@ int setfilparams(const AFPObj *obj, struct vol *vol, ad_getattr(adp, &bshort); oshort = bshort; if ( ntohs( ashort ) & ATTRBIT_SETCLR ) { + ashort &= ~htons(vol->v_ignattr); bshort |= htons( ntohs( ashort ) & ~ATTRBIT_SETCLR ); } else { bshort &= ~ashort; @@ -1514,7 +1529,7 @@ done: WRITE lock on read only file. */ -static int check_attrib(struct adouble *adp) +static int check_attrib(const struct vol *vol, struct adouble *adp) { uint16_t bshort = 0; @@ -1522,10 +1537,10 @@ uint16_t bshort = 0; /* * Does kFPDeleteInhibitBit (bit 8) set? */ - if ((bshort & htons(ATTRBIT_NODELETE))) { + if (!(vol->v_ignattr & ATTRBIT_NODELETE) && (bshort & htons(ATTRBIT_NODELETE))) { return AFPERR_OLOCK; } - if ((bshort & htons(ATTRBIT_DOPEN | ATTRBIT_ROPEN))) { + if ((bshort & htons(ATTRBIT_DOPEN | ATTRBIT_ROPEN))) { return AFPERR_BUSY; } return 0; @@ -1550,7 +1565,7 @@ int deletefile(const struct vol *vol, int dirfd, char *file, int checkAttrib) * ad_open would create a 0 byte resource fork */ if ( ad_metadataat(dirfd, file, ADFLAGS_CHECK_OF, &ad) == 0 ) { - if ((err = check_attrib(&ad))) { + if ((err = check_attrib(vol, &ad))) { ad_close(&ad, ADFLAGS_HF | ADFLAGS_CHECK_OF); return err; } @@ -1579,7 +1594,7 @@ int deletefile(const struct vol *vol, int dirfd, char *file, int checkAttrib) adp = &ad; } - if ( adp && AD_RSRC_OPEN(adp) != -1 ) { /* there's a resource fork */ + if ( adp && AD_RSRC_OPEN(adp) ) { /* there's a resource fork */ adflags |= ADFLAGS_RF; /* FIXME we have a pb here because we want to know if a file is open * there's a 'priority inversion' if you can't open the ressource fork RW @@ -1601,8 +1616,15 @@ int deletefile(const struct vol *vol, int dirfd, char *file, int checkAttrib) err = AFPERR_BUSY; } else if (!(err = vol->vfs->vfs_deletefile(vol, dirfd, file)) && !(err = netatalk_unlinkat(dirfd, file )) ) { cnid_t id; - if (checkAttrib && (id = cnid_get(vol->v_cdb, curdir->d_did, file, strlen(file)))) { - cnid_delete(vol->v_cdb, id); + if (checkAttrib) { + AFP_CNID_START("cnid_get"); + id = cnid_get(vol->v_cdb, curdir->d_did, file, strlen(file)); + AFP_CNID_DONE(); + if (id) { + AFP_CNID_START("cnid_delete"); + cnid_delete(vol->v_cdb, id); + AFP_CNID_DONE(); + } } } @@ -1640,7 +1662,7 @@ int afp_createid(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, si return( AFPERR_PARAM); } - if (vol->v_cdb == NULL || !(vol->v_cdb->flags & CNID_FLAG_PERSISTENT)) { + if (vol->v_cdb == NULL || !(vol->v_cdb->cnid_db_flags & CNID_FLAG_PERSISTENT)) { return AFPERR_NOOP; } @@ -1675,7 +1697,10 @@ int afp_createid(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, si return AFPERR_PARAM; } st = &s_path->st; - if ((id = cnid_lookup(vol->v_cdb, st, did, upath, len = strlen(upath)))) { + AFP_CNID_START("cnid_lookup"); + id = cnid_lookup(vol->v_cdb, st, did, upath, len = strlen(upath)); + AFP_CNID_DONE(); + if (id) { memcpy(rbuf, &id, sizeof(id)); *rbuflen = sizeof(id); return AFPERR_EXISTID; @@ -1708,7 +1733,9 @@ static int reenumerate_loop(struct dirent *de, char *mname _U_, void *data) return 0; /* update or add to cnid */ + AFP_CNID_START("cnid_add"); aint = cnid_add(vol->v_cdb, &path.st, did, de->d_name, strlen(de->d_name), 0); /* ignore errors */ + AFP_CNID_DONE(); return 0; } @@ -1774,7 +1801,7 @@ int afp_resolveid(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_ return( AFPERR_PARAM); } - if (vol->v_cdb == NULL || !(vol->v_cdb->flags & CNID_FLAG_PERSISTENT)) { + if (vol->v_cdb == NULL || !(vol->v_cdb->cnid_db_flags & CNID_FLAG_PERSISTENT)) { return AFPERR_NOOP; } @@ -1787,7 +1814,10 @@ int afp_resolveid(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_ return AFPERR_NOID; } retry: - if (NULL == (upath = cnid_resolve(vol->v_cdb, &id, buffer, len)) ) { + AFP_CNID_START("cnid_resolve"); + upath = cnid_resolve(vol->v_cdb, &id, buffer, len); + AFP_CNID_DONE(); + if (upath == NULL) { return AFPERR_NOID; /* was AFPERR_BADID, but help older Macs */ } @@ -1879,7 +1909,7 @@ int afp_deleteid(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_ return( AFPERR_PARAM); } - if (vol->v_cdb == NULL || !(vol->v_cdb->flags & CNID_FLAG_PERSISTENT)) { + if (vol->v_cdb == NULL || !(vol->v_cdb->cnid_db_flags & CNID_FLAG_PERSISTENT)) { return AFPERR_NOOP; } @@ -1890,7 +1920,10 @@ int afp_deleteid(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_ ibuf += sizeof(id); fileid = id; - if (NULL == (upath = cnid_resolve(vol->v_cdb, &id, buffer, len)) ) { + AFP_CNID_START("cnid_resolve"); + upath = cnid_resolve(vol->v_cdb, &id, buffer, len); + AFP_CNID_DONE(); + if (upath == NULL) { return AFPERR_NOID; } @@ -1923,7 +1956,9 @@ int afp_deleteid(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_ return AFPERR_BADTYPE; delete: + AFP_CNID_START("cnid_delete"); if (cnid_delete(vol->v_cdb, fileid)) { + AFP_CNID_DONE(); switch (errno) { case EROFS: return AFPERR_VLOCK; @@ -1934,7 +1969,7 @@ delete: return AFPERR_PARAM; } } - + AFP_CNID_DONE(); return err; } @@ -2062,7 +2097,9 @@ int afp_exchangefiles(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U /* look for the source cnid. if it doesn't exist, don't worry about * it. */ + AFP_CNID_START("cnid_lookup"); sid = cnid_lookup(vol->v_cdb, &srcst, sdir->d_did, supath,slen = strlen(supath)); + AFP_CNID_DONE(); if (NULL == ( dir = dirlookup( vol, did )) ) { err = afp_errno; /* was AFPERR_PARAM */ @@ -2105,7 +2142,9 @@ int afp_exchangefiles(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U /* look for destination id. */ upath = path->u_name; + AFP_CNID_START("cnid_lookup"); did = cnid_lookup(vol->v_cdb, &destst, curdir->d_did, upath, dlen = strlen(upath)); + AFP_CNID_DONE(); /* construct a temp name. * NOTE: the temp file will be in the dest file's directory. it @@ -2139,13 +2178,20 @@ int afp_exchangefiles(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U goto err_dest_to_src; of_rename(vol, s_of, curdir, temp, curdir, path->m_name); - /* id's need switching. src -> dest and dest -> src. + /* + * id's need switching. src -> dest and dest -> src. * we need to re-stat() if it was a cross device copy. - */ - if (sid) + */ + if (sid) { + AFP_CNID_START("cnid_delete"); cnid_delete(vol->v_cdb, sid); - if (did) + AFP_CNID_DONE(); + } + if (did) { + AFP_CNID_START("cnid_delete"); cnid_delete(vol->v_cdb, did); + AFP_CNID_DONE(); + } if ((did && ( (crossdev && ostat(upath, &srcst, vol_syml_opt(vol)) < 0) || cnid_update(vol->v_cdb, did, &srcst, curdir->d_did,upath, dlen) < 0)) @@ -2163,6 +2209,42 @@ int afp_exchangefiles(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U } goto err_temp_to_dest; } + + if (AD_META_OPEN(adsp) || AD_META_OPEN(addp)) { + struct adouble adtmp; + bool opened_ads, opened_add; + + ad_init(&adtmp, vol); + ad_init_offsets(&adtmp); + + if (!AD_META_OPEN(adsp)) { + if (ad_open(adsp, p, ADFLAGS_HF) != 0) + return -1; + opened_ads = true; + } + + if (!AD_META_OPEN(addp)) { + if (ad_open(addp, upath, ADFLAGS_HF) != 0) + return -1; + opened_add = true; + } + + if (ad_copy_header(&adtmp, adsp) != 0) + goto err_temp_to_dest; + if (ad_copy_header(adsp, addp) != 0) + goto err_temp_to_dest; + if (ad_copy_header(addp, &adtmp) != 0) + goto err_temp_to_dest; + ad_flush(adsp); + ad_flush(addp); + + if (opened_ads) + ad_close(adsp, ADFLAGS_HF); + if (opened_add) + ad_close(addp, ADFLAGS_HF); + } + + /* FIXME: we should switch ressource fork too */ /* here we need to reopen if crossdev */ if (sid && ad_setid(addp, destst.st_dev, destst.st_ino, sid, sdir->d_did, vol->v_stamp))