📄 rf.c
字号:
/* * Author: Christopher G. Phillips * Copyright (C) 1994 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * The author makes no representations about the suitability of this * software for any purpose. This software is provided ``as is'' * without express or implied warranty. */#include <stdio.h>#include <stdlib.h>#include <limits.h>#include <sys/types.h>#include <netinet/in.h>#if CHAR_BIT == 8#if UCHAR_MAX == 255Utypedef unsigned char u8bit_t;#endif#elsetypedef no_8_bit_type u8bit_t; /* error */#endif#if USHRT_MAX == 65535Utypedef unsigned short u16bit_t;typedef short s16bit_t;#elsetypedef no_16_bit_type u16bit_t; /* error */#endif#if UINT_MAX == 4294967295Utypedef unsigned int u32bit_t;typedef int s32bit_t;#elsetypedef no_32_bit_type u32bit_t; /* error */#endifstruct header { u32bit_t data_offset; /* offset from beginning of resource file to resource data */ u32bit_t map_offset; /* offset from beginning of resource file to resource map */ u32bit_t data_length; /* Length of resource data */ u32bit_t map_length; /* Length of resource map */};#define HEADERSIZE 16struct map { /* * First there are 22 bytes of zeros: * * 16 bytes: reserved for copy of resource header * 4 bytes: reserved for handle to next resource map to be searched * 2 bytes: reserved for file reference number */ char header[16]; char handle[4]; char reference_number[2]; u16bit_t attributes; /* resource file attributes */ u16bit_t typelist_offset; /* offset from beginning of resource map to type list */ u16bit_t namelist_offset; /* offset from beginning of resource map to resource name list */};#define MAPSIZE 28/* * Resource file attributes */#define MAP_READ_ONLY 0x80 /* set if file is read-only */#define MAP_COMPACT 0x40 /* set to compact file on update */#define MAP_CHANGED 0x20 /* set to write map on update */struct type { char type[4]; /* resource type */ u16bit_t nresources; /* number of resources of this type in the map (NOT minus 1) */ u16bit_t offset; /* offset from beginning of type list to reference list for resources of this type */};#define TYPESIZE 8struct resource { u16bit_t ID; /* resource ID */ s16bit_t name_length_offset; /* offset from beginning of resource name list to length of resource name or -1 if none */ char attributes; /* resource attributes */ u32bit_t data_length_offset; /* offset from beginning of resource data to length of data for this resource */ /* NOTE: length_offset is really only 24 bits */};#define RESOURCESIZE 12/* * Resource attributes */#define RES_SYS_HEAP 0x40 /* set if read into system heap */#define RES_PURGEABLE 0x20 /* set if purgeable */#define RES_LOCKED 0x10 /* set if locked */#define RES_PROTECTED 0x08 /* set if protected */#define RES_PRELOAD 0x04 /* set if to be preloaded */#define RES_CHANGED 0x02 /* set if to be written to resource file *//* * #defines specific to this application */#define FREAD(nbytes, s, fp) if (fread(buf, 1, nbytes, fp) != nbytes) \ error("read from " s, fp)#define FREADM(nbytes, s, fp) if (fread(mbuf, 1, nbytes, fp) != nbytes) \ error("read from " s, fp)#define FSEEK(offset, s, fp) if (fseek(fp, offset, SEEK_SET) == -1) \ error("seek to " s, fp)#define CVT32(a, index) a = ntohl(*(u32bit_t *)&buf[index])#define CVT16(a, index) a = ntohs(*(u16bit_t *)&buf[index])voidod(unsigned char *buf, size_t length){ size_t nlines = (length + 15) / 16; size_t line; size_t left = length; short charnum; for (line = 0; line < nlines; line++) { for (charnum = 0; charnum < 16 && left; charnum++, left--) { if (charnum && (charnum % 2) == 0) putchar(' '); printf("%02x", buf[length - left]); } putchar('\n'); }}voidpstr(const unsigned char *s, int length){ while (length--) { if (isprint(*s)) putchar(*s); else printf("\\%0o", *s); s++; }}voiderror(char *s, FILE *fp){ if (fp && ferror(fp)) perror(s); else fprintf(stderr, "Bad file format: %s\n", s); exit(1);}voidprintrf(FILE *fp){ unsigned char buf[BUFSIZ]; int i; int j; long typelist_offset; long namelist_offset; long offset; struct header header; char system_use[112]; char app_data[128]; struct map map; u16bit_t ntypes; struct type type; struct resource resource; u8bit_t name_length; u32bit_t data_length; unsigned char *mbuf = NULL; long type_offset; long resource_offset; /* * Read the header. */ FREAD(HEADERSIZE, "header", fp); CVT32(header.data_offset, 0); CVT32(header.map_offset, 4); CVT32(header.data_length, 8); CVT32(header.map_length, 12); /* * The header is followed by 112 bytes reserved * for system use and then 128 bytes available * for application data. */ if (fread(system_use, 1, sizeof system_use, fp) != sizeof system_use) error("system_use", fp); if (fread(app_data, 1, sizeof app_data, fp) != sizeof app_data) error("app_data", fp); /* * Read the resource map. */ FSEEK(header.map_offset, "map", fp); FREAD(MAPSIZE, "map", fp); CVT16(map.attributes, 22); CVT16(map.typelist_offset, 24); typelist_offset = header.map_offset + map.typelist_offset; CVT16(map.namelist_offset, 26); namelist_offset = header.map_offset + map.namelist_offset; printf("Resource file attributes:"); if (map.attributes == 0) printf(" none"); else {#define DOATTR(attr, string) if (map.attributes & attr) { \ printf(" " string); \ map.attributes &= ~attr; \ } DOATTR(MAP_READ_ONLY, "read_only") DOATTR(MAP_COMPACT, "compact") DOATTR(MAP_CHANGED, "changed")#undef DOATTR } if (map.attributes) printf(" UNKNOWN"); printf("\n\n"); /* * The type list contains * * 2 bytes: number of resource types in the map minus 1 * * followed immediately by the types. */ FSEEK(typelist_offset, "type list", fp); FREAD(2, "type list", fp); CVT16(ntypes, 0); ntypes++; /* * Read the types. */ type_offset = typelist_offset + 2; for (i = 0; i < ntypes; i++, type_offset += TYPESIZE) { FSEEK(type_offset, "type", fp); FREAD(TYPESIZE, "type", fp); strncpy(type.type, buf, sizeof type.type); CVT16(type.nresources, 4); type.nresources++; CVT16(type.offset, 6); if (i) putchar('\n'); printf("Resource type: \"%4.4s\"\n", type.type); printf("\n"); /* * Read the resources. */ resource_offset = typelist_offset + type.offset; for (j = 0; j < type.nresources; j++, resource_offset += RESOURCESIZE) { FSEEK(resource_offset, "resource", fp); FREAD(RESOURCESIZE, "resource", fp); CVT16(resource.ID, 0); CVT16(resource.name_length_offset, 2); resource.attributes = buf[4]; CVT32(resource.data_length_offset, 4); resource.data_length_offset &= 0x00ffffff; if (j) putchar('\n'); printf("ID %d\n", resource.ID); printf("Attributes:"); if (resource.attributes == 0) printf(" none"); else {#define DOATTR(attr, string) if (resource.attributes & attr) { \ printf(" " string); \ resource.attributes &= ~attr; \ } DOATTR(RES_SYS_HEAP, "sys_head") DOATTR(RES_PURGEABLE, "purgeable") DOATTR(RES_LOCKED, "locked") DOATTR(RES_PROTECTED, "protected") DOATTR(RES_PRELOAD, "preload") DOATTR(RES_CHANGED, "changed")#undef DOATTR } if (resource.attributes) printf(" UNKNOWN"); putchar('\n'); if (resource.name_length_offset != -1) { /* * Read resource name. */ FSEEK(namelist_offset + resource.name_length_offset, "resource name", fp); FREAD(1, "resource name length", fp); name_length = buf[0]; FREAD(name_length, "actual resource name", fp); printf("Name length: %d\n", name_length); printf("Name: \""); pstr(buf, name_length); printf("\"\n"); } else printf("No name\n"); /* * Read resource data. */ FSEEK(header.data_offset + resource.data_length_offset, "resource data", fp); FREAD(4, "resource data length", fp); CVT32(data_length, 0); if (data_length && (mbuf = realloc(mbuf, data_length)) == NULL) { perror("realloc"); exit(1); } if (data_length) printf("Bytes %lx to %lx\n", (long)(header.data_offset + resource.data_length_offset) + 4, (long)(data_length + header.data_offset + resource.data_length_offset + 4 - 1)); FREADM(data_length, "actual resource data", fp); od(mbuf, data_length); } }}intmain(int argc, char **argv){ FILE *fp; if (--argc) { if ((fp = fopen(argv[1], "r")) == NULL) { perror(argv[1]); exit(1); } } else { fprintf(stderr, "Usage: %s filename\n", argv[0]); exit(2); } printrf(fp); exit(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -