1*f0d9efc0Sbeck /*
2*f0d9efc0Sbeck * hfsutils - tools for reading and writing Macintosh HFS volumes
3*f0d9efc0Sbeck * Copyright (C) 1996, 1997 Robert Leslie
4*f0d9efc0Sbeck *
5*f0d9efc0Sbeck * This program is free software; you can redistribute it and/or modify
6*f0d9efc0Sbeck * it under the terms of the GNU General Public License as published by
7*f0d9efc0Sbeck * the Free Software Foundation; either version 2 of the License, or
8*f0d9efc0Sbeck * (at your option) any later version.
9*f0d9efc0Sbeck *
10*f0d9efc0Sbeck * This program is distributed in the hope that it will be useful,
11*f0d9efc0Sbeck * but WITHOUT ANY WARRANTY; without even the implied warranty of
12*f0d9efc0Sbeck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13*f0d9efc0Sbeck * GNU General Public License for more details.
14*f0d9efc0Sbeck *
15*f0d9efc0Sbeck * You should have received a copy of the GNU General Public License
16*f0d9efc0Sbeck * along with this program; if not, write to the Free Software
17*f0d9efc0Sbeck * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18*f0d9efc0Sbeck */
19*f0d9efc0Sbeck
20*f0d9efc0Sbeck # include <string.h>
21*f0d9efc0Sbeck # include <errno.h>
22*f0d9efc0Sbeck
23*f0d9efc0Sbeck # include "internal.h"
24*f0d9efc0Sbeck # include "data.h"
25*f0d9efc0Sbeck # include "block.h"
26*f0d9efc0Sbeck # include "file.h"
27*f0d9efc0Sbeck # include "btree.h"
28*f0d9efc0Sbeck # include "record.h"
29*f0d9efc0Sbeck # include "volume.h"
30*f0d9efc0Sbeck
31*f0d9efc0Sbeck /* #include <stdio.h> */
32*f0d9efc0Sbeck
33*f0d9efc0Sbeck
34*f0d9efc0Sbeck /*
35*f0d9efc0Sbeck * NAME: file->selectfork()
36*f0d9efc0Sbeck * DESCRIPTION: choose a fork for file operations
37*f0d9efc0Sbeck */
f_selectfork(hfsfile * file,int fork)38*f0d9efc0Sbeck void f_selectfork(hfsfile *file, int fork)
39*f0d9efc0Sbeck {
40*f0d9efc0Sbeck if (fork == 0)
41*f0d9efc0Sbeck {
42*f0d9efc0Sbeck file->fork = fkData;
43*f0d9efc0Sbeck memcpy(file->ext, file->cat.u.fil.filExtRec, sizeof(ExtDataRec));
44*f0d9efc0Sbeck }
45*f0d9efc0Sbeck else
46*f0d9efc0Sbeck {
47*f0d9efc0Sbeck file->fork = fkRsrc;
48*f0d9efc0Sbeck memcpy(file->ext, file->cat.u.fil.filRExtRec, sizeof(ExtDataRec));
49*f0d9efc0Sbeck }
50*f0d9efc0Sbeck
51*f0d9efc0Sbeck file->fabn = 0;
52*f0d9efc0Sbeck file->pos = 0;
53*f0d9efc0Sbeck }
54*f0d9efc0Sbeck
55*f0d9efc0Sbeck /*
56*f0d9efc0Sbeck * NAME: file->getptrs()
57*f0d9efc0Sbeck * DESCRIPTION: make pointers to the current fork's lengths and extents
58*f0d9efc0Sbeck */
f_getptrs(hfsfile * file,unsigned long ** lglen,unsigned long ** pylen,ExtDataRec ** extrec)59*f0d9efc0Sbeck void f_getptrs(hfsfile *file, unsigned long **lglen,
60*f0d9efc0Sbeck unsigned long **pylen, ExtDataRec **extrec)
61*f0d9efc0Sbeck {
62*f0d9efc0Sbeck if (file->fork == fkData)
63*f0d9efc0Sbeck {
64*f0d9efc0Sbeck if (lglen)
65*f0d9efc0Sbeck *lglen = &file->cat.u.fil.filLgLen;
66*f0d9efc0Sbeck if (pylen)
67*f0d9efc0Sbeck *pylen = &file->cat.u.fil.filPyLen;
68*f0d9efc0Sbeck if (extrec)
69*f0d9efc0Sbeck *extrec = &file->cat.u.fil.filExtRec;
70*f0d9efc0Sbeck }
71*f0d9efc0Sbeck else
72*f0d9efc0Sbeck {
73*f0d9efc0Sbeck if (lglen)
74*f0d9efc0Sbeck *lglen = &file->cat.u.fil.filRLgLen;
75*f0d9efc0Sbeck if (pylen)
76*f0d9efc0Sbeck *pylen = &file->cat.u.fil.filRPyLen;
77*f0d9efc0Sbeck if (extrec)
78*f0d9efc0Sbeck *extrec = &file->cat.u.fil.filRExtRec;
79*f0d9efc0Sbeck }
80*f0d9efc0Sbeck }
81*f0d9efc0Sbeck
82*f0d9efc0Sbeck /*
83*f0d9efc0Sbeck * NAME: file->doblock()
84*f0d9efc0Sbeck * DESCRIPTION: read or write a numbered block from a file
85*f0d9efc0Sbeck */
f_doblock(hfsfile * file,unsigned long num,block * bp,int (* func)(hfsvol *,unsigned int,unsigned int,block *))86*f0d9efc0Sbeck int f_doblock(hfsfile *file, unsigned long num, block *bp,
87*f0d9efc0Sbeck int (*func)(hfsvol *, unsigned int, unsigned int, block *))
88*f0d9efc0Sbeck {
89*f0d9efc0Sbeck unsigned int abnum;
90*f0d9efc0Sbeck unsigned int blnum;
91*f0d9efc0Sbeck unsigned int fabn;
92*f0d9efc0Sbeck int i;
93*f0d9efc0Sbeck
94*f0d9efc0Sbeck abnum = num / file->vol->lpa;
95*f0d9efc0Sbeck blnum = num % file->vol->lpa;
96*f0d9efc0Sbeck
97*f0d9efc0Sbeck /* locate the appropriate extent record */
98*f0d9efc0Sbeck
99*f0d9efc0Sbeck fabn = file->fabn;
100*f0d9efc0Sbeck
101*f0d9efc0Sbeck if (abnum < fabn)
102*f0d9efc0Sbeck {
103*f0d9efc0Sbeck ExtDataRec *extrec;
104*f0d9efc0Sbeck
105*f0d9efc0Sbeck f_getptrs(file, 0, 0, &extrec);
106*f0d9efc0Sbeck
107*f0d9efc0Sbeck fabn = file->fabn = 0;
108*f0d9efc0Sbeck memcpy(file->ext, extrec, sizeof(ExtDataRec));
109*f0d9efc0Sbeck }
110*f0d9efc0Sbeck else
111*f0d9efc0Sbeck abnum -= fabn;
112*f0d9efc0Sbeck
113*f0d9efc0Sbeck while (1)
114*f0d9efc0Sbeck {
115*f0d9efc0Sbeck unsigned int num;
116*f0d9efc0Sbeck
117*f0d9efc0Sbeck for (i = 0; i < 3; ++i)
118*f0d9efc0Sbeck {
119*f0d9efc0Sbeck num = file->ext[i].xdrNumABlks;
120*f0d9efc0Sbeck
121*f0d9efc0Sbeck #ifdef APPLE_HYB
122*f0d9efc0Sbeck if (i > 0) {
123*f0d9efc0Sbeck /* SHOULD NOT HAPPEN! - all the files should not be fragmented
124*f0d9efc0Sbeck if this happens, then a serious problem has occured, may be
125*f0d9efc0Sbeck a hard linked file? */
126*f0d9efc0Sbeck #ifdef DEBUG
127*f0d9efc0Sbeck fprintf(stderr,"file: %s %d\n",file->name, i); */
128*f0d9efc0Sbeck #endif /* DEBUG */
129*f0d9efc0Sbeck ERROR(HCE_ERROR, "Possible Catalog file overflow - please report error");
130*f0d9efc0Sbeck return -1;
131*f0d9efc0Sbeck }
132*f0d9efc0Sbeck #endif /* APPLE_HYB */
133*f0d9efc0Sbeck if (abnum < num)
134*f0d9efc0Sbeck return func(file->vol, file->ext[i].xdrStABN + abnum, blnum, bp);
135*f0d9efc0Sbeck
136*f0d9efc0Sbeck fabn += num;
137*f0d9efc0Sbeck abnum -= num;
138*f0d9efc0Sbeck }
139*f0d9efc0Sbeck
140*f0d9efc0Sbeck if (v_extsearch(file, fabn, &file->ext, 0) <= 0)
141*f0d9efc0Sbeck return -1;
142*f0d9efc0Sbeck
143*f0d9efc0Sbeck file->fabn = fabn;
144*f0d9efc0Sbeck }
145*f0d9efc0Sbeck }
146*f0d9efc0Sbeck
147*f0d9efc0Sbeck /*
148*f0d9efc0Sbeck * NAME: file->alloc()
149*f0d9efc0Sbeck * DESCRIPTION: reserve disk blocks for a file
150*f0d9efc0Sbeck */
f_alloc(hfsfile * file)151*f0d9efc0Sbeck int f_alloc(hfsfile *file)
152*f0d9efc0Sbeck {
153*f0d9efc0Sbeck hfsvol *vol = file->vol;
154*f0d9efc0Sbeck ExtDescriptor blocks;
155*f0d9efc0Sbeck ExtDataRec *extrec;
156*f0d9efc0Sbeck unsigned long *pylen, clumpsz;
157*f0d9efc0Sbeck unsigned int start, end;
158*f0d9efc0Sbeck node n;
159*f0d9efc0Sbeck int i;
160*f0d9efc0Sbeck
161*f0d9efc0Sbeck clumpsz = file->clump;
162*f0d9efc0Sbeck if (clumpsz == 0)
163*f0d9efc0Sbeck clumpsz = vol->mdb.drClpSiz;
164*f0d9efc0Sbeck
165*f0d9efc0Sbeck blocks.xdrNumABlks = clumpsz / vol->mdb.drAlBlkSiz;
166*f0d9efc0Sbeck
167*f0d9efc0Sbeck if (v_allocblocks(vol, &blocks) < 0)
168*f0d9efc0Sbeck return -1;
169*f0d9efc0Sbeck
170*f0d9efc0Sbeck /* update the file's extents */
171*f0d9efc0Sbeck
172*f0d9efc0Sbeck f_getptrs(file, 0, &pylen, &extrec);
173*f0d9efc0Sbeck
174*f0d9efc0Sbeck start = file->fabn;
175*f0d9efc0Sbeck end = *pylen / vol->mdb.drAlBlkSiz;
176*f0d9efc0Sbeck
177*f0d9efc0Sbeck n.nnum = 0;
178*f0d9efc0Sbeck i = -1;
179*f0d9efc0Sbeck
180*f0d9efc0Sbeck while (start < end)
181*f0d9efc0Sbeck {
182*f0d9efc0Sbeck for (i = 0; i < 3; ++i)
183*f0d9efc0Sbeck {
184*f0d9efc0Sbeck unsigned int num;
185*f0d9efc0Sbeck
186*f0d9efc0Sbeck num = file->ext[i].xdrNumABlks;
187*f0d9efc0Sbeck start += num;
188*f0d9efc0Sbeck
189*f0d9efc0Sbeck if (start == end)
190*f0d9efc0Sbeck break;
191*f0d9efc0Sbeck else if (start > end)
192*f0d9efc0Sbeck {
193*f0d9efc0Sbeck v_freeblocks(vol, &blocks);
194*f0d9efc0Sbeck ERROR(EIO, "file extents exceed file physical length");
195*f0d9efc0Sbeck return -1;
196*f0d9efc0Sbeck }
197*f0d9efc0Sbeck else if (num == 0)
198*f0d9efc0Sbeck {
199*f0d9efc0Sbeck v_freeblocks(vol, &blocks);
200*f0d9efc0Sbeck ERROR(EIO, "empty file extent");
201*f0d9efc0Sbeck return -1;
202*f0d9efc0Sbeck }
203*f0d9efc0Sbeck }
204*f0d9efc0Sbeck
205*f0d9efc0Sbeck if (start == end)
206*f0d9efc0Sbeck break;
207*f0d9efc0Sbeck
208*f0d9efc0Sbeck if (v_extsearch(file, start, &file->ext, &n) <= 0)
209*f0d9efc0Sbeck {
210*f0d9efc0Sbeck v_freeblocks(vol, &blocks);
211*f0d9efc0Sbeck return -1;
212*f0d9efc0Sbeck }
213*f0d9efc0Sbeck
214*f0d9efc0Sbeck file->fabn = start;
215*f0d9efc0Sbeck }
216*f0d9efc0Sbeck
217*f0d9efc0Sbeck if (i >= 0 &&
218*f0d9efc0Sbeck file->ext[i].xdrStABN + file->ext[i].xdrNumABlks == blocks.xdrStABN)
219*f0d9efc0Sbeck file->ext[i].xdrNumABlks += blocks.xdrNumABlks;
220*f0d9efc0Sbeck else
221*f0d9efc0Sbeck {
222*f0d9efc0Sbeck /* create a new extent descriptor */
223*f0d9efc0Sbeck
224*f0d9efc0Sbeck if (++i < 3)
225*f0d9efc0Sbeck file->ext[i] = blocks;
226*f0d9efc0Sbeck else
227*f0d9efc0Sbeck {
228*f0d9efc0Sbeck ExtKeyRec key;
229*f0d9efc0Sbeck unsigned char record[HFS_EXTRECMAXLEN];
230*f0d9efc0Sbeck int reclen;
231*f0d9efc0Sbeck
232*f0d9efc0Sbeck /* record is full; create a new one */
233*f0d9efc0Sbeck
234*f0d9efc0Sbeck file->ext[0] = blocks;
235*f0d9efc0Sbeck
236*f0d9efc0Sbeck for (i = 1; i < 3; ++i)
237*f0d9efc0Sbeck {
238*f0d9efc0Sbeck file->ext[i].xdrStABN = 0;
239*f0d9efc0Sbeck file->ext[i].xdrNumABlks = 0;
240*f0d9efc0Sbeck }
241*f0d9efc0Sbeck
242*f0d9efc0Sbeck file->fabn = start;
243*f0d9efc0Sbeck
244*f0d9efc0Sbeck r_makeextkey(&key, file->fork, file->cat.u.fil.filFlNum, end);
245*f0d9efc0Sbeck r_packextkey(&key, record, &reclen);
246*f0d9efc0Sbeck r_packextdata(&file->ext, HFS_RECDATA(record), &reclen);
247*f0d9efc0Sbeck
248*f0d9efc0Sbeck if (bt_insert(&vol->ext, record, reclen) < 0)
249*f0d9efc0Sbeck {
250*f0d9efc0Sbeck v_freeblocks(vol, &blocks);
251*f0d9efc0Sbeck return -1;
252*f0d9efc0Sbeck }
253*f0d9efc0Sbeck
254*f0d9efc0Sbeck i = -1;
255*f0d9efc0Sbeck }
256*f0d9efc0Sbeck }
257*f0d9efc0Sbeck
258*f0d9efc0Sbeck if (i >= 0)
259*f0d9efc0Sbeck {
260*f0d9efc0Sbeck /* store the modified extent record */
261*f0d9efc0Sbeck
262*f0d9efc0Sbeck if (file->fabn)
263*f0d9efc0Sbeck {
264*f0d9efc0Sbeck if ((n.nnum == 0 &&
265*f0d9efc0Sbeck v_extsearch(file, file->fabn, 0, &n) <= 0) ||
266*f0d9efc0Sbeck v_putextrec(&file->ext, &n) < 0)
267*f0d9efc0Sbeck {
268*f0d9efc0Sbeck v_freeblocks(vol, &blocks);
269*f0d9efc0Sbeck return -1;
270*f0d9efc0Sbeck }
271*f0d9efc0Sbeck }
272*f0d9efc0Sbeck else
273*f0d9efc0Sbeck memcpy(extrec, file->ext, sizeof(ExtDataRec));
274*f0d9efc0Sbeck }
275*f0d9efc0Sbeck
276*f0d9efc0Sbeck *pylen += blocks.xdrNumABlks * vol->mdb.drAlBlkSiz;
277*f0d9efc0Sbeck
278*f0d9efc0Sbeck file->flags |= HFS_UPDATE_CATREC;
279*f0d9efc0Sbeck
280*f0d9efc0Sbeck return blocks.xdrNumABlks;
281*f0d9efc0Sbeck }
282*f0d9efc0Sbeck
283*f0d9efc0Sbeck /*
284*f0d9efc0Sbeck * NAME: file->trunc()
285*f0d9efc0Sbeck * DESCRIPTION: release disk blocks unneeded by a file
286*f0d9efc0Sbeck */
f_trunc(hfsfile * file)287*f0d9efc0Sbeck int f_trunc(hfsfile *file)
288*f0d9efc0Sbeck {
289*f0d9efc0Sbeck ExtDataRec *extrec;
290*f0d9efc0Sbeck unsigned long *lglen, *pylen, alblksz, newpylen;
291*f0d9efc0Sbeck unsigned int dlen, start, end;
292*f0d9efc0Sbeck node n;
293*f0d9efc0Sbeck int i;
294*f0d9efc0Sbeck
295*f0d9efc0Sbeck f_getptrs(file, &lglen, &pylen, &extrec);
296*f0d9efc0Sbeck
297*f0d9efc0Sbeck alblksz = file->vol->mdb.drAlBlkSiz;
298*f0d9efc0Sbeck newpylen = (*lglen / alblksz + (*lglen % alblksz != 0)) * alblksz;
299*f0d9efc0Sbeck
300*f0d9efc0Sbeck if (newpylen > *pylen)
301*f0d9efc0Sbeck {
302*f0d9efc0Sbeck ERROR(EIO, "file size exceeds physical length");
303*f0d9efc0Sbeck return -1;
304*f0d9efc0Sbeck }
305*f0d9efc0Sbeck else if (newpylen == *pylen)
306*f0d9efc0Sbeck return 0;
307*f0d9efc0Sbeck
308*f0d9efc0Sbeck dlen = (*pylen - newpylen) / alblksz;
309*f0d9efc0Sbeck
310*f0d9efc0Sbeck start = file->fabn;
311*f0d9efc0Sbeck end = newpylen / alblksz;
312*f0d9efc0Sbeck
313*f0d9efc0Sbeck if (start >= end)
314*f0d9efc0Sbeck {
315*f0d9efc0Sbeck start = file->fabn = 0;
316*f0d9efc0Sbeck memcpy(file->ext, extrec, sizeof(ExtDataRec));
317*f0d9efc0Sbeck }
318*f0d9efc0Sbeck
319*f0d9efc0Sbeck n.nnum = 0;
320*f0d9efc0Sbeck i = -1;
321*f0d9efc0Sbeck
322*f0d9efc0Sbeck while (start < end)
323*f0d9efc0Sbeck {
324*f0d9efc0Sbeck for (i = 0; i < 3; ++i)
325*f0d9efc0Sbeck {
326*f0d9efc0Sbeck unsigned int num;
327*f0d9efc0Sbeck
328*f0d9efc0Sbeck num = file->ext[i].xdrNumABlks;
329*f0d9efc0Sbeck start += num;
330*f0d9efc0Sbeck
331*f0d9efc0Sbeck if (start >= end)
332*f0d9efc0Sbeck break;
333*f0d9efc0Sbeck else if (num == 0)
334*f0d9efc0Sbeck {
335*f0d9efc0Sbeck ERROR(EIO, "empty file extent");
336*f0d9efc0Sbeck return -1;
337*f0d9efc0Sbeck }
338*f0d9efc0Sbeck }
339*f0d9efc0Sbeck
340*f0d9efc0Sbeck if (start >= end)
341*f0d9efc0Sbeck break;
342*f0d9efc0Sbeck
343*f0d9efc0Sbeck if (v_extsearch(file, start, &file->ext, &n) <= 0)
344*f0d9efc0Sbeck return -1;
345*f0d9efc0Sbeck
346*f0d9efc0Sbeck file->fabn = start;
347*f0d9efc0Sbeck }
348*f0d9efc0Sbeck
349*f0d9efc0Sbeck if (start > end)
350*f0d9efc0Sbeck {
351*f0d9efc0Sbeck ExtDescriptor blocks;
352*f0d9efc0Sbeck
353*f0d9efc0Sbeck file->ext[i].xdrNumABlks -= start - end;
354*f0d9efc0Sbeck dlen -= start - end;
355*f0d9efc0Sbeck
356*f0d9efc0Sbeck blocks.xdrStABN = file->ext[i].xdrStABN + file->ext[i].xdrNumABlks;
357*f0d9efc0Sbeck blocks.xdrNumABlks = start - end;
358*f0d9efc0Sbeck
359*f0d9efc0Sbeck v_freeblocks(file->vol, &blocks);
360*f0d9efc0Sbeck }
361*f0d9efc0Sbeck
362*f0d9efc0Sbeck *pylen = newpylen;
363*f0d9efc0Sbeck
364*f0d9efc0Sbeck file->flags |= HFS_UPDATE_CATREC;
365*f0d9efc0Sbeck
366*f0d9efc0Sbeck do
367*f0d9efc0Sbeck {
368*f0d9efc0Sbeck while (dlen && ++i < 3)
369*f0d9efc0Sbeck {
370*f0d9efc0Sbeck unsigned int num;
371*f0d9efc0Sbeck
372*f0d9efc0Sbeck num = file->ext[i].xdrNumABlks;
373*f0d9efc0Sbeck start += num;
374*f0d9efc0Sbeck
375*f0d9efc0Sbeck if (num == 0)
376*f0d9efc0Sbeck {
377*f0d9efc0Sbeck ERROR(EIO, "empty file extent");
378*f0d9efc0Sbeck return -1;
379*f0d9efc0Sbeck }
380*f0d9efc0Sbeck else if (num > dlen)
381*f0d9efc0Sbeck {
382*f0d9efc0Sbeck ERROR(EIO, "file extents exceed physical size");
383*f0d9efc0Sbeck return -1;
384*f0d9efc0Sbeck }
385*f0d9efc0Sbeck
386*f0d9efc0Sbeck dlen -= num;
387*f0d9efc0Sbeck v_freeblocks(file->vol, &file->ext[i]);
388*f0d9efc0Sbeck
389*f0d9efc0Sbeck file->ext[i].xdrStABN = 0;
390*f0d9efc0Sbeck file->ext[i].xdrNumABlks = 0;
391*f0d9efc0Sbeck }
392*f0d9efc0Sbeck
393*f0d9efc0Sbeck if (file->fabn)
394*f0d9efc0Sbeck {
395*f0d9efc0Sbeck if (n.nnum == 0 &&
396*f0d9efc0Sbeck v_extsearch(file, file->fabn, 0, &n) <= 0)
397*f0d9efc0Sbeck return -1;
398*f0d9efc0Sbeck
399*f0d9efc0Sbeck if (file->ext[0].xdrNumABlks)
400*f0d9efc0Sbeck {
401*f0d9efc0Sbeck if (v_putextrec(&file->ext, &n) < 0)
402*f0d9efc0Sbeck return -1;
403*f0d9efc0Sbeck }
404*f0d9efc0Sbeck else
405*f0d9efc0Sbeck {
406*f0d9efc0Sbeck if (bt_delete(&file->vol->ext, HFS_NODEREC(n, n.rnum)) < 0)
407*f0d9efc0Sbeck return -1;
408*f0d9efc0Sbeck
409*f0d9efc0Sbeck n.nnum = 0;
410*f0d9efc0Sbeck }
411*f0d9efc0Sbeck }
412*f0d9efc0Sbeck else
413*f0d9efc0Sbeck memcpy(extrec, file->ext, sizeof(ExtDataRec));
414*f0d9efc0Sbeck
415*f0d9efc0Sbeck if (dlen)
416*f0d9efc0Sbeck {
417*f0d9efc0Sbeck if (v_extsearch(file, start, &file->ext, &n) <= 0)
418*f0d9efc0Sbeck return -1;
419*f0d9efc0Sbeck
420*f0d9efc0Sbeck file->fabn = start;
421*f0d9efc0Sbeck i = -1;
422*f0d9efc0Sbeck }
423*f0d9efc0Sbeck }
424*f0d9efc0Sbeck while (dlen);
425*f0d9efc0Sbeck
426*f0d9efc0Sbeck return 0;
427*f0d9efc0Sbeck }
428*f0d9efc0Sbeck
429*f0d9efc0Sbeck /*
430*f0d9efc0Sbeck * NAME: file->flush()
431*f0d9efc0Sbeck * DESCRIPTION: flush all pending changes to an open file
432*f0d9efc0Sbeck */
f_flush(hfsfile * file)433*f0d9efc0Sbeck int f_flush(hfsfile *file)
434*f0d9efc0Sbeck {
435*f0d9efc0Sbeck hfsvol *vol = file->vol;
436*f0d9efc0Sbeck
437*f0d9efc0Sbeck if (! (vol->flags & HFS_READONLY))
438*f0d9efc0Sbeck {
439*f0d9efc0Sbeck if (file->flags & HFS_UPDATE_CATREC)
440*f0d9efc0Sbeck {
441*f0d9efc0Sbeck node n;
442*f0d9efc0Sbeck
443*f0d9efc0Sbeck file->cat.u.fil.filStBlk = file->cat.u.fil.filExtRec[0].xdrStABN;
444*f0d9efc0Sbeck file->cat.u.fil.filRStBlk = file->cat.u.fil.filRExtRec[0].xdrStABN;
445*f0d9efc0Sbeck file->cat.u.fil.filClpSize = file->clump;
446*f0d9efc0Sbeck
447*f0d9efc0Sbeck if (v_catsearch(file->vol, file->parid, file->name, 0, 0, &n) <= 0 ||
448*f0d9efc0Sbeck v_putcatrec(&file->cat, &n) < 0)
449*f0d9efc0Sbeck return -1;
450*f0d9efc0Sbeck
451*f0d9efc0Sbeck file->flags &= ~HFS_UPDATE_CATREC;
452*f0d9efc0Sbeck }
453*f0d9efc0Sbeck }
454*f0d9efc0Sbeck
455*f0d9efc0Sbeck return 0;
456*f0d9efc0Sbeck }
457