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