2 * Copyright (c) 1990,1991 Regents of The University of Michigan.
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.
15 * Research Systems Unix Group
16 * The University of Michigan
18 * 535 W. William Street
21 * netatalk@itd.umich.edu
26 * @brief Part of Netatalk's AppleDouble implementatation
29 #ifndef _ATALK_ADOUBLE_H
30 #define _ATALK_ADOUBLE_H
36 #include <atalk/standards.h>
39 #include <sys/types.h>
48 #include <atalk/bstrlib.h>
51 #define AD_VERSION2 0x00020000
52 #define AD_VERSION_EA 0x00020002
55 #define AD_VERSION AD_VERSION2
58 * AppleDouble entry IDs.
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 */
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)
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
90 #define AD_APPLESINGLE_MAGIC 0x00051600
91 #define AD_APPLEDOUBLE_MAGIC 0x00051607
92 #define AD_MAGIC AD_APPLEDOUBLE_MAGIC
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 */
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
119 #define ADEID_NUM_V2 13
120 #define ADEID_NUM_EA 5
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
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)
133 #if AD_DATASZ_EA != 342
134 #error bad size for AD_DATASZ_EA
137 #define AD_DATASZ_MAX 1024
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
145 #define RFORK_EA_ALLOCSIZE (128*1024) /* 128k */
147 typedef uint32_t cnid_t;
154 typedef struct adf_lock_t {
157 int *refcount; /* handle read locks with multiple users */
161 int adf_fd; /* -1: invalid, -2: symlink */
164 adf_lock_t *adf_lock;
165 int adf_refcount, adf_lockcount, adf_lockmax;
168 /* some header protection */
169 #define AD_INITED 0xad494e54 /* ad"INT" */
170 #define AD_CLOSED 0xadc10ced
174 struct adouble_fops {
175 const char *(*ad_path)(const char *, int);
176 int (*ad_mkrf)(const char *);
177 int (*ad_rebuild_header)(struct adouble *);
178 int (*ad_header_read)(struct adouble *, struct stat *);
179 int (*ad_header_upgrade)(struct adouble *, const char *);
183 uint32_t ad_magic; /* Official adouble magic */
184 uint32_t ad_version; /* Official adouble version number */
186 struct ad_entry ad_eid[ADEID_MAX];
187 struct ad_fd ad_data_fork; /* the data fork */
188 struct ad_fd ad_resource_fork; /* adouble:v2 -> the adouble file *
189 * adouble:ea -> unused */
190 struct ad_fd *ad_rfp; /* adouble:v2 -> ad_resource_fork *
191 * adouble:ea -> ad_data_fork */
192 struct ad_fd *ad_mdp; /* adouble:v2 -> ad_resource_fork *
193 * adouble:ea -> ad_data_fork */
194 int ad_vers; /* Our adouble version info (AD_VERSION*) */
195 int ad_adflags; /* ad_open flags adflags like ADFLAGS_DIR */
198 int ad_refcount; /* multiple forks may open one adouble */
199 void *ad_resforkbuf; /* buffer for AD_VERSION_EA ressource fork */
200 size_t ad_resforkbufsize; /* size of ad_resforkbuf */
201 size_t ad_maxeafssize; /* maximum EA size allowed from the fs */
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 */
206 struct adouble_fops *ad_ops;
207 uint16_t ad_open_forks; /* open forks (by others) */
208 char ad_data[AD_DATASZ_MAX];
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 */
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)
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)
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)
248 #define AD_FILELOCK_BASE (UINT32_C(0x7FFFFFFF) - 9)
251 #define BYTELOCK_MAX (AD_FILELOCK_BASE - 1)
253 /* datafork and rsrcfork sharemode locks */
254 #define AD_FILELOCK_OPEN_WR (AD_FILELOCK_BASE + 0)
255 #define AD_FILELOCK_OPEN_RD (AD_FILELOCK_BASE + 1)
256 #define AD_FILELOCK_RSRC_OPEN_WR (AD_FILELOCK_BASE + 2)
257 #define AD_FILELOCK_RSRC_OPEN_RD (AD_FILELOCK_BASE + 3)
259 #define AD_FILELOCK_DENY_WR (AD_FILELOCK_BASE + 4)
260 #define AD_FILELOCK_DENY_RD (AD_FILELOCK_BASE + 5)
261 #define AD_FILELOCK_RSRC_DENY_WR (AD_FILELOCK_BASE + 6)
262 #define AD_FILELOCK_RSRC_DENY_RD (AD_FILELOCK_BASE + 7)
265 #define AD_FILELOCK_OPEN_NONE (AD_FILELOCK_BASE + 8)
266 #define AD_FILELOCK_RSRC_OPEN_NONE (AD_FILELOCK_BASE + 9)
268 /* time stuff. we overload the bits a little. */
269 #define AD_DATE_CREATE 0
270 #define AD_DATE_MODIFY 4
271 #define AD_DATE_BACKUP 8
272 #define AD_DATE_ACCESS 12
273 #define AD_DATE_MASK (AD_DATE_CREATE | AD_DATE_MODIFY | \
274 AD_DATE_BACKUP | AD_DATE_ACCESS)
275 #define AD_DATE_UNIX (1 << 10)
276 #define AD_DATE_START htonl(0x80000000)
277 #define AD_DATE_DELTA 946684800
278 #define AD_DATE_FROM_UNIX(x) htonl((x) - AD_DATE_DELTA)
279 #define AD_DATE_TO_UNIX(x) (ntohl(x) + AD_DATE_DELTA)
281 /* various finder offset and info bits */
282 #define FINDERINFO_FRTYPEOFF 0
283 #define FINDERINFO_FRCREATOFF 4
284 #define FINDERINFO_FRFLAGOFF 8
286 /* FinderInfo Flags, char in `ad ls`, valid for files|dirs */
287 #define FINDERINFO_ISONDESK (1) /* "d", fd */
288 #define FINDERINFO_COLOR (0x0e)
289 #define FINDERINFO_HIDEEXT (1<<4) /* "e", fd */
290 #define FINDERINFO_ISHARED (1<<6) /* "m", f */
291 #define FINDERINFO_HASNOINITS (1<<7) /* "n", f */
292 #define FINDERINFO_HASBEENINITED (1<<8) /* "i", fd */
293 #define FINDERINFO_HASCUSTOMICON (1<<10) /* "c", fd */
294 #define FINDERINFO_ISSTATIONNERY (1<<11) /* "t", f */
295 #define FINDERINFO_NAMELOCKED (1<<12) /* "s", fd */
296 #define FINDERINFO_HASBUNDLE (1<<13) /* "b", fd */
297 #define FINDERINFO_INVISIBLE (1<<14) /* "v", fd */
298 #define FINDERINFO_ISALIAS (1<<15) /* "a", fd */
300 #define FINDERINFO_FRVIEWOFF 14
301 #define FINDERINFO_CUSTOMICON 0x4
302 #define FINDERINFO_CLOSEDVIEW 0x100
305 The "shared" and "invisible" attributes are opaque and stored and
306 retrieved from the FinderFlags. This fixes Bug #2802236:
307 <https://sourceforge.net/tracker/?func=detail&aid=2802236&group_id=8642&atid=108642>
310 /* AFP attributes, char in `ad ls`, valid for files|dirs */
311 #define ATTRBIT_INVISIBLE (1<<0) /* opaque from FinderInfo */
312 #define ATTRBIT_MULTIUSER (1<<1) /* file: opaque, dir: see below */
313 #define ATTRBIT_SYSTEM (1<<2) /* "y", fd */
314 #define ATTRBIT_DOPEN (1<<3) /* data fork already open. Not stored, computed on the fly */
315 #define ATTRBIT_ROPEN (1<<4) /* resource fork already open. Not stored, computed on the fly */
316 #define ATTRBIT_NOWRITE (1<<5) /* "w", f, write inhibit(v2)/read-only(v1) bit */
317 #define ATTRBIT_BACKUP (1<<6) /* "p", fd */
318 #define ATTRBIT_NORENAME (1<<7) /* "r", fd */
319 #define ATTRBIT_NODELETE (1<<8) /* "l", fd */
320 #define ATTRBIT_NOCOPY (1<<10) /* "o", f */
321 #define ATTRBIT_SETCLR (1<<15) /* set/clear bit (d) */
323 /* AFP attributes for dirs. These should probably be computed on the fly.
324 * We don't do that, nor does e.g. OS S X 10.5 Server */
325 #define ATTRBIT_EXPFLDR (1<<1) /* Folder is a sharepoint */
326 #define ATTRBIT_MOUNTED (1<<3) /* Directory is mounted by a user */
327 #define ATTRBIT_SHARED (1<<4) /* Shared area, called IsExpFolder in spec */
329 /* private AFPFileInfo bits */
330 #define AD_AFPFILEI_OWNER (1 << 0) /* any owner */
331 #define AD_AFPFILEI_GROUP (1 << 1) /* ignore group */
332 #define AD_AFPFILEI_BLANKACCESS (1 << 2) /* blank access permissions */
334 #define ad_data_fileno(ad) ((ad)->ad_data_fork.adf_fd)
335 #define ad_reso_fileno(ad) ((ad)->ad_rfp->adf_fd)
336 #define ad_meta_fileno(ad) ((ad)->ad_mdp->adf_fd)
338 #define AD_DATA_OPEN(ad) ((ad)->ad_adflags & ADFLAGS_DF)
339 #define AD_META_OPEN(ad) ((ad)->ad_adflags & ADFLAGS_HF)
340 #define AD_RSRC_OPEN(ad) ((ad)->ad_adflags & ADFLAGS_RF)
342 #define ad_getversion(ad) ((ad)->ad_version)
344 #define ad_getentrylen(ad,eid) ((ad)->ad_eid[(eid)].ade_len)
345 #define ad_setentrylen(ad,eid,len) ((ad)->ad_eid[(eid)].ade_len = (len))
346 #define ad_getentryoff(ad,eid) ((ad)->ad_eid[(eid)].ade_off)
347 #define ad_entry(ad,eid) ((caddr_t)(ad)->ad_data + (ad)->ad_eid[(eid)].ade_off)
349 #define ad_get_RF_flags(ad) ((ad)->ad_rfp->adf_flags)
350 #define ad_get_MD_flags(ad) ((ad)->ad_mdp->adf_flags)
352 /* Refcounting open forks using one struct adouble */
353 #define ad_ref(ad) (ad)->ad_refcount++
354 #define ad_unref(ad) --((ad)->ad_refcount)
357 extern int ad_rebuild_adouble_header (struct adouble *);
358 extern int ad_rebuild_sfm_header (struct adouble *);
359 extern int ad_copy_header (struct adouble *, struct adouble *);
360 extern int ad_flush (struct adouble *);
361 extern int ad_close (struct adouble *, int);
362 extern int fsetrsrcea(struct adouble *ad, int fd, const char *eaname, const void *value, size_t size, int flags);
365 extern int ad_testlock (struct adouble *adp, int eid, off_t off);
366 extern uint16_t ad_openforks(struct adouble *adp, uint16_t);
367 extern int ad_lock(struct adouble *, uint32_t eid, int type, off_t off, off_t len, int user);
368 extern void ad_unlock(struct adouble *, int user);
369 extern int ad_tmplock(struct adouble *, uint32_t eid, int type, off_t off, off_t len, int user);
372 extern const char *adflags2logstr(int adflags);
373 extern int ad_setfuid (const uid_t );
374 extern uid_t ad_getfuid (void );
375 extern char *ad_dir (const char *);
376 extern const char *ad_path (const char *, int);
377 extern const char *ad_path_ea (const char *, int);
378 extern int ad_mode (const char *, mode_t);
379 extern int ad_mkdir (const char *, mode_t);
381 extern void ad_init (struct adouble *, const struct vol * restrict);
382 extern void ad_init_old (struct adouble *ad, int flags, int options);
383 extern int ad_open (struct adouble *ad, const char *path, int adflags, ...);
384 extern int ad_openat (struct adouble *, int dirfd, const char *path, int adflags, ...);
385 extern int ad_refresh (struct adouble *);
386 extern int ad_stat (const char *, struct stat *);
387 extern int ad_metadata (const char *, int, struct adouble *);
388 extern int ad_metadataat (int, const char *, int, struct adouble *);
390 /* build a resource fork mode from the data fork mode:
391 * remove X mode and extend header to RW if R or W (W if R for locking),
393 static inline mode_t ad_hf_mode (mode_t mode)
395 mode &= ~(S_IXUSR | S_IXGRP | S_IXOTH);
396 /* fnctl lock need write access */
397 if ((mode & S_IRUSR))
399 if ((mode & S_IRGRP))
401 if ((mode & S_IROTH))
404 /* if write mode set add read mode */
405 if ((mode & S_IWUSR))
407 if ((mode & S_IWGRP))
409 if ((mode & S_IWOTH))
415 /* ad_read.c/ad_write.c */
416 extern int sys_ftruncate(int fd, off_t length);
417 extern ssize_t ad_read(struct adouble *, uint32_t, off_t, char *, size_t);
418 extern ssize_t ad_pread(struct ad_fd *, void *, size_t, off_t);
419 extern ssize_t ad_write(struct adouble *, uint32_t, off_t, int, const char *, size_t);
420 extern ssize_t adf_pread(struct ad_fd *, void *, size_t, off_t);
421 extern ssize_t adf_pwrite(struct ad_fd *, const void *, size_t, off_t);
422 extern int ad_dtruncate(struct adouble *, off_t);
423 extern int ad_rtruncate(struct adouble *, off_t);
426 extern off_t ad_size (const struct adouble *, uint32_t );
429 extern void *ad_mmapread(struct adouble *, uint32_t, off_t, size_t);
430 extern void *ad_mmapwrite(struct adouble *, uint32_t, off_t, int, size_t);
431 #define ad_munmap(buf, len) (munmap((buf), (len)))
434 extern int ad_setdate(struct adouble *, unsigned int, uint32_t);
435 extern int ad_getdate(const struct adouble *, unsigned int, uint32_t *);
438 extern int ad_setattr(const struct adouble *, uint16_t);
439 extern int ad_getattr(const struct adouble *, uint16_t *);
440 extern int ad_setname(struct adouble *, const char *);
441 extern int ad_setid(struct adouble *, dev_t dev, ino_t ino, uint32_t, uint32_t, const void *);
442 extern uint32_t ad_getid(struct adouble *, dev_t, ino_t, cnid_t, const void *);
443 extern uint32_t ad_forcegetid(struct adouble *adp);
446 extern int ad_readfile_init(const struct adouble *ad, int eid, off_t *off, int end);
449 #endif /* _ATALK_ADOUBLE_H */