"Fossies" - the Fresh Open Source Software Archive 
Member "mpack-1.6/macfile.c" (16 Feb 1995, 11034 Bytes) of package /linux/misc/old/mpack-1.6.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "macfile.c" see the
Fossies "Dox" file reference documentation.
1 /* macfile.c -- simple applesingle/appledouble encoding/decoding routines
2 */
3 /* (C) Copyright 1995 by Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify, distribute, and sell this software
7 * and its documentation for any purpose is hereby granted without
8 * fee, provided that the above copyright notice appear in all copies
9 * and that both that copyright notice and this permission notice
10 * appear in supporting documentation, and that the name of Carnegie
11 * Mellon University not be used in advertising or publicity
12 * pertaining to distribution of the software without specific,
13 * written prior permission. Carnegie Mellon University makes no
14 * representations about the suitability of this software for any
15 * purpose. It is provided "as is" without express or implied
16 * warranty.
17 *
18 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
19 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
20 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
21 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
23 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
24 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
25 * SOFTWARE.
26 */
27 /* (C) Copyright 1994-1995 by Christopher J. Newman
28 * All Rights Reserved.
29 *
30 * Permission to use, copy, modify, distribute, and sell this software and its
31 * documentation for any purpose is hereby granted without fee, provided that
32 * the above copyright notice appear in all copies and that both that
33 * copyright notice and this permission notice appear in supporting
34 * documentation, and that the name of Christopher J. Newman not be used in
35 * advertising or publicity pertaining to distribution of the software without
36 * specific, written prior permission. Christopher J. Newman makes no
37 * representations about the suitability of this software for any purpose. It
38 * is provided "as is" without express or implied warranty.
39 *
40 * CHRISTOPHER J. NEWMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
41 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
42 * SHALL CHRISTOPHER J. NEWMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR
43 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
44 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
45 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
46 * OF THIS SOFTWARE.
47 */
48
49 #include <stdio.h>
50 #include <string.h>
51 #include "macmpack.h" /* for copy_buf & watch */
52
53 /* applefile definitions used */
54 #define APPLESINGLE_MAGIC 0x00051600L
55 #define APPLEDOUBLE_MAGIC 0x00051607L
56 #define VERSION 0x00020000
57 #define ENT_DFORK 1
58 #define ENT_RFORK 2
59 #define ENT_NAME 3
60 #define ENT_COMMENT 4
61 #define ENT_DATES 8
62 #define ENT_FINFO 9
63 #define CONVERT_TIME 1265437696L
64
65 /* applefile structures */
66 typedef struct ap_header {
67 long magic;
68 long version;
69 char fill[16];
70 short entries;
71 } ap_header;
72 typedef struct ap_entry {
73 unsigned long id;
74 unsigned long offset;
75 unsigned long length;
76 } ap_entry;
77 typedef struct ap_dates {
78 long create, modify, backup, access;
79 } ap_dates;
80
81 /* default number of entries */
82 #define NUM_ENTRIES 6
83
84 /* Generate an applefile
85 * outfile -- output file
86 * fpb -- hierarchical file parameter block
87 * rfork, dfork -- resource & data forks
88 * returns -1 on failure, 0 on success
89 *
90 * closes dfork & rfork, but not outputfile
91 */
92 int encode_applefile(FILE *outfile, HFileInfo *fpb, FILE *rfork, FILE *dfork)
93 {
94 ap_header head;
95 ap_entry entries[NUM_ENTRIES];
96 ap_dates dates;
97 short i, count;
98 long comlen, procID;
99 DateTimeRec cur_time;
100 unsigned long cur_secs;
101 IOParam vinfo;
102 GetVolParmsInfoBuffer vp;
103 DTPBRec dtp;
104 char comment[256];
105
106 /* make sure things look OK */
107 if (!rfork || !outfile) {
108 if (rfork) fclose(rfork);
109 if (dfork) fclose(dfork);
110 if (outfile) fclose(outfile);
111 return (-1);
112 }
113
114 /* get a file comment, if possible */
115 procID = 0;
116 GetWDInfo(fpb->ioVRefNum, &fpb->ioVRefNum, &fpb->ioDirID, &procID);
117 memset((void *) &vinfo, '\0', sizeof (vinfo));
118 vinfo.ioVRefNum = fpb->ioVRefNum;
119 vinfo.ioBuffer = (Ptr) &vp;
120 vinfo.ioReqCount = sizeof (vp);
121 comlen = 0;
122 if (PBHGetVolParmsSync((HParmBlkPtr) &vinfo) == noErr &&
123 ((vp.vMAttrib >> bHasDesktopMgr) & 1)) {
124 memset((void *) &dtp, '\0', sizeof (dtp));
125 dtp.ioVRefNum = fpb->ioVRefNum;
126 if (PBDTGetPath(&dtp) == noErr) {
127 dtp.ioDTBuffer = (Ptr) comment;
128 dtp.ioNamePtr = fpb->ioNamePtr;
129 dtp.ioDirID = fpb->ioFlParID;
130 if (PBDTGetCommentSync(&dtp) == noErr) comlen = dtp.ioDTActCount;
131 }
132 }
133
134 /* write header */
135 head.magic = dfork ? APPLESINGLE_MAGIC : APPLEDOUBLE_MAGIC;
136 head.version = VERSION;
137 memset(head.fill, '\0', sizeof (head.fill));
138 head.entries = NUM_ENTRIES - (dfork ? 0 : 1);
139 fwrite((char *) &head, sizeof (head), 1, outfile);
140
141 /* write entry descriptors */
142 entries[0].offset = sizeof (head) + sizeof (ap_entry) * head.entries;
143 entries[0].id = ENT_NAME;
144 entries[0].length = *fpb->ioNamePtr;
145 entries[1].id = ENT_FINFO;
146 entries[1].length = sizeof (FInfo) + sizeof (FXInfo);
147 entries[2].id = ENT_DATES;
148 entries[2].length = sizeof (ap_dates);
149 entries[3].id = ENT_COMMENT;
150 entries[3].length = comlen;
151 entries[4].id = ENT_RFORK;
152 entries[4].length = fpb->ioFlRLgLen;
153 entries[5].id = ENT_DFORK;
154 entries[5].length = fpb->ioFlLgLen;
155 for (i = 1; i < NUM_ENTRIES; ++i) {
156 entries[i].offset = entries[i-1].offset + entries[i-1].length;
157 }
158 fwrite((char *) entries, sizeof (ap_entry), head.entries, outfile);
159
160 /* write name */
161 fwrite((char *) fpb->ioNamePtr + 1, *fpb->ioNamePtr, 1, outfile);
162 /* write finder info */
163 fwrite((char *) &fpb->ioFlFndrInfo, sizeof (FInfo), 1, outfile);
164 fwrite((char *) &fpb->ioFlXFndrInfo, sizeof (FXInfo), 1, outfile);
165 /* write dates */
166 GetTime(&cur_time);
167 Date2Secs(&cur_time, &cur_secs);
168 dates.create = fpb->ioFlCrDat + CONVERT_TIME;
169 dates.modify = fpb->ioFlMdDat + CONVERT_TIME;
170 dates.backup = fpb->ioFlBkDat + CONVERT_TIME;
171 dates.access = cur_secs + CONVERT_TIME;
172 fwrite((char *) &dates, sizeof (ap_dates), 1, outfile);
173 /* write comment */
174 if (comlen) fwrite(comment, sizeof (char), comlen, outfile);
175 /* write resource fork */
176 while ((count = fread(copy_buf, sizeof (char), sizeof (copy_buf), rfork)) > 0) {
177 fwrite(copy_buf, sizeof (char), count, outfile);
178 }
179 fclose(rfork);
180 /* write data fork */
181 if (dfork) {
182 while ((count = fread(copy_buf, sizeof (char), sizeof (copy_buf), dfork)) > 0) {
183 fwrite(copy_buf, sizeof (char), count, outfile);
184 }
185 fclose(dfork);
186 }
187
188 return (0);
189 }
190
191 /* decode an applefile
192 * infile -- input file
193 * fspec -- file spec of saved file
194 * returns -1 on failure, 0 on success
195 */
196 int decode_applefile(FILE *infile, FSSpec *fspec)
197 {
198 ap_header head;
199 ap_entry entries[NUM_ENTRIES + 1];
200 ap_dates dates;
201 StandardFileReply reply;
202 int i, j;
203 short refnum;
204 long count;
205 OSErr err;
206 HFileInfo *fpb;
207 CInfoPBRec cipbr;
208 long procID;
209 IOParam vinfo;
210 GetVolParmsInfoBuffer vp;
211 DTPBRec dtp;
212 char comment[256];
213
214 /* read & verify header */
215 fread((char *) &head, sizeof (head), 1, infile);
216 if (head.magic != APPLESINGLE_MAGIC && head.magic != APPLEDOUBLE_MAGIC) {
217 return (-1);
218 }
219 if (head.version != VERSION) {
220 return (-1);
221 }
222
223 /* read entries */
224 for (i = j = 0; i < head.entries; ++i) {
225 fread((char *) (entries + j), sizeof (ap_entry), 1, infile);
226 if (j < NUM_ENTRIES) switch (entries[j].id) {
227 case ENT_NAME:
228 case ENT_FINFO:
229 case ENT_DATES:
230 case ENT_COMMENT:
231 case ENT_RFORK:
232 case ENT_DFORK:
233 ++j;
234 break;
235 }
236 }
237
238 /* read name */
239 for (i = 0; i < j && entries[i].id != ENT_NAME; ++i);
240 if (i == j) return (-1);
241 fseek(infile, entries[i].offset, SEEK_SET);
242 if (entries[i].length > 63) entries[i].length = 63;
243 *fspec->name = fread((char *) fspec->name + 1, sizeof (char), entries[i].length, infile);
244 SetCursor(&arrow);
245 NAputFile("\pSave decoded file as:", fspec->name, &reply);
246 SetCursor(&watch);
247 statrefresh();
248 if (!reply.sfGood) return (didchat = -1);
249 *fspec = reply.sfFile;
250
251 /* create & get info for file */
252 if (reply.sfReplacing) HDelete(fspec->vRefNum, fspec->parID, fspec->name);
253 if (HCreate(fspec->vRefNum, fspec->parID, fspec->name, '????', '????') != noErr) {
254 return (-1);
255 }
256 fpb = (HFileInfo *) &cipbr;
257 fpb->ioVRefNum = fspec->vRefNum;
258 fpb->ioNamePtr = fspec->name;
259 fpb->ioDirID = fspec->parID;
260 fpb->ioFDirIndex = 0;
261 PBGetCatInfoSync(&cipbr);
262
263 /* get finder info */
264 for (i = 0; i < j && entries[i].id != ENT_FINFO; ++i);
265 if (i < j) {
266 fseek(infile, entries[i].offset, SEEK_SET);
267 fread((char *) &fpb->ioFlFndrInfo, sizeof (FInfo), 1, infile);
268 fread((char *) &fpb->ioFlXFndrInfo, sizeof (FXInfo), 1, infile);
269 fpb->ioFlFndrInfo.fdFlags &= 0xf800; /* clear flags maintained by finder */
270 }
271
272 /* get file date info */
273 for (i = 0; i < j && entries[i].id != ENT_DATES; ++i);
274 if (i < j) {
275 fseek(infile, entries[i].offset, SEEK_SET);
276 fread((char *) &dates, sizeof (dates), 1, infile);
277 fpb->ioFlCrDat = dates.create - CONVERT_TIME;
278 fpb->ioFlMdDat = dates.modify - CONVERT_TIME;
279 fpb->ioFlBkDat = dates.backup - CONVERT_TIME;
280 }
281
282 /* update info */
283 fpb->ioDirID = fpb->ioFlParID;
284 PBSetCatInfoSync(&cipbr);
285
286 /* get comment & save it */
287 for (i = 0; i < j && entries[i].id != ENT_COMMENT; ++i);
288 if (i < j && entries[i].length != 0) {
289 memset((void *) &vinfo, '\0', sizeof (vinfo));
290 vinfo.ioVRefNum = fpb->ioVRefNum;
291 vinfo.ioBuffer = (Ptr) &vp;
292 vinfo.ioReqCount = sizeof (vp);
293 if (PBHGetVolParmsSync((HParmBlkPtr) &vinfo) == noErr &&
294 ((vp.vMAttrib >> bHasDesktopMgr) & 1)) {
295 memset((void *) &dtp, '\0', sizeof (dtp));
296 dtp.ioVRefNum = fpb->ioVRefNum;
297 if (PBDTGetPath(&dtp) == noErr) {
298 if (entries[i].length > 255) entries[i].length = 255;
299 fseek(infile, entries[i].offset, SEEK_SET);
300 fread(comment, entries[i].length, 1, infile);
301 dtp.ioDTBuffer = (Ptr) comment;
302 dtp.ioNamePtr = fpb->ioNamePtr;
303 dtp.ioDirID = fpb->ioDirID;
304 dtp.ioDTReqCount = entries[i].length;
305 if (PBDTSetCommentSync(&dtp) == noErr) {
306 PBDTFlushSync(&dtp);
307 }
308 }
309 }
310 }
311
312 /* do resource/data forks */
313 for (i = 0; i < j; ++i) {
314 if (entries[i].id == ENT_RFORK || entries[i].id == ENT_DFORK) {
315 fseek(infile, entries[i].offset, SEEK_SET);
316 if (entries[i].id == ENT_DFORK) {
317 err = HOpen(fspec->vRefNum, fspec->parID, fspec->name, 2, &refnum);
318 } else {
319 err = HOpenRF(fspec->vRefNum, fspec->parID, fspec->name, 2, &refnum);
320 }
321 if (err != noErr) {
322 HDelete(fspec->vRefNum, fspec->parID, fspec->name);
323 return (-1);
324 }
325 while (entries[i].length > sizeof (copy_buf)) {
326 count = fread(copy_buf, sizeof (char), sizeof (copy_buf), infile);
327 entries[i].length -= count;
328 FSWrite(refnum, &count, (Ptr) copy_buf);
329 }
330 count = fread(copy_buf, sizeof (char), entries[i].length, infile);
331 FSWrite(refnum, &count, (Ptr) copy_buf);
332 FSClose(refnum);
333 }
334 }
335
336 return (0);
337 }