xref: /netbsd-src/external/gpl2/mkhybrid/dist/apple.c (revision 61549db5f15a0e24ae58567abcbc4f1f9328b9e6)
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