xref: /dragonfly/sys/vfs/hpfs/hpfs_subr.c (revision b1999ea8e0519ad29816e6e3462677466770be1e)
1 /*-
2  * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org)
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD: src/sys/fs/hpfs/hpfs_subr.c,v 1.1 1999/12/09 19:09:59 semenu Exp $
27  */
28 
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/kernel.h>
32 #include <sys/proc.h>
33 #include <sys/time.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <sys/vnode.h>
37 #include <sys/mount.h>
38 #include <sys/malloc.h>
39 #include <sys/buf.h>
40 
41 #include <sys/buf2.h>
42 
43 #include "hpfs.h"
44 #include "hpfsmount.h"
45 #include "hpfs_subr.h"
46 
47 u_long
hpfs_checksum(u_int8_t * object,int size)48 hpfs_checksum(
49           u_int8_t *object,
50           int size)
51 {
52           int i;
53           u_long csum=0L;
54           for (i=0; i < size; i++) {
55                     csum += (u_long) *object++;
56                     csum = (csum << 7) + (csum >> (25));
57           }
58           return (csum);
59 }
60 
61 void
hpfs_bmdeinit(struct hpfsmount * hpmp)62 hpfs_bmdeinit(
63           struct hpfsmount *hpmp)
64 {
65           struct buf *bp;
66           int i;
67 
68           dprintf(("hpmp_bmdeinit: "));
69 
70           if (!(hpmp->hpm_mp->mnt_flag & MNT_RDONLY)) {
71                     /*
72                      * Write down BitMap.
73                      */
74                     for (i=0; i<hpmp->hpm_dbnum; i++) {
75                               dprintf(("[%d: 0x%x] ", i, hpmp->hpm_bmind[i]));
76 
77                               bp = getblk(hpmp->hpm_devvp,
78                                             dbtodoff(hpmp->hpm_bmind[i]),
79                                             BMSIZE, 0, 0);
80                               clrbuf(bp);
81 
82                               bcopy(hpmp->hpm_bitmap + BMSIZE * i, bp->b_data,
83                                     BMSIZE);
84 
85                               bwrite(bp);
86                     }
87           }
88 
89           kfree(hpmp->hpm_bitmap, M_HPFSMNT);
90           kfree(hpmp->hpm_bmind, M_HPFSMNT);
91 
92           dprintf(("\n"));
93 }
94 
95 /*
96  * Initialize BitMap management, includes calculation of
97  * available blocks number.
98  */
99 int
hpfs_bminit(struct hpfsmount * hpmp)100 hpfs_bminit(
101           struct hpfsmount *hpmp)
102 {
103           struct buf *bp;
104           int error, i, k;
105           u_long dbavail;
106 
107           dprintf(("hpfs_bminit: "));
108 
109           hpmp->hpm_dbnum = (hpmp->hpm_su.su_btotal + 0x3FFF) / 0x4000;
110 
111           dprintf(("0x%lx data bands, ", hpmp->hpm_dbnum));
112 
113           hpmp->hpm_bmind = kmalloc(hpmp->hpm_dbnum * sizeof(lsn_t), M_HPFSMNT,
114                                           M_WAITOK);
115 
116           hpmp->hpm_bitmap = kmalloc(hpmp->hpm_dbnum * BMSIZE, M_HPFSMNT,
117                                            M_WAITOK);
118 
119           error = bread(hpmp->hpm_devvp, dbtodoff(hpmp->hpm_su.su_bitmap.lsn1),
120                     ((hpmp->hpm_dbnum + 0x7F) & ~(0x7F)) << 2, &bp);
121           if (error) {
122                     brelse(bp);
123                     kfree(hpmp->hpm_bitmap, M_HPFSMNT);
124                     kfree(hpmp->hpm_bmind, M_HPFSMNT);
125                     dprintf((" error %d\n", error));
126                     return (error);
127           }
128           bcopy(bp->b_data, hpmp->hpm_bmind, hpmp->hpm_dbnum * sizeof(lsn_t));
129 
130           brelse(bp);
131 
132           /*
133            * Read in all BitMap
134            */
135           for (i=0; i<hpmp->hpm_dbnum; i++) {
136                     dprintf(("[%d: 0x%x] ", i, hpmp->hpm_bmind[i]));
137 
138                     error = bread(hpmp->hpm_devvp, dbtodoff(hpmp->hpm_bmind[i]),
139                                         BMSIZE, &bp);
140                     if (error) {
141                               brelse(bp);
142                               kfree(hpmp->hpm_bitmap, M_HPFSMNT);
143                               kfree(hpmp->hpm_bmind, M_HPFSMNT);
144                               dprintf((" error %d\n", error));
145                               return (error);
146                     }
147                     bcopy(bp->b_data, hpmp->hpm_bitmap + BMSIZE * i, BMSIZE);
148 
149                     brelse(bp);
150           }
151 
152           /*
153            * Look througth BitMap       and count free bits
154            */
155           dbavail = 0;
156           for (i=0; i < hpmp->hpm_su.su_btotal >> 5; i++) {
157                     u_int32_t mask;
158                     for (k=0, mask=1; k < 32; k++, mask<<=1)
159                               if(((u_int32_t *)hpmp->hpm_bitmap)[i] & mask)
160                                         dbavail ++;
161 
162           }
163           hpmp->hpm_bavail = dbavail;
164 
165           return (0);
166 }
167 
168 int
hpfs_cmpfname(struct hpfsmount * hpmp,char * uname,int ulen,char * dname,int dlen,u_int16_t cp)169 hpfs_cmpfname (
170           struct hpfsmount *hpmp,
171           char * uname,
172           int ulen,
173           char * dname,
174           int dlen,
175           u_int16_t cp)
176 {
177           int i, res;
178 
179           for (i = 0; i < ulen && i < dlen; i++) {
180                     res = hpfs_toupper(hpmp, hpfs_u2d(hpmp, uname[i]), cp) -
181                           hpfs_toupper(hpmp, dname[i], cp);
182                     if (res)
183                               return res;
184           }
185           return (ulen - dlen);
186 }
187 
188 int
hpfs_cpstrnnicmp(struct hpfsmount * hpmp,char * str1,int str1len,u_int16_t str1cp,char * str2,int str2len,u_int16_t str2cp)189 hpfs_cpstrnnicmp (
190           struct hpfsmount *hpmp,
191           char * str1,
192           int str1len,
193           u_int16_t str1cp,
194           char * str2,
195           int str2len,
196           u_int16_t str2cp)
197 {
198           int i, res;
199 
200           for (i = 0; i < str1len && i < str2len; i++) {
201                     res = (int)hpfs_toupper(hpmp, ((u_char *)str1)[i], str1cp) -
202                           (int)hpfs_toupper(hpmp, ((u_char *)str2)[i], str2cp);
203                     if (res)
204                               return res;
205           }
206           return (str1len - str2len);
207 }
208 
209 
210 int
hpfs_cpload(struct hpfsmount * hpmp,struct cpiblk * cpibp,struct cpdblk * cpdbp)211 hpfs_cpload (
212           struct hpfsmount *hpmp,
213           struct cpiblk *cpibp,
214           struct cpdblk *cpdbp)
215 {
216           struct buf *bp;
217           struct cpdsec * cpdsp;
218           int error, i;
219 
220           error = bread(hpmp->hpm_devvp, dbtodoff(cpibp->b_cpdsec), DEV_BSIZE, &bp);
221           if (error) {
222                     brelse(bp);
223                     return (error);
224           }
225 
226           cpdsp = (struct cpdsec *)bp->b_data;
227 
228           for (i=cpdsp->d_cpfirst; i<cpdsp->d_cpcnt; i++) {
229                     if (cpdsp->d_cpdblk[i].b_cpid == cpibp->b_cpid) {
230                               bcopy(cpdsp->d_cpdblk + i, cpdbp,
231                                     sizeof(struct cpdblk));
232 
233                               brelse(bp);
234 
235                               return (0);
236                     }
237           }
238 
239           brelse(bp);
240 
241           return (ENOENT);
242 }
243 
244 
245 /*
246  * Initialize Code Page information management.
247  * Load all copdepages in memory.
248  */
249 int
hpfs_cpinit(struct hpfsmount * hpmp,struct hpfs_args * argsp)250 hpfs_cpinit (
251           struct hpfsmount *hpmp,
252           struct hpfs_args *argsp)
253 {
254           struct buf *bp;
255           int error, i;
256           lsn_t lsn;
257           int cpicnt;
258           struct cpisec * cpisp;
259           struct cpiblk * cpibp;
260           struct cpdblk * cpdbp;
261 
262           dprintf(("hpfs_cpinit: \n"));
263 
264           if (argsp->flags & HPFSMNT_TABLES) {
265                     bcopy(argsp->d2u, hpmp->hpm_d2u, sizeof(u_char) * 0x80);
266                     bcopy(argsp->u2d, hpmp->hpm_u2d, sizeof(u_char) * 0x80);
267           } else {
268                     for (i=0x0; i<0x80;i++) {
269                               hpmp->hpm_d2u[i] = i + 0x80;
270                               hpmp->hpm_u2d[i] = i + 0x80;
271                     }
272           }
273 
274           cpicnt = hpmp->hpm_sp.sp_cpinum;
275 
276           hpmp->hpm_cpdblk = kmalloc(cpicnt * sizeof(struct cpdblk), M_HPFSMNT,
277                                            M_WAITOK);
278 
279           cpdbp = hpmp->hpm_cpdblk;
280           lsn = hpmp->hpm_sp.sp_cpi;
281 
282           while (cpicnt > 0) {
283                     error = bread(hpmp->hpm_devvp, dbtodoff(lsn), DEV_BSIZE, &bp);
284                     if (error) {
285                               brelse(bp);
286                               return (error);
287                     }
288 
289                     cpisp = (struct cpisec *)bp->b_data;
290 
291                     cpibp = cpisp->s_cpi;
292                     for (i=0; i<cpisp->s_cpicnt; i++, cpicnt --, cpdbp++, cpibp++) {
293                               dprintf(("hpfs_cpinit: Country: %d, CP: %d (%d)\n",
294                                          cpibp->b_country, cpibp->b_cpid,
295                                          cpibp->b_vcpid));
296 
297                               error = hpfs_cpload(hpmp, cpibp, cpdbp);
298                               if (error) {
299                                         brelse(bp);
300                                         return (error);
301                               }
302                     }
303                     lsn = cpisp->s_next;
304                     brelse(bp);
305           }
306 
307           return (0);
308 }
309 
310 int
hpfs_cpdeinit(struct hpfsmount * hpmp)311 hpfs_cpdeinit (
312           struct hpfsmount *hpmp)
313 {
314           dprintf(("hpmp_cpdeinit: "));
315           kfree(hpmp->hpm_cpdblk, M_HPFSMNT);
316           return (0);
317 }
318 
319 /*
320  * Lookup for a run of blocks.
321  */
322 int
hpfs_bmlookup(struct hpfsmount * hpmp,u_long flags,lsn_t lsn,u_long len,lsn_t * lsnp,u_long * lenp)323 hpfs_bmlookup (
324           struct hpfsmount *hpmp,
325           u_long flags,       /* 1 means we want right len blocks in run, not less */
326           lsn_t lsn,                    /* We want near this one */
327           u_long len,                   /* We want such long */
328           lsn_t *lsnp,        /* We got here */
329           u_long *lenp)       /* We got this long */
330 {
331           u_int32_t * bitmap;
332           u_int32_t mask;
333           int i,k;
334           int cband, vcband;
335           u_int bandsz;
336           int count;
337 
338           dprintf(("hpfs_bmlookup: lsn: 0x%x, len 0x%lx | Step1\n", lsn, len));
339 
340           if (lsn > hpmp->hpm_su.su_btotal) {
341                     kprintf("hpfs_bmlookup: OUT OF VOLUME\n");
342                     return ENOSPC;
343           }
344           if (len > hpmp->hpm_bavail) {
345                     kprintf("hpfs_bmlookup: OUT OF SPACE\n");
346                     return ENOSPC;
347           }
348           i = lsn >> 5;
349           k = lsn & 0x1F;
350           mask = 1 << k;
351           bitmap = (u_int32_t *)hpmp->hpm_bitmap + i;
352 
353           if (*bitmap & mask) {
354                     *lsnp = lsn;
355                     *lenp = 0;
356                     for (; k < 32; k++, mask<<=1) {
357                               if (*bitmap & mask)
358                                         (*lenp) ++;
359                               else {
360                                         if (flags & 1)
361                                                   goto step2;
362                                         else
363                                                   return (0);
364                               }
365 
366                               if (*lenp == len)
367                                         return (0);
368                     }
369 
370                     bitmap++;
371                     i++;
372                     for (; i < hpmp->hpm_su.su_btotal >> 5; i++, bitmap++) {
373                               for (k=0, mask=1; k < 32; k++, mask<<=1) {
374                                         if (*bitmap & mask)
375                                                   (*lenp) ++;
376                                         else {
377                                                   if (flags & 1)
378                                                             goto step2;
379                                                   else
380                                                             return (0);
381                                         }
382 
383                                         if (*lenp == len)
384                                                   return (0);
385                               }
386                     }
387                     return (0);
388           }
389 
390 step2:
391           /*
392            * Lookup all bands begining from cband, lookup for first block
393            */
394           cband = (lsn >> 14);
395           dprintf(("hpfs_bmlookup: Step2: band 0x%x (0x%lx)\n",
396                      cband, hpmp->hpm_dbnum));
397           for (vcband = 0; vcband < hpmp->hpm_dbnum; vcband ++, cband++) {
398                     cband = cband % hpmp->hpm_dbnum;
399                     bandsz = min (hpmp->hpm_su.su_btotal - (cband << 14), 0x4000);
400                     dprintf(("hpfs_bmlookup: band: %d, sz: 0x%x\n", cband, bandsz));
401 
402                     bitmap = (u_int32_t *)hpmp->hpm_bitmap + (cband << 9);
403                     *lsnp = cband << 14;
404                     *lenp = 0;
405                     count = 0;
406                     for (i=0; i < bandsz >> 5; i++, bitmap++) {
407                               for (k=0, mask=1; k < 32; k++, mask<<=1) {
408                                         if (*bitmap & mask) {
409                                                   if (count) {
410                                                             (*lenp) ++;
411                                                   } else {
412                                                             count = 1;
413                                                             *lsnp = (cband << 14) + (i << 5) + k;
414                                                             *lenp = 1;
415                                                   }
416                                         } else {
417                                                   if ((*lenp) && !(flags & 1)) {
418                                                             return (0);
419                                                   } else {
420                                                             count = 0;
421                                                   }
422                                         }
423 
424                                         if (*lenp == len)
425                                                   return (0);
426                               }
427                     }
428                     if (cband == hpmp->hpm_dbnum - 1)  {
429                               if ((*lenp) && !(flags & 1)) {
430                                         return (0);
431                               } else {
432                                         count = 0;
433                               }
434                     }
435           }
436 
437           return (ENOSPC);
438 }
439 
440 /*
441  * Lookup a single free block.          XXX Need locking on BitMap operations
442  * VERY STUPID ROUTINE!!!
443  */
444 int
hpfs_bmfblookup(struct hpfsmount * hpmp,lsn_t * lp)445 hpfs_bmfblookup (
446           struct hpfsmount *hpmp,
447           lsn_t *lp)
448 {
449           u_int32_t * bitmap;
450           int i,k;
451 
452           dprintf(("hpfs_bmfblookup: "));
453 
454           bitmap = (u_int32_t *)hpmp->hpm_bitmap;
455           for (i=0; i < hpmp->hpm_su.su_btotal >> 5; i++, bitmap++) {
456                     k = ffs(*bitmap);
457                     if (k) {
458                               *lp = (i << 5) + k - 1;
459                               dprintf((" found: 0x%x\n",*lp));
460                               return (0);
461                     }
462           }
463 
464           return (ENOSPC);
465 }
466 
467 /*
468  * Mark contignous block of blocks.
469  */
470 int
hpfs_bmmark(struct hpfsmount * hpmp,lsn_t bn,u_long bl,int state)471 hpfs_bmmark (
472           struct hpfsmount *hpmp,
473           lsn_t bn,
474           u_long bl,
475           int state)
476 {
477           u_int32_t * bitmap;
478           int i, didprint = 0;
479 
480           dprintf(("hpfs_bmmark(0x%x, 0x%lx, %d): \n",bn,bl, state));
481 
482           if ((bn > hpmp->hpm_su.su_btotal) || (bn+bl > hpmp->hpm_su.su_btotal)) {
483                     kprintf("hpfs_bmmark: MARKING OUT OF VOLUME\n");
484                     return 0;
485           }
486           bitmap = (u_int32_t *)hpmp->hpm_bitmap;
487           bitmap += bn >> 5;
488 
489           while (bl > 0) {
490                     for (i = bn & 0x1F; (i < 0x20) && (bl > 0) ; i++, bl--) {
491                               if (state) {
492                                         if ( *bitmap & (1 << i)) {
493                                                   if (!didprint) {
494                                                             kprintf("hpfs_bmmark: ALREADY FREE\n");
495                                                             didprint = 1;
496                                                   }
497                                         } else
498                                                   hpmp->hpm_bavail++;
499 
500                                         *bitmap |= (1 << i);
501                               } else {
502                                         if ((~(*bitmap)) & (1 << i)) {
503                                                   if (!didprint) {
504                                                             kprintf("hpfs_bmmark: ALREADY BUSY\n");
505                                                             didprint = 1;
506                                                   }
507                                         } else
508                                                   hpmp->hpm_bavail--;
509 
510                                         *bitmap &= ~(1 << i);
511                               }
512                     }
513                     bn = 0;
514                     bitmap++;
515           }
516 
517           return (0);
518 }
519 
520 
521 int
hpfs_validateparent(struct hpfsnode * hp)522 hpfs_validateparent (
523           struct hpfsnode *hp)
524 {
525           struct hpfsnode *dhp;
526           struct vnode *dvp;
527           struct hpfsmount *hpmp = hp->h_hpmp;
528           struct buf *bp;
529           struct dirblk *dp;
530           struct hpfsdirent *dep;
531           lsn_t lsn, olsn;
532           int level, error;
533 
534           dprintf(("hpfs_validatetimes(0x%x): [parent: 0x%x] ",
535                     hp->h_no, hp->h_fn.fn_parent));
536 
537           if (hp->h_no == hp->h_fn.fn_parent) {
538                     dhp = hp;
539           } else {
540                     error = VFS_VGET(hpmp->hpm_mp, NULL, hp->h_fn.fn_parent, &dvp);
541                     if (error)
542                               return (error);
543                     dhp = VTOHP(dvp);
544           }
545 
546           lsn = ((alleaf_t *)dhp->h_fn.fn_abd)->al_lsn;
547 
548           olsn = 0;
549           level = 1;
550           bp = NULL;
551 
552 dive:
553           dprintf(("[dive 0x%x] ", lsn));
554           if (bp != NULL)
555                     brelse(bp);
556           error = bread(dhp->h_devvp, dbtodoff(lsn), D_BSIZE, &bp);
557           if (error)
558                     goto failed;
559 
560           dp = (struct dirblk *) bp->b_data;
561           if (dp->d_magic != D_MAGIC) {
562                     kprintf("hpfs_validatetimes: magic doesn't match\n");
563                     error = EINVAL;
564                     goto failed;
565           }
566 
567           dep = D_DIRENT(dp);
568 
569           if (olsn) {
570                     dprintf(("[restore 0x%x] ", olsn));
571 
572                     while(!(dep->de_flag & DE_END) ) {
573                               if((dep->de_flag & DE_DOWN) &&
574                                  (olsn == DE_DOWNLSN(dep)))
575                                                    break;
576                               dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen);
577                     }
578 
579                     if((dep->de_flag & DE_DOWN) && (olsn == DE_DOWNLSN(dep))) {
580                               if (dep->de_flag & DE_END)
581                                         goto blockdone;
582 
583                               if (hp->h_no == dep->de_fnode) {
584                                         dprintf(("[found] "));
585                                         goto readdone;
586                               }
587 
588                               dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen);
589                     } else {
590                               kprintf("hpfs_validatetimes: ERROR! oLSN not found\n");
591                               error = EINVAL;
592                               goto failed;
593                     }
594           }
595 
596           olsn = 0;
597 
598           while(!(dep->de_flag & DE_END)) {
599                     if(dep->de_flag & DE_DOWN) {
600                               lsn = DE_DOWNLSN(dep);
601                               level++;
602                               goto dive;
603                     }
604 
605                     if (hp->h_no == dep->de_fnode) {
606                               dprintf(("[found] "));
607                               goto readdone;
608                     }
609 
610                     dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen);
611           }
612 
613           if(dep->de_flag & DE_DOWN) {
614                     dprintf(("[enddive] "));
615                     lsn = DE_DOWNLSN(dep);
616                     level++;
617                     goto dive;
618           }
619 
620 blockdone:
621           dprintf(("[EOB] "));
622           olsn = lsn;
623           lsn = dp->d_parent;
624           level--;
625           dprintf(("[level %d] ", level));
626           if (level > 0)
627                     goto dive;          /* undive really */
628 
629           goto failed;
630 
631 readdone:
632           bcopy(dep->de_name,hp->h_name,dep->de_namelen);
633           hp->h_name[dep->de_namelen] = '\0';
634           hp->h_namelen = dep->de_namelen;
635           hp->h_ctime = dep->de_ctime;
636           hp->h_atime = dep->de_atime;
637           hp->h_mtime = dep->de_mtime;
638           hp->h_flag |= H_PARVALID;
639 
640           dprintf(("[readdone]"));
641 
642 failed:
643           dprintf(("\n"));
644           if (bp != NULL)
645                     brelse(bp);
646           if (hp != dhp)
647                     vput(dvp);
648 
649           return (error);
650 }
651 
652 struct timespec
hpfstimetounix(u_long hptime)653 hpfstimetounix (
654           u_long hptime)
655 {
656           struct timespec t;
657 
658           t.tv_nsec = 0;
659           t.tv_sec = hptime;
660 
661           return t;
662 }
663 
664 /*
665  * Write down changes done to parent dir, these are only times for now.
666  * hpfsnode have to be locked.
667  */
668 int
hpfs_updateparent(struct hpfsnode * hp)669 hpfs_updateparent (
670           struct hpfsnode *hp)
671 {
672           struct hpfsnode *dhp;
673           struct vnode *dvp;
674           struct hpfsdirent *dep;
675           struct buf * bp;
676           int error;
677 
678           dprintf(("hpfs_updateparent(0x%x): \n", hp->h_no));
679 
680           if (!(hp->h_flag & H_PARCHANGE))
681                     return (0);
682 
683           if (!(hp->h_flag & H_PARVALID)) {
684                     error = hpfs_validateparent (hp);
685                     if (error)
686                               return (error);
687           }
688 
689           if (hp->h_no == hp->h_fn.fn_parent) {
690                     dhp = hp;
691           } else {
692                     error = VFS_VGET(hp->h_hpmp->hpm_mp, NULL,
693                                          hp->h_fn.fn_parent, &dvp);
694                     if (error)
695                               return (error);
696                     dhp = VTOHP(dvp);
697           }
698 
699           error = hpfs_genlookupbyname (dhp, hp->h_name, hp->h_namelen,
700                                                   &bp, &dep);
701           if (error) {
702                     goto failed;
703           }
704 
705           dep->de_atime = hp->h_atime;
706           dep->de_mtime = hp->h_mtime;
707           dep->de_size = hp->h_fn.fn_size;
708 
709           bdwrite (bp);
710 
711           hp->h_flag &= ~H_PARCHANGE;
712 
713           error = 0;
714 failed:
715           if (hp != dhp)
716                     vput(dvp);
717 
718           return (0);
719 }
720 
721 /*
722  * Write down on disk changes done to fnode. hpfsnode have to be locked.
723  */
724 int
hpfs_update(struct hpfsnode * hp)725 hpfs_update (
726           struct hpfsnode *hp)
727 {
728           struct buf * bp;
729 
730           dprintf(("hpfs_update(0x%x): \n", hp->h_no));
731 
732           if (!(hp->h_flag & H_CHANGE))
733                     return (0);
734 
735           bp = getblk(hp->h_devvp, dbtodoff(hp->h_no), FNODESIZE, 0, 0);
736           clrbuf(bp);
737 
738           bcopy (&hp->h_fn, bp->b_data, sizeof(struct fnode));
739           bdwrite (bp);
740 
741           hp->h_flag &= ~H_CHANGE;
742 
743           if (hp->h_flag & H_PARCHANGE)
744                     return (hpfs_updateparent(hp));
745 
746           return (0);
747 }
748 
749 /*
750  * Truncate file to specifed size. hpfsnode have to be locked.
751  */
752 int
hpfs_truncate(struct hpfsnode * hp,u_long size)753 hpfs_truncate (
754           struct hpfsnode *hp,
755           u_long size)
756 {
757           struct hpfsmount *hpmp = hp->h_hpmp;
758           lsn_t newblen;
759 #ifdef HPFS_DEBUG
760           lsn_t oldblen;
761 #endif
762           int error, pf;
763 
764           dprintf(("hpfs_truncate(0x%x, 0x%x -> 0x%lx): ",
765                     hp->h_no, hp->h_fn.fn_size, size));
766 
767           newblen = (size + DEV_BSIZE - 1) >> DEV_BSHIFT;
768 #ifdef HPFS_DEBUG
769           oldblen = (hp->h_fn.fn_size + DEV_BSIZE - 1) >> DEV_BSHIFT;
770 #endif
771 
772           dprintf(("blen: 0x%x -> 0x%x\n", oldblen, newblen));
773 
774           error = hpfs_truncatealblk (hpmp, &hp->h_fn.fn_ab, newblen, &pf);
775           if (error)
776                     return (error);
777           if (pf) {
778                     hp->h_fn.fn_ab.ab_flag = 0;
779                     hp->h_fn.fn_ab.ab_freecnt = 0x8;
780                     hp->h_fn.fn_ab.ab_busycnt = 0x0;
781                     hp->h_fn.fn_ab.ab_freeoff = sizeof(alblk_t);
782           }
783 
784           hp->h_fn.fn_size = size;
785 
786           hp->h_flag |= (H_CHANGE | H_PARCHANGE);
787 
788           dprintf(("hpfs_truncate: successful\n"));
789 
790           return (0);
791 }
792 
793 /*
794  * Enlarge file to specifed size. hpfsnode have to be locked.
795  */
796 int
hpfs_extend(struct hpfsnode * hp,u_long size)797 hpfs_extend (
798           struct hpfsnode *hp,
799           u_long size)
800 {
801           struct hpfsmount *hpmp = hp->h_hpmp;
802           lsn_t newblen, oldblen;
803           int error;
804 
805           dprintf(("hpfs_extend(0x%x, 0x%x -> 0x%lx): ",
806                     hp->h_no, hp->h_fn.fn_size, size));
807 
808           if (hpmp->hpm_bavail < 0x10)
809                     return (ENOSPC);
810 
811           newblen = (size + DEV_BSIZE - 1) >> DEV_BSHIFT;
812           oldblen = (hp->h_fn.fn_size + DEV_BSIZE - 1) >> DEV_BSHIFT;
813 
814           dprintf(("blen: 0x%x -> 0x%x\n", oldblen, newblen));
815 
816           error = hpfs_addextent(hpmp, hp, newblen - oldblen);
817           if (error) {
818                     kprintf("hpfs_extend: FAILED TO ADD EXTENT %d\n", error);
819                     return (error);
820           }
821 
822           hp->h_fn.fn_size = size;
823 
824           hp->h_flag |= (H_CHANGE | H_PARCHANGE);
825 
826           dprintf(("hpfs_extend: successful\n"));
827 
828           return (0);
829 }
830 
831 /*
832  * Read AlSec structure, and check if magic is valid.
833  * You don't need to brelse buf on error.
834  */
835 int
hpfs_breadstruct(struct hpfsmount * hpmp,lsn_t lsn,u_int len,u_int32_t magic,struct buf ** bpp)836 hpfs_breadstruct (
837           struct hpfsmount *hpmp,
838           lsn_t lsn,
839           u_int len,
840           u_int32_t magic,
841           struct buf **bpp)
842 {
843           struct buf *bp;
844           u_int32_t *mp;
845           int error;
846 
847           dprintf(("hpfs_breadstruct: reading at 0x%x\n", lsn));
848 
849           *bpp = NULL;
850 
851           error = bread(hpmp->hpm_devvp, dbtodoff(lsn), len, &bp);
852           if (error) {
853                     brelse(bp);
854                     return (error);
855           }
856           mp = (u_int32_t *) bp->b_data;
857           if (*mp != magic) {
858                     brelse(bp);
859                     kprintf("hpfs_breadstruct: MAGIC DOESN'T MATCH (0x%08x != 0x%08x)\n",
860                               *mp, magic);
861                     return (EINVAL);
862           }
863 
864           *bpp = bp;
865 
866           return (0);
867 }
868 
869