17c478bd9Sstevel@tonic-gate /* fsys_jfs.c - an implementation for the IBM JFS file system */
27c478bd9Sstevel@tonic-gate /*
37c478bd9Sstevel@tonic-gate  *  GRUB  --  GRand Unified Bootloader
47c478bd9Sstevel@tonic-gate  *  Copyright (C) 2001,2002  Free Software Foundation, Inc.
57c478bd9Sstevel@tonic-gate  *
67c478bd9Sstevel@tonic-gate  *  This program is free software; you can redistribute it and/or modify
77c478bd9Sstevel@tonic-gate  *  it under the terms of the GNU General Public License as published by
87c478bd9Sstevel@tonic-gate  *  the Free Software Foundation; either version 2 of the License, or
97c478bd9Sstevel@tonic-gate  *  (at your option) any later version.
107c478bd9Sstevel@tonic-gate  *
117c478bd9Sstevel@tonic-gate  *  This program is distributed in the hope that it will be useful,
127c478bd9Sstevel@tonic-gate  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
137c478bd9Sstevel@tonic-gate  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
147c478bd9Sstevel@tonic-gate  *  GNU General Public License for more details.
157c478bd9Sstevel@tonic-gate  *
167c478bd9Sstevel@tonic-gate  *  You should have received a copy of the GNU General Public License
177c478bd9Sstevel@tonic-gate  *  along with this program; if not, write to the Free Software
187c478bd9Sstevel@tonic-gate  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
197c478bd9Sstevel@tonic-gate  */
207c478bd9Sstevel@tonic-gate 
217c478bd9Sstevel@tonic-gate #ifdef FSYS_JFS
227c478bd9Sstevel@tonic-gate 
237c478bd9Sstevel@tonic-gate #include "shared.h"
247c478bd9Sstevel@tonic-gate #include "filesys.h"
257c478bd9Sstevel@tonic-gate #include "jfs.h"
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #define MAX_LINK_COUNT	8
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate #define DTTYPE_INLINE	0
307c478bd9Sstevel@tonic-gate #define DTTYPE_PAGE	1
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate struct jfs_info
337c478bd9Sstevel@tonic-gate {
347c478bd9Sstevel@tonic-gate 	int bsize;
357c478bd9Sstevel@tonic-gate 	int l2bsize;
367c478bd9Sstevel@tonic-gate 	int bdlog;
377c478bd9Sstevel@tonic-gate 	int xindex;
387c478bd9Sstevel@tonic-gate 	int xlastindex;
397c478bd9Sstevel@tonic-gate 	int sindex;
407c478bd9Sstevel@tonic-gate 	int slastindex;
417c478bd9Sstevel@tonic-gate 	int de_index;
427c478bd9Sstevel@tonic-gate 	int dttype;
437c478bd9Sstevel@tonic-gate 	xad_t *xad;
447c478bd9Sstevel@tonic-gate 	ldtentry_t *de;
457c478bd9Sstevel@tonic-gate };
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate static struct jfs_info jfs;
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate #define xtpage		((xtpage_t *)FSYS_BUF)
507c478bd9Sstevel@tonic-gate #define dtpage		((dtpage_t *)((char *)FSYS_BUF + 4096))
517c478bd9Sstevel@tonic-gate #define fileset		((dinode_t *)((char *)FSYS_BUF + 8192))
527c478bd9Sstevel@tonic-gate #define inode		((dinode_t *)((char *)FSYS_BUF + 8192 + sizeof(dinode_t)))
537c478bd9Sstevel@tonic-gate #define dtroot		((dtroot_t *)(&inode->di_btroot))
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate static ldtentry_t de_always[2] = {
567c478bd9Sstevel@tonic-gate 	{1, -1, 2, {'.', '.'}},
577c478bd9Sstevel@tonic-gate 	{1, -1, 1, {'.'}}
587c478bd9Sstevel@tonic-gate };
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate static int
isinxt(s64 key,s64 offset,s64 len)617c478bd9Sstevel@tonic-gate isinxt (s64 key, s64 offset, s64 len)
627c478bd9Sstevel@tonic-gate {
637c478bd9Sstevel@tonic-gate 	return (key >= offset) ? (key < offset + len ? 1 : 0) : 0;
647c478bd9Sstevel@tonic-gate }
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate static xad_t *
first_extent(dinode_t * di)677c478bd9Sstevel@tonic-gate first_extent (dinode_t *di)
687c478bd9Sstevel@tonic-gate {
697c478bd9Sstevel@tonic-gate 	xtpage_t *xtp;
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate 	jfs.xindex = 2;
727c478bd9Sstevel@tonic-gate 	xtp = (xtpage_t *)&di->di_btroot;
737c478bd9Sstevel@tonic-gate 	jfs.xad = &xtp->xad[2];
747c478bd9Sstevel@tonic-gate 	if (xtp->header.flag & BT_LEAF) {
757c478bd9Sstevel@tonic-gate 	    	jfs.xlastindex = xtp->header.nextindex;
767c478bd9Sstevel@tonic-gate 	} else {
777c478bd9Sstevel@tonic-gate 		do {
787c478bd9Sstevel@tonic-gate 			devread (addressXAD (jfs.xad) << jfs.bdlog, 0,
797c478bd9Sstevel@tonic-gate 				 sizeof(xtpage_t), (char *)xtpage);
807c478bd9Sstevel@tonic-gate 			jfs.xad = &xtpage->xad[2];
817c478bd9Sstevel@tonic-gate 		} while (!(xtpage->header.flag & BT_LEAF));
827c478bd9Sstevel@tonic-gate 		jfs.xlastindex = xtpage->header.nextindex;
837c478bd9Sstevel@tonic-gate 	}
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate 	return jfs.xad;
867c478bd9Sstevel@tonic-gate }
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate static xad_t *
next_extent(void)897c478bd9Sstevel@tonic-gate next_extent (void)
907c478bd9Sstevel@tonic-gate {
917c478bd9Sstevel@tonic-gate 	if (++jfs.xindex < jfs.xlastindex) {
927c478bd9Sstevel@tonic-gate 	} else if (xtpage->header.next) {
937c478bd9Sstevel@tonic-gate 		devread (xtpage->header.next << jfs.bdlog, 0,
947c478bd9Sstevel@tonic-gate 			 sizeof(xtpage_t), (char *)xtpage);
957c478bd9Sstevel@tonic-gate 		jfs.xlastindex = xtpage->header.nextindex;
967c478bd9Sstevel@tonic-gate 		jfs.xindex = XTENTRYSTART;
977c478bd9Sstevel@tonic-gate 		jfs.xad = &xtpage->xad[XTENTRYSTART];
987c478bd9Sstevel@tonic-gate 	} else {
997c478bd9Sstevel@tonic-gate 		return NULL;
1007c478bd9Sstevel@tonic-gate 	}
1017c478bd9Sstevel@tonic-gate 	return ++jfs.xad;
1027c478bd9Sstevel@tonic-gate }
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate static void
di_read(u32 inum,dinode_t * di)1067c478bd9Sstevel@tonic-gate di_read (u32 inum, dinode_t *di)
1077c478bd9Sstevel@tonic-gate {
1087c478bd9Sstevel@tonic-gate 	s64 key;
1097c478bd9Sstevel@tonic-gate 	u32 xd, ioffset;
1107c478bd9Sstevel@tonic-gate 	s64 offset;
1117c478bd9Sstevel@tonic-gate 	xad_t *xad;
1127c478bd9Sstevel@tonic-gate 	pxd_t pxd;
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate 	key = (((inum >> L2INOSPERIAG) << L2INOSPERIAG) + 4096) >> jfs.l2bsize;
1157c478bd9Sstevel@tonic-gate 	xd = (inum & (INOSPERIAG - 1)) >> L2INOSPEREXT;
1167c478bd9Sstevel@tonic-gate 	ioffset = ((inum & (INOSPERIAG - 1)) & (INOSPEREXT - 1)) << L2DISIZE;
1177c478bd9Sstevel@tonic-gate 	xad = first_extent (fileset);
1187c478bd9Sstevel@tonic-gate 	do {
1197c478bd9Sstevel@tonic-gate 		offset = offsetXAD (xad);
1207c478bd9Sstevel@tonic-gate 		if (isinxt (key, offset, lengthXAD (xad))) {
1217c478bd9Sstevel@tonic-gate 			devread ((addressXAD (xad) + key - offset) << jfs.bdlog,
1227c478bd9Sstevel@tonic-gate 				 3072 + xd*sizeof(pxd_t), sizeof(pxd_t), (char *)&pxd);
1237c478bd9Sstevel@tonic-gate 			devread (addressPXD (&pxd) << jfs.bdlog,
1247c478bd9Sstevel@tonic-gate 				 ioffset, DISIZE, (char *)di);
1257c478bd9Sstevel@tonic-gate 			break;
1267c478bd9Sstevel@tonic-gate 		}
1277c478bd9Sstevel@tonic-gate 	} while ((xad = next_extent ()));
1287c478bd9Sstevel@tonic-gate }
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate static ldtentry_t *
next_dentry(void)1317c478bd9Sstevel@tonic-gate next_dentry (void)
1327c478bd9Sstevel@tonic-gate {
1337c478bd9Sstevel@tonic-gate 	ldtentry_t *de;
1347c478bd9Sstevel@tonic-gate 	s8 *stbl;
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate 	if (jfs.dttype == DTTYPE_INLINE) {
1377c478bd9Sstevel@tonic-gate 		if (jfs.sindex < jfs.slastindex) {
1387c478bd9Sstevel@tonic-gate 			return (ldtentry_t *)&dtroot->slot[(int)dtroot->header.stbl[jfs.sindex++]];
1397c478bd9Sstevel@tonic-gate 		}
1407c478bd9Sstevel@tonic-gate 	} else {
1417c478bd9Sstevel@tonic-gate 		de = (ldtentry_t *)dtpage->slot;
1427c478bd9Sstevel@tonic-gate 		stbl = (s8 *)&de[(int)dtpage->header.stblindex];
1437c478bd9Sstevel@tonic-gate 		if (jfs.sindex < jfs.slastindex) {
1447c478bd9Sstevel@tonic-gate 			return &de[(int)stbl[jfs.sindex++]];
1457c478bd9Sstevel@tonic-gate 		} else if (dtpage->header.next) {
1467c478bd9Sstevel@tonic-gate 			devread (dtpage->header.next << jfs.bdlog, 0,
1477c478bd9Sstevel@tonic-gate 				 sizeof(dtpage_t), (char *)dtpage);
1487c478bd9Sstevel@tonic-gate 			jfs.slastindex = dtpage->header.nextindex;
1497c478bd9Sstevel@tonic-gate 			jfs.sindex = 1;
1507c478bd9Sstevel@tonic-gate 			return &de[(int)((s8 *)&de[(int)dtpage->header.stblindex])[0]];
1517c478bd9Sstevel@tonic-gate 		}
1527c478bd9Sstevel@tonic-gate 	}
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 	return (jfs.de_index < 2) ? &de_always[jfs.de_index++] : NULL;
1557c478bd9Sstevel@tonic-gate }
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate static ldtentry_t *
first_dentry(void)1587c478bd9Sstevel@tonic-gate first_dentry (void)
1597c478bd9Sstevel@tonic-gate {
1607c478bd9Sstevel@tonic-gate 	dtroot_t *dtr;
1617c478bd9Sstevel@tonic-gate 	pxd_t *xd;
1627c478bd9Sstevel@tonic-gate 	idtentry_t *de;
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 	dtr = (dtroot_t *)&inode->di_btroot;
1657c478bd9Sstevel@tonic-gate 	jfs.sindex = 0;
1667c478bd9Sstevel@tonic-gate 	jfs.de_index = 0;
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate 	de_always[0].inumber = inode->di_parent;
1697c478bd9Sstevel@tonic-gate 	de_always[1].inumber = inode->di_number;
1707c478bd9Sstevel@tonic-gate 	if (dtr->header.flag & BT_LEAF) {
1717c478bd9Sstevel@tonic-gate 		jfs.dttype = DTTYPE_INLINE;
1727c478bd9Sstevel@tonic-gate 		jfs.slastindex = dtr->header.nextindex;
1737c478bd9Sstevel@tonic-gate 	} else {
1747c478bd9Sstevel@tonic-gate 		de = (idtentry_t *)dtpage->slot;
1757c478bd9Sstevel@tonic-gate 		jfs.dttype = DTTYPE_PAGE;
1767c478bd9Sstevel@tonic-gate 		xd = &((idtentry_t *)dtr->slot)[(int)dtr->header.stbl[0]].xd;
1777c478bd9Sstevel@tonic-gate 		for (;;) {
1787c478bd9Sstevel@tonic-gate 			devread (addressPXD (xd) << jfs.bdlog, 0,
1797c478bd9Sstevel@tonic-gate 				 sizeof(dtpage_t), (char *)dtpage);
1807c478bd9Sstevel@tonic-gate 			if (dtpage->header.flag & BT_LEAF)
1817c478bd9Sstevel@tonic-gate 				break;
1827c478bd9Sstevel@tonic-gate 			xd = &de[(int)((s8 *)&de[(int)dtpage->header.stblindex])[0]].xd;
1837c478bd9Sstevel@tonic-gate 		}
1847c478bd9Sstevel@tonic-gate 		jfs.slastindex = dtpage->header.nextindex;
1857c478bd9Sstevel@tonic-gate 	}
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate 	return next_dentry ();
1887c478bd9Sstevel@tonic-gate }
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate static dtslot_t *
next_dslot(int next)1927c478bd9Sstevel@tonic-gate next_dslot (int next)
1937c478bd9Sstevel@tonic-gate {
1947c478bd9Sstevel@tonic-gate 	return (jfs.dttype == DTTYPE_INLINE)
1957c478bd9Sstevel@tonic-gate 		? (dtslot_t *)&dtroot->slot[next]
1967c478bd9Sstevel@tonic-gate 		: &((dtslot_t *)dtpage->slot)[next];
1977c478bd9Sstevel@tonic-gate }
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate static void
uni2ansi(UniChar * uni,char * ansi,int len)2007c478bd9Sstevel@tonic-gate uni2ansi (UniChar *uni, char *ansi, int len)
2017c478bd9Sstevel@tonic-gate {
2027c478bd9Sstevel@tonic-gate 	for (; len; len--, uni++)
2037c478bd9Sstevel@tonic-gate 		*ansi++ = (*uni & 0xff80) ? '?' : *(char *)uni;
2047c478bd9Sstevel@tonic-gate }
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate int
jfs_mount(void)2077c478bd9Sstevel@tonic-gate jfs_mount (void)
2087c478bd9Sstevel@tonic-gate {
2097c478bd9Sstevel@tonic-gate 	struct jfs_superblock super;
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 	if (part_length < MINJFS >> SECTOR_BITS
2127c478bd9Sstevel@tonic-gate 	    || !devread (SUPER1_OFF >> SECTOR_BITS, 0,
2137c478bd9Sstevel@tonic-gate 			 sizeof(struct jfs_superblock), (char *)&super)
2147c478bd9Sstevel@tonic-gate 	    || (super.s_magic != JFS_MAGIC)
2157c478bd9Sstevel@tonic-gate 	    || !devread ((AITBL_OFF >> SECTOR_BITS) + FILESYSTEM_I,
2167c478bd9Sstevel@tonic-gate 			 0, DISIZE, (char*)fileset)) {
2177c478bd9Sstevel@tonic-gate 		return 0;
2187c478bd9Sstevel@tonic-gate 	}
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate 	jfs.bsize = super.s_bsize;
2217c478bd9Sstevel@tonic-gate 	jfs.l2bsize = super.s_l2bsize;
2227c478bd9Sstevel@tonic-gate 	jfs.bdlog = jfs.l2bsize - SECTOR_BITS;
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 	return 1;
2257c478bd9Sstevel@tonic-gate }
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate int
jfs_read(char * buf,int len)2287c478bd9Sstevel@tonic-gate jfs_read (char *buf, int len)
2297c478bd9Sstevel@tonic-gate {
2307c478bd9Sstevel@tonic-gate 	xad_t *xad;
2317c478bd9Sstevel@tonic-gate 	s64 endofprev, endofcur;
2327c478bd9Sstevel@tonic-gate 	s64 offset, xadlen;
2337c478bd9Sstevel@tonic-gate 	int toread, startpos, endpos;
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate 	startpos = filepos;
2367c478bd9Sstevel@tonic-gate 	endpos = filepos + len;
2377c478bd9Sstevel@tonic-gate 	endofprev = (1ULL << 62) - 1;
2387c478bd9Sstevel@tonic-gate 	xad = first_extent (inode);
2397c478bd9Sstevel@tonic-gate 	do {
2407c478bd9Sstevel@tonic-gate 		offset = offsetXAD (xad);
2417c478bd9Sstevel@tonic-gate 		xadlen = lengthXAD (xad);
2427c478bd9Sstevel@tonic-gate 		if (isinxt (filepos >> jfs.l2bsize, offset, xadlen)) {
2437c478bd9Sstevel@tonic-gate 			endofcur = (offset + xadlen) << jfs.l2bsize;
2447c478bd9Sstevel@tonic-gate 			toread = (endofcur >= endpos)
2457c478bd9Sstevel@tonic-gate 				  ? len : (endofcur - filepos);
2467c478bd9Sstevel@tonic-gate 
2477c478bd9Sstevel@tonic-gate 			disk_read_func = disk_read_hook;
2487c478bd9Sstevel@tonic-gate 			devread (addressXAD (xad) << jfs.bdlog,
2497c478bd9Sstevel@tonic-gate 				 filepos - (offset << jfs.l2bsize), toread, buf);
2507c478bd9Sstevel@tonic-gate 			disk_read_func = NULL;
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 			buf += toread;
2537c478bd9Sstevel@tonic-gate 			len -= toread;
2547c478bd9Sstevel@tonic-gate 			filepos += toread;
2557c478bd9Sstevel@tonic-gate 		} else if (offset > endofprev) {
2567c478bd9Sstevel@tonic-gate 			toread = ((offset << jfs.l2bsize) >= endpos)
2577c478bd9Sstevel@tonic-gate 				  ? len : ((offset - endofprev) << jfs.l2bsize);
2587c478bd9Sstevel@tonic-gate 			len -= toread;
2597c478bd9Sstevel@tonic-gate 			filepos += toread;
2607c478bd9Sstevel@tonic-gate 			for (; toread; toread--) {
2617c478bd9Sstevel@tonic-gate 				*buf++ = 0;
2627c478bd9Sstevel@tonic-gate 			}
2637c478bd9Sstevel@tonic-gate 			continue;
2647c478bd9Sstevel@tonic-gate 		}
2657c478bd9Sstevel@tonic-gate 		endofprev = offset + xadlen;
2667c478bd9Sstevel@tonic-gate 		xad = next_extent ();
2677c478bd9Sstevel@tonic-gate 	} while (len > 0 && xad);
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate 	return filepos - startpos;
2707c478bd9Sstevel@tonic-gate }
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate int
jfs_dir(char * dirname)2737c478bd9Sstevel@tonic-gate jfs_dir (char *dirname)
2747c478bd9Sstevel@tonic-gate {
2757c478bd9Sstevel@tonic-gate 	char *ptr, *rest, ch;
2767c478bd9Sstevel@tonic-gate 	ldtentry_t *de;
2777c478bd9Sstevel@tonic-gate 	dtslot_t *ds;
2787c478bd9Sstevel@tonic-gate 	u32 inum, parent_inum;
2797c478bd9Sstevel@tonic-gate 	s64 di_size;
2807c478bd9Sstevel@tonic-gate 	u32 di_mode;
2817c478bd9Sstevel@tonic-gate 	int namlen, cmp, n, link_count;
2827c478bd9Sstevel@tonic-gate 	char namebuf[JFS_NAME_MAX + 1], linkbuf[JFS_PATH_MAX];
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate 	parent_inum = inum = ROOT_I;
2857c478bd9Sstevel@tonic-gate 	link_count = 0;
2867c478bd9Sstevel@tonic-gate 	for (;;) {
2877c478bd9Sstevel@tonic-gate 		di_read (inum, inode);
2887c478bd9Sstevel@tonic-gate 		di_size = inode->di_size;
2897c478bd9Sstevel@tonic-gate 		di_mode = inode->di_mode;
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate 		if ((di_mode & IFMT) == IFLNK) {
2927c478bd9Sstevel@tonic-gate 			if (++link_count > MAX_LINK_COUNT) {
2937c478bd9Sstevel@tonic-gate 				errnum = ERR_SYMLINK_LOOP;
2947c478bd9Sstevel@tonic-gate 				return 0;
2957c478bd9Sstevel@tonic-gate 			}
2967c478bd9Sstevel@tonic-gate 			if (di_size < (di_mode & INLINEEA ? 256 : 128)) {
2977c478bd9Sstevel@tonic-gate 				grub_memmove (linkbuf, inode->di_fastsymlink, di_size);
2987c478bd9Sstevel@tonic-gate 				n = di_size;
2997c478bd9Sstevel@tonic-gate 			} else if (di_size < JFS_PATH_MAX - 1) {
3007c478bd9Sstevel@tonic-gate 				filepos = 0;
3017c478bd9Sstevel@tonic-gate 				filemax = di_size;
3027c478bd9Sstevel@tonic-gate 				n = jfs_read (linkbuf, filemax);
3037c478bd9Sstevel@tonic-gate 			} else {
3047c478bd9Sstevel@tonic-gate 				errnum = ERR_FILELENGTH;
3057c478bd9Sstevel@tonic-gate 				return 0;
3067c478bd9Sstevel@tonic-gate 			}
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate 			inum = (linkbuf[0] == '/') ? ROOT_I : parent_inum;
3097c478bd9Sstevel@tonic-gate 			while (n < (JFS_PATH_MAX - 1) && (linkbuf[n++] = *dirname++));
3107c478bd9Sstevel@tonic-gate 			linkbuf[n] = 0;
3117c478bd9Sstevel@tonic-gate 			dirname = linkbuf;
3127c478bd9Sstevel@tonic-gate 			continue;
3137c478bd9Sstevel@tonic-gate 		}
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate 		if (!*dirname || isspace (*dirname)) {
3167c478bd9Sstevel@tonic-gate 			if ((di_mode & IFMT) != IFREG) {
3177c478bd9Sstevel@tonic-gate 				errnum = ERR_BAD_FILETYPE;
3187c478bd9Sstevel@tonic-gate 				return 0;
3197c478bd9Sstevel@tonic-gate 			}
3207c478bd9Sstevel@tonic-gate 			filepos = 0;
3217c478bd9Sstevel@tonic-gate 			filemax = di_size;
3227c478bd9Sstevel@tonic-gate 			return 1;
3237c478bd9Sstevel@tonic-gate 		}
3247c478bd9Sstevel@tonic-gate 
3257c478bd9Sstevel@tonic-gate 		if ((di_mode & IFMT) != IFDIR) {
3267c478bd9Sstevel@tonic-gate 			errnum = ERR_BAD_FILETYPE;
3277c478bd9Sstevel@tonic-gate 			return 0;
3287c478bd9Sstevel@tonic-gate 		}
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate 		for (; *dirname == '/'; dirname++);
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate 		for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++);
3337c478bd9Sstevel@tonic-gate 		*rest = 0;
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate 		de = first_dentry ();
3367c478bd9Sstevel@tonic-gate 		for (;;) {
3377c478bd9Sstevel@tonic-gate 			namlen = de->namlen;
3387c478bd9Sstevel@tonic-gate 			if (de->next == -1) {
3397c478bd9Sstevel@tonic-gate 				uni2ansi (de->name, namebuf, namlen);
3407c478bd9Sstevel@tonic-gate 				namebuf[namlen] = 0;
3417c478bd9Sstevel@tonic-gate 			} else {
3427c478bd9Sstevel@tonic-gate 				uni2ansi (de->name, namebuf, DTLHDRDATALEN);
3437c478bd9Sstevel@tonic-gate 				ptr = namebuf;
3447c478bd9Sstevel@tonic-gate 				ptr += DTLHDRDATALEN;
3457c478bd9Sstevel@tonic-gate 				namlen -= DTLHDRDATALEN;
3467c478bd9Sstevel@tonic-gate 				ds = next_dslot (de->next);
3477c478bd9Sstevel@tonic-gate 				while (ds->next != -1) {
3487c478bd9Sstevel@tonic-gate 					uni2ansi (ds->name, ptr, DTSLOTDATALEN);
3497c478bd9Sstevel@tonic-gate 					ptr += DTSLOTDATALEN;
3507c478bd9Sstevel@tonic-gate 					namlen -= DTSLOTDATALEN;
3517c478bd9Sstevel@tonic-gate 					ds = next_dslot (ds->next);
3527c478bd9Sstevel@tonic-gate 				}
3537c478bd9Sstevel@tonic-gate 				uni2ansi (ds->name, ptr, namlen);
3547c478bd9Sstevel@tonic-gate 				ptr += namlen;
3557c478bd9Sstevel@tonic-gate 				*ptr = 0;
3567c478bd9Sstevel@tonic-gate 			}
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate 			cmp = (!*dirname) ? -1 : substring (dirname, namebuf);
3597c478bd9Sstevel@tonic-gate #ifndef STAGE1_5
3607c478bd9Sstevel@tonic-gate 			if (print_possibilities && ch != '/'
3617c478bd9Sstevel@tonic-gate 			    && cmp <= 0) {
3627c478bd9Sstevel@tonic-gate 				if (print_possibilities > 0)
3637c478bd9Sstevel@tonic-gate 					print_possibilities = -print_possibilities;
3647c478bd9Sstevel@tonic-gate 				print_a_completion (namebuf);
3657c478bd9Sstevel@tonic-gate 			} else
3667c478bd9Sstevel@tonic-gate #endif
3677c478bd9Sstevel@tonic-gate 			if (cmp == 0) {
3687c478bd9Sstevel@tonic-gate 				parent_inum = inum;
3697c478bd9Sstevel@tonic-gate 				inum = de->inumber;
3707c478bd9Sstevel@tonic-gate 		        	*(dirname = rest) = ch;
3717c478bd9Sstevel@tonic-gate 				break;
3727c478bd9Sstevel@tonic-gate 			}
3737c478bd9Sstevel@tonic-gate 			de = next_dentry ();
3747c478bd9Sstevel@tonic-gate 			if (de == NULL) {
3757c478bd9Sstevel@tonic-gate 				if (print_possibilities < 0)
3767c478bd9Sstevel@tonic-gate 					return 1;
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate 				errnum = ERR_FILE_NOT_FOUND;
3797c478bd9Sstevel@tonic-gate 				*rest = ch;
3807c478bd9Sstevel@tonic-gate 				return 0;
3817c478bd9Sstevel@tonic-gate 			}
3827c478bd9Sstevel@tonic-gate 		}
3837c478bd9Sstevel@tonic-gate 	}
3847c478bd9Sstevel@tonic-gate }
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate int
jfs_embed(unsigned long long * start_sector,int needed_sectors)387*2e1aefd1SJoshua M. Clulow jfs_embed (unsigned long long *start_sector, int needed_sectors)
3887c478bd9Sstevel@tonic-gate {
3897c478bd9Sstevel@tonic-gate 	struct jfs_superblock super;
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate 	if (needed_sectors > 63
3927c478bd9Sstevel@tonic-gate 	    || !devread (SUPER1_OFF >> SECTOR_BITS, 0,
3937c478bd9Sstevel@tonic-gate 			 sizeof (struct jfs_superblock),
3947c478bd9Sstevel@tonic-gate 			 (char *)&super)
3957c478bd9Sstevel@tonic-gate 	    || (super.s_magic != JFS_MAGIC)) {
3967c478bd9Sstevel@tonic-gate 		return 0;
3977c478bd9Sstevel@tonic-gate 	}
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate 	*start_sector = 1;
4007c478bd9Sstevel@tonic-gate 	return 1;
4017c478bd9Sstevel@tonic-gate }
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate #endif /* FSYS_JFS */
404