• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/ap/gpl/timemachine/netatalk-2.2.0/libatalk/adouble/
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