]> arthur.barton.de Git - netatalk.git/blob - include/atalk/adouble.h
d4558f5ec6a6c2b1c8c42d60a0120e9d40124518
[netatalk.git] / include / atalk / adouble.h
1 /*
2  * Copyright (c) 1990,1991 Regents of The University of Michigan.
3  * All Rights Reserved.
4  *
5  * Permission to use, copy, modify, and distribute this software and
6  * its documentation for any purpose and without fee is hereby granted,
7  * provided that the above copyright notice appears in all copies and
8  * that both that copyright notice and this permission notice appear
9  * in supporting documentation, and that the name of The University
10  * of Michigan not be used in advertising or publicity pertaining to
11  * distribution of the software without specific, written prior
12  * permission. This software is supplied as is without expressed or
13  * implied warranties of any kind.
14  *
15  *  Research Systems Unix Group
16  *  The University of Michigan
17  *  c/o Mike Clark
18  *  535 W. William Street
19  *  Ann Arbor, Michigan
20  *  +1-313-763-0525
21  *  netatalk@itd.umich.edu
22  */
23
24 /*!
25  * @file
26  * @brief Part of Netatalk's AppleDouble implementatation
27  */
28
29 #ifndef _ATALK_ADOUBLE_H
30 #define _ATALK_ADOUBLE_H
31
32 #ifdef HAVE_CONFIG_H
33 #include <config.h>
34 #endif
35
36 #include <atalk/standards.h>
37
38 #include <inttypes.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <unistd.h>
42 #include <fcntl.h>
43
44 #include <sys/mman.h>
45
46 #include <sys/time.h>
47
48 #include <atalk/bstrlib.h>
49
50 /* version info */
51 #define AD_VERSION2     0x00020000
52 #define AD_VERSION_EA   0x00020002
53
54 /* default */
55 #define AD_VERSION      AD_VERSION2
56
57 /*
58  * AppleDouble entry IDs.
59  */
60 #define ADEID_DFORK         1
61 #define ADEID_RFORK         2
62 #define ADEID_NAME          3
63 #define ADEID_COMMENT       4
64 #define ADEID_ICONBW        5
65 #define ADEID_ICONCOL       6
66 #define ADEID_FILEI         7  /* v1, replaced by: */
67 #define ADEID_FILEDATESI    8  /* this */
68 #define ADEID_FINDERI       9
69 #define ADEID_MACFILEI      10 /* we don't use this */
70 #define ADEID_PRODOSFILEI   11 /* we store prodos info here */
71 #define ADEID_MSDOSFILEI    12 /* we don't use this */
72 #define ADEID_SHORTNAME     13
73 #define ADEID_AFPFILEI      14 /* where the rest of the FILEI info goes */
74 #define ADEID_DID           15
75
76 /* netatalk private note fileid reused DID */
77 #define ADEID_PRIVDEV       16
78 #define ADEID_PRIVINO       17
79 #define ADEID_PRIVSYN       18 /* in synch with database */
80 #define ADEID_PRIVID        19
81 #define ADEID_MAX           (ADEID_PRIVID + 1)
82
83 /* These are the real ids for these entries, as stored in the adouble file */
84 #define AD_DEV              0x80444556
85 #define AD_INO              0x80494E4F
86 #define AD_SYN              0x8053594E
87 #define AD_ID               0x8053567E
88
89 /* magic */
90 #define AD_APPLESINGLE_MAGIC 0x00051600
91 #define AD_APPLEDOUBLE_MAGIC 0x00051607
92 #define AD_MAGIC             AD_APPLEDOUBLE_MAGIC
93
94 /* sizes of relevant entry bits */
95 #define ADEDLEN_MAGIC       4
96 #define ADEDLEN_VERSION     4
97 #define ADEDLEN_FILLER      16
98 #define ADEDLEN_NENTRIES    2
99 #define AD_HEADER_LEN       (ADEDLEN_MAGIC + ADEDLEN_VERSION + ADEDLEN_FILLER + ADEDLEN_NENTRIES)
100 #define AD_ENTRY_LEN        12  /* size of a single entry header */
101
102 /* field widths */
103 #define ADEDLEN_NAME            255
104 #define ADEDLEN_COMMENT         200
105 #define ADEDLEN_FILEI           16
106 #define ADEDLEN_FINDERI         32
107 #define ADEDLEN_FILEDATESI      16
108 #define ADEDLEN_SHORTNAME       12 /* length up to 8.3 */
109 #define ADEDLEN_AFPFILEI        4
110 #define ADEDLEN_MACFILEI        4
111 #define ADEDLEN_PRODOSFILEI     8
112 #define ADEDLEN_MSDOSFILEI      2
113 #define ADEDLEN_DID             4
114 #define ADEDLEN_PRIVDEV         8
115 #define ADEDLEN_PRIVINO         8
116 #define ADEDLEN_PRIVSYN         8
117 #define ADEDLEN_PRIVID          4
118
119 #define ADEID_NUM_V2            13
120 #define ADEID_NUM_EA            5
121
122 #define AD_DATASZ2 (AD_HEADER_LEN + ADEDLEN_NAME + ADEDLEN_COMMENT + ADEDLEN_FILEI + \
123                     ADEDLEN_FINDERI + ADEDLEN_DID + ADEDLEN_AFPFILEI + ADEDLEN_SHORTNAME + \
124                     ADEDLEN_PRODOSFILEI + ADEDLEN_PRIVDEV + ADEDLEN_PRIVINO + \
125                     ADEDLEN_PRIVSYN + ADEDLEN_PRIVID + (ADEID_NUM_V2 * AD_ENTRY_LEN))
126 #if AD_DATASZ2 != 741
127 #error bad size for AD_DATASZ2
128 #endif
129
130 #define AD_DATASZ_EA (AD_HEADER_LEN + (ADEID_NUM_EA * AD_ENTRY_LEN) + ADEDLEN_FINDERI + \
131                       ADEDLEN_COMMENT + ADEDLEN_FILEDATESI + ADEDLEN_AFPFILEI + ADEDLEN_PRIVID)
132
133 #if AD_DATASZ_EA != 342
134 #error bad size for AD_DATASZ_EA
135 #endif
136
137 #define AD_DATASZ_MAX   1024
138
139 #if AD_VERSION == AD_VERSION2
140 #define AD_DATASZ   AD_DATASZ2
141 #elif AD_VERSION == AD_VERSION_EA
142 #define AD_DATASZ   AD_DATASZ_EA
143 #endif
144
145 #define RFORK_EA_ALLOCSIZE (128*1024) /* 128k */
146
147 typedef uint32_t cnid_t;
148
149 struct ad_entry {
150     off_t     ade_off;
151     ssize_t   ade_len;
152 };
153
154 typedef struct adf_lock_t {
155     struct flock lock;
156     int user;
157     int *refcount; /* handle read locks with multiple users */
158 } adf_lock_t;
159
160 struct ad_fd {
161     int          adf_fd;        /* -1: invalid, -2: symlink */
162     char         *adf_syml;
163     int          adf_flags;
164     int          adf_excl;
165     adf_lock_t   *adf_lock;
166     int          adf_refcount, adf_lockcount, adf_lockmax;
167 };
168
169 /* some header protection */
170 #define AD_INITED  0xad494e54  /* ad"INT" */
171 #define AD_CLOSED  0xadc10ced
172
173 struct adouble;
174
175 struct adouble_fops {
176     const char *(*ad_path)(const char *, int);
177     int  (*ad_mkrf)(const char *);
178     int  (*ad_rebuild_header)(struct adouble *);
179     int  (*ad_header_read)(struct adouble *, struct stat *);
180     int  (*ad_header_upgrade)(struct adouble *, const char *);
181 };
182
183 struct adouble {
184     uint32_t            ad_magic;         /* Official adouble magic                   */
185     uint32_t            ad_version;       /* Official adouble version number          */
186     char                ad_filler[16];
187     struct ad_entry     ad_eid[ADEID_MAX];
188     struct ad_fd        ad_data_fork;     /* the data fork                            */
189     struct ad_fd        ad_resource_fork; /* adouble:v2 -> the adouble file           *
190                                            * adouble:ea -> unused                     */
191     struct ad_fd        *ad_rfp;          /* adouble:v2 -> ad_resource_fork           *
192                                            * adouble:ea -> ad_data_fork               */
193     struct ad_fd        *ad_mdp;          /* adouble:v2 -> ad_resource_fork           *
194                                            * adouble:ea -> ad_data_fork               */
195     int                 ad_flags;         /* Our adouble version info (AD_VERSION*)   */
196     int                 ad_adflags;       /* ad_open flags adflags like ADFLAGS_DIR   */
197     uint32_t            ad_inited;
198     int                 ad_options;
199     int                 ad_refcount;       /* multiple forks may open one adouble     */
200     void                *ad_resforkbuf;    /* buffer for AD_VERSION_EA ressource fork */
201     size_t              ad_resforkbufsize; /* size of ad_resforkbuf                   */
202     off_t               ad_rlen;           /* ressource fork len with AFP 3.0         *
203                                             * the header parameter size is too small. */
204     char                *ad_m_name;        /* mac name for open fork                  */
205     int                 ad_m_namelen;
206     struct adouble_fops *ad_ops;
207     uint16_t            ad_open_forks;     /* open forks (by others)                  */
208     char                ad_data[AD_DATASZ_MAX];
209 };
210
211 #define ADFLAGS_DF        (1<<0)
212 #define ADFLAGS_RF        (1<<1)
213 #define ADFLAGS_HF        (1<<2)
214 #define ADFLAGS_DIR       (1<<3)
215 #define ADFLAGS_NOHF      (1<<4)  /* not an error if no ressource fork */
216 #define ADFLAGS_CHECK_OF  (1<<6)  /* check for open forks from us and other afpd's */
217 #define ADFLAGS_SETSHRMD  (1<<7)  /* setting share mode must be done with excl fcnt lock,
218                                      which implies that the file must be openend rw.
219                                      If it can't be opened rw (eg EPERM or EROFS) it will
220                                      be opened ro and the fcntl locks will be shared, that
221                                      at least prevent other users who have rw access to the
222                                      file from placing excl locks. */
223 #define ADFLAGS_RDWR      (1<<8)  /* open read/write */
224 #define ADFLAGS_RDONLY    (1<<9)  /* open read only */
225 #define ADFLAGS_CREATE    (1<<10)  /* create file, open called with O_CREAT */
226 #define ADFLAGS_EXCL      (1<<11)  /* exclusive open, open called with O_EXCL */
227 #define ADFLAGS_TRUNC     (1<<12) /* truncate, open called with O_TRUNC */
228
229 #define ADVOL_NODEV      (1 << 0)
230 #define ADVOL_CACHE      (1 << 1)
231 #define ADVOL_UNIXPRIV   (1 << 2) /* adouble unix priv */
232 #define ADVOL_INVDOTS    (1 << 3) /* dot files (.DS_Store) are invisible) */
233 #define ADVOL_NOADOUBLE  (1 << 4)
234
235 /* lock flags */
236 #define ADLOCK_CLR      (0)
237 #define ADLOCK_RD       (1<<0)
238 #define ADLOCK_WR       (1<<1)
239 #define ADLOCK_MASK     (ADLOCK_RD | ADLOCK_WR)
240 #define ADLOCK_UPGRADE  (1<<2)
241 #define ADLOCK_FILELOCK (1<<3)
242
243 /* we use this so that we can use the same mechanism for both byte
244  * locks and file synchronization locks. */
245 #if _FILE_OFFSET_BITS == 64
246 #define AD_FILELOCK_BASE (UINT64_C(0x7FFFFFFFFFFFFFFF) - 9)
247 #else
248 #define AD_FILELOCK_BASE (UINT32_C(0x7FFFFFFF) - 9)
249 #endif
250
251 #define BYTELOCK_MAX (AD_FILELOCK_BASE - 1)
252
253 #define AD_FILELOCK_OPEN_WR        (AD_FILELOCK_BASE + 0)
254 #define AD_FILELOCK_OPEN_RD        (AD_FILELOCK_BASE + 1)
255 #define AD_FILELOCK_DENY_WR        (AD_FILELOCK_BASE + 2)
256 #define AD_FILELOCK_DENY_RD        (AD_FILELOCK_BASE + 3)
257 #define AD_FILELOCK_OPEN_NONE      (AD_FILELOCK_BASE + 4)
258
259 /* time stuff. we overload the bits a little.  */
260 #define AD_DATE_CREATE         0
261 #define AD_DATE_MODIFY         4
262 #define AD_DATE_BACKUP         8
263 #define AD_DATE_ACCESS        12
264 #define AD_DATE_MASK          (AD_DATE_CREATE | AD_DATE_MODIFY | \
265                               AD_DATE_BACKUP | AD_DATE_ACCESS)
266 #define AD_DATE_UNIX          (1 << 10)
267 #define AD_DATE_START         htonl(0x80000000)
268 #define AD_DATE_DELTA         946684800
269 #define AD_DATE_FROM_UNIX(x)  htonl((x) - AD_DATE_DELTA)
270 #define AD_DATE_TO_UNIX(x)    (ntohl(x) + AD_DATE_DELTA)
271
272 /* various finder offset and info bits */
273 #define FINDERINFO_FRTYPEOFF   0
274 #define FINDERINFO_FRCREATOFF  4
275 #define FINDERINFO_FRFLAGOFF   8
276
277 /* FinderInfo Flags, char in `ad ls`, valid for files|dirs */
278 #define FINDERINFO_ISONDESK      (1)     /* "d", fd */
279 #define FINDERINFO_COLOR         (0x0e)
280 #define FINDERINFO_HIDEEXT       (1<<4)  /* "e", fd */
281 #define FINDERINFO_ISHARED       (1<<6)  /* "m", f  */
282 #define FINDERINFO_HASNOINITS    (1<<7)  /* "n", f  */
283 #define FINDERINFO_HASBEENINITED (1<<8)  /* "i", fd */
284 #define FINDERINFO_HASCUSTOMICON (1<<10) /* "c", fd */
285 #define FINDERINFO_ISSTATIONNERY (1<<11) /* "t", f  */
286 #define FINDERINFO_NAMELOCKED    (1<<12) /* "s", fd */
287 #define FINDERINFO_HASBUNDLE     (1<<13) /* "b", fd */
288 #define FINDERINFO_INVISIBLE     (1<<14) /* "v", fd */
289 #define FINDERINFO_ISALIAS       (1<<15) /* "a", fd */
290
291 #define FINDERINFO_FRVIEWOFF  14
292 #define FINDERINFO_CUSTOMICON 0x4
293 #define FINDERINFO_CLOSEDVIEW 0x100
294
295 /*
296   The "shared" and "invisible" attributes are opaque and stored and
297   retrieved from the FinderFlags. This fixes Bug #2802236:
298   <https://sourceforge.net/tracker/?func=detail&aid=2802236&group_id=8642&atid=108642>
299 */
300
301 /* AFP attributes, char in `ad ls`, valid for files|dirs */
302 #define ATTRBIT_INVISIBLE (1<<0)  /* opaque from FinderInfo */
303 #define ATTRBIT_MULTIUSER (1<<1)  /* file: opaque, dir: see below */
304 #define ATTRBIT_SYSTEM    (1<<2)  /* "y", fd */
305 #define ATTRBIT_DOPEN     (1<<3)  /* data fork already open. Not stored, computed on the fly */
306 #define ATTRBIT_ROPEN     (1<<4)  /* resource fork already open. Not stored, computed on the fly */
307 #define ATTRBIT_NOWRITE   (1<<5)  /* "w", f, write inhibit(v2)/read-only(v1) bit */
308 #define ATTRBIT_BACKUP    (1<<6)  /* "p", fd */
309 #define ATTRBIT_NORENAME  (1<<7)  /* "r", fd */
310 #define ATTRBIT_NODELETE  (1<<8)  /* "l", fd */
311 #define ATTRBIT_NOCOPY    (1<<10) /* "o", f */
312 #define ATTRBIT_SETCLR    (1<<15) /* set/clear bit (d) */
313
314 /* AFP attributes for dirs. These should probably be computed on the fly.
315  * We don't do that, nor does e.g. OS S X 10.5 Server */
316 #define ATTRBIT_EXPFLDR   (1<<1)  /* Folder is a sharepoint */
317 #define ATTRBIT_MOUNTED   (1<<3)  /* Directory is mounted by a user */
318 #define ATTRBIT_SHARED    (1<<4)  /* Shared area, called IsExpFolder in spec */
319
320 /* private AFPFileInfo bits */
321 #define AD_AFPFILEI_OWNER       (1 << 0) /* any owner */
322 #define AD_AFPFILEI_GROUP       (1 << 1) /* ignore group */
323 #define AD_AFPFILEI_BLANKACCESS (1 << 2) /* blank access permissions */
324
325 #define ad_data_fileno(ad)  ((ad)->ad_data_fork.adf_fd)
326 #define ad_reso_fileno(ad)  ((ad)->ad_rfp->adf_fd)
327 #define ad_meta_fileno(ad)  ((ad)->ad_mdp->adf_fd)
328
329 #define ad_getversion(ad)   ((ad)->ad_version)
330
331 #define ad_getentrylen(ad,eid)     ((ad)->ad_eid[(eid)].ade_len)
332 #define ad_setentrylen(ad,eid,len) ((ad)->ad_eid[(eid)].ade_len = (len))
333 #define ad_getentryoff(ad,eid)     ((ad)->ad_eid[(eid)].ade_off)
334 #define ad_entry(ad,eid)           ((caddr_t)(ad)->ad_data + (ad)->ad_eid[(eid)].ade_off)
335
336 #define ad_get_RF_flags(ad) ((ad)->ad_rfp->adf_flags)
337 #define ad_get_MD_flags(ad) ((ad)->ad_mdp->adf_flags)
338
339 /* Refcounting open forks using one struct adouble */
340 #define ad_ref(ad)   (ad)->ad_refcount++
341 #define ad_unref(ad) --((ad)->ad_refcount)
342
343 /* ad_flush.c */
344 extern int ad_rebuild_adouble_header (struct adouble *);
345 extern int ad_rebuild_sfm_header (struct adouble *);
346 extern int ad_copy_header (struct adouble *, struct adouble *);
347 extern int ad_flush (struct adouble *);
348 extern int ad_close (struct adouble *, int);
349
350 /* ad_lock.c */
351 extern int ad_testlock      (struct adouble *adp, int eid, off_t off);
352 extern uint16_t ad_openforks(struct adouble *adp, uint16_t);
353 extern int ad_excl_lock     (struct adouble *adp, uint32_t eid);
354
355 extern int ad_lock(struct adouble *, uint32_t eid, int type, off_t off, off_t len, int user);
356 extern void ad_unlock(struct adouble *, int user);
357 extern int ad_tmplock(struct adouble *, uint32_t eid, int type, off_t off, off_t len, int user);
358
359 /* ad_open.c */
360 extern const char *adflags2logstr(int adflags);
361 extern int ad_setfuid     (const uid_t );
362 extern uid_t ad_getfuid   (void );
363 extern char *ad_dir       (const char *);
364 extern const char *ad_path      (const char *, int);
365 extern const char *ad_path_ea   (const char *, int);
366 extern int ad_mode        (const char *, int);
367 extern int ad_mkdir       (const char *, int);
368 extern void ad_init       (struct adouble *, int, int );
369 extern int ad_open        (struct adouble *ad, const char *path, int adflags, ...);
370 extern int ad_openat      (struct adouble *, int dirfd, const char *path, int adflags, ...);
371 extern int ad_refresh     (struct adouble *);
372 extern int ad_stat        (const char *, struct stat *);
373 extern int ad_metadata    (const char *, int, struct adouble *);
374 extern int ad_metadataat  (int, const char *, int, struct adouble *);
375
376 /* build a resource fork mode from the data fork mode:
377  * remove X mode and extend header to RW if R or W (W if R for locking),
378  */
379 static inline mode_t ad_hf_mode (mode_t mode)
380 {
381     mode &= ~(S_IXUSR | S_IXGRP | S_IXOTH);
382     /* fnctl lock need write access */
383     if ((mode & S_IRUSR))
384         mode |= S_IWUSR;
385     if ((mode & S_IRGRP))
386         mode |= S_IWGRP;
387     if ((mode & S_IROTH))
388         mode |= S_IWOTH;
389
390     /* if write mode set add read mode */
391     if ((mode & S_IWUSR))
392         mode |= S_IRUSR;
393     if ((mode & S_IWGRP))
394         mode |= S_IRGRP;
395     if ((mode & S_IWOTH))
396         mode |= S_IROTH;
397
398     return mode;
399 }
400
401 /* ad_read.c/ad_write.c */
402 extern int     sys_ftruncate(int fd, off_t length);
403 extern ssize_t ad_read(struct adouble *, uint32_t, off_t, char *, size_t);
404 extern ssize_t ad_pread(struct ad_fd *, void *, size_t, off_t);
405 extern ssize_t ad_write(struct adouble *, uint32_t, off_t, int, const char *, size_t);
406 extern ssize_t adf_pread(struct ad_fd *, void *, size_t, off_t);
407 extern ssize_t adf_pwrite(struct ad_fd *, const void *, size_t, off_t);
408 extern int     ad_dtruncate(struct adouble *, off_t);
409 extern int     ad_rtruncate(struct adouble *, off_t);
410
411 /* ad_size.c */
412 extern off_t ad_size (const struct adouble *, uint32_t );
413
414 /* ad_mmap.c */
415 extern void *ad_mmapread(struct adouble *, uint32_t, off_t, size_t);
416 extern void *ad_mmapwrite(struct adouble *, uint32_t, off_t, int, size_t);
417 #define ad_munmap(buf, len)  (munmap((buf), (len)))
418
419 /* ad_date.c */
420 extern int ad_setdate(struct adouble *, unsigned int, uint32_t);
421 extern int ad_getdate(const struct adouble *, unsigned int, uint32_t *);
422
423 /* ad_attr.c */
424 extern int       ad_setattr(const struct adouble *, uint16_t);
425 extern int       ad_getattr(const struct adouble *, uint16_t *);
426 extern int       ad_setname(struct adouble *, const char *);
427 extern int       ad_setid(struct adouble *, dev_t dev, ino_t ino, uint32_t, uint32_t, const void *);
428 extern uint32_t  ad_getid(struct adouble *, dev_t, ino_t, cnid_t, const void *);
429 extern uint32_t  ad_forcegetid(struct adouble *adp);
430
431 #ifdef WITH_SENDFILE
432 extern int ad_readfile_init(const struct adouble *ad, int eid, off_t *off, int end);
433 #endif
434
435 #endif /* _ATALK_ADOUBLE_H */