📄 apple.c
字号:
/* @(#)apple.c 1.5 00/04/27 joerg, Copyright 1997, 1998, 1999, 2000 James Pearson */#ifndef lintstatic char sccsid[] = "@(#)apple.c 1.5 00/04/27 joerg, Copyright 1997, 1998, 1999, 2000 James Pearson";#endif/* * Copyright (c) 1997, 1998, 1999, 2000 James Pearson * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. *//* * Unix-HFS file interface including maping file extensions to TYPE/CREATOR * * Adapted from mkhfs routines for mkhybrid * * James Pearson 1/5/97 * Bug fix JCP 4/12/97 * Updated for 1.12 and added more Unix HFS filetypes. JCP 21/1/98 * Tidy up to use Finfo and Dinfo for all formats where * possible JCP 25/4/2000 * * Things still to de done: * * Check file size = finder + rsrc [+ data] is needed */#ifdef APPLE_HYB#include <mconfig.h>#include <stdio.h>#include <errno.h>#include <unixstd.h>#include <fctldefs.h>#include <mkisofs.h>#include <stdxlib.h>#include <ctype.h>#include <sys/types.h>#include <netinet/in.h>#include <apple.h>/* tidy up mkisofs definition ... */typedef struct directory_entry dir_ent;/* routines for getting HFS names and info */#ifndef HAVE_STRCASECMPstatic int strcasecmp __PR((const char *s1, const char *s2));#endifstatic int get_none_dir __PR((char *, char *, dir_ent *, int));static int get_none_info __PR((char *, char *, dir_ent *, int));static int get_cap_dir __PR((char *, char *, dir_ent *, int));static int get_cap_info __PR((char *, char *, dir_ent *, int));static int get_es_dir __PR((char *, char *, dir_ent *, int));static int get_es_info __PR((char *, char *, dir_ent *, int));static int get_dbl_dir __PR((char *, char *, dir_ent *, int));static int get_dbl_info __PR((char *, char *, dir_ent *, int));static int get_mb_info __PR((char *, char *, dir_ent *, int));static int get_sgl_info __PR((char *, char *, dir_ent *, int));static int get_fe_dir __PR((char *, char *, dir_ent *, int));static int get_fe_info __PR((char *, char *, dir_ent *, int));static int get_sgi_dir __PR((char *, char *, dir_ent *, int));static int get_sgi_info __PR((char *, char *, dir_ent *, int));static int get_sfm_info __PR((char *, char *, dir_ent *, int));static void set_ct __PR((hfsdirent *, char *, char *));static void set_Dinfo __PR((byte *, hfsdirent *));static void set_Finfo __PR((byte *, hfsdirent *));static void cstrncpy __PR((char *, char *, int));static unsigned char dehex __PR((char));static unsigned char hex2char __PR((char *));static void hstrncpy __PR((unsigned char *, char *, int));static int read_info_file __PR((char *, void *, int));/*static unsigned short calc_mb_crc __PR((unsigned char *, long, unsigned short));*/static struct hfs_info *get_hfs_fe_info __PR((struct hfs_info *, char *));static struct hfs_info *get_hfs_sgi_info __PR((struct hfs_info *, char *));static struct hfs_info *match_key __PR((struct hfs_info *, char *));static int get_hfs_itype __PR((char *, char *, char *));static void map_ext __PR((char *, char **, char **, short *, char *));static afpmap **map; /* list of mappings */static afpmap *defmap; /* the default mapping */static int last_ent; /* previous mapped entry */static int map_num; /* number of mappings */static int mlen; /* min extension length */static char tmp[PATH_MAX];/* tmp working buffer */static int hfs_num; /* number of file types */static char p_buf[PATH_MAX];/* info working buffer */static FILE *p_fp = NULL; /* probe File pointer */static int p_num = 0; /* probe bytes read */static unsigned int hselect; /* type of HFS file selected */struct hfs_type { /* Types of various HFS Unix files */ int type; /* type of file */ int flags; /* special flags */ char *info; /* finderinfo name */ char *rsrc; /* resource fork name */ int (*get_info) __PR((char *, char *, dir_ent *, int)); /* finderinfo * function */ int (*get_dir) __PR((char *, char *, dir_ent *, int)); /* directory * name * function */ char *desc; /* description */};/* Above filled in */static struct hfs_type hfs_types[] = { {TYPE_NONE, INSERT, "", "", get_none_info, get_none_dir, "None"}, {TYPE_CAP, INSERT, ".finderinfo/", ".resource/", get_cap_info, get_cap_dir, "CAP"}, {TYPE_NETA, INSERT, ".AppleDouble/", ".AppleDouble/", get_dbl_info, get_dbl_dir, "Netatalk"}, {TYPE_DBL, INSERT, "%", "%", get_dbl_info, get_dbl_dir, "AppleDouble"}, {TYPE_ESH, INSERT, ".rsrc/", ".rsrc/", get_es_info, get_es_dir, "EtherShare/UShare"}, {TYPE_FEU, NOPEND, "FINDER.DAT", "RESOURCE.FRK/", get_fe_info, get_fe_dir, "Exchange"}, {TYPE_FEL, NOPEND, "finder.dat", "resource.frk/", get_fe_info, get_fe_dir, "Exchange"}, {TYPE_SGI, NOPEND, ".HSancillary", ".HSResource/", get_sgi_info, get_sgi_dir, "XINET/SGI"}, {TYPE_MBIN, PROBE, "", "", get_mb_info, get_none_dir, "MacBinary"}, {TYPE_SGL, PROBE, "", "", get_sgl_info, get_none_dir, "AppleSingle"}, {TYPE_DAVE, INSERT, "resource.frk/", "resource.frk/", get_dbl_info, get_dbl_dir, "DAVE"}, {TYPE_SFM, APPEND | NORSRC, ":Afp_AfpInfo", ":Afp_Resource", get_sfm_info, get_none_dir, "SFM"}};/* used by get_magic_match() return */static char tmp_type[CT_SIZE + 1], tmp_creator[CT_SIZE + 1];#ifdef __used__/* * An array useful for CRC calculations that use 0x1021 as the "seed" * taken from mcvert.c modified by Jim Van Verth. */static unsigned short mb_magic[] = { 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0};#endif /* __used__ */#ifndef HAVE_STRCASECMPstatic intstrcasecmp(s1, s2) const char *s1; const char *s2;{ while (tolower(*s1) == tolower(*s2)) { if (*s1 == 0) return (0); s1++; s2++; } return (tolower(*s1) - tolower(*s2));}#endif/* * set_ct: set CREATOR and TYPE in hfs_ent * * CREATOR and TYPE are padded with spaces if not CT_SIZE long */static voidset_ct(hfs_ent, c, t) hfsdirent *hfs_ent; char *c; char *t;{ memset(hfs_ent->u.file.type, ' ', CT_SIZE); memset(hfs_ent->u.file.creator, ' ', CT_SIZE); strncpy(hfs_ent->u.file.type, t, MIN(CT_SIZE, strlen(t))); strncpy(hfs_ent->u.file.creator, c, MIN(CT_SIZE, strlen(c))); hfs_ent->u.file.type[CT_SIZE] = '\0'; hfs_ent->u.file.creator[CT_SIZE] = '\0'; return;}/* * cstrncopy: Cap Unix name to HFS name * * ':' is replaced by '%' and string is terminated with '\0' */static voidcstrncpy(t, f, c) char *t; char *f; int c;{ while (c-- && *f) { switch (*f) { case ':': *t = '%'; break; default: *t = *f; break; } t++; f++; } *t = '\0';}/* * dehex() * * Given a hexadecimal digit in ASCII, return the integer representation. * * Taken from linux/fs/hfs/trans.c by Paul H. Hargrove */#ifdef PROTOTYPESstatic unsigned chardehex(char c)#elsestatic unsigned chardehex(c) char c;#endif{ if ((c >= '0') && (c <= '9')) { return c - '0'; } if ((c >= 'a') && (c <= 'f')) { return c - 'a' + 10; } if ((c >= 'A') && (c <= 'F')) { return c - 'A' + 10; }/* return 0xff; */ return (0);}static unsigned charhex2char(s) char *s;{ unsigned char i1; unsigned char i2; unsigned char o; if (strlen(++s) < 2) return (0); i1 = (unsigned char) s[0]; i2 = (unsigned char) s[1]; if (!isxdigit(i1) || !isxdigit(i2)) return (0); o = (dehex(i1) << 4) & 0xf0; o |= (dehex(i2) & 0xf); return (o);}/* * hstrncpy: Unix name to HFS name with special character * translation. * * "%xx" or ":xx" is assumed to be a "special" character and * replaced by character code given by the hex characters "xx" * * if "xx" is not a hex number, then it is left alone - except * that ":" is replaced by "%" * */static voidhstrncpy(t, f, c) unsigned char *t; char *f; int c;{ unsigned char o; while (c-- && *f) { switch (*f) { case ':': case '%': if ((o = hex2char(f)) == 0) { *t = '%'; } else { *t = o; f += 2; } break; default: *t = *f; break; } t++; f++; } *t = '\0';}/* * basename: find just the filename with any directory component *//* not used at the moment ...static charbasename(a) char *a;{ char *b; if((b = strchr(a, '/'))) return(++b); else return(a);}*//* * set_Dinfo: set directory info */static voidset_Dinfo(ptr, ent) byte *ptr; hfsdirent *ent;{ Dinfo *dinfo = (Dinfo *)ptr; /* finder flags */ ent->fdflags = d_getw((unsigned char *) dinfo->frFlags); if (icon_pos) { ent->u.dir.rect.top = d_getw((unsigned char *) dinfo->frRect[0]); ent->u.dir.rect.left = d_getw((unsigned char *) dinfo->frRect[1]); ent->u.dir.rect.bottom = d_getw((unsigned char *) dinfo->frRect[2]); ent->u.dir.rect.right = d_getw((unsigned char *) dinfo->frRect[3]); ent->fdlocation.v = d_getw((unsigned char *) dinfo->frLocation[0]); ent->fdlocation.h = d_getw((unsigned char *) dinfo->frLocation[1]); ent->u.dir.view = d_getw((unsigned char *) dinfo->frView); ent->u.dir.frscroll.v = d_getw((unsigned char *) dinfo->frScroll[0]); ent->u.dir.frscroll.h = d_getw((unsigned char *) dinfo->frScroll[1]); } else { /* * clear HFS_FNDR_HASBEENINITED to have tidy desktop ?? */ ent->fdflags &= 0xfeff; }}/* * set_Finfo: set file info */static voidset_Finfo(ptr, ent) byte *ptr; hfsdirent *ent;{ Finfo *finfo = (Finfo *)ptr; /* type and creator from finder info */ set_ct(ent, finfo->fdCreator, finfo->fdType); /* finder flags */ ent->fdflags = d_getw((unsigned char *) finfo->fdFlags); if (icon_pos) { ent->fdlocation.v = d_getw((unsigned char *) finfo->fdLocation[0]); ent->fdlocation.h = d_getw((unsigned char *) finfo->fdLocation[1]); } else { /* * clear HFS_FNDR_HASBEENINITED to have tidy desktop ?? */ ent->fdflags &= 0xfeff; }}/* * get_none_dir: ordinary Unix directory */static intget_none_dir(hname, dname, s_entry, ret) char *hname; char *dname; dir_ent *s_entry; int ret;{ /* just copy the given name */ hstrncpy((unsigned char *) (s_entry->hfs_ent->name), dname, HFS_MAX_FLEN); return (ret);}/* * get_none_info: ordinary Unix file - try to map extension */static intget_none_info(hname, dname, s_entry, ret) char *hname; char *dname; dir_ent *s_entry; int ret;{ char *t, *c; hfsdirent *hfs_ent = s_entry->hfs_ent; map_ext(dname, &t, &c, &s_entry->hfs_ent->fdflags, s_entry->whole_name); /* just copy the given name */ hstrncpy((unsigned char *) (hfs_ent->name), dname, HFS_MAX_FLEN); set_ct(hfs_ent, c, t); return (ret);}/* * read_info_file: open and read a finderinfo file for an HFS file * or directory */static intread_info_file(name, info, len) char *name; /* finderinfo filename */ void *info; /* info buffer */ int len; /* length of above */{ FILE *fp; int num; /* clear out any old finderinfo stuf */ memset(info, 0, len); if ((fp = fopen(name, "rb")) == NULL) return (-1); /* read and ignore if the file is short - checked later */ num = fread(info, 1, len, fp); fclose(fp); return (num);}/* * get_cap_dir: get the CAP name for a directory */static intget_cap_dir(hname, dname, s_entry, ret) char *hname; /* whole path */ char *dname; /* this dir name */ dir_ent *s_entry; /* directory entry */ int ret;{ FileInfo info; /* finderinfo struct */ int num = -1; /* bytes read */ hfsdirent *hfs_ent = s_entry->hfs_ent; num = read_info_file(hname, &info, sizeof(FileInfo)); /* check finder info is OK */ if (num > 0 && info.fi_magic1 == FI_MAGIC1 && info.fi_magic == FI_MAGIC && info.fi_bitmap & FI_BM_MACINTOSHFILENAME) { /* use the finderinfo name if it exists */ cstrncpy((char *) (hfs_ent->name), (char *) (info.fi_macfilename), HFS_MAX_FLEN); set_Dinfo(info.finderinfo, hfs_ent); return (ret); } else { /* otherwise give it it's Unix name */ hstrncpy((unsigned char *) (s_entry->hfs_ent->name), dname, HFS_MAX_FLEN); return (TYPE_NONE); }}/*** get_cap_info: get CAP finderinfo for a file*/static intget_cap_info(hname, dname, s_entry, ret) char *hname; /* whole path */ char *dname; /* this dir name */ dir_ent *s_entry; /* directory entry */ int ret;{ FileInfo info; /* finderinfo struct */ int num = -1; /* bytes read */ hfsdirent *hfs_ent = s_entry->hfs_ent; num = read_info_file(hname, &info, sizeof(info)); /* check finder info is OK */ if (num > 0 && info.fi_magic1 == FI_MAGIC1 && info.fi_magic == FI_MAGIC) { if (info.fi_bitmap & FI_BM_MACINTOSHFILENAME) { /* use the finderinfo name if it exists */ cstrncpy((char *) (hfs_ent->name), (char *) (info.fi_macfilename), HFS_MAX_FLEN); } else { /* use Unix name */ hstrncpy((unsigned char *) (hfs_ent->name), dname, HFS_MAX_FLEN); } set_Finfo(info.finderinfo, hfs_ent);#ifdef USE_MAC_DATES /* * set created/modified dates - these date should have already * been set from the Unix data fork dates. The finderinfo dates * are in Mac format - but we have to convert them back to Unix * for the time being */ if ((info.fi_datemagic & FI_CDATE)) { /* use libhfs routines to get correct byte order */ hfs_ent->crdate = d_toutime(d_getl(info.fi_ctime)); } if (info.fi_datemagic & FI_MDATE) { hfs_ent->mddate = d_toutime(d_getl(info.fi_mtime)); }#endif /* USE_MAC_DATES */ } else { /* failed to open/read finderinfo - so try afpfile mapping */ if (verbose > 2) { fprintf(stderr, "warning: %s doesn't appear to be a %s file\n", s_entry->whole_name, hfs_types[ret].desc); } ret = get_none_info(hname, dname, s_entry, TYPE_NONE); } return (ret);}/* * get_es_dir: get EtherShare/UShare finderinfo for a directory * * based on code from Jens-Uwe Mager (jum@helios.de) and Phil Sylvester * <psylvstr@interaccess.com> */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -