xref: /netbsd-src/sys/fs/filecorefs/filecore_utils.c (revision 57920690e6a5f49ca814fd57c83389eaa084cf26)
1*57920690Smsaitoh /*	$NetBSD: filecore_utils.c,v 1.12 2020/09/29 02:58:52 msaitoh Exp $	*/
2aad01611Sagc 
3aad01611Sagc /*-
4aad01611Sagc  * Copyright (c) 1994 The Regents of the University of California.
5aad01611Sagc  * All rights reserved.
6aad01611Sagc  *
7aad01611Sagc  * This code includes code derived from software contributed to the
8aad01611Sagc  * NetBSD project by Mark Brinicombe.
9aad01611Sagc  *
10aad01611Sagc  * Redistribution and use in source and binary forms, with or without
11aad01611Sagc  * modification, are permitted provided that the following conditions
12aad01611Sagc  * are met:
13aad01611Sagc  * 1. Redistributions of source code must retain the above copyright
14aad01611Sagc  *    notice, this list of conditions and the following disclaimer.
15aad01611Sagc  * 2. Redistributions in binary form must reproduce the above copyright
16aad01611Sagc  *    notice, this list of conditions and the following disclaimer in the
17aad01611Sagc  *    documentation and/or other materials provided with the distribution.
18aad01611Sagc  * 3. Neither the name of the University nor the names of its contributors
19aad01611Sagc  *    may be used to endorse or promote products derived from this software
20aad01611Sagc  *    without specific prior written permission.
21aad01611Sagc  *
22aad01611Sagc  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23aad01611Sagc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24aad01611Sagc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25aad01611Sagc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26aad01611Sagc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27aad01611Sagc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28aad01611Sagc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29aad01611Sagc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30aad01611Sagc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31aad01611Sagc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32aad01611Sagc  * SUCH DAMAGE.
33aad01611Sagc  *
34aad01611Sagc  *	filecore_utils.c	1.1	1998/6/26
35aad01611Sagc  */
365356de15Sjdolecek 
375356de15Sjdolecek /*-
385356de15Sjdolecek  * Copyright (c) 1998 Andrew McMurry
395356de15Sjdolecek  *
405356de15Sjdolecek  * This code includes code derived from software contributed to the
415356de15Sjdolecek  * NetBSD project by Mark Brinicombe.
425356de15Sjdolecek  *
435356de15Sjdolecek  * Redistribution and use in source and binary forms, with or without
445356de15Sjdolecek  * modification, are permitted provided that the following conditions
455356de15Sjdolecek  * are met:
465356de15Sjdolecek  * 1. Redistributions of source code must retain the above copyright
475356de15Sjdolecek  *    notice, this list of conditions and the following disclaimer.
485356de15Sjdolecek  * 2. Redistributions in binary form must reproduce the above copyright
495356de15Sjdolecek  *    notice, this list of conditions and the following disclaimer in the
505356de15Sjdolecek  *    documentation and/or other materials provided with the distribution.
515356de15Sjdolecek  * 3. All advertising materials mentioning features or use of this software
525356de15Sjdolecek  *    must display the following acknowledgement:
535356de15Sjdolecek  *	This product includes software developed by the University of
545356de15Sjdolecek  *	California, Berkeley and its contributors.
555356de15Sjdolecek  * 4. Neither the name of the University nor the names of its contributors
565356de15Sjdolecek  *    may be used to endorse or promote products derived from this software
575356de15Sjdolecek  *    without specific prior written permission.
585356de15Sjdolecek  *
595356de15Sjdolecek  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
605356de15Sjdolecek  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
615356de15Sjdolecek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
625356de15Sjdolecek  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
635356de15Sjdolecek  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
645356de15Sjdolecek  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
655356de15Sjdolecek  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
665356de15Sjdolecek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
675356de15Sjdolecek  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
685356de15Sjdolecek  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
695356de15Sjdolecek  * SUCH DAMAGE.
705356de15Sjdolecek  *
715356de15Sjdolecek  *	filecore_utils.c	1.1	1998/6/26
725356de15Sjdolecek  */
735356de15Sjdolecek 
745356de15Sjdolecek /*
755356de15Sjdolecek  * Copyright (c) 1998 Christopher G. Demetriou.  All rights reserved.
765356de15Sjdolecek  *
775356de15Sjdolecek  * Redistribution and use in source and binary forms, with or without
785356de15Sjdolecek  * modification, are permitted provided that the following conditions
795356de15Sjdolecek  * are met:
805356de15Sjdolecek  * 1. Redistributions of source code must retain the above copyright
815356de15Sjdolecek  *    notice, this list of conditions and the following disclaimer.
825356de15Sjdolecek  * 2. Redistributions in binary form must reproduce the above copyright
835356de15Sjdolecek  *    notice, this list of conditions and the following disclaimer in the
845356de15Sjdolecek  *    documentation and/or other materials provided with the distribution.
855356de15Sjdolecek  * 3. All advertising materials mentioning features or use of this software
865356de15Sjdolecek  *    must display the following acknowledgement:
875356de15Sjdolecek  *      This product includes software developed by Christopher G. Demetriou
885356de15Sjdolecek  *	for the NetBSD Project.
895356de15Sjdolecek  * 4. The name of the author may not be used to endorse or promote products
905356de15Sjdolecek  *    derived from this software without specific prior written permission
915356de15Sjdolecek  *
925356de15Sjdolecek  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
935356de15Sjdolecek  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
945356de15Sjdolecek  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
955356de15Sjdolecek  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
965356de15Sjdolecek  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
975356de15Sjdolecek  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
985356de15Sjdolecek  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
995356de15Sjdolecek  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1005356de15Sjdolecek  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
1015356de15Sjdolecek  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1025356de15Sjdolecek  */
1035356de15Sjdolecek 
1045356de15Sjdolecek #include <sys/cdefs.h>
105*57920690Smsaitoh __KERNEL_RCSID(0, "$NetBSD: filecore_utils.c,v 1.12 2020/09/29 02:58:52 msaitoh Exp $");
1065356de15Sjdolecek 
1075356de15Sjdolecek #include <sys/param.h>
1085356de15Sjdolecek #include <sys/systm.h>
1095356de15Sjdolecek #include <sys/stat.h>
1105356de15Sjdolecek #include <sys/buf.h>
1115356de15Sjdolecek #include <sys/mount.h>
1125356de15Sjdolecek #include <sys/vnode.h>
1135356de15Sjdolecek #include <sys/dirent.h>
114641b7ad8Schristos #include <sys/kauth.h>
1155356de15Sjdolecek 
1165356de15Sjdolecek #include <fs/filecorefs/filecore.h>
1175356de15Sjdolecek #include <fs/filecorefs/filecore_extern.h>
1185356de15Sjdolecek #include <fs/filecorefs/filecore_node.h>
1195356de15Sjdolecek #include <fs/filecorefs/filecore_mount.h>
1205356de15Sjdolecek 
1215356de15Sjdolecek /*
1225356de15Sjdolecek  * int filecore_bbchecksum(u_char *bootblock)
1235356de15Sjdolecek  *
1245356de15Sjdolecek  * Calculates the filecore boot block checksum. This is used to validate
1255356de15Sjdolecek  * a filecore boot block on the disk.  If a boot block is validated then
1265356de15Sjdolecek  * it is used to locate the partition table. If the boot block is not
1275356de15Sjdolecek  * validated, it is assumed that the whole disk is NetBSD.
1285356de15Sjdolecek  *
1295356de15Sjdolecek  * The basic algorithm is:
1305356de15Sjdolecek  *
1315356de15Sjdolecek  *	for (each byte in block, excluding checksum) {
1325356de15Sjdolecek  *		sum += byte;
1335356de15Sjdolecek  *		if (sum > 255)
1345356de15Sjdolecek  *			sum -= 255;
1355356de15Sjdolecek  *	}
1365356de15Sjdolecek  *
1375356de15Sjdolecek  * That's equivalent to summing all of the bytes in the block
1385356de15Sjdolecek  * (excluding the checksum byte, of course), then calculating the
1395356de15Sjdolecek  * checksum as "cksum = sum - ((sum - 1) / 255) * 255)".  That
1405356de15Sjdolecek  * expression may or may not yield a faster checksum function,
1415356de15Sjdolecek  * but it's easier to reason about.
1425356de15Sjdolecek  *
1435356de15Sjdolecek  * Note that if you have a block filled with bytes of a single
1445356de15Sjdolecek  * value "X" (regardless of that value!) and calculate the cksum
1455356de15Sjdolecek  * of the block (excluding the checksum byte), you will _always_
1465356de15Sjdolecek  * end up with a checksum of X.  (Do the math; that can be derived
1475356de15Sjdolecek  * from the checksum calculation function!)  That means that
1485356de15Sjdolecek  * blocks which contain bytes which all have the same value will
149*57920690Smsaitoh  * always checksum properly.  That's a _very_ unlikely occurrence
1505356de15Sjdolecek  * (probably impossible, actually) for a valid filecore boot block,
1515356de15Sjdolecek  * so we treat such blocks as invalid.
1525356de15Sjdolecek  */
1535356de15Sjdolecek int
filecore_bbchecksum(void * bb)154454af1c0Sdsl filecore_bbchecksum(void *bb)
1555356de15Sjdolecek {
1565356de15Sjdolecek 	u_char *bootblock = bb;
1575356de15Sjdolecek 	u_char byte0, accum_diff;
1585356de15Sjdolecek 	u_int sum;
1595356de15Sjdolecek 	int i;
1605356de15Sjdolecek 
1615356de15Sjdolecek 	sum = 0;
1625356de15Sjdolecek 	accum_diff = 0;
1635356de15Sjdolecek 	byte0 = bootblock[0];
1645356de15Sjdolecek 
1655356de15Sjdolecek 	/*
1665356de15Sjdolecek 	 * Sum the contents of the block, keeping track of whether
1675356de15Sjdolecek 	 * or not all bytes are the same.  If 'accum_diff' ends up
1685356de15Sjdolecek 	 * being zero, all of the bytes are, in fact, the same.
1695356de15Sjdolecek 	 */
1705356de15Sjdolecek 	for (i = 0; i < 511; ++i) {
1715356de15Sjdolecek 		sum += bootblock[i];
1725356de15Sjdolecek 		accum_diff |= bootblock[i] ^ byte0;
1735356de15Sjdolecek 	}
1745356de15Sjdolecek 
1755356de15Sjdolecek 	/*
1765356de15Sjdolecek 	 * Check to see if the checksum byte is the same as the
1775356de15Sjdolecek 	 * rest of the bytes, too.  (Note that if all of the bytes
1785356de15Sjdolecek 	 * are the same except the checksum, a checksum compare
1795356de15Sjdolecek 	 * won't succeed, but that's not our problem.)
1805356de15Sjdolecek 	 */
1815356de15Sjdolecek 	accum_diff |= bootblock[i] ^ byte0;
1825356de15Sjdolecek 	sum = (sum - ((sum - 1) / 255) * 255);
1835356de15Sjdolecek 
1845356de15Sjdolecek 	/*
1855356de15Sjdolecek 	 * If all bytes in block are the same
1865356de15Sjdolecek 	 * or the checksum does not match ; call it invalid.
1875356de15Sjdolecek 	 */
1885356de15Sjdolecek 	if (accum_diff == 0 || sum != bootblock[511])
1895356de15Sjdolecek 		return -1;
1905356de15Sjdolecek 	return 0;
1915356de15Sjdolecek }
1925356de15Sjdolecek 
1935356de15Sjdolecek mode_t
filecore_mode(struct filecore_node * ip)194454af1c0Sdsl filecore_mode(struct filecore_node *ip)
1955356de15Sjdolecek {
1965356de15Sjdolecek 	mode_t m = 0;
1975356de15Sjdolecek 	int rf = 0;
1985356de15Sjdolecek 
1995356de15Sjdolecek 	if ((ip->i_dirent.attr & FILECORE_ATTR_READ) ||
2005356de15Sjdolecek 	    (ip->i_mnt->fc_mntflags & FILECOREMNT_OWNREAD) ||
2015356de15Sjdolecek 	    (ip->i_dirent.attr & FILECORE_ATTR_DIR))
2025356de15Sjdolecek 		rf = 1;
2035356de15Sjdolecek 	if (ip->i_mnt->fc_mntflags & FILECOREMNT_ALLACCESS) {
2045356de15Sjdolecek 		m |= S_IRUSR | S_IXUSR;
2055356de15Sjdolecek 		if (rf || (ip->i_dirent.attr & FILECORE_ATTR_OREAD))
2065356de15Sjdolecek 			m |= S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
2075356de15Sjdolecek 	} else if (ip->i_mnt->fc_mntflags & FILECOREMNT_OWNACCESS) {
2085356de15Sjdolecek 		if (rf) m |= S_IRUSR | S_IXUSR;
2095356de15Sjdolecek 		if (ip->i_dirent.attr & FILECORE_ATTR_OREAD)
2105356de15Sjdolecek 			m |= S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
2115356de15Sjdolecek 	} else {
2125356de15Sjdolecek 		m |= S_IRUSR | S_IXUSR;
2135356de15Sjdolecek 		if (rf) m |= S_IRGRP | S_IXGRP;
2145356de15Sjdolecek 		if (ip->i_dirent.attr & FILECORE_ATTR_OREAD)
2155356de15Sjdolecek 			m |= S_IROTH | S_IXOTH;
2165356de15Sjdolecek 	}
2175356de15Sjdolecek 	if (ip->i_dirent.attr & FILECORE_ATTR_DIR) {
2185356de15Sjdolecek 		m |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
2195356de15Sjdolecek 	} else
2205356de15Sjdolecek 		m |= S_IFREG;
2215356de15Sjdolecek 	return m;
2225356de15Sjdolecek }
2235356de15Sjdolecek 
2245356de15Sjdolecek struct timespec
filecore_time(struct filecore_node * ip)225454af1c0Sdsl filecore_time(struct filecore_node *ip)
2265356de15Sjdolecek {
2275356de15Sjdolecek 	struct timespec ts;
2285356de15Sjdolecek 	u_int64_t cs;
2295356de15Sjdolecek 
2305356de15Sjdolecek 	cs = (((u_int64_t)(ip->i_dirent.load & 0xFF)) << 32)
2315356de15Sjdolecek 	    + ip->i_dirent.exec - ((u_int64_t)1725772500 << 7);
2325356de15Sjdolecek 	ts.tv_sec = cs / 100;
2335356de15Sjdolecek 	ts.tv_nsec = (cs % 100) * 10000000;
2345356de15Sjdolecek 	return ts;
2355356de15Sjdolecek }
2365356de15Sjdolecek 
2375356de15Sjdolecek ino_t
filecore_getparent(struct filecore_node * ip)238454af1c0Sdsl filecore_getparent(struct filecore_node *ip)
2395356de15Sjdolecek {
2405356de15Sjdolecek 	struct buf *pbp;
2415356de15Sjdolecek 	u_int32_t addr;
2425356de15Sjdolecek 	u_int32_t paddr;
2435356de15Sjdolecek 	int error = 0;
2445356de15Sjdolecek 	int i = 0;
2455356de15Sjdolecek 
2465356de15Sjdolecek #ifdef FILECORE_DEBUG
2471498ad22Sad 	printf("filecore_getparent(ino=%llx)\n", (long long)ip->i_number);
2485356de15Sjdolecek #endif
2495356de15Sjdolecek 	if (ip->i_parent != -2) {
2505356de15Sjdolecek 		return ip->i_parent;
2515356de15Sjdolecek 	}
2525356de15Sjdolecek 	if (ip->i_number == FILECORE_ROOTINO) {
2535356de15Sjdolecek 		ip->i_parent = ip->i_number;
2545356de15Sjdolecek 		return ip->i_number;
2555356de15Sjdolecek 	}
2565356de15Sjdolecek 	addr = ip->i_number & FILECORE_INO_MASK;
2575356de15Sjdolecek 	/* Read directory data for parent dir to find its parent */
2585356de15Sjdolecek #ifdef FILECORE_DEBUG
2595356de15Sjdolecek 	printf("filecore_getparent() read parent dir contents\n");
2605356de15Sjdolecek #endif
2615356de15Sjdolecek 	error = filecore_bread(ip->i_mnt, addr, FILECORE_DIR_SIZE,
2625356de15Sjdolecek 	    NOCRED, &pbp);
2635356de15Sjdolecek 	if (error) {
2645356de15Sjdolecek 		return error;
2655356de15Sjdolecek 	}
2665356de15Sjdolecek 	paddr = fcdirtail(pbp->b_data)->parent1
2675356de15Sjdolecek 	    | fcdirtail(pbp->b_data)->parent2 << 16;
2685356de15Sjdolecek #ifdef FILECORE_DEBUG_BR
2695356de15Sjdolecek 	printf("brelse(%p) ut1\n", pbp);
2705356de15Sjdolecek #endif
2719f56dfa5Sad 	brelse(pbp, 0);
2725356de15Sjdolecek 
2735356de15Sjdolecek 	/* If parent's parent is the parent then parent is root dir */
2745356de15Sjdolecek 	if (paddr == addr) {
2755356de15Sjdolecek 		ip->i_parent = FILECORE_ROOTINO;
2765356de15Sjdolecek 		return FILECORE_ROOTINO;
2775356de15Sjdolecek 	}
2785356de15Sjdolecek 
2795356de15Sjdolecek #ifdef FILECORE_DEBUG
2805356de15Sjdolecek 	printf("filecore_getparent() read grand-parent dir contents\n");
2815356de15Sjdolecek #endif
2825356de15Sjdolecek 	error = filecore_bread(ip->i_mnt, paddr, FILECORE_DIR_SIZE,
2835356de15Sjdolecek 	    NOCRED, &pbp);
2845356de15Sjdolecek 	if (error) {
2855356de15Sjdolecek 		return error;
2865356de15Sjdolecek 	}
2875356de15Sjdolecek 	while (fcdirentry(pbp->b_data,i)->addr != addr) {
2885356de15Sjdolecek 		if (fcdirentry(pbp->b_data, i++)->name[0] == 0) {
2895356de15Sjdolecek #ifdef FILECORE_DEBUG_BR
2905356de15Sjdolecek 			printf("brelse(%p) ut2\n", pbp);
2915356de15Sjdolecek #endif
2929f56dfa5Sad 			brelse(pbp, 0);
2935356de15Sjdolecek 			return FILECORE_ROOTINO;
2945356de15Sjdolecek 		}
2955356de15Sjdolecek 	}
2965356de15Sjdolecek #ifdef FILECORE_DEBUG_BR
2975356de15Sjdolecek 	printf("brelse(%p) ut3\n", pbp);
2985356de15Sjdolecek #endif
2999f56dfa5Sad 	brelse(pbp, 0);
3005356de15Sjdolecek 	ip->i_parent = paddr + (i << FILECORE_INO_INDEX);
3015356de15Sjdolecek 	return (paddr + (i << FILECORE_INO_INDEX));
3025356de15Sjdolecek }
3035356de15Sjdolecek 
3045356de15Sjdolecek int
filecore_fn2unix(char * fcfn,char * ufn,u_int16_t * len)305454af1c0Sdsl filecore_fn2unix(char *fcfn, char *ufn, u_int16_t *len)
3065356de15Sjdolecek {
3075356de15Sjdolecek 	int i = 0;
3085356de15Sjdolecek 
3095356de15Sjdolecek 	if (*fcfn == 0)
3105356de15Sjdolecek 		return (-1);
3115356de15Sjdolecek 	while (i++ < 10 && *fcfn >= ' ') {
3125356de15Sjdolecek 		if (*fcfn == '/')
3135356de15Sjdolecek 			*ufn++ = '.';
3145356de15Sjdolecek 		else
3155356de15Sjdolecek 			*ufn++ = *fcfn;
3165356de15Sjdolecek 		fcfn++;
3175356de15Sjdolecek 	}
318362a4a0bSchristos #ifdef notdef
319362a4a0bSchristos 	if (ip->i_mnt->fc_mntflags & FILECOREMNT_FILETYPE) {
3205356de15Sjdolecek 		*ufn++ = ',';
321362a4a0bSchristos 		*ufn++ = hexdigits[(ip->i_dirent.load >> 10) & 15];
322362a4a0bSchristos 		*ufn++ = hexdigits[(ip->i_dirent.load >> 9) & 15];
323362a4a0bSchristos 		*ufn++ = hexdigits[(ip->i_dirent.load >> 8) & 15];
324362a4a0bSchristos 	}
325362a4a0bSchristos #endif
3265356de15Sjdolecek 	*ufn = 0;
3275356de15Sjdolecek 	*len = i - 1;
3285356de15Sjdolecek 	return 0;
3295356de15Sjdolecek }
3305356de15Sjdolecek 
3315356de15Sjdolecek int
filecore_fncmp(const char * fcfn,const char * ufn,u_short len)332454af1c0Sdsl filecore_fncmp(const char *fcfn, const char *ufn, u_short len)
3335356de15Sjdolecek {
3345356de15Sjdolecek 	char f, u;
3355356de15Sjdolecek 	int i = 0;
3365356de15Sjdolecek 
3375356de15Sjdolecek 	if (*fcfn == 0 || len > 10)
3385356de15Sjdolecek 		return -1;
3395356de15Sjdolecek 	while (i++ < len) {
3405356de15Sjdolecek 		if (*fcfn < ' ')
3415356de15Sjdolecek 			return 1;
3425356de15Sjdolecek 		f = *fcfn++;
3435356de15Sjdolecek 		u = *ufn++;
3445356de15Sjdolecek 		if (u == '.')
3455356de15Sjdolecek 			u = '/';
3465356de15Sjdolecek 		if (u >= 'a' && u <= 'z') u -= 'a' - 'A';
3475356de15Sjdolecek 		if (f >= 'a' && f <= 'z') f -= 'a' - 'A';
3485356de15Sjdolecek 		if (f < u)
3495356de15Sjdolecek 			return 1;
3505356de15Sjdolecek 		else if (f > u)
3515356de15Sjdolecek 			return -1;
3525356de15Sjdolecek 	}
3535356de15Sjdolecek 	if (len == 10 || *fcfn < ' ')
3545356de15Sjdolecek 		return 0;
3555356de15Sjdolecek 	return -1;
3565356de15Sjdolecek }
357