• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src/router/netatalk-3.0.5/libatalk/adouble/
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