1#ifdef HAVE_CONFIG_H 2#include "config.h" 3#endif /* HAVE_CONFIG_H */ 4 5#include <string.h> 6#include <arpa/inet.h> 7#include <atalk/adouble.h> 8#include <atalk/logger.h> 9 10#define FILEIOFF_ATTR 14 11#define AFPFILEIOFF_ATTR 2 12 13/* 14 Note: 15 the "shared" and "invisible" attributes are opaque and stored and 16 retrieved from the FinderFlags. This fixes Bug #2802236: 17 <https://sourceforge.net/tracker/?func=detail&aid=2802236&group_id=8642&atid=108642> 18 */ 19int ad_getattr(const struct adouble *ad, uint16_t *attr) 20{ 21 uint16_t fflags; 22 *attr = 0; 23 24 if (ad_getentryoff(ad, ADEID_AFPFILEI)) { 25 memcpy(attr, ad_entry(ad, ADEID_AFPFILEI) + AFPFILEIOFF_ATTR, 2); 26 27 /* Now get opaque flags from FinderInfo */ 28 memcpy(&fflags, ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRFLAGOFF, 2); 29 if (fflags & htons(FINDERINFO_INVISIBLE)) 30 *attr |= htons(ATTRBIT_INVISIBLE); 31 else 32 *attr &= htons(~ATTRBIT_INVISIBLE); 33 /* 34 * This one is tricky, I actually got it wrong the first time: 35 * for directories bit 1<<1 is ATTRBIT_EXPFLDR and is NOT opaque ! 36 */ 37 if ( ! (ad->ad_adflags & ADFLAGS_DIR)) { 38 if (fflags & htons(FINDERINFO_ISHARED)) 39 *attr |= htons(ATTRBIT_MULTIUSER); 40 else 41 *attr &= htons(~ATTRBIT_MULTIUSER); 42 } 43 } 44 45 *attr |= htons(ad->ad_open_forks); 46 47 return 0; 48} 49 50/* ----------------- */ 51int ad_setattr(const struct adouble *ad, const uint16_t attribute) 52{ 53 uint16_t fflags; 54 55 /* we don't save open forks indicator */ 56 uint16_t attr = attribute & ~htons(ATTRBIT_DOPEN | ATTRBIT_ROPEN); 57 58 /* Proactively (10.4 does indeed try to set ATTRBIT_MULTIUSER (=ATTRBIT_EXPFLDR) 59 for dirs with SetFile -a M <dir> ) disable all flags not defined for dirs. */ 60 if (ad->ad_adflags & ADFLAGS_DIR) 61 attr &= ~(ATTRBIT_MULTIUSER | ATTRBIT_NOWRITE | ATTRBIT_NOCOPY); 62 63 if (ad_getentryoff(ad, ADEID_AFPFILEI) && ad_getentryoff(ad, ADEID_FINDERI)) { 64 memcpy(ad_entry(ad, ADEID_AFPFILEI) + AFPFILEIOFF_ATTR, &attr, sizeof(attr)); 65 66 /* Now set opaque flags in FinderInfo too */ 67 memcpy(&fflags, ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRFLAGOFF, 2); 68 if (attr & htons(ATTRBIT_INVISIBLE)) 69 fflags |= htons(FINDERINFO_INVISIBLE); 70 else 71 fflags &= htons(~FINDERINFO_INVISIBLE); 72 73 /* See above comment in ad_getattr() */ 74 if (attr & htons(ATTRBIT_MULTIUSER)) { 75 if ( ! (ad->ad_adflags & ADFLAGS_DIR) ) 76 fflags |= htons(FINDERINFO_ISHARED); 77 } else 78 fflags &= htons(~FINDERINFO_ISHARED); 79 80 memcpy(ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRFLAGOFF, &fflags, 2); 81 } 82 83 return 0; 84} 85 86/* -------------- 87 * save file/folder ID in AppleDoubleV2 netatalk private parameters 88 * return 1 if resource fork has been modified 89 */ 90int ad_setid (struct adouble *adp, const dev_t dev, const ino_t ino , const uint32_t id, const cnid_t did, const void *stamp) 91{ 92 uint32_t tmp; 93 94 ad_setentrylen( adp, ADEID_PRIVID, sizeof(id)); 95 tmp = id; 96 if (adp->ad_vers == AD_VERSION_EA) 97 tmp = htonl(tmp); 98 memcpy(ad_entry( adp, ADEID_PRIVID ), &tmp, sizeof(tmp)); 99 100 ad_setentrylen( adp, ADEID_PRIVDEV, sizeof(dev_t)); 101 if ((adp->ad_options & ADVOL_NODEV)) { 102 memset(ad_entry( adp, ADEID_PRIVDEV ), 0, sizeof(dev_t)); 103 } else { 104 memcpy(ad_entry( adp, ADEID_PRIVDEV ), &dev, sizeof(dev_t)); 105 } 106 107 ad_setentrylen( adp, ADEID_PRIVINO, sizeof(ino_t)); 108 memcpy(ad_entry( adp, ADEID_PRIVINO ), &ino, sizeof(ino_t)); 109 110 ad_setentrylen( adp, ADEID_DID, sizeof(did)); 111 memcpy(ad_entry( adp, ADEID_DID ), &did, sizeof(did)); 112 113 ad_setentrylen( adp, ADEID_PRIVSYN, ADEDLEN_PRIVSYN); 114 memcpy(ad_entry( adp, ADEID_PRIVSYN ), stamp, ADEDLEN_PRIVSYN); 115 116 return 1; 117} 118 119/* ----------------------------- */ 120uint32_t ad_getid (struct adouble *adp, const dev_t st_dev, const ino_t st_ino , const cnid_t did, const void *stamp _U_) 121{ 122 uint32_t aint = 0; 123 dev_t dev; 124 ino_t ino; 125 cnid_t a_did; 126 127 if (adp) { 128 if (sizeof(dev_t) == ad_getentrylen(adp, ADEID_PRIVDEV)) { 129 memcpy(&dev, ad_entry(adp, ADEID_PRIVDEV), sizeof(dev_t)); 130 memcpy(&ino, ad_entry(adp, ADEID_PRIVINO), sizeof(ino_t)); 131 memcpy(&a_did, ad_entry(adp, ADEID_DID), sizeof(cnid_t)); 132 133 if (((adp->ad_options & ADVOL_NODEV) || (dev == st_dev)) 134 && ino == st_ino 135 && (!did || a_did == did) ) { 136 memcpy(&aint, ad_entry(adp, ADEID_PRIVID), sizeof(aint)); 137 if (adp->ad_vers == AD_VERSION2) 138 return aint; 139 else 140 return ntohl(aint); 141 } 142 } 143 } 144 return 0; 145} 146 147/* ----------------------------- */ 148uint32_t ad_forcegetid (struct adouble *adp) 149{ 150 uint32_t aint = 0; 151 152 if (adp) { 153 memcpy(&aint, ad_entry(adp, ADEID_PRIVID), sizeof(aint)); 154 if (adp->ad_vers == AD_VERSION2) 155 return aint; 156 else 157 return ntohl(aint); 158 } 159 return 0; 160} 161 162/* ----------------- 163 * set resource fork filename attribute. 164 */ 165int ad_setname(struct adouble *ad, const char *path) 166{ 167 int len; 168 if ((len = strlen(path)) > ADEDLEN_NAME) 169 len = ADEDLEN_NAME; 170 if (path && ad_getentryoff(ad, ADEID_NAME)) { 171 ad_setentrylen( ad, ADEID_NAME, len); 172 memcpy(ad_entry( ad, ADEID_NAME ), path, len); 173 return 1; 174 } 175 return 0; 176} 177