1ddaa4e7dStsutsui /*
2ddaa4e7dStsutsui ** Unix-HFS file interface including maping file extensions to TYPE/CREATOR
3ddaa4e7dStsutsui **
4ddaa4e7dStsutsui ** Adapted from mkhfs routines for mkhybrid
5ddaa4e7dStsutsui **
6ddaa4e7dStsutsui ** James Pearson 1/5/97
7ddaa4e7dStsutsui ** Bug fix JCP 4/12/97
8ddaa4e7dStsutsui ** Updated for 1.12 and added more Unix HFS filetypes. JCP 21/1/98
9ddaa4e7dStsutsui **
10ddaa4e7dStsutsui ** Things still to de done:
11ddaa4e7dStsutsui **
12ddaa4e7dStsutsui ** Check SGI (XINET) structs
13ddaa4e7dStsutsui ** Check file size = finder + rsrc [+ data] is needed
14ddaa4e7dStsutsui ** AppleSingle/Double version 2?
15ddaa4e7dStsutsui ** Clean up byte order swapping.
16ddaa4e7dStsutsui */
17ddaa4e7dStsutsui
18ddaa4e7dStsutsui #ifdef APPLE_HYB
19ddaa4e7dStsutsui
20ddaa4e7dStsutsui #include <ctype.h>
21ddaa4e7dStsutsui #include <errno.h>
22ddaa4e7dStsutsui #include <unistd.h>
23ddaa4e7dStsutsui #include <err.h>
24ddaa4e7dStsutsui #include <fcntl.h>
25ddaa4e7dStsutsui #include <config.h>
26ddaa4e7dStsutsui #include <stdlib.h>
27ddaa4e7dStsutsui #include <sys/types.h>
28ddaa4e7dStsutsui #include <netinet/in.h>
29ddaa4e7dStsutsui #include <apple.h>
30ddaa4e7dStsutsui #include "apple_proto.h"
31ddaa4e7dStsutsui #include <mkisofs.h>
32ddaa4e7dStsutsui
33ddaa4e7dStsutsui /* tidy up mkisofs definition ... */
34ddaa4e7dStsutsui typedef struct directory_entry dir_ent;
35ddaa4e7dStsutsui
36ddaa4e7dStsutsui /* routines for getting HFS names and info */
37a11dc48bStsutsui static int get_none_dir(char *, const char *, dir_ent *, int);
38ddaa4e7dStsutsui static int get_none_info(char *, char *, dir_ent *, int);
39a11dc48bStsutsui static int get_cap_dir(char *, const char *, dir_ent *, int);
40ddaa4e7dStsutsui static int get_cap_info(char *, char *, dir_ent *, int);
41ddaa4e7dStsutsui static int get_es_info(char *, char *, dir_ent *, int);
42ddaa4e7dStsutsui static int get_dbl_info(char *, char *, dir_ent *, int);
43ddaa4e7dStsutsui static int get_mb_info(char *, char *, dir_ent *, int);
44ddaa4e7dStsutsui static int get_sgl_info(char *, char *, dir_ent *, int);
45a11dc48bStsutsui static int get_fe_dir(char *, const char *, dir_ent *, int);
46ddaa4e7dStsutsui static int get_fe_info(char *, char *, dir_ent *, int);
47a11dc48bStsutsui static int get_sgi_dir(char *, const char *, dir_ent *, int);
48ddaa4e7dStsutsui static int get_sgi_info(char *, char *, dir_ent *, int);
49ddaa4e7dStsutsui
50ddaa4e7dStsutsui void map_ext(char *, char **, char **, unsigned short *, char *);
51ddaa4e7dStsutsui static afpmap **map; /* list of mappings */
52ddaa4e7dStsutsui static afpmap *defmap; /* the default mapping */
53ddaa4e7dStsutsui static int last_ent; /* previous mapped entry */
54ddaa4e7dStsutsui static int map_num; /* number of mappings */
55ddaa4e7dStsutsui static int mlen; /* min extension length */
56ddaa4e7dStsutsui static char tmp[MAXPATHLEN]; /* tmp working buffer */
57ddaa4e7dStsutsui static int hfs_num; /* number of file types */
58ddaa4e7dStsutsui static char p_buf[MAXPATHLEN]; /* info working buffer */
59ddaa4e7dStsutsui static FILE *p_fp = NULL; /* probe File pointer */
60ddaa4e7dStsutsui static int p_num = 0; /* probe bytes read */
61ddaa4e7dStsutsui static unsigned int hselect; /* type of HFS file selected */
62ddaa4e7dStsutsui
63ddaa4e7dStsutsui struct hfs_type { /* Types of various HFS Unix files */
64ddaa4e7dStsutsui int type; /* type of file */
65ddaa4e7dStsutsui int flags; /* special flags */
66a11dc48bStsutsui const char *info; /* finderinfo name */
67a11dc48bStsutsui const char *rsrc; /* resource fork name */
68ddaa4e7dStsutsui int (*get_info)(char*, char*, dir_ent*,int); /* finderinfo function */
69a11dc48bStsutsui int (*get_dir)(char*, const char*,dir_ent*,int); /* directory name function */
70a11dc48bStsutsui const char *desc; /* description */
71ddaa4e7dStsutsui };
72ddaa4e7dStsutsui
73ddaa4e7dStsutsui /* Above filled in */
74ddaa4e7dStsutsui static struct hfs_type hfs_types[] = {
75ddaa4e7dStsutsui {TYPE_NONE,0,"", "", get_none_info, get_none_dir,"None"},
76ddaa4e7dStsutsui {TYPE_CAP,0,".finderinfo/", ".resource/", get_cap_info, get_cap_dir,"CAP"},
77ddaa4e7dStsutsui {TYPE_NETA,0,".AppleDouble/", ".AppleDouble/", get_dbl_info, get_none_dir,"Netatalk"},
78ddaa4e7dStsutsui {TYPE_DBL,0,"%", "%", get_dbl_info, get_none_dir,"AppleDouble"},
79ddaa4e7dStsutsui {TYPE_ESH, 0,".rsrc/", ".rsrc/", get_es_info, get_none_dir,"EtherShare/UShare"},
80ddaa4e7dStsutsui {TYPE_FEU,2,"FINDER.DAT", "RESOURCE.FRK/", get_fe_info, get_fe_dir,"Exchange"},
81ddaa4e7dStsutsui {TYPE_FEL,2,"finder.dat", "resource.frk/", get_fe_info, get_fe_dir,"Exchange"},
82ddaa4e7dStsutsui {TYPE_SGI,2,".HSancillary", ".HSResource/", get_sgi_info, get_sgi_dir,"XINET/SGI"},
83ddaa4e7dStsutsui {TYPE_MBIN,1,"", "", get_mb_info, get_none_dir,"MacBinary"},
84ddaa4e7dStsutsui {TYPE_SGL,1,"", "", get_sgl_info, get_none_dir,"AppleSingle"}
85ddaa4e7dStsutsui };
86ddaa4e7dStsutsui
87ddaa4e7dStsutsui /* used by get_magic_match() return */
88ddaa4e7dStsutsui static char tmp_type[CT_SIZE+1], tmp_creator[CT_SIZE+1];
89ddaa4e7dStsutsui
90ddaa4e7dStsutsui /*
91ddaa4e7dStsutsui ** cstrncopy: Cap Unix name to HFS name
92ddaa4e7dStsutsui **
93ddaa4e7dStsutsui ** ':' is replaced by '%' and string is terminated with '\0'
94ddaa4e7dStsutsui */
95*61549db5Stsutsui static void
cstrncpy(char * t,const char * f,int c)96a11dc48bStsutsui cstrncpy(char *t, const char *f, int c)
97ddaa4e7dStsutsui {
98ddaa4e7dStsutsui while (c-- && *f)
99ddaa4e7dStsutsui {
100ddaa4e7dStsutsui switch (*f)
101ddaa4e7dStsutsui {
102ddaa4e7dStsutsui case ':':
103ddaa4e7dStsutsui *t = '%';
104ddaa4e7dStsutsui break;
105ddaa4e7dStsutsui default:
106ddaa4e7dStsutsui *t = *f;
107ddaa4e7dStsutsui break;
108ddaa4e7dStsutsui }
109ddaa4e7dStsutsui t++; f++;
110ddaa4e7dStsutsui }
111ddaa4e7dStsutsui
112ddaa4e7dStsutsui *t = '\0';
113ddaa4e7dStsutsui }
114ddaa4e7dStsutsui /*
115ddaa4e7dStsutsui ** dehex()
116ddaa4e7dStsutsui **
117ddaa4e7dStsutsui ** Given a hexadecimal digit in ASCII, return the integer representation.
118ddaa4e7dStsutsui **
119ddaa4e7dStsutsui ** Taken from linux/fs/hfs/trans.c by Paul H. Hargrove
120ddaa4e7dStsutsui */
121ddaa4e7dStsutsui static unsigned char
dehex(char c)122ddaa4e7dStsutsui dehex(char c)
123ddaa4e7dStsutsui {
124ddaa4e7dStsutsui if ((c>='0')&&(c<='9')) {
125ddaa4e7dStsutsui return c-'0';
126ddaa4e7dStsutsui }
127ddaa4e7dStsutsui if ((c>='a')&&(c<='f')) {
128ddaa4e7dStsutsui return c-'a'+10;
129ddaa4e7dStsutsui }
130ddaa4e7dStsutsui if ((c>='A')&&(c<='F')) {
131ddaa4e7dStsutsui return c-'A'+10;
132ddaa4e7dStsutsui }
133ddaa4e7dStsutsui /* return 0xff; */
134ddaa4e7dStsutsui return (0);
135ddaa4e7dStsutsui }
136ddaa4e7dStsutsui
137ddaa4e7dStsutsui static unsigned char
hex2char(const char * s)138a11dc48bStsutsui hex2char(const char *s)
139ddaa4e7dStsutsui {
140ddaa4e7dStsutsui unsigned char o;
141ddaa4e7dStsutsui
142ddaa4e7dStsutsui if(strlen(++s) < 2)
143ddaa4e7dStsutsui return(0);
144ddaa4e7dStsutsui
145*61549db5Stsutsui if (!isxdigit((int)(u_char)*s) || !isxdigit((int)(u_char)*(s+1)))
146ddaa4e7dStsutsui return(0);
147ddaa4e7dStsutsui
148ddaa4e7dStsutsui o = (dehex(*s) << 4) & 0xf0;
149ddaa4e7dStsutsui s++;
150ddaa4e7dStsutsui o |= (dehex(*s) & 0xf);
151ddaa4e7dStsutsui
152ddaa4e7dStsutsui return (o);
153ddaa4e7dStsutsui }
154ddaa4e7dStsutsui
155ddaa4e7dStsutsui /*
156ddaa4e7dStsutsui ** hstrncpy: Unix name to HFS name with special character
157ddaa4e7dStsutsui ** translation.
158ddaa4e7dStsutsui **
159ddaa4e7dStsutsui ** "%xx" or ":xx" is assumed to be a "special" character and
160ddaa4e7dStsutsui ** replaced by character code given by the hex characters "xx"
161ddaa4e7dStsutsui **
162ddaa4e7dStsutsui ** if "xx" is not a hex number, then it is left alone - except
163ddaa4e7dStsutsui ** that ":" is replaced by "%"
164ddaa4e7dStsutsui **
165ddaa4e7dStsutsui */
166*61549db5Stsutsui static void
hstrncpy(unsigned char * t,const char * f,int c)167a11dc48bStsutsui hstrncpy(unsigned char *t, const char *f, int c)
168ddaa4e7dStsutsui {
169ddaa4e7dStsutsui unsigned char o;
170ddaa4e7dStsutsui while (c-- && *f)
171ddaa4e7dStsutsui {
172ddaa4e7dStsutsui switch (*f)
173ddaa4e7dStsutsui {
174ddaa4e7dStsutsui case ':':
175ddaa4e7dStsutsui case '%':
176ddaa4e7dStsutsui if ((o = hex2char(f)) == 0) {
177ddaa4e7dStsutsui *t = '%';
178ddaa4e7dStsutsui }
179ddaa4e7dStsutsui else {
180ddaa4e7dStsutsui *t = o;
181ddaa4e7dStsutsui f += 2;
182ddaa4e7dStsutsui }
183ddaa4e7dStsutsui break;
184ddaa4e7dStsutsui default:
185ddaa4e7dStsutsui *t = *f;
186ddaa4e7dStsutsui break;
187ddaa4e7dStsutsui }
188ddaa4e7dStsutsui t++; f++;
189ddaa4e7dStsutsui }
190ddaa4e7dStsutsui
191ddaa4e7dStsutsui *t = '\0';
192ddaa4e7dStsutsui }
193ddaa4e7dStsutsui
194ddaa4e7dStsutsui /*
195ddaa4e7dStsutsui ** basename: find just the filename with any directory component
196ddaa4e7dStsutsui */
197ddaa4e7dStsutsui /* not used at the moment ...
198ddaa4e7dStsutsui static char
199ddaa4e7dStsutsui basename(char *a)
200ddaa4e7dStsutsui {
201ddaa4e7dStsutsui char *b;
202ddaa4e7dStsutsui
203ddaa4e7dStsutsui if((b = strchr(a, '/')))
204ddaa4e7dStsutsui return(++b);
205ddaa4e7dStsutsui else
206ddaa4e7dStsutsui return(a);
207ddaa4e7dStsutsui }
208ddaa4e7dStsutsui */
209ddaa4e7dStsutsui
210ddaa4e7dStsutsui /*
211ddaa4e7dStsutsui ** get_none_dir: ordinary Unix directory
212ddaa4e7dStsutsui */
213ddaa4e7dStsutsui int
get_none_dir(char * hname,const char * dname,dir_ent * s_entry,int ret)214a11dc48bStsutsui get_none_dir(char *hname, const char *dname, dir_ent *s_entry, int ret)
215ddaa4e7dStsutsui {
216ddaa4e7dStsutsui /* just copy the given name */
217ddaa4e7dStsutsui hstrncpy(s_entry->hfs_ent->name, dname, HFS_MAX_FLEN);
218ddaa4e7dStsutsui
219ddaa4e7dStsutsui return(ret);
220ddaa4e7dStsutsui }
221ddaa4e7dStsutsui
222ddaa4e7dStsutsui /*
223ddaa4e7dStsutsui ** get_none_info: ordinary Unix file - try to map extension
224ddaa4e7dStsutsui */
225ddaa4e7dStsutsui int
get_none_info(char * hname,char * dname,dir_ent * s_entry,int ret)226ddaa4e7dStsutsui get_none_info(char *hname, char *dname, dir_ent *s_entry, int ret)
227ddaa4e7dStsutsui {
228ddaa4e7dStsutsui char *t, *c;
229ddaa4e7dStsutsui hfsdirent *hfs_ent = s_entry->hfs_ent;
230ddaa4e7dStsutsui
231ddaa4e7dStsutsui map_ext(dname, &t, &c, &s_entry->hfs_ent->fdflags, s_entry->whole_name);
232ddaa4e7dStsutsui
233ddaa4e7dStsutsui /* just copy the given name */
234ddaa4e7dStsutsui hstrncpy(hfs_ent->name, dname, HFS_MAX_FLEN);
235ddaa4e7dStsutsui
236ddaa4e7dStsutsui strncpy(hfs_ent->type, t, CT_SIZE);
237ddaa4e7dStsutsui strncpy(hfs_ent->creator, c, CT_SIZE);
238ddaa4e7dStsutsui hfs_ent->type[CT_SIZE] = '\0';
239ddaa4e7dStsutsui hfs_ent->creator[CT_SIZE] = '\0';
240ddaa4e7dStsutsui
241ddaa4e7dStsutsui return(ret);
242ddaa4e7dStsutsui }
243ddaa4e7dStsutsui /*
244ddaa4e7dStsutsui ** read_info_file: open and read a finderinfo file for an HFS file
245ddaa4e7dStsutsui ** or directory
246ddaa4e7dStsutsui */
247*61549db5Stsutsui static int
read_info_file(char * name,void * info,int len)248ddaa4e7dStsutsui read_info_file(char *name, void *info, int len)
249ddaa4e7dStsutsui /* char *name; finderinfo filename */
250ddaa4e7dStsutsui /* void *info; info buffer */
251ddaa4e7dStsutsui /* int len; length of above */
252ddaa4e7dStsutsui {
253ddaa4e7dStsutsui FILE *fp;
254ddaa4e7dStsutsui int num;
255ddaa4e7dStsutsui
256ddaa4e7dStsutsui /* clear out any old finderinfo stuf */
257ddaa4e7dStsutsui memset(info, 0, len);
258ddaa4e7dStsutsui
259ddaa4e7dStsutsui if ((fp = fopen(name,"rb")) == NULL)
260ddaa4e7dStsutsui return(-1);
261ddaa4e7dStsutsui
262ddaa4e7dStsutsui /* read and ignore if the file is short - checked later */
263ddaa4e7dStsutsui num = fread(info,1,len,fp);
264ddaa4e7dStsutsui
265ddaa4e7dStsutsui fclose(fp);
266ddaa4e7dStsutsui
267ddaa4e7dStsutsui return(num);
268ddaa4e7dStsutsui }
269ddaa4e7dStsutsui /*
270ddaa4e7dStsutsui ** get_cap_dir: get the CAP name for a directory
271ddaa4e7dStsutsui */
272ddaa4e7dStsutsui int
get_cap_dir(char * hname,const char * dname,dir_ent * s_entry,int ret)273a11dc48bStsutsui get_cap_dir(char *hname, const char *dname, dir_ent *s_entry, int ret)
274ddaa4e7dStsutsui /* char *hname whole path */
275a11dc48bStsutsui /* const char *dname this dir name */
276ddaa4e7dStsutsui /* dir_ent *s_entry directory entry */
277ddaa4e7dStsutsui {
278ddaa4e7dStsutsui FileInfo info; /* finderinfo struct */
279ddaa4e7dStsutsui int num = -1; /* bytes read */
280ddaa4e7dStsutsui
281ddaa4e7dStsutsui num = read_info_file(hname, &info, sizeof(FileInfo));
282ddaa4e7dStsutsui
283ddaa4e7dStsutsui /* check finder info is OK */
284ddaa4e7dStsutsui if (num > 0
285ddaa4e7dStsutsui && info.fi_magic1 == FI_MAGIC1
286ddaa4e7dStsutsui && info.fi_magic == FI_MAGIC
287ddaa4e7dStsutsui && info.fi_bitmap & FI_BM_MACINTOSHFILENAME) {
288ddaa4e7dStsutsui /* use the finderinfo name if it exists */
289ddaa4e7dStsutsui cstrncpy(s_entry->hfs_ent->name, info.fi_macfilename, HFS_MAX_FLEN);
290ddaa4e7dStsutsui return (ret);
291ddaa4e7dStsutsui }
292ddaa4e7dStsutsui else {
293ddaa4e7dStsutsui /* otherwise give it it's Unix name */
294ddaa4e7dStsutsui hstrncpy(s_entry->hfs_ent->name, dname, HFS_MAX_FLEN);
295ddaa4e7dStsutsui return (TYPE_NONE);
296ddaa4e7dStsutsui }
297ddaa4e7dStsutsui }
298ddaa4e7dStsutsui
299ddaa4e7dStsutsui /*
300ddaa4e7dStsutsui ** get_cap_info: get CAP finderinfo for a file
301ddaa4e7dStsutsui */
302ddaa4e7dStsutsui int
get_cap_info(char * hname,char * dname,dir_ent * s_entry,int ret)303ddaa4e7dStsutsui get_cap_info(char *hname, char *dname, dir_ent *s_entry, int ret)
304ddaa4e7dStsutsui /* char *hname whole path */
305ddaa4e7dStsutsui /* char *dname this dir name */
306ddaa4e7dStsutsui /* dir_ent *s_entry directory entry */
307ddaa4e7dStsutsui {
308ddaa4e7dStsutsui FileInfo info; /* finderinfo struct */
309ddaa4e7dStsutsui int num = -1; /* bytes read */
310ddaa4e7dStsutsui char *c;
311ddaa4e7dStsutsui char *t;
312ddaa4e7dStsutsui hfsdirent *hfs_ent = s_entry->hfs_ent;
313ddaa4e7dStsutsui
314ddaa4e7dStsutsui num = read_info_file(hname, &info, sizeof(info));
315ddaa4e7dStsutsui
316ddaa4e7dStsutsui /* check finder info is OK */
317ddaa4e7dStsutsui if (num > 0
318ddaa4e7dStsutsui && info.fi_magic1 == FI_MAGIC1
319ddaa4e7dStsutsui && info.fi_magic == FI_MAGIC) {
320ddaa4e7dStsutsui
321ddaa4e7dStsutsui if (info.fi_bitmap & FI_BM_MACINTOSHFILENAME) {
322ddaa4e7dStsutsui /* use the finderinfo name if it exists */
323ddaa4e7dStsutsui cstrncpy(hfs_ent->name, info.fi_macfilename, HFS_MAX_FLEN);
324ddaa4e7dStsutsui }
325ddaa4e7dStsutsui else {
326ddaa4e7dStsutsui /* use Unix name */
327ddaa4e7dStsutsui hstrncpy(hfs_ent->name, dname, HFS_MAX_FLEN);
328ddaa4e7dStsutsui }
329ddaa4e7dStsutsui
330ddaa4e7dStsutsui /* type and creator from finder info */
331ddaa4e7dStsutsui t = info.fdType;
332ddaa4e7dStsutsui c = info.fdCreator;
333ddaa4e7dStsutsui
334ddaa4e7dStsutsui strncpy(hfs_ent->type, t, CT_SIZE);
335ddaa4e7dStsutsui strncpy(hfs_ent->creator, c, CT_SIZE);
336ddaa4e7dStsutsui hfs_ent->type[CT_SIZE] = '\0';
337ddaa4e7dStsutsui hfs_ent->creator[CT_SIZE] = '\0';
338ddaa4e7dStsutsui
339ddaa4e7dStsutsui /* finder flags */
340ddaa4e7dStsutsui hfs_ent->fdflags = d_getw((unsigned char *)&info.fdFlags);
341ddaa4e7dStsutsui /* clear HFS_FNDR_HASBEENINITED to have tidy desktop ?? */
342ddaa4e7dStsutsui hfs_ent->fdflags &= 0xfeff;
343ddaa4e7dStsutsui
344ddaa4e7dStsutsui #ifdef USE_MAC_DATES
345ddaa4e7dStsutsui /* set created/modified dates - these date should have already
346ddaa4e7dStsutsui been set from the Unix data fork dates. The finderinfo dates
347ddaa4e7dStsutsui are in Mac format - but we have to convert them back to Unix
348ddaa4e7dStsutsui for the time being */
349ddaa4e7dStsutsui if ((info.fi_datemagic & FI_CDATE)) {
350ddaa4e7dStsutsui /* use libhfs routines to get correct byte order */
351ddaa4e7dStsutsui hfs_ent->crdate = d_toutime(d_getl(info.fi_ctime));
352ddaa4e7dStsutsui }
353ddaa4e7dStsutsui if (info.fi_datemagic & FI_MDATE) {
354ddaa4e7dStsutsui hfs_ent->mddate = d_toutime(d_getl(info.fi_mtime));
355ddaa4e7dStsutsui }
356ddaa4e7dStsutsui #endif /* USE_MAC_DATES */
357ddaa4e7dStsutsui }
358ddaa4e7dStsutsui else {
359ddaa4e7dStsutsui /* failed to open/read finderinfo - so try afpfile mapping */
360ddaa4e7dStsutsui if (verbose > 2) {
361ddaa4e7dStsutsui fprintf(stderr, "warning: %s doesn't appear to be a %s file\n",
362ddaa4e7dStsutsui s_entry->whole_name, hfs_types[ret].desc);
363ddaa4e7dStsutsui }
364ddaa4e7dStsutsui
365ddaa4e7dStsutsui ret = get_none_info(hname, dname, s_entry, TYPE_NONE);
366ddaa4e7dStsutsui }
367ddaa4e7dStsutsui
368ddaa4e7dStsutsui return (ret);
369ddaa4e7dStsutsui }
370ddaa4e7dStsutsui
371ddaa4e7dStsutsui /*
372ddaa4e7dStsutsui ** get_es_info: get EtherShare/UShare finderinfo for a file
373ddaa4e7dStsutsui **
374ddaa4e7dStsutsui ** based on code from Jens-Uwe Mager (jum@helios.de) and Phil Sylvester
375ddaa4e7dStsutsui ** <psylvstr@interaccess.com>
376ddaa4e7dStsutsui */
377ddaa4e7dStsutsui int
get_es_info(char * hname,char * dname,dir_ent * s_entry,int ret)378ddaa4e7dStsutsui get_es_info(char *hname, char *dname, dir_ent *s_entry, int ret)
379ddaa4e7dStsutsui /* char *hname whole path */
380ddaa4e7dStsutsui /* char *dname this dir name */
381ddaa4e7dStsutsui /* dir_ent *s_entry directory entry */
382ddaa4e7dStsutsui {
383ddaa4e7dStsutsui es_FileInfo *einfo; /* EtherShare info struct */
384ddaa4e7dStsutsui us_FileInfo *uinfo; /* UShare info struct */
385ddaa4e7dStsutsui char info[ES_INFO_SIZE]; /* finderinfo buffer */
386ddaa4e7dStsutsui int num = -1; /* bytes read */
387ddaa4e7dStsutsui char *c;
388ddaa4e7dStsutsui char *t;
389ddaa4e7dStsutsui hfsdirent *hfs_ent = s_entry->hfs_ent;
390ddaa4e7dStsutsui dir_ent *s_entry1;
391ddaa4e7dStsutsui
392ddaa4e7dStsutsui /* the EtherShare and UShare file layout is the same, but they
393ddaa4e7dStsutsui store finderinfo differently */
394ddaa4e7dStsutsui einfo = (es_FileInfo *)info;
395ddaa4e7dStsutsui uinfo = (us_FileInfo *)info;
396ddaa4e7dStsutsui
397ddaa4e7dStsutsui num = read_info_file(hname, info, sizeof(info));
398ddaa4e7dStsutsui
399ddaa4e7dStsutsui /* check finder info for EtherShare finderinfo */
400ddaa4e7dStsutsui if (num >= sizeof(es_FileInfo) &&
401ddaa4e7dStsutsui ntohl(einfo->magic) == ES_MAGIC &&
402ddaa4e7dStsutsui ntohs(einfo->version) == ES_VERSION) {
403ddaa4e7dStsutsui
404ddaa4e7dStsutsui /* type and creator from finder info */
405ddaa4e7dStsutsui t = einfo->fdType;
406ddaa4e7dStsutsui c = einfo->fdCreator;
407ddaa4e7dStsutsui
408ddaa4e7dStsutsui /* finder flags */
409ddaa4e7dStsutsui hfs_ent->fdflags = d_getw((unsigned char *)&einfo->fdFlags);
410ddaa4e7dStsutsui
411ddaa4e7dStsutsui /* set create date - modified date set from the Unix data
412ddaa4e7dStsutsui fork date */
413ddaa4e7dStsutsui hfs_ent->crdate = d_getl((unsigned char *)&einfo->createTime);
414ddaa4e7dStsutsui }
415ddaa4e7dStsutsui else if (num >= sizeof(us_FileInfo)) {
416ddaa4e7dStsutsui /* UShare has no magic number, so we assume that this is
417ddaa4e7dStsutsui a valid info/resource file ... */
418ddaa4e7dStsutsui
419ddaa4e7dStsutsui /* type and creator from finder info */
420ddaa4e7dStsutsui t = uinfo->fdType;
421ddaa4e7dStsutsui c = uinfo->fdCreator;
422ddaa4e7dStsutsui
423ddaa4e7dStsutsui /* finder flags */
424ddaa4e7dStsutsui hfs_ent->fdflags = d_getw((unsigned char *)&uinfo->fdFlags);
425ddaa4e7dStsutsui
426ddaa4e7dStsutsui /* set create and modified date - if they exist */
427ddaa4e7dStsutsui if (uinfo->ctime)
428ddaa4e7dStsutsui hfs_ent->crdate = d_getl((unsigned char *)&uinfo->ctime);
429ddaa4e7dStsutsui
430ddaa4e7dStsutsui if (uinfo->mtime)
431ddaa4e7dStsutsui hfs_ent->mddate = d_getl((unsigned char *)&uinfo->mtime);
432ddaa4e7dStsutsui }
433ddaa4e7dStsutsui else {
434ddaa4e7dStsutsui /* failed to open/read finderinfo - so try afpfile mapping */
435ddaa4e7dStsutsui if (verbose > 2) {
436ddaa4e7dStsutsui fprintf(stderr, "warning: %s doesn't appear to be a %s file\n",
437ddaa4e7dStsutsui s_entry->whole_name, hfs_types[ret].desc);
438ddaa4e7dStsutsui }
439ddaa4e7dStsutsui
440ddaa4e7dStsutsui ret = get_none_info(hname, dname, s_entry, TYPE_NONE);
441ddaa4e7dStsutsui return (ret);
442ddaa4e7dStsutsui }
443ddaa4e7dStsutsui
444ddaa4e7dStsutsui /* this should exist ... */
445ddaa4e7dStsutsui if ((s_entry1 = s_entry->assoc) == NULL)
446ddaa4e7dStsutsui errx(1, "TYPE_ESH error - shouldn't happen!");
447ddaa4e7dStsutsui
448ddaa4e7dStsutsui /* fill in the HFS info stuff */
449ddaa4e7dStsutsui strncpy(hfs_ent->type, t, CT_SIZE);
450ddaa4e7dStsutsui strncpy(hfs_ent->creator, c, CT_SIZE);
451ddaa4e7dStsutsui hfs_ent->type[CT_SIZE] = '\0';
452ddaa4e7dStsutsui hfs_ent->creator[CT_SIZE] = '\0';
453ddaa4e7dStsutsui
454ddaa4e7dStsutsui /* clear HFS_FNDR_HASBEENINITED to have tidy desktop ?? */
455ddaa4e7dStsutsui hfs_ent->fdflags &= 0xfeff;
456ddaa4e7dStsutsui
457ddaa4e7dStsutsui /* set name */
458ddaa4e7dStsutsui hstrncpy(hfs_ent->name, dname, HFS_MAX_FLEN);
459ddaa4e7dStsutsui
460ddaa4e7dStsutsui /* real rsrc file starts ES_INFO_SIZE bytes into the file */
461ddaa4e7dStsutsui if(s_entry1->size <= ES_INFO_SIZE) {
462ddaa4e7dStsutsui s_entry1->size = 0;
463ddaa4e7dStsutsui hfs_ent->rsize = 0;
464ddaa4e7dStsutsui }
465ddaa4e7dStsutsui else {
466ddaa4e7dStsutsui s_entry1->size -= ES_INFO_SIZE;
467ddaa4e7dStsutsui hfs_ent->rsize = s_entry1->size;
468ddaa4e7dStsutsui s_entry1->hfs_off = ES_INFO_SIZE;
469ddaa4e7dStsutsui }
470ddaa4e7dStsutsui
471ddaa4e7dStsutsui set_733((char *) s_entry1->isorec.size, s_entry1->size);
472ddaa4e7dStsutsui
473ddaa4e7dStsutsui return (ret);
474ddaa4e7dStsutsui }
475ddaa4e7dStsutsui
476ddaa4e7dStsutsui /*
477ddaa4e7dStsutsui * calc_crc() --
478ddaa4e7dStsutsui * Compute the MacBinary II-style CRC for the data pointed to by p, with the
479ddaa4e7dStsutsui * crc seeded to seed.
480ddaa4e7dStsutsui *
481ddaa4e7dStsutsui * Modified by Jim Van Verth to use the magic array for efficiency.
482ddaa4e7dStsutsui */
483ddaa4e7dStsutsui static unsigned short
calc_mb_crc(unsigned char * p,long len,unsigned short seed)484ddaa4e7dStsutsui calc_mb_crc(unsigned char *p, long len, unsigned short seed)
485ddaa4e7dStsutsui {
486ddaa4e7dStsutsui unsigned short hold; /* crc computed so far */
487ddaa4e7dStsutsui long i; /* index into data */
488ddaa4e7dStsutsui
489ddaa4e7dStsutsui hold = seed; /* start with seed */
490ddaa4e7dStsutsui for (i = 0; i < len; i++, p++) {
491ddaa4e7dStsutsui hold ^= (*p << 8);
492ddaa4e7dStsutsui hold = (hold << 8) ^ mb_magic[(unsigned char)(hold >> 8)];
493ddaa4e7dStsutsui }
494ddaa4e7dStsutsui
495ddaa4e7dStsutsui return (hold);
496ddaa4e7dStsutsui } /* calc_mb_crc() */
497ddaa4e7dStsutsui
498ddaa4e7dStsutsui int
get_mb_info(char * hname,char * dname,dir_ent * s_entry,int ret)499ddaa4e7dStsutsui get_mb_info(char *hname, char *dname, dir_ent *s_entry, int ret)
500ddaa4e7dStsutsui /* char *hname whole path */
501ddaa4e7dStsutsui /* char *dname this dir name */
502ddaa4e7dStsutsui /* dir_ent *s_entry directory entry */
503ddaa4e7dStsutsui {
504ddaa4e7dStsutsui mb_info *info; /* finderinfo struct */
505ddaa4e7dStsutsui char *c;
506ddaa4e7dStsutsui char *t;
507ddaa4e7dStsutsui hfsdirent *hfs_ent;
508ddaa4e7dStsutsui dir_ent *s_entry1;
509ddaa4e7dStsutsui int i;
510ddaa4e7dStsutsui #ifdef TEST_CODE
511ddaa4e7dStsutsui unsigned short crc_file, crc_calc;
512ddaa4e7dStsutsui #endif
513ddaa4e7dStsutsui
514ddaa4e7dStsutsui info = (mb_info *)p_buf;
515ddaa4e7dStsutsui
516ddaa4e7dStsutsui /* routine called twice for each file - first to check that
517ddaa4e7dStsutsui it is a valid MacBinary file, second to fill in the HFS
518ddaa4e7dStsutsui info. p_buf holds the required raw data and it *should*
519ddaa4e7dStsutsui remain the same between the two calls */
520ddaa4e7dStsutsui
521ddaa4e7dStsutsui if (s_entry == 0) {
522ddaa4e7dStsutsui /* test that the CRC is OK - not set for MacBinary I files
523ddaa4e7dStsutsui (and incorrect in some MacBinary II files!). If this
524ddaa4e7dStsutsui fails, then perform some other checks */
525ddaa4e7dStsutsui
526ddaa4e7dStsutsui #ifdef TEST_CODE
527ddaa4e7dStsutsui /* leave this out for the time being ... */
528ddaa4e7dStsutsui if (p_num >= MB_SIZE && info->version == 0 && info->zero1 == 0) {
529ddaa4e7dStsutsui crc_calc = calc_mb_crc((unsigned char *)info, 124, 0);
530ddaa4e7dStsutsui crc_file = d_getw(info->crc);
531ddaa4e7dStsutsui #ifdef DEBUG
532ddaa4e7dStsutsui fprintf(stderr,"%s: file %d, calc %d\n",hname,crc_file,crc_calc);
533ddaa4e7dStsutsui #endif /* DEBUG */
534ddaa4e7dStsutsui if (crc_file == crc_calc)
535ddaa4e7dStsutsui return (ret);
536ddaa4e7dStsutsui }
537ddaa4e7dStsutsui #endif /* TEST_CODE */
538ddaa4e7dStsutsui
539ddaa4e7dStsutsui /* check some of the fields for a valid MacBinary file
540ddaa4e7dStsutsui not zero1 and zero2 SHOULD be zero - but some files incorrect */
541ddaa4e7dStsutsui
542ddaa4e7dStsutsui /* if (p_num < MB_SIZE || info->nlen > 63 || info->zero2 || */
543ddaa4e7dStsutsui if (p_num < MB_SIZE || info->zero1 ||
544ddaa4e7dStsutsui info->zero2 || info->nlen > 63 ||
545ddaa4e7dStsutsui info->version || info->nlen == 0 || *info->name == 0)
546ddaa4e7dStsutsui return (TYPE_NONE);
547ddaa4e7dStsutsui
548ddaa4e7dStsutsui /* check that the filename is OKish */
549ddaa4e7dStsutsui for (i=0;i<info->nlen;i++)
550ddaa4e7dStsutsui if(info->name[i] == 0)
551ddaa4e7dStsutsui return (TYPE_NONE);
552ddaa4e7dStsutsui
553ddaa4e7dStsutsui /* check CREATOR and TYPE are valid */
554ddaa4e7dStsutsui for (i=0;i<4;i++)
555ddaa4e7dStsutsui if(info->type[i] == 0 || info->auth[i] == 0)
556ddaa4e7dStsutsui return (TYPE_NONE);
557ddaa4e7dStsutsui }
558ddaa4e7dStsutsui else {
559ddaa4e7dStsutsui /* we have a vaild MacBinary file, so fill in the bits */
560ddaa4e7dStsutsui
561ddaa4e7dStsutsui /* this should exist ... */
562ddaa4e7dStsutsui if((s_entry1 = s_entry->assoc) == NULL)
563ddaa4e7dStsutsui errx(1, "TYPE_MBIN error - shouldn't happen!");
564ddaa4e7dStsutsui
565ddaa4e7dStsutsui hfs_ent = s_entry->hfs_ent;
566ddaa4e7dStsutsui
567ddaa4e7dStsutsui /* type and creator from finder info */
568ddaa4e7dStsutsui t = info->type;
569ddaa4e7dStsutsui c = info->auth;
570ddaa4e7dStsutsui
571ddaa4e7dStsutsui strncpy(hfs_ent->type, t, CT_SIZE);
572ddaa4e7dStsutsui strncpy(hfs_ent->creator, c, CT_SIZE);
573ddaa4e7dStsutsui hfs_ent->type[CT_SIZE] = '\0';
574ddaa4e7dStsutsui hfs_ent->creator[CT_SIZE] = '\0';
575ddaa4e7dStsutsui
576ddaa4e7dStsutsui /* finder flags */
577ddaa4e7dStsutsui hfs_ent->fdflags = ((info->flags << 8) & 0xff00) | info->flags2;
578ddaa4e7dStsutsui /* clear HFS_FNDR_HASBEENINITED to have tidy desktop ?? */
579ddaa4e7dStsutsui hfs_ent->fdflags &= 0xfeff;
580ddaa4e7dStsutsui
581ddaa4e7dStsutsui /* set created/modified dates - these date should have already
582ddaa4e7dStsutsui been set from the Unix data fork dates. The finderinfo dates
583ddaa4e7dStsutsui are in Mac format - but we have to convert them back to Unix
584ddaa4e7dStsutsui for the time being */
585ddaa4e7dStsutsui
586ddaa4e7dStsutsui hfs_ent->crdate = d_toutime(d_getl(info->cdate));
587ddaa4e7dStsutsui hfs_ent->mddate = d_toutime(d_getl(info->mdate));
588ddaa4e7dStsutsui
589ddaa4e7dStsutsui /* set name */
590ddaa4e7dStsutsui /* hstrncpy(hfs_ent->name, info->name, HFS_MAX_FLEN); */
591ddaa4e7dStsutsui hstrncpy(hfs_ent->name, info->name, MIN(HFS_MAX_FLEN, info->nlen));
592ddaa4e7dStsutsui
593ddaa4e7dStsutsui /* set correct fork sizes */
594ddaa4e7dStsutsui hfs_ent->dsize = d_getl(info->dflen);
595ddaa4e7dStsutsui hfs_ent->rsize = d_getl(info->rflen);
596ddaa4e7dStsutsui
597ddaa4e7dStsutsui /* update directory entries for data fork */
598ddaa4e7dStsutsui s_entry->size = hfs_ent->dsize;
599ddaa4e7dStsutsui s_entry->hfs_off = MB_SIZE;
600ddaa4e7dStsutsui set_733((char *) s_entry->isorec.size, s_entry->size);
601ddaa4e7dStsutsui
602ddaa4e7dStsutsui /* real rsrc file starts after data fork (must be a multiple
603ddaa4e7dStsutsui of MB_SIZE) */
604ddaa4e7dStsutsui s_entry1->size = hfs_ent->rsize;
605ddaa4e7dStsutsui s_entry1->hfs_off = MB_SIZE + V_ROUND_UP(hfs_ent->dsize, MB_SIZE);
606ddaa4e7dStsutsui set_733((char *) s_entry1->isorec.size, s_entry1->size);
607ddaa4e7dStsutsui }
608ddaa4e7dStsutsui
609ddaa4e7dStsutsui return (ret);
610ddaa4e7dStsutsui }
611ddaa4e7dStsutsui
612ddaa4e7dStsutsui /*
613ddaa4e7dStsutsui ** get_dbl_info: get Apple double finderinfo for a file
614ddaa4e7dStsutsui **
615ddaa4e7dStsutsui ** Based on code from cvt2cap.c (c) May 1988, Paul Campbell
616ddaa4e7dStsutsui */
617ddaa4e7dStsutsui int
get_dbl_info(char * hname,char * dname,dir_ent * s_entry,int ret)618ddaa4e7dStsutsui get_dbl_info(char *hname, char *dname, dir_ent *s_entry, int ret)
619ddaa4e7dStsutsui /* char *hname whole path */
620ddaa4e7dStsutsui /* char *dname this dir name */
621ddaa4e7dStsutsui /* dir_ent *s_entry directory entry */
622ddaa4e7dStsutsui {
623ddaa4e7dStsutsui FileInfo info; /* finderinfo struct */
624ddaa4e7dStsutsui a_hdr *hp;
625ddaa4e7dStsutsui a_entry *ep;
626ddaa4e7dStsutsui int num = -1; /* bytes read */
627ddaa4e7dStsutsui char *c;
628ddaa4e7dStsutsui char *t;
629ddaa4e7dStsutsui int nentries;
630ddaa4e7dStsutsui FILE *fp;
631ddaa4e7dStsutsui hfsdirent *hfs_ent = s_entry->hfs_ent;
632ddaa4e7dStsutsui dir_ent *s_entry1;
633ddaa4e7dStsutsui char name[64];
634ddaa4e7dStsutsui int i;
635ddaa4e7dStsutsui int fail = 0;
636ddaa4e7dStsutsui
637ddaa4e7dStsutsui hp = (a_hdr *)p_buf;;
638ddaa4e7dStsutsui memset(hp, 0, A_HDR_SIZE);
639ddaa4e7dStsutsui
640ddaa4e7dStsutsui memset(name, 0, sizeof(name));
641ddaa4e7dStsutsui
642ddaa4e7dStsutsui /* get the rsrc file info - should exist ... */
643ddaa4e7dStsutsui if ((s_entry1 = s_entry->assoc) == NULL)
644ddaa4e7dStsutsui errx(1, "TYPE_DBL error - shouldn't happen!");
645ddaa4e7dStsutsui
646ddaa4e7dStsutsui /* open and read the info/rsrc file (it's the same file) */
647ddaa4e7dStsutsui if ((fp = fopen(hname,"rb")) != NULL)
648ddaa4e7dStsutsui num = fread(hp, 1, A_HDR_SIZE, fp);
649ddaa4e7dStsutsui
650ddaa4e7dStsutsui /* check finder info is OK - some Netatalk files don't have
651ddaa4e7dStsutsui magic or version set - ignore if it's a netatalk file */
652ddaa4e7dStsutsui if (num == A_HDR_SIZE && ((ret == TYPE_NETA) ||
653ddaa4e7dStsutsui (ntohl(hp->magic) == APPLE_DOUBLE &&
654ddaa4e7dStsutsui ntohl(hp->version) == A_VERSION))) {
655ddaa4e7dStsutsui
656ddaa4e7dStsutsui /* read TOC of the AppleDouble file */
657ddaa4e7dStsutsui nentries = (int)ntohs(hp->nentries);
658ddaa4e7dStsutsui if(fread(hp->entries, A_ENTRY_SIZE, nentries, fp) < 1) {
659ddaa4e7dStsutsui fail = 1;
660ddaa4e7dStsutsui nentries = 0;
661ddaa4e7dStsutsui }
662ddaa4e7dStsutsui
663ddaa4e7dStsutsui /* extract what is needed */
664ddaa4e7dStsutsui for (i=0, ep=hp->entries; i<nentries; i++,ep++) {
665ddaa4e7dStsutsui switch(ntohl(ep->id)) {
666ddaa4e7dStsutsui case ID_FINDER:
667ddaa4e7dStsutsui /* get the finder info */
668ddaa4e7dStsutsui fseek(fp, ntohl(ep->offset), 0);
669ddaa4e7dStsutsui if (fread(&info, ntohl(ep->length), 1, fp) < 1) {
670ddaa4e7dStsutsui fail = 1;
671ddaa4e7dStsutsui }
672ddaa4e7dStsutsui break;
673ddaa4e7dStsutsui case ID_RESOURCE:
674ddaa4e7dStsutsui /* set the offset and correct rsrc fork size */
675ddaa4e7dStsutsui s_entry1->size = ntohl(ep->length);
676ddaa4e7dStsutsui hfs_ent->rsize = s_entry1->size;
677ddaa4e7dStsutsui /* offset to start of real rsrc fork */
678ddaa4e7dStsutsui s_entry1->hfs_off = ntohl(ep->offset);
679ddaa4e7dStsutsui set_733((char *) s_entry1->isorec.size, s_entry1->size);
680ddaa4e7dStsutsui break;
681ddaa4e7dStsutsui case ID_NAME:
682ddaa4e7dStsutsui /* get Mac file name */
683ddaa4e7dStsutsui fseek(fp, ntohl(ep->offset), 0);
684ddaa4e7dStsutsui if(fread(name, ntohl(ep->length), 1, fp) < 1)
685ddaa4e7dStsutsui *name = '\0';
686ddaa4e7dStsutsui break;
687ddaa4e7dStsutsui default:
688ddaa4e7dStsutsui break;
689ddaa4e7dStsutsui }
690ddaa4e7dStsutsui }
691ddaa4e7dStsutsui
692ddaa4e7dStsutsui fclose(fp);
693ddaa4e7dStsutsui
694ddaa4e7dStsutsui /* skip this if we had a problem */
695ddaa4e7dStsutsui if (!fail) {
696ddaa4e7dStsutsui /* type and creator from finder info */
697ddaa4e7dStsutsui t = info.fdType;
698ddaa4e7dStsutsui c = info.fdCreator;
699ddaa4e7dStsutsui
700ddaa4e7dStsutsui strncpy(hfs_ent->type, t, CT_SIZE);
701ddaa4e7dStsutsui strncpy(hfs_ent->creator, c, CT_SIZE);
702ddaa4e7dStsutsui hfs_ent->type[CT_SIZE] = '\0';
703ddaa4e7dStsutsui hfs_ent->creator[CT_SIZE] = '\0';
704ddaa4e7dStsutsui
705ddaa4e7dStsutsui /* finder flags */
706ddaa4e7dStsutsui hfs_ent->fdflags = d_getw((unsigned char *)&info.fdFlags);
707ddaa4e7dStsutsui /* clear HFS_FNDR_HASBEENINITED to have tidy desktop ?? */
708ddaa4e7dStsutsui hfs_ent->fdflags &= 0xfeff;
709ddaa4e7dStsutsui
710ddaa4e7dStsutsui /* use stored name if it exists */
711ddaa4e7dStsutsui if (*name)
712ddaa4e7dStsutsui cstrncpy(hfs_ent->name, name, HFS_MAX_FLEN);
713ddaa4e7dStsutsui else
714ddaa4e7dStsutsui hstrncpy(hfs_ent->name, dname, HFS_MAX_FLEN);
715ddaa4e7dStsutsui }
716ddaa4e7dStsutsui }
717ddaa4e7dStsutsui else {
718ddaa4e7dStsutsui /* failed to open/read finderinfo */
719ddaa4e7dStsutsui fail = 1;
720ddaa4e7dStsutsui if (fp)
721ddaa4e7dStsutsui fclose(fp);
722ddaa4e7dStsutsui }
723ddaa4e7dStsutsui
724ddaa4e7dStsutsui if (fail) {
725ddaa4e7dStsutsui /* problem with the file - try mapping/magic */
726ddaa4e7dStsutsui if (verbose > 2) {
727ddaa4e7dStsutsui fprintf(stderr, "warning: %s doesn't appear to be a %s file\n",
728ddaa4e7dStsutsui s_entry->whole_name, hfs_types[ret].desc);
729ddaa4e7dStsutsui }
730ddaa4e7dStsutsui ret = get_none_info(hname, dname, s_entry, TYPE_NONE);
731ddaa4e7dStsutsui }
732ddaa4e7dStsutsui
733ddaa4e7dStsutsui return (ret);
734ddaa4e7dStsutsui }
735ddaa4e7dStsutsui /*
736ddaa4e7dStsutsui ** get_sgl_info: get Apple single finderinfo for a file
737ddaa4e7dStsutsui **
738ddaa4e7dStsutsui ** Based on code from cvt2cap.c (c) May 1988, Paul Campbell
739ddaa4e7dStsutsui */
740ddaa4e7dStsutsui int
get_sgl_info(char * hname,char * dname,dir_ent * s_entry,int ret)741ddaa4e7dStsutsui get_sgl_info(char *hname, char *dname, dir_ent *s_entry, int ret)
742ddaa4e7dStsutsui /* char *hname whole path */
743ddaa4e7dStsutsui /* char *dname this dir name */
744ddaa4e7dStsutsui /* dir_ent *s_entry directory entry */
745ddaa4e7dStsutsui {
746ddaa4e7dStsutsui FileInfo *info = 0; /* finderinfo struct */
747ddaa4e7dStsutsui a_hdr *hp;
748ddaa4e7dStsutsui static a_entry *entries;
749ddaa4e7dStsutsui a_entry *ep;
750ddaa4e7dStsutsui char *c;
751ddaa4e7dStsutsui char *t;
752ddaa4e7dStsutsui int nentries;
753ddaa4e7dStsutsui hfsdirent *hfs_ent;
754ddaa4e7dStsutsui dir_ent *s_entry1;
755ddaa4e7dStsutsui char name[64];
756ddaa4e7dStsutsui int i;
757ddaa4e7dStsutsui
758ddaa4e7dStsutsui /* routine called twice for each file - first to check that
759ddaa4e7dStsutsui it is a valid MacBinary file, second to fill in the HFS
760ddaa4e7dStsutsui info. p_buf holds the required raw data and it *should*
761ddaa4e7dStsutsui remain the same between the two calls */
762ddaa4e7dStsutsui
763ddaa4e7dStsutsui hp = (a_hdr *)p_buf;
764ddaa4e7dStsutsui
765ddaa4e7dStsutsui if (s_entry == 0) {
766ddaa4e7dStsutsui if (p_num < A_HDR_SIZE ||
767ddaa4e7dStsutsui ntohl(hp->magic) != APPLE_SINGLE ||
768ddaa4e7dStsutsui ntohl(hp->version) != A_VERSION)
769ddaa4e7dStsutsui return (TYPE_NONE);
770ddaa4e7dStsutsui
771ddaa4e7dStsutsui /* check we have TOC for the AppleSingle file */
772ddaa4e7dStsutsui nentries = (int)ntohs(hp->nentries);
773ddaa4e7dStsutsui if (p_num < (A_HDR_SIZE + nentries*A_ENTRY_SIZE))
774ddaa4e7dStsutsui return (TYPE_NONE);
775ddaa4e7dStsutsui
776ddaa4e7dStsutsui /* save the TOC */
777ddaa4e7dStsutsui entries = (a_entry *)e_malloc(nentries*A_ENTRY_SIZE);
778ddaa4e7dStsutsui
779ddaa4e7dStsutsui memcpy(entries, (p_buf+A_HDR_SIZE), nentries*A_ENTRY_SIZE);
780ddaa4e7dStsutsui }
781ddaa4e7dStsutsui else {
782ddaa4e7dStsutsui /* have a vaild AppleSingle File */
783ddaa4e7dStsutsui memset(name, 0, sizeof(name));
784ddaa4e7dStsutsui
785ddaa4e7dStsutsui /* get the rsrc file info - should exist ... */
786ddaa4e7dStsutsui if ((s_entry1 = s_entry->assoc) == NULL)
787ddaa4e7dStsutsui errx(1, "TYPE_SGL error - shouldn't happen!");
788ddaa4e7dStsutsui
789ddaa4e7dStsutsui hfs_ent = s_entry->hfs_ent;
790ddaa4e7dStsutsui
791ddaa4e7dStsutsui nentries = (int)ntohs(hp->nentries);
792ddaa4e7dStsutsui
793ddaa4e7dStsutsui /* extract what is needed */
794ddaa4e7dStsutsui for (i=0, ep=entries; i<nentries; i++,ep++) {
795ddaa4e7dStsutsui switch(ntohl(ep->id)) {
796ddaa4e7dStsutsui case ID_FINDER:
797ddaa4e7dStsutsui /* get the finder info */
798ddaa4e7dStsutsui info = (FileInfo *)(p_buf + ntohl(ep->offset));
799ddaa4e7dStsutsui break;
800ddaa4e7dStsutsui case ID_DATA:
801ddaa4e7dStsutsui /* set the offset and correct data fork size */
802ddaa4e7dStsutsui hfs_ent->dsize = s_entry->size = ntohl(ep->length);
803ddaa4e7dStsutsui /* offset to start of real data fork */
804ddaa4e7dStsutsui s_entry->hfs_off = ntohl(ep->offset);
805ddaa4e7dStsutsui set_733((char *) s_entry->isorec.size, s_entry->size);
806ddaa4e7dStsutsui break;
807ddaa4e7dStsutsui case ID_RESOURCE:
808ddaa4e7dStsutsui /* set the offset and correct rsrc fork size */
809ddaa4e7dStsutsui hfs_ent->rsize = s_entry1->size = ntohl(ep->length);
810ddaa4e7dStsutsui /* offset to start of real rsrc fork */
811ddaa4e7dStsutsui s_entry1->hfs_off = ntohl(ep->offset);
812ddaa4e7dStsutsui set_733((char *) s_entry1->isorec.size, s_entry1->size);
813ddaa4e7dStsutsui break;
814ddaa4e7dStsutsui case ID_NAME:
815ddaa4e7dStsutsui strncpy(name, (p_buf+ntohl(ep->offset)),
816ddaa4e7dStsutsui ntohl(ep->length));
817ddaa4e7dStsutsui break;
818ddaa4e7dStsutsui default:
819ddaa4e7dStsutsui break;
820ddaa4e7dStsutsui }
821ddaa4e7dStsutsui }
822ddaa4e7dStsutsui
823ddaa4e7dStsutsui free(entries);
824ddaa4e7dStsutsui
825ddaa4e7dStsutsui if (info == NULL) {
826ddaa4e7dStsutsui /* failed to open/read finderinfo - so try afpfile mapping */
827ddaa4e7dStsutsui if (verbose > 2) {
828ddaa4e7dStsutsui fprintf(stderr, "warning: %s doesn't appear to be a %s file\n",
829ddaa4e7dStsutsui s_entry->whole_name, hfs_types[ret].desc);
830ddaa4e7dStsutsui }
831ddaa4e7dStsutsui ret = get_none_info(hname, dname, s_entry, TYPE_NONE);
832ddaa4e7dStsutsui return (ret);
833ddaa4e7dStsutsui }
834ddaa4e7dStsutsui
835ddaa4e7dStsutsui /* type and creator from finder info */
836ddaa4e7dStsutsui t = info->fdType;
837ddaa4e7dStsutsui c = info->fdCreator;
838ddaa4e7dStsutsui
839ddaa4e7dStsutsui strncpy(hfs_ent->type, t, CT_SIZE);
840ddaa4e7dStsutsui strncpy(hfs_ent->creator, c, CT_SIZE);
841ddaa4e7dStsutsui hfs_ent->type[CT_SIZE] = '\0';
842ddaa4e7dStsutsui hfs_ent->creator[CT_SIZE] = '\0';
843ddaa4e7dStsutsui
844ddaa4e7dStsutsui /* finder flags */
845ddaa4e7dStsutsui hfs_ent->fdflags = d_getw((unsigned char *)&info->fdFlags);
846ddaa4e7dStsutsui /* clear HFS_FNDR_HASBEENINITED to have tidy desktop ?? */
847ddaa4e7dStsutsui hfs_ent->fdflags &= 0xfeff;
848ddaa4e7dStsutsui
849ddaa4e7dStsutsui /* use stored name if it exists */
850ddaa4e7dStsutsui if (*name)
851ddaa4e7dStsutsui cstrncpy(hfs_ent->name, name, HFS_MAX_FLEN);
852ddaa4e7dStsutsui else
853ddaa4e7dStsutsui hstrncpy(hfs_ent->name, dname, HFS_MAX_FLEN);
854ddaa4e7dStsutsui }
855ddaa4e7dStsutsui
856ddaa4e7dStsutsui return (ret);
857ddaa4e7dStsutsui }
858ddaa4e7dStsutsui
859ddaa4e7dStsutsui /*
860ddaa4e7dStsutsui ** get_hfs_fe_info: read in the whole finderinfo for a PC Exchange
861ddaa4e7dStsutsui ** directory - saves on reading this many times for each file.
862ddaa4e7dStsutsui **
863ddaa4e7dStsutsui ** Based of information provided by Mark Weinstein <mrwesq@earthlink.net>
864ddaa4e7dStsutsui **
865ddaa4e7dStsutsui ** Note: the FINDER.DAT file layout depends on the FAT cluster size
866ddaa4e7dStsutsui ** therefore, files should only be read directly from the FAT media
867ddaa4e7dStsutsui **
868ddaa4e7dStsutsui ** Only tested with PC Exchange v2.1 - don't know if it will work
869ddaa4e7dStsutsui ** with v2.2 and above.
870ddaa4e7dStsutsui */
871*61549db5Stsutsui static struct hfs_info *
get_hfs_fe_info(struct hfs_info * hfs_info,char * name)872ddaa4e7dStsutsui get_hfs_fe_info(struct hfs_info *hfs_info, char *name)
873ddaa4e7dStsutsui {
874ddaa4e7dStsutsui FILE *fp;
875ddaa4e7dStsutsui int fe_num, fe_pad;
876ddaa4e7dStsutsui fe_info info;
877ddaa4e7dStsutsui int c = 0;
878ddaa4e7dStsutsui struct hfs_info *hfs_info1 = NULL;
879ddaa4e7dStsutsui hfsdirent *hfs_ent;
880ddaa4e7dStsutsui char keyname[12];
881ddaa4e7dStsutsui char *s, *e, *k;
882ddaa4e7dStsutsui int i;
883ddaa4e7dStsutsui
884ddaa4e7dStsutsui if ((fp = fopen(name, "rb")) == NULL)
885ddaa4e7dStsutsui return(NULL);
886ddaa4e7dStsutsui
887785d5adeStsutsui /*
888785d5adeStsutsui * no longer attempt to find out FAT cluster
889785d5adeStsutsui * - rely on command line parameter
890785d5adeStsutsui */
891785d5adeStsutsui if (afe_size <= 0)
892ddaa4e7dStsutsui return(NULL);
893ddaa4e7dStsutsui
894785d5adeStsutsui fe_num = afe_size / FE_SIZE;
895785d5adeStsutsui fe_pad = afe_size % FE_SIZE;
896ddaa4e7dStsutsui
897ddaa4e7dStsutsui while(fread(&info, 1, FE_SIZE, fp) != 0) {
898ddaa4e7dStsutsui
899ddaa4e7dStsutsui /* the Mac name may be NULL - so ignore this entry */
900ddaa4e7dStsutsui if (info.nlen != 0) {
901ddaa4e7dStsutsui
902ddaa4e7dStsutsui hfs_info1 = (struct hfs_info *)e_malloc(sizeof(struct hfs_info));
903ddaa4e7dStsutsui /* add this entry to the list */
904ddaa4e7dStsutsui hfs_info1->next = hfs_info;
905ddaa4e7dStsutsui hfs_info = hfs_info1;
906ddaa4e7dStsutsui
907ddaa4e7dStsutsui hfs_ent = &hfs_info1->hfs_ent;
908ddaa4e7dStsutsui
909ddaa4e7dStsutsui /* get the bits we need - ignore [cm]time for the moment */
910ddaa4e7dStsutsui cstrncpy(hfs_ent->name, info.name, info.nlen);
911ddaa4e7dStsutsui
912ddaa4e7dStsutsui strncpy(hfs_ent->type, info.type, CT_SIZE);
913ddaa4e7dStsutsui strncpy(hfs_ent->creator, info.creator, CT_SIZE);
914ddaa4e7dStsutsui
915ddaa4e7dStsutsui hfs_ent->type[CT_SIZE] = hfs_ent->creator[CT_SIZE] = '\0';
916ddaa4e7dStsutsui
917ddaa4e7dStsutsui hfs_ent->fdflags = d_getw(info.flags);
918ddaa4e7dStsutsui
919ddaa4e7dStsutsui s = info.sname;
920ddaa4e7dStsutsui e = info.ext;
921ddaa4e7dStsutsui k = keyname;
922ddaa4e7dStsutsui
923ddaa4e7dStsutsui /* short (Unix) name is stored in PC format, so needs
924ddaa4e7dStsutsui to be mangled a bit */
925ddaa4e7dStsutsui
926ddaa4e7dStsutsui /* name part */
927ddaa4e7dStsutsui for(i=0;i<8;i++,s++,k++) {
928ddaa4e7dStsutsui if(*s == ' ')
929ddaa4e7dStsutsui break;
930ddaa4e7dStsutsui else
931ddaa4e7dStsutsui *k = *s;
932ddaa4e7dStsutsui }
933ddaa4e7dStsutsui
934ddaa4e7dStsutsui /* extension - if it exists */
935ddaa4e7dStsutsui if (strncmp(info.ext, " ", 3)) {
936ddaa4e7dStsutsui *k = '.';
937ddaa4e7dStsutsui k++;
938ddaa4e7dStsutsui for(i=0;i<3;i++,e++,k++) {
939ddaa4e7dStsutsui if(*e == ' ')
940ddaa4e7dStsutsui break;
941ddaa4e7dStsutsui else
942ddaa4e7dStsutsui *k = *e;
943ddaa4e7dStsutsui }
944ddaa4e7dStsutsui }
945ddaa4e7dStsutsui *k = '\0';
946ddaa4e7dStsutsui
947ddaa4e7dStsutsui hfs_info1->keyname = strdup(keyname);
948ddaa4e7dStsutsui }
949ddaa4e7dStsutsui
950ddaa4e7dStsutsui /* each record is FE_SIZE long, and there are FE_NUM
951ddaa4e7dStsutsui per each "cluster size", so we may need to skip the padding */
952ddaa4e7dStsutsui if (++c == fe_num) {
953ddaa4e7dStsutsui c = 0;
954ddaa4e7dStsutsui fseek(fp, fe_pad, 1);
955ddaa4e7dStsutsui }
956ddaa4e7dStsutsui }
957ddaa4e7dStsutsui fclose (fp);
958ddaa4e7dStsutsui
959ddaa4e7dStsutsui return (hfs_info);
960ddaa4e7dStsutsui }
961ddaa4e7dStsutsui
962ddaa4e7dStsutsui /*
963ddaa4e7dStsutsui ** get_hfs_sgi_info: read in the whole finderinfo for a SGI (XINET)
964ddaa4e7dStsutsui ** directory - saves on reading this many times for each
965ddaa4e7dStsutsui ** file.
966ddaa4e7dStsutsui */
967*61549db5Stsutsui static struct hfs_info *
get_hfs_sgi_info(struct hfs_info * hfs_info,char * name)968ddaa4e7dStsutsui get_hfs_sgi_info(struct hfs_info *hfs_info, char *name)
969ddaa4e7dStsutsui {
970ddaa4e7dStsutsui FILE *fp;
971ddaa4e7dStsutsui sgi_info info;
972ddaa4e7dStsutsui struct hfs_info *hfs_info1 = NULL;
973ddaa4e7dStsutsui hfsdirent *hfs_ent;
974ddaa4e7dStsutsui
975ddaa4e7dStsutsui if ((fp = fopen(name, "rb")) == NULL)
976ddaa4e7dStsutsui return(NULL);
977ddaa4e7dStsutsui
978ddaa4e7dStsutsui while(fread(&info, 1, SGI_SIZE, fp) != 0) {
979ddaa4e7dStsutsui
980ddaa4e7dStsutsui hfs_info1 = (struct hfs_info *)e_malloc(sizeof(struct hfs_info));
981ddaa4e7dStsutsui /* add thsi entry to the list */
982ddaa4e7dStsutsui hfs_info1->next = hfs_info;
983ddaa4e7dStsutsui hfs_info = hfs_info1;
984ddaa4e7dStsutsui
985ddaa4e7dStsutsui hfs_ent = &hfs_info1->hfs_ent;
986ddaa4e7dStsutsui
987ddaa4e7dStsutsui /* get the bits we need - ignore [cm]time for the moment */
988ddaa4e7dStsutsui cstrncpy(hfs_ent->name, info.name, HFS_MAX_FLEN);
989ddaa4e7dStsutsui
990ddaa4e7dStsutsui strncpy(hfs_ent->type, info.type, CT_SIZE);
991ddaa4e7dStsutsui strncpy(hfs_ent->creator, info.creator, CT_SIZE);
992ddaa4e7dStsutsui
993ddaa4e7dStsutsui hfs_ent->type[CT_SIZE] = hfs_ent->creator[CT_SIZE] = '\0';
994ddaa4e7dStsutsui
995ddaa4e7dStsutsui /* don't know about flags at the moment */
996ddaa4e7dStsutsui /* hfs_ent->fdflags = d_getw((unsigned char *)&info.flags); */
997ddaa4e7dStsutsui
998ddaa4e7dStsutsui /* use the HFS name as the key */
999ddaa4e7dStsutsui hfs_info1->keyname = hfs_ent->name;
1000ddaa4e7dStsutsui
1001ddaa4e7dStsutsui }
1002ddaa4e7dStsutsui fclose (fp);
1003ddaa4e7dStsutsui
1004ddaa4e7dStsutsui return (hfs_info);
1005ddaa4e7dStsutsui }
1006ddaa4e7dStsutsui
1007ddaa4e7dStsutsui /*
1008ddaa4e7dStsutsui ** del_hfs_info: delete the info list and recover memory
1009ddaa4e7dStsutsui */
1010ddaa4e7dStsutsui void
del_hfs_info(struct hfs_info * hfs_info)1011ddaa4e7dStsutsui del_hfs_info(struct hfs_info *hfs_info)
1012ddaa4e7dStsutsui {
1013ddaa4e7dStsutsui struct hfs_info *hfs_info1;
1014ddaa4e7dStsutsui
1015ddaa4e7dStsutsui while (hfs_info) {
1016ddaa4e7dStsutsui hfs_info1 = hfs_info;
1017ddaa4e7dStsutsui hfs_info = hfs_info->next;
1018ddaa4e7dStsutsui
1019ddaa4e7dStsutsui /* key may be the same as the HFS name - so don't free it */
1020ddaa4e7dStsutsui *hfs_info1->hfs_ent.name = '\0';
1021ddaa4e7dStsutsui if (*hfs_info1->keyname)
1022ddaa4e7dStsutsui free(hfs_info1->keyname);
1023ddaa4e7dStsutsui free(hfs_info1);
1024ddaa4e7dStsutsui }
1025ddaa4e7dStsutsui }
1026ddaa4e7dStsutsui
1027ddaa4e7dStsutsui /*
1028ddaa4e7dStsutsui ** match_key: find the correct hfs_ent using the Unix filename
1029ddaa4e7dStsutsui ** as the key
1030ddaa4e7dStsutsui */
1031*61549db5Stsutsui static hfsdirent *
match_key(struct hfs_info * hfs_info,const char * key)1032a11dc48bStsutsui match_key(struct hfs_info *hfs_info, const char *key)
1033ddaa4e7dStsutsui {
1034ddaa4e7dStsutsui while (hfs_info) {
1035ddaa4e7dStsutsui if (!strcasecmp(key, hfs_info->keyname))
1036ddaa4e7dStsutsui return (&hfs_info->hfs_ent);
1037ddaa4e7dStsutsui hfs_info = hfs_info->next;
1038ddaa4e7dStsutsui }
1039ddaa4e7dStsutsui
1040ddaa4e7dStsutsui return (NULL);
1041ddaa4e7dStsutsui }
1042ddaa4e7dStsutsui
1043ddaa4e7dStsutsui /*
1044ddaa4e7dStsutsui ** get_fe_dir: get PC Exchange directory name
1045ddaa4e7dStsutsui **
1046ddaa4e7dStsutsui ** base on probing with od ...
1047ddaa4e7dStsutsui */
1048ddaa4e7dStsutsui int
get_fe_dir(char * hname,const char * dname,dir_ent * s_entry,int ret)1049a11dc48bStsutsui get_fe_dir(char *hname, const char *dname, dir_ent *s_entry, int ret)
1050ddaa4e7dStsutsui /* char *hname whole path */
1051a11dc48bStsutsui /* const char *dname this dir name */
1052ddaa4e7dStsutsui /* dir_ent *s_entry directory entry */
1053ddaa4e7dStsutsui {
1054ddaa4e7dStsutsui struct hfs_info *hfs_info;
1055ddaa4e7dStsutsui hfsdirent *hfs_ent;
1056ddaa4e7dStsutsui
1057ddaa4e7dStsutsui /* cached finderinfo stored with parent directory */
1058ddaa4e7dStsutsui hfs_info = s_entry->filedir->hfs_info;
1059ddaa4e7dStsutsui
1060ddaa4e7dStsutsui /* if we have no cache, then make one and store it */
1061ddaa4e7dStsutsui if (hfs_info == NULL) {
1062ddaa4e7dStsutsui if ((hfs_info = get_hfs_fe_info(hfs_info, hname)) == NULL)
1063ddaa4e7dStsutsui ret = TYPE_NONE;
1064ddaa4e7dStsutsui else
1065ddaa4e7dStsutsui s_entry->filedir->hfs_info = hfs_info;
1066ddaa4e7dStsutsui }
1067ddaa4e7dStsutsui
1068ddaa4e7dStsutsui if (ret != TYPE_NONE) {
1069ddaa4e7dStsutsui /* see if we can find the details of this file */
1070ddaa4e7dStsutsui if ((hfs_ent = match_key(hfs_info, dname)) != NULL) {
1071ddaa4e7dStsutsui strcpy(s_entry->hfs_ent->name, hfs_ent->name);
1072ddaa4e7dStsutsui return (ret);
1073ddaa4e7dStsutsui }
1074ddaa4e7dStsutsui }
1075ddaa4e7dStsutsui
1076ddaa4e7dStsutsui /* can't find the entry, so use the Unix name */
1077ddaa4e7dStsutsui hstrncpy(s_entry->hfs_ent->name, dname, HFS_MAX_FLEN);
1078ddaa4e7dStsutsui
1079ddaa4e7dStsutsui return(TYPE_NONE);
1080ddaa4e7dStsutsui }
1081ddaa4e7dStsutsui
1082ddaa4e7dStsutsui /*
1083ddaa4e7dStsutsui ** get_fe_info: get PC Exchange file details.
1084ddaa4e7dStsutsui **
1085ddaa4e7dStsutsui ** base on probing with od and details from Mark Weinstein
1086ddaa4e7dStsutsui ** <mrwesq@earthlink.net>
1087ddaa4e7dStsutsui */
1088ddaa4e7dStsutsui int
get_fe_info(char * hname,char * dname,dir_ent * s_entry,int ret)1089ddaa4e7dStsutsui get_fe_info(char *hname, char *dname, dir_ent *s_entry, int ret)
1090ddaa4e7dStsutsui /* char *hname whole path */
1091ddaa4e7dStsutsui /* char *dname this dir name */
1092ddaa4e7dStsutsui /* dir_ent *s_entry directory entry */
1093ddaa4e7dStsutsui {
1094ddaa4e7dStsutsui struct hfs_info *hfs_info;
1095ddaa4e7dStsutsui hfsdirent *hfs_ent;
1096ddaa4e7dStsutsui
1097ddaa4e7dStsutsui /* cached finderinfo stored with parent directory */
1098ddaa4e7dStsutsui hfs_info = s_entry->filedir->hfs_info;
1099ddaa4e7dStsutsui
1100ddaa4e7dStsutsui /* if we have no cache, then make one and store it */
1101ddaa4e7dStsutsui if (hfs_info == NULL) {
1102ddaa4e7dStsutsui if ((hfs_info = get_hfs_fe_info(hfs_info, hname)) == NULL)
1103ddaa4e7dStsutsui ret = TYPE_NONE;
1104ddaa4e7dStsutsui else
1105ddaa4e7dStsutsui s_entry->filedir->hfs_info = hfs_info;
1106ddaa4e7dStsutsui }
1107ddaa4e7dStsutsui
1108ddaa4e7dStsutsui if (ret != TYPE_NONE) {
1109ddaa4e7dStsutsui char *dn = dname;
1110ddaa4e7dStsutsui #ifdef _WIN32_TEST
1111ddaa4e7dStsutsui /* may have a problem here - v2.2 has long filenames,
1112ddaa4e7dStsutsui but we need to key on the short filename, so we need
1113ddaa4e7dStsutsui do go a bit of win32 stuff ... */
1114ddaa4e7dStsutsui
1115ddaa4e7dStsutsui char sname[1024], lname[1024];
1116ddaa4e7dStsutsui
1117ddaa4e7dStsutsui cygwin32_conv_to_full_win32_path(s_entry->whole_name, lname);
1118ddaa4e7dStsutsui
1119ddaa4e7dStsutsui if (GetShortPathName(lname, sname, sizeof(sname))) {
1120ddaa4e7dStsutsui if (dn = strrchr(sname, '\\'))
1121ddaa4e7dStsutsui dn++;
1122ddaa4e7dStsutsui else
1123ddaa4e7dStsutsui dn = sname;
1124ddaa4e7dStsutsui }
1125ddaa4e7dStsutsui #endif /* _WIN32 */
1126ddaa4e7dStsutsui
1127ddaa4e7dStsutsui /* see if we can find the details of this file */
1128ddaa4e7dStsutsui if ((hfs_ent = match_key(hfs_info, dn)) != NULL) {
1129ddaa4e7dStsutsui strcpy(s_entry->hfs_ent->name, hfs_ent->name);
1130ddaa4e7dStsutsui strcpy(s_entry->hfs_ent->type, hfs_ent->type);
1131ddaa4e7dStsutsui strcpy(s_entry->hfs_ent->creator, hfs_ent->creator);
1132ddaa4e7dStsutsui /* clear HFS_FNDR_HASBEENINITED flag */
1133ddaa4e7dStsutsui s_entry->hfs_ent->fdflags = hfs_ent->fdflags & 0xfeff;
1134ddaa4e7dStsutsui return (ret);
1135ddaa4e7dStsutsui }
1136ddaa4e7dStsutsui }
1137ddaa4e7dStsutsui
1138ddaa4e7dStsutsui /* no entry found - use extension mapping */
1139ddaa4e7dStsutsui if (verbose > 2) {
1140ddaa4e7dStsutsui fprintf(stderr, "warning: %s doesn't appear to be a %s file\n",
1141ddaa4e7dStsutsui s_entry->whole_name, hfs_types[ret].desc);
1142ddaa4e7dStsutsui }
1143ddaa4e7dStsutsui
1144ddaa4e7dStsutsui ret = get_none_info(hname, dname, s_entry, TYPE_NONE);
1145ddaa4e7dStsutsui
1146ddaa4e7dStsutsui return(TYPE_NONE);
1147ddaa4e7dStsutsui }
1148ddaa4e7dStsutsui
1149ddaa4e7dStsutsui /*
1150ddaa4e7dStsutsui ** get_sgi_dir: get SGI (XINET) HFS directory name
1151ddaa4e7dStsutsui **
1152ddaa4e7dStsutsui ** base on probing with od ...
1153ddaa4e7dStsutsui */
1154ddaa4e7dStsutsui int
get_sgi_dir(char * hname,const char * dname,dir_ent * s_entry,int ret)1155a11dc48bStsutsui get_sgi_dir(char *hname, const char *dname, dir_ent *s_entry, int ret)
1156ddaa4e7dStsutsui /* char *hname whole path */
1157a11dc48bStsutsui /* const char *dname this dir name */
1158ddaa4e7dStsutsui /* dir_ent *s_entry directory entry */
1159ddaa4e7dStsutsui {
1160ddaa4e7dStsutsui struct hfs_info *hfs_info;
1161ddaa4e7dStsutsui hfsdirent *hfs_ent;
1162ddaa4e7dStsutsui
1163ddaa4e7dStsutsui /* cached finderinfo stored with parent directory */
1164ddaa4e7dStsutsui hfs_info = s_entry->filedir->hfs_info;
1165ddaa4e7dStsutsui
1166ddaa4e7dStsutsui /* if we haven't got a cache, then make one */
1167ddaa4e7dStsutsui if (hfs_info == NULL) {
1168ddaa4e7dStsutsui if ((hfs_info = get_hfs_sgi_info(hfs_info, hname)) == NULL)
1169ddaa4e7dStsutsui ret = TYPE_NONE;
1170ddaa4e7dStsutsui else
1171ddaa4e7dStsutsui s_entry->filedir->hfs_info = hfs_info;
1172ddaa4e7dStsutsui }
1173ddaa4e7dStsutsui
1174ddaa4e7dStsutsui /* find the matching entry in the cache */
1175ddaa4e7dStsutsui if (ret != TYPE_NONE) {
1176ddaa4e7dStsutsui /* key is (hopefully) the real Mac name */
1177ddaa4e7dStsutsui cstrncpy(tmp, dname, strlen(dname));
1178ddaa4e7dStsutsui if ((hfs_ent = match_key(hfs_info, tmp)) != NULL) {
1179ddaa4e7dStsutsui strcpy(s_entry->hfs_ent->name, hfs_ent->name);
1180ddaa4e7dStsutsui return (ret);
1181ddaa4e7dStsutsui }
1182ddaa4e7dStsutsui }
1183ddaa4e7dStsutsui
1184ddaa4e7dStsutsui /* no entry found - use Unix name */
1185ddaa4e7dStsutsui hstrncpy(s_entry->hfs_ent->name, dname, HFS_MAX_FLEN);
1186ddaa4e7dStsutsui
1187ddaa4e7dStsutsui return(TYPE_NONE);
1188ddaa4e7dStsutsui }
1189ddaa4e7dStsutsui
1190ddaa4e7dStsutsui /*
1191ddaa4e7dStsutsui ** get_sgi_info: get SGI (XINET) HFS finder info
1192ddaa4e7dStsutsui **
1193ddaa4e7dStsutsui ** base on probing with od ...
1194ddaa4e7dStsutsui */
1195ddaa4e7dStsutsui int
get_sgi_info(char * hname,char * dname,dir_ent * s_entry,int ret)1196ddaa4e7dStsutsui get_sgi_info(char *hname, char *dname, dir_ent *s_entry, int ret)
1197ddaa4e7dStsutsui /* char *hname whole path */
1198ddaa4e7dStsutsui /* char *dname this dir name */
1199ddaa4e7dStsutsui /* dir_ent *s_entry directory entry */
1200ddaa4e7dStsutsui {
1201ddaa4e7dStsutsui struct hfs_info *hfs_info;
1202ddaa4e7dStsutsui hfsdirent *hfs_ent;
1203ddaa4e7dStsutsui
1204ddaa4e7dStsutsui /* cached finderinfo stored with parent directory */
1205ddaa4e7dStsutsui hfs_info = s_entry->filedir->hfs_info;
1206ddaa4e7dStsutsui
1207ddaa4e7dStsutsui /* if we haven't got a cache, then make one */
1208ddaa4e7dStsutsui if (hfs_info == NULL) {
1209ddaa4e7dStsutsui if ((hfs_info = get_hfs_sgi_info(hfs_info, hname)) == NULL)
1210ddaa4e7dStsutsui ret = TYPE_NONE;
1211ddaa4e7dStsutsui else
1212ddaa4e7dStsutsui s_entry->filedir->hfs_info = hfs_info;
1213ddaa4e7dStsutsui }
1214ddaa4e7dStsutsui
1215ddaa4e7dStsutsui if (ret != TYPE_NONE) {
1216ddaa4e7dStsutsui /* tmp is the same as hname here, but we don't need hname
1217ddaa4e7dStsutsui anymore in this function ... see if we can find the
1218ddaa4e7dStsutsui details of this file using the Unix name as the key */
1219ddaa4e7dStsutsui cstrncpy(tmp, dname, strlen(dname));
1220ddaa4e7dStsutsui if ((hfs_ent = match_key(hfs_info, tmp)) != NULL) {
1221ddaa4e7dStsutsui strcpy(s_entry->hfs_ent->name, hfs_ent->name);
1222ddaa4e7dStsutsui strcpy(s_entry->hfs_ent->type, hfs_ent->type);
1223ddaa4e7dStsutsui strcpy(s_entry->hfs_ent->creator, hfs_ent->creator);
1224ddaa4e7dStsutsui /* s_entry->hfs_ent->fdflags = hfs_ent->fdflags; */
1225ddaa4e7dStsutsui return (ret);
1226ddaa4e7dStsutsui }
1227ddaa4e7dStsutsui }
1228ddaa4e7dStsutsui
1229ddaa4e7dStsutsui /* no entry found, so try file extension */
1230ddaa4e7dStsutsui if (verbose > 2) {
1231ddaa4e7dStsutsui fprintf(stderr, "warning: %s doesn't appear to be a %s file\n",
1232ddaa4e7dStsutsui s_entry->whole_name, hfs_types[ret].desc);
1233ddaa4e7dStsutsui }
1234ddaa4e7dStsutsui
1235ddaa4e7dStsutsui ret = get_none_info(hname, dname, s_entry, TYPE_NONE);
1236ddaa4e7dStsutsui
1237ddaa4e7dStsutsui return(TYPE_NONE);
1238ddaa4e7dStsutsui }
1239ddaa4e7dStsutsui
1240ddaa4e7dStsutsui /*
1241ddaa4e7dStsutsui ** get_hfs_itype: get the type of HFS info for a file
1242ddaa4e7dStsutsui */
1243*61549db5Stsutsui static int
get_hfs_itype(const char * wname,const char * dname,char * htmp)1244a11dc48bStsutsui get_hfs_itype(const char *wname, const char *dname, char *htmp)
1245ddaa4e7dStsutsui {
1246ddaa4e7dStsutsui int wlen, i;
1247ddaa4e7dStsutsui
1248ddaa4e7dStsutsui wlen = strlen(wname) - strlen(dname);
1249ddaa4e7dStsutsui
1250ddaa4e7dStsutsui /* search through the known types looking for matches */
1251ddaa4e7dStsutsui for (i=1;i<hfs_num;i++) {
1252ddaa4e7dStsutsui /* skip the ones that we don't care about */
1253ddaa4e7dStsutsui if ((hfs_types[i].flags & 0x1) || *(hfs_types[i].info) == TYPE_NONE)
1254ddaa4e7dStsutsui continue;
1255ddaa4e7dStsutsui
1256ddaa4e7dStsutsui strcpy(htmp, wname);
1257ddaa4e7dStsutsui
1258ddaa4e7dStsutsui sprintf(htmp+wlen, "%s%s", hfs_types[i].info,
1259ddaa4e7dStsutsui (hfs_types[i].flags & 0x2) ? "" : dname);
1260ddaa4e7dStsutsui if (!access(tmp, R_OK))
1261ddaa4e7dStsutsui return (hfs_types[i].type);
1262ddaa4e7dStsutsui }
1263ddaa4e7dStsutsui
1264ddaa4e7dStsutsui return (TYPE_NONE);
1265ddaa4e7dStsutsui }
1266ddaa4e7dStsutsui
1267ddaa4e7dStsutsui /*
1268ddaa4e7dStsutsui ** get_hfs_dir: set the HFS directory name
1269ddaa4e7dStsutsui */
1270ddaa4e7dStsutsui int
get_hfs_dir(const char * wname,const const char * dname,dir_ent * s_entry)1271a11dc48bStsutsui get_hfs_dir(const char *wname, const const char *dname, dir_ent *s_entry)
1272ddaa4e7dStsutsui {
1273ddaa4e7dStsutsui int type;
1274ddaa4e7dStsutsui
1275ddaa4e7dStsutsui /* get the HFS file type from the info file (if it exists) */
1276ddaa4e7dStsutsui type = get_hfs_itype(wname, dname, tmp);
1277ddaa4e7dStsutsui
1278ddaa4e7dStsutsui /* try to get the required info */
1279ddaa4e7dStsutsui type = (*(hfs_types[type].get_dir))(tmp, dname, s_entry, type);
1280ddaa4e7dStsutsui
1281ddaa4e7dStsutsui return (type);
1282ddaa4e7dStsutsui }
1283ddaa4e7dStsutsui
1284ddaa4e7dStsutsui /*
1285ddaa4e7dStsutsui ** get_hfs_info: set the HFS info for a file
1286ddaa4e7dStsutsui */
1287ddaa4e7dStsutsui int
get_hfs_info(char * wname,char * dname,dir_ent * s_entry)1288ddaa4e7dStsutsui get_hfs_info(char *wname, char *dname, dir_ent *s_entry)
1289ddaa4e7dStsutsui {
1290ddaa4e7dStsutsui int type, wlen, i;
1291ddaa4e7dStsutsui
1292ddaa4e7dStsutsui wlen = strlen(wname) - strlen(dname);
1293ddaa4e7dStsutsui
1294ddaa4e7dStsutsui /* we may already know the type of Unix/HFS file - so process */
1295ddaa4e7dStsutsui if (s_entry->hfs_type != TYPE_NONE) {
1296ddaa4e7dStsutsui
1297ddaa4e7dStsutsui /*
1298ddaa4e7dStsutsui i = 0;
1299ddaa4e7dStsutsui for(type=1;i<hfs_num;type++) {
1300ddaa4e7dStsutsui if (s_entry->hfs_type == hfs_types[type].type) {
1301ddaa4e7dStsutsui i = type;
1302ddaa4e7dStsutsui break;
1303ddaa4e7dStsutsui }
1304ddaa4e7dStsutsui }
1305ddaa4e7dStsutsui */
1306ddaa4e7dStsutsui type = s_entry->hfs_type;
1307ddaa4e7dStsutsui
1308ddaa4e7dStsutsui strcpy(tmp, wname);
1309ddaa4e7dStsutsui sprintf(tmp+wlen, "%s%s", hfs_types[type].info,
1310ddaa4e7dStsutsui (hfs_types[type].flags & 0x2) ? "" : dname);
1311ddaa4e7dStsutsui type = (*(hfs_types[type].get_info))(tmp, dname, s_entry, type);
1312ddaa4e7dStsutsui
1313ddaa4e7dStsutsui /* if everything is as expected, then return */
1314ddaa4e7dStsutsui if (s_entry->hfs_type == type)
1315ddaa4e7dStsutsui return(type);
1316ddaa4e7dStsutsui }
1317ddaa4e7dStsutsui
1318ddaa4e7dStsutsui /* we don't know what type we have so, find out */
1319ddaa4e7dStsutsui for (i=1;i<hfs_num;i++) {
1320ddaa4e7dStsutsui if ((hfs_types[i].flags & 0x1) || *(hfs_types[i].info) == TYPE_NONE)
1321ddaa4e7dStsutsui continue;
1322ddaa4e7dStsutsui
1323ddaa4e7dStsutsui strcpy(tmp, wname);
1324ddaa4e7dStsutsui
1325ddaa4e7dStsutsui sprintf(tmp+wlen, "%s%s", hfs_types[i].info,
1326ddaa4e7dStsutsui (hfs_types[i].flags & 0x2) ? "" : dname);
1327ddaa4e7dStsutsui
1328ddaa4e7dStsutsui /* if the file exists - and not a type we've already tried */
1329ddaa4e7dStsutsui if (!access(tmp, R_OK) && i != s_entry->hfs_type) {
1330ddaa4e7dStsutsui type = (*(hfs_types[i].get_info))(tmp, dname, s_entry, i);
1331ddaa4e7dStsutsui s_entry->hfs_type = type;
1332ddaa4e7dStsutsui return (type);
1333ddaa4e7dStsutsui }
1334ddaa4e7dStsutsui }
1335ddaa4e7dStsutsui
1336ddaa4e7dStsutsui /* nothing found, so just a Unix file */
1337ddaa4e7dStsutsui type = (*(hfs_types[TYPE_NONE].get_info))(wname, dname, s_entry, TYPE_NONE);
1338ddaa4e7dStsutsui
1339ddaa4e7dStsutsui return (type);
1340ddaa4e7dStsutsui }
1341ddaa4e7dStsutsui
1342ddaa4e7dStsutsui /*
1343ddaa4e7dStsutsui ** get_hfs_rname: set the name of the Unix rsrc file for a file
1344ddaa4e7dStsutsui */
1345ddaa4e7dStsutsui int
get_hfs_rname(char * wname,char * dname,char * rname)1346ddaa4e7dStsutsui get_hfs_rname(char *wname, char *dname, char *rname)
1347ddaa4e7dStsutsui {
1348ddaa4e7dStsutsui int wlen, type, i;
1349ddaa4e7dStsutsui int p_fd = -1;
1350ddaa4e7dStsutsui
1351ddaa4e7dStsutsui wlen = strlen(wname) - strlen(dname);
1352ddaa4e7dStsutsui
1353ddaa4e7dStsutsui /* try to find what sort of Unix HFS file type we have */
1354ddaa4e7dStsutsui for (i=1;i<hfs_num;i++) {
1355ddaa4e7dStsutsui /* skip if don't want to probe the files - (default) */
1356ddaa4e7dStsutsui if (hfs_types[i].flags & 0x1)
1357ddaa4e7dStsutsui continue;
1358ddaa4e7dStsutsui
1359ddaa4e7dStsutsui strcpy(rname, wname);
1360ddaa4e7dStsutsui
1361ddaa4e7dStsutsui /* if we have a different info file, the find out it's type */
1362ddaa4e7dStsutsui if (*(hfs_types[i].rsrc)) {
1363ddaa4e7dStsutsui sprintf(rname+wlen, "%s%s", hfs_types[i].rsrc, dname);
1364ddaa4e7dStsutsui if (!access(rname, R_OK))
1365ddaa4e7dStsutsui return (hfs_types[i].type);
1366ddaa4e7dStsutsui }
1367ddaa4e7dStsutsui else {
1368ddaa4e7dStsutsui /* if we are probing, then have a look at the contents to
1369ddaa4e7dStsutsui find type */
1370ddaa4e7dStsutsui if (p_fd < 0) {
1371ddaa4e7dStsutsui /* open file, if not already open */
1372ddaa4e7dStsutsui if((p_fd = open(wname, O_RDONLY | O_BINARY)) < 0) {
1373ddaa4e7dStsutsui /* can't open it, then give up */
1374ddaa4e7dStsutsui return (TYPE_NONE);
1375ddaa4e7dStsutsui } else {
1376ddaa4e7dStsutsui if((p_num = read(p_fd, p_buf, sizeof(p_buf))) <= 0) {
1377ddaa4e7dStsutsui /* can't read, or zero length - give up */
1378ddaa4e7dStsutsui close(p_fd);
1379ddaa4e7dStsutsui return(TYPE_NONE);
1380ddaa4e7dStsutsui }
1381ddaa4e7dStsutsui /* get file pointer and close file */
1382ddaa4e7dStsutsui p_fp = fdopen(p_fd, "rb");
1383ddaa4e7dStsutsui close(p_fd);
1384ddaa4e7dStsutsui if(p_fp == NULL)
1385ddaa4e7dStsutsui return(TYPE_NONE);
1386ddaa4e7dStsutsui }
1387ddaa4e7dStsutsui }
1388ddaa4e7dStsutsui /* call routine to do the work - use the given dname as
1389ddaa4e7dStsutsui this is the name we may use on the CD */
1390ddaa4e7dStsutsui type = (*(hfs_types[i].get_info))(rname, dname, 0, i);
1391ddaa4e7dStsutsui if (type != 0) {
1392ddaa4e7dStsutsui fclose(p_fp);
1393ddaa4e7dStsutsui return (type);
1394ddaa4e7dStsutsui }
1395ddaa4e7dStsutsui if (p_fp) {
1396ddaa4e7dStsutsui /* close file - just use contents of buffer next time */
1397ddaa4e7dStsutsui fclose(p_fp);
1398ddaa4e7dStsutsui p_fp = NULL;
1399ddaa4e7dStsutsui }
1400ddaa4e7dStsutsui }
1401ddaa4e7dStsutsui }
1402ddaa4e7dStsutsui
1403ddaa4e7dStsutsui return (0);
1404ddaa4e7dStsutsui }
1405ddaa4e7dStsutsui
1406ddaa4e7dStsutsui /*
1407ddaa4e7dStsutsui ** hfs_exclude: file/directory names that hold finder/resource
1408ddaa4e7dStsutsui ** information that we want to exclude from the tree.
1409ddaa4e7dStsutsui ** These files/directories are processed later ...
1410ddaa4e7dStsutsui */
1411ddaa4e7dStsutsui int
hfs_exclude(char * d_name)1412ddaa4e7dStsutsui hfs_exclude(char *d_name)
1413ddaa4e7dStsutsui {
1414ddaa4e7dStsutsui /* we don't exclude "." and ".." */
1415ddaa4e7dStsutsui if (!strcmp(d_name,"."))
1416ddaa4e7dStsutsui return 0;
1417ddaa4e7dStsutsui if (!strcmp(d_name,".."))
1418ddaa4e7dStsutsui return 0;
1419ddaa4e7dStsutsui
1420ddaa4e7dStsutsui /* do not add the following to our list of dir entries */
1421ddaa4e7dStsutsui if (DO_CAP & hselect) {
1422ddaa4e7dStsutsui /* CAP */
1423ddaa4e7dStsutsui if(!strcmp(d_name,".finderinfo"))
1424ddaa4e7dStsutsui return 1;
1425ddaa4e7dStsutsui if(!strcmp(d_name,".resource"))
1426ddaa4e7dStsutsui return 1;
1427ddaa4e7dStsutsui if(!strcmp(d_name,".ADeskTop"))
1428ddaa4e7dStsutsui return 1;
1429ddaa4e7dStsutsui if(!strcmp(d_name,".IDeskTop"))
1430ddaa4e7dStsutsui return 1;
1431ddaa4e7dStsutsui if(!strcmp(d_name,"Network Trash Folder"))
1432ddaa4e7dStsutsui return 1;
1433ddaa4e7dStsutsui /* special case when HFS volume is mounted using Linux's hfs_fs
1434ddaa4e7dStsutsui Brad Midgley <brad@pht.com> */
1435ddaa4e7dStsutsui if(!strcmp(d_name,".rootinfo"))
1436ddaa4e7dStsutsui return 1;
1437ddaa4e7dStsutsui }
1438ddaa4e7dStsutsui
1439ddaa4e7dStsutsui if (DO_ESH & hselect) {
1440ddaa4e7dStsutsui /* Helios EtherShare files */
1441ddaa4e7dStsutsui if(!strcmp(d_name,".rsrc"))
1442ddaa4e7dStsutsui return 1;
1443ddaa4e7dStsutsui if(!strcmp(d_name,".Desktop"))
1444ddaa4e7dStsutsui return 1;
1445ddaa4e7dStsutsui if(!strcmp(d_name,".DeskServer"))
1446ddaa4e7dStsutsui return 1;
1447ddaa4e7dStsutsui if(!strcmp(d_name,".Label"))
1448ddaa4e7dStsutsui return 1;
1449ddaa4e7dStsutsui }
1450ddaa4e7dStsutsui
1451ddaa4e7dStsutsui if (DO_DBL & hselect) {
1452ddaa4e7dStsutsui /* Apple Double */
1453ddaa4e7dStsutsui if (*d_name == '%')
1454ddaa4e7dStsutsui return 1;
1455ddaa4e7dStsutsui }
1456ddaa4e7dStsutsui
1457ddaa4e7dStsutsui if (DO_NETA & hselect) {
1458ddaa4e7dStsutsui if(!strcmp(d_name,".AppleDouble"))
1459ddaa4e7dStsutsui return 1;
1460ddaa4e7dStsutsui if(!strcmp(d_name,".AppleDesktop"))
1461ddaa4e7dStsutsui return 1;
1462ddaa4e7dStsutsui }
1463ddaa4e7dStsutsui
1464ddaa4e7dStsutsui if ((DO_FEU & hselect) || ( DO_FEL & hselect)) {
1465ddaa4e7dStsutsui /* PC Exchange */
1466ddaa4e7dStsutsui if(!strcmp(d_name,"RESOURCE.FRK"))
1467ddaa4e7dStsutsui return 1;
1468ddaa4e7dStsutsui if(!strcmp(d_name,"FINDER.DAT"))
1469ddaa4e7dStsutsui return 1;
1470ddaa4e7dStsutsui if(!strcmp(d_name,"DESKTOP"))
1471ddaa4e7dStsutsui return 1;
1472ddaa4e7dStsutsui if(!strcmp(d_name,"FILEID.DAT"))
1473ddaa4e7dStsutsui return 1;
1474ddaa4e7dStsutsui if(!strcmp(d_name,"resource.frk"))
1475ddaa4e7dStsutsui return 1;
1476ddaa4e7dStsutsui if(!strcmp(d_name,"finder.dat"))
1477ddaa4e7dStsutsui return 1;
1478ddaa4e7dStsutsui if(!strcmp(d_name,"desktop"))
1479ddaa4e7dStsutsui return 1;
1480ddaa4e7dStsutsui if(!strcmp(d_name,"fileid.dat"))
1481ddaa4e7dStsutsui return 1;
1482ddaa4e7dStsutsui }
1483ddaa4e7dStsutsui
1484ddaa4e7dStsutsui if (DO_SGI | hselect) {
1485ddaa4e7dStsutsui /* SGI */
1486ddaa4e7dStsutsui if(!strcmp(d_name,".HSResource"))
1487ddaa4e7dStsutsui return 1;
1488ddaa4e7dStsutsui if(!strcmp(d_name,".HSancillary"))
1489ddaa4e7dStsutsui return 1;
1490ddaa4e7dStsutsui }
1491ddaa4e7dStsutsui
1492ddaa4e7dStsutsui return 0;
1493ddaa4e7dStsutsui }
1494ddaa4e7dStsutsui /*
1495ddaa4e7dStsutsui ** print_hfs_info: print info about the HFS files.
1496ddaa4e7dStsutsui **
1497ddaa4e7dStsutsui */
1498ddaa4e7dStsutsui void
print_hfs_info(dir_ent * s_entry)1499ddaa4e7dStsutsui print_hfs_info(dir_ent *s_entry)
1500ddaa4e7dStsutsui {
1501ddaa4e7dStsutsui fprintf(stderr,"Name: %s\n",s_entry->whole_name);
1502ddaa4e7dStsutsui fprintf(stderr,"\tFile type: %s\n",hfs_types[s_entry->hfs_type].desc);
1503ddaa4e7dStsutsui fprintf(stderr,"\tHFS Name: %s\n",s_entry->hfs_ent->name);
1504ddaa4e7dStsutsui fprintf(stderr,"\tISO Name: %s\n",s_entry->isorec.name);
1505ddaa4e7dStsutsui fprintf(stderr,"\tCREATOR: %s\n",s_entry->hfs_ent->creator);
1506ddaa4e7dStsutsui fprintf(stderr,"\tTYPE: %s\n", s_entry->hfs_ent->type);
1507ddaa4e7dStsutsui }
1508ddaa4e7dStsutsui
1509ddaa4e7dStsutsui
1510ddaa4e7dStsutsui /*
1511ddaa4e7dStsutsui ** hfs_init: sets up the mapping list from the afpfile as well
1512ddaa4e7dStsutsui ** the default mapping (with or without) an afpfile
1513ddaa4e7dStsutsui */
1514ddaa4e7dStsutsui void
hfs_init(char * name,unsigned short fdflags,int probe,int nomacfiles,unsigned int hfs_select)1515ddaa4e7dStsutsui hfs_init(char *name, unsigned short fdflags, int probe, int nomacfiles,
1516ddaa4e7dStsutsui unsigned int hfs_select)
1517ddaa4e7dStsutsui #if 0
1518ddaa4e7dStsutsui char *name; /* afpfile name */
1519ddaa4e7dStsutsui u_short *fdflags; /* default finder flags */
1520ddaa4e7dStsutsui int probe; /* probe flag */
1521ddaa4e7dStsutsui int nomacfiles; /* don't look for mac files */
1522ddaa4e7dStsutsui u_int hfs_select /* select certain mac files */
1523ddaa4e7dStsutsui #endif
1524ddaa4e7dStsutsui {
1525ddaa4e7dStsutsui FILE *fp; /* File pointer */
1526ddaa4e7dStsutsui int count = NUMMAP; /* max number of entries */
1527ddaa4e7dStsutsui char buf[MAXPATHLEN]; /* working buffer */
1528ddaa4e7dStsutsui afpmap *amap; /* mapping entry */
1529ddaa4e7dStsutsui char *c, *t, *e;
1530ddaa4e7dStsutsui int i;
1531ddaa4e7dStsutsui
1532ddaa4e7dStsutsui /* setup number of Unix/HFS filetype - we may wish to not bother */
1533ddaa4e7dStsutsui if (nomacfiles)
1534ddaa4e7dStsutsui hfs_num = 0;
1535ddaa4e7dStsutsui else
1536ddaa4e7dStsutsui hfs_num = sizeof(hfs_types)/sizeof(struct hfs_type);
1537ddaa4e7dStsutsui
1538ddaa4e7dStsutsui /* we may want to probe all files */
1539ddaa4e7dStsutsui if (probe || hfs_select)
1540ddaa4e7dStsutsui for(i=0;i<hfs_num;i++)
1541ddaa4e7dStsutsui hfs_types[i].flags &= ~1; /* 0xfffffffe */
1542ddaa4e7dStsutsui
1543ddaa4e7dStsutsui /* if we have selected certain types of Mac/Unix files, then
1544ddaa4e7dStsutsui turn off the filetype */
1545ddaa4e7dStsutsui if (hfs_select)
1546ddaa4e7dStsutsui for(i=1;i<hfs_num;i++)
1547ddaa4e7dStsutsui if (!((1 << i) & hfs_select))
1548ddaa4e7dStsutsui hfs_types[i].flags |= 0x1;
1549ddaa4e7dStsutsui
1550ddaa4e7dStsutsui /* save what types have been selected (set all if none have) */
1551ddaa4e7dStsutsui if (hfs_select)
1552ddaa4e7dStsutsui hselect = hfs_select;
1553ddaa4e7dStsutsui else
1554ddaa4e7dStsutsui hselect = ~0;
1555ddaa4e7dStsutsui
1556ddaa4e7dStsutsui #ifdef DEBUG
1557ddaa4e7dStsutsui for(i=0;i<hfs_num;i++)
1558ddaa4e7dStsutsui fprintf(stderr,"type = %d flags = %d\n", i, hfs_types[i].flags);
1559ddaa4e7dStsutsui #endif /* DEBUG */
1560ddaa4e7dStsutsui
1561ddaa4e7dStsutsui /* min length set to max to start with */
1562ddaa4e7dStsutsui mlen = MAXPATHLEN;
1563ddaa4e7dStsutsui
1564ddaa4e7dStsutsui /* initialise magic file */
1565ddaa4e7dStsutsui if(magic_file && init_magic(magic_file) != 0)
1566ddaa4e7dStsutsui errx(1, "unable to open magic file");
1567ddaa4e7dStsutsui
1568ddaa4e7dStsutsui /* set defaults */
1569ddaa4e7dStsutsui map_num = last_ent = 0;
1570ddaa4e7dStsutsui
1571ddaa4e7dStsutsui /* allocate memory for the default entry */
1572ddaa4e7dStsutsui if((defmap = (afpmap *)malloc(sizeof(afpmap))) == NULL)
1573ddaa4e7dStsutsui errx(1, "not enough memory");
1574ddaa4e7dStsutsui
1575ddaa4e7dStsutsui /* set default values */
1576ddaa4e7dStsutsui defmap->extn = DEFMATCH;
1577ddaa4e7dStsutsui
1578ddaa4e7dStsutsui /* make sure creator and type are 4 chars long */
1579ddaa4e7dStsutsui strcpy(defmap->type, BLANK);
1580ddaa4e7dStsutsui strcpy(defmap->creator, BLANK);
1581ddaa4e7dStsutsui
1582ddaa4e7dStsutsui e = deftype;
1583ddaa4e7dStsutsui t = defmap->type;
1584ddaa4e7dStsutsui
1585ddaa4e7dStsutsui while(*e && (e - deftype) < CT_SIZE)
1586ddaa4e7dStsutsui *t++ = *e++;
1587ddaa4e7dStsutsui
1588ddaa4e7dStsutsui e = defcreator;
1589ddaa4e7dStsutsui c = defmap->creator;
1590ddaa4e7dStsutsui
1591ddaa4e7dStsutsui while(*e && (e - defcreator) < CT_SIZE)
1592ddaa4e7dStsutsui *c++ = *e++;
1593ddaa4e7dStsutsui
1594ddaa4e7dStsutsui /* length is not important here */
1595ddaa4e7dStsutsui defmap->elen = 0;
1596ddaa4e7dStsutsui
1597ddaa4e7dStsutsui /* no flags */
1598ddaa4e7dStsutsui defmap->fdflags = fdflags;
1599ddaa4e7dStsutsui
1600ddaa4e7dStsutsui /* no afpfile - no mappings */
1601ddaa4e7dStsutsui if (*name == '\0') {
1602ddaa4e7dStsutsui map = NULL;
1603ddaa4e7dStsutsui return;
1604ddaa4e7dStsutsui }
1605ddaa4e7dStsutsui
1606ddaa4e7dStsutsui if((fp = fopen(name,"r")) == NULL)
1607ddaa4e7dStsutsui err(1, "unable to open mapping file: %s", name);
1608ddaa4e7dStsutsui
1609ddaa4e7dStsutsui if((map = (afpmap **)malloc(NUMMAP * sizeof(afpmap *))) == NULL)
1610ddaa4e7dStsutsui errx(1, "not enough memory");
1611ddaa4e7dStsutsui
1612ddaa4e7dStsutsui /* read afpfile line by line */
1613ddaa4e7dStsutsui while(fgets(buf, MAXPATHLEN, fp) != NULL) {
1614ddaa4e7dStsutsui /* ignore any comment lines */
1615ddaa4e7dStsutsui c = tmp;
1616ddaa4e7dStsutsui *c = '\0';
1617ddaa4e7dStsutsui if (sscanf(buf,"%1s", c) == EOF || *c == '#')
1618ddaa4e7dStsutsui continue;
1619ddaa4e7dStsutsui
1620ddaa4e7dStsutsui /* increase list size if needed */
1621ddaa4e7dStsutsui if (map_num == count) {
1622ddaa4e7dStsutsui count += NUMMAP;
1623ddaa4e7dStsutsui map = (afpmap **)realloc(map, count * sizeof(afpmap *));
1624ddaa4e7dStsutsui if (map == NULL)
1625ddaa4e7dStsutsui errx(1, "not enough memory");
1626ddaa4e7dStsutsui }
1627ddaa4e7dStsutsui
1628ddaa4e7dStsutsui /* allocate memory for this entry */
1629ddaa4e7dStsutsui if((amap = (afpmap *)malloc(sizeof(afpmap))) == NULL)
1630ddaa4e7dStsutsui errx(1, "not enough memory");
1631ddaa4e7dStsutsui
1632ddaa4e7dStsutsui t = amap->type;
1633ddaa4e7dStsutsui c = amap->creator;
1634ddaa4e7dStsutsui
1635ddaa4e7dStsutsui /* extract the info */
1636ddaa4e7dStsutsui if(sscanf(buf, "%s%*s%*1s%c%c%c%c%*1s%*1s%c%c%c%c%*1s",
1637ddaa4e7dStsutsui tmp, c, c+1, c+2, c+3, t, t+1, t+2, t+3) != 9) {
1638ddaa4e7dStsutsui fprintf(stderr,"error scanning afpfile %s - continuing", name);
1639ddaa4e7dStsutsui free(amap);
1640ddaa4e7dStsutsui continue;
1641ddaa4e7dStsutsui }
1642ddaa4e7dStsutsui
1643ddaa4e7dStsutsui /* copy the extension found */
1644ddaa4e7dStsutsui if ((amap->extn = (char *)strdup(tmp)) == NULL)
1645ddaa4e7dStsutsui errx(1, "not enough memory");
1646ddaa4e7dStsutsui
1647ddaa4e7dStsutsui /* set end-of-string */
1648ddaa4e7dStsutsui *(t+4) = *(c+4) = '\0';
1649ddaa4e7dStsutsui
1650ddaa4e7dStsutsui /* find the length of the extension */
1651ddaa4e7dStsutsui amap->elen = strlen(amap->extn);
1652ddaa4e7dStsutsui
1653ddaa4e7dStsutsui /* set flags */
1654ddaa4e7dStsutsui amap->fdflags = fdflags;
1655ddaa4e7dStsutsui
1656ddaa4e7dStsutsui /* see if we have the default creator/type */
1657ddaa4e7dStsutsui if(!strcmp(amap->extn, DEFMATCH)) {
1658ddaa4e7dStsutsui /* get rid of the old default */
1659ddaa4e7dStsutsui free(defmap);
1660ddaa4e7dStsutsui /* make this the default */
1661ddaa4e7dStsutsui defmap = amap;
1662ddaa4e7dStsutsui continue;
1663ddaa4e7dStsutsui }
1664ddaa4e7dStsutsui
1665ddaa4e7dStsutsui /* update the smallest extension length */
1666ddaa4e7dStsutsui mlen = MIN(mlen, amap->elen);
1667ddaa4e7dStsutsui
1668ddaa4e7dStsutsui /* add entry to the list */
1669ddaa4e7dStsutsui map[map_num++] = amap;
1670ddaa4e7dStsutsui
1671ddaa4e7dStsutsui }
1672ddaa4e7dStsutsui
1673ddaa4e7dStsutsui /* free up some memory */
1674ddaa4e7dStsutsui if (map_num != count) {
1675ddaa4e7dStsutsui map = (afpmap **)realloc(map, map_num * sizeof(afpmap *));
1676ddaa4e7dStsutsui if (map == NULL)
1677ddaa4e7dStsutsui errx(1, "not enough memory");
1678ddaa4e7dStsutsui }
1679ddaa4e7dStsutsui
1680ddaa4e7dStsutsui }
1681ddaa4e7dStsutsui
1682ddaa4e7dStsutsui /*
1683ddaa4e7dStsutsui ** map_ext: map a files extension with the list to get type/creator
1684ddaa4e7dStsutsui */
1685ddaa4e7dStsutsui void
map_ext(char * name,char ** type,char ** creator,unsigned short * fdflags,char * whole_name)1686ddaa4e7dStsutsui map_ext(char *name, char **type, char **creator, unsigned short *fdflags,
1687ddaa4e7dStsutsui char *whole_name)
1688ddaa4e7dStsutsui #if 0
1689ddaa4e7dStsutsui char *name; /* filename */
1690ddaa4e7dStsutsui char **type; /* set type */
1691ddaa4e7dStsutsui char **creator; /* set creator */
1692ddaa4e7dStsutsui u_short *fdflags; /* set finder flags */
1693ddaa4e7dStsutsui #endif
1694ddaa4e7dStsutsui {
1695ddaa4e7dStsutsui int i; /* loop counter */
1696ddaa4e7dStsutsui int len; /* filename length */
1697ddaa4e7dStsutsui afpmap *amap; /* mapping entry */
1698ddaa4e7dStsutsui char *ret;
1699ddaa4e7dStsutsui
1700ddaa4e7dStsutsui /* we don't take fdflags from the map or magic file */
1701ddaa4e7dStsutsui *fdflags = defmap->fdflags;
1702ddaa4e7dStsutsui
1703ddaa4e7dStsutsui /* if we have a magic file and we want to search it first, then
1704ddaa4e7dStsutsui try to get a match */
1705ddaa4e7dStsutsui if (magic_file && hfs_last == MAP_LAST) {
1706ddaa4e7dStsutsui ret = get_magic_match(whole_name);
1707ddaa4e7dStsutsui
1708ddaa4e7dStsutsui if (ret) {
1709ddaa4e7dStsutsui if (sscanf(ret, "%4s%4s", tmp_creator, tmp_type) == 2) {
1710ddaa4e7dStsutsui *type = tmp_type;
1711ddaa4e7dStsutsui *creator = tmp_creator;
1712ddaa4e7dStsutsui return;
1713ddaa4e7dStsutsui }
1714ddaa4e7dStsutsui }
1715ddaa4e7dStsutsui }
1716ddaa4e7dStsutsui
1717ddaa4e7dStsutsui len = strlen(name);
1718ddaa4e7dStsutsui
1719ddaa4e7dStsutsui /* have an afpfile and filename if long enough */
1720ddaa4e7dStsutsui if(map && len >= mlen) {
1721ddaa4e7dStsutsui /* search through the list - we start where we left
1722ddaa4e7dStsutsui off last time in case this file is of the same type
1723ddaa4e7dStsutsui as the last one */
1724ddaa4e7dStsutsui for(i=0;i<map_num;i++) {
1725ddaa4e7dStsutsui amap = map[last_ent];
1726ddaa4e7dStsutsui
1727ddaa4e7dStsutsui /* compare the end of the filename */
1728ddaa4e7dStsutsui /* if (!strcmp((name + len - amap->elen), amap->extn)) { */
1729ddaa4e7dStsutsui if (!strcasecmp((name + len - amap->elen), amap->extn)) {
1730ddaa4e7dStsutsui /* set the required info */
1731ddaa4e7dStsutsui *type = amap->type;
1732ddaa4e7dStsutsui *creator = amap->creator;
1733ddaa4e7dStsutsui *fdflags = amap->fdflags;
1734ddaa4e7dStsutsui return;
1735ddaa4e7dStsutsui }
1736ddaa4e7dStsutsui /* move on to the next entry - wrapping round if neccessary */
1737ddaa4e7dStsutsui last_ent++;
1738ddaa4e7dStsutsui last_ent %= map_num;
1739ddaa4e7dStsutsui }
1740ddaa4e7dStsutsui }
1741ddaa4e7dStsutsui
1742ddaa4e7dStsutsui /* if no matches are found, file name too short, or no
1743ddaa4e7dStsutsui afpfile, then take defaults */
1744ddaa4e7dStsutsui *type = defmap->type;
1745ddaa4e7dStsutsui *creator = defmap->creator;
1746ddaa4e7dStsutsui
1747ddaa4e7dStsutsui /* if we have a magic file and we haven't searched yet, then try
1748ddaa4e7dStsutsui to get a match */
1749ddaa4e7dStsutsui if (magic_file && hfs_last == MAG_LAST) {
1750ddaa4e7dStsutsui ret = get_magic_match(whole_name);
1751ddaa4e7dStsutsui
1752ddaa4e7dStsutsui if (ret) {
1753ddaa4e7dStsutsui if (sscanf(ret, "%4s%4s", tmp_creator, tmp_type) == 2) {
1754ddaa4e7dStsutsui *type = tmp_type;
1755ddaa4e7dStsutsui *creator = tmp_creator;
1756ddaa4e7dStsutsui }
1757ddaa4e7dStsutsui }
1758ddaa4e7dStsutsui }
1759ddaa4e7dStsutsui }
1760ddaa4e7dStsutsui
1761ddaa4e7dStsutsui void
delete_rsrc_ent(dir_ent * s_entry)1762ddaa4e7dStsutsui delete_rsrc_ent(dir_ent *s_entry)
1763ddaa4e7dStsutsui {
1764ddaa4e7dStsutsui dir_ent *s_entry1 = s_entry->next;
1765ddaa4e7dStsutsui
1766ddaa4e7dStsutsui if (s_entry1 == NULL)
1767ddaa4e7dStsutsui return;
1768ddaa4e7dStsutsui
1769ddaa4e7dStsutsui s_entry->next = s_entry1->next;
1770ddaa4e7dStsutsui s_entry->assoc = NULL;
1771ddaa4e7dStsutsui
1772ddaa4e7dStsutsui free(s_entry1->name);
1773ddaa4e7dStsutsui free(s_entry1->whole_name);
1774ddaa4e7dStsutsui
1775ddaa4e7dStsutsui free(s_entry1);
1776ddaa4e7dStsutsui }
1777ddaa4e7dStsutsui
1778ddaa4e7dStsutsui void
clean_hfs()1779ddaa4e7dStsutsui clean_hfs()
1780ddaa4e7dStsutsui {
1781ddaa4e7dStsutsui if (map)
1782ddaa4e7dStsutsui free(map);
1783ddaa4e7dStsutsui
1784ddaa4e7dStsutsui if (defmap)
1785ddaa4e7dStsutsui free(defmap);
1786ddaa4e7dStsutsui
1787ddaa4e7dStsutsui if (magic_file)
1788ddaa4e7dStsutsui clean_magic();
1789ddaa4e7dStsutsui }
1790ddaa4e7dStsutsui
1791ddaa4e7dStsutsui #else
1792ddaa4e7dStsutsui #include <stdio.h>
1793ddaa4e7dStsutsui #endif /* APPLE_HYB */
1794