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