2005-02-27 01:58:54 +03:00
|
|
|
/* $NetBSD: filecore_utils.c,v 1.3 2005/02/26 22:58:55 perry Exp $ */
|
1998-08-14 07:26:12 +04:00
|
|
|
|
|
|
|
/*-
|
|
|
|
* Copyright (c) 1994 The Regents of the University of California.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* This code includes code derived from software contributed to the
|
|
|
|
* NetBSD project by Mark Brinicombe.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
2003-08-07 20:26:28 +04:00
|
|
|
* 3. Neither the name of the University nor the names of its contributors
|
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*
|
|
|
|
* filecore_utils.c 1.1 1998/6/26
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*-
|
|
|
|
* Copyright (c) 1998 Andrew McMurry
|
|
|
|
*
|
|
|
|
* This code includes code derived from software contributed to the
|
|
|
|
* NetBSD project by Mark Brinicombe.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
1998-08-14 07:26:12 +04:00
|
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
|
|
* must display the following acknowledgement:
|
|
|
|
* This product includes software developed by the University of
|
|
|
|
* California, Berkeley and its contributors.
|
|
|
|
* 4. Neither the name of the University nor the names of its contributors
|
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*
|
|
|
|
* filecore_utils.c 1.1 1998/6/26
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (c) 1998 Christopher G. Demetriou. All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
|
|
* must display the following acknowledgement:
|
|
|
|
* This product includes software developed by Christopher G. Demetriou
|
|
|
|
* for the NetBSD Project.
|
|
|
|
* 4. The name of the author may not be used to endorse or promote products
|
|
|
|
* derived from this software without specific prior written permission
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
2001-11-13 01:54:03 +03:00
|
|
|
#include <sys/cdefs.h>
|
2005-02-27 01:58:54 +03:00
|
|
|
__KERNEL_RCSID(0, "$NetBSD: filecore_utils.c,v 1.3 2005/02/26 22:58:55 perry Exp $");
|
2001-11-13 01:54:03 +03:00
|
|
|
|
1998-08-14 07:26:12 +04:00
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/systm.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/buf.h>
|
|
|
|
#include <sys/mount.h>
|
|
|
|
#include <sys/vnode.h>
|
|
|
|
#include <sys/dirent.h>
|
|
|
|
|
2002-12-23 20:30:36 +03:00
|
|
|
#include <fs/filecorefs/filecore.h>
|
|
|
|
#include <fs/filecorefs/filecore_extern.h>
|
|
|
|
#include <fs/filecorefs/filecore_node.h>
|
|
|
|
#include <fs/filecorefs/filecore_mount.h>
|
1998-08-14 07:26:12 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* int filecore_bbchecksum(u_char *bootblock)
|
|
|
|
*
|
|
|
|
* Calculates the filecore boot block checksum. This is used to validate
|
|
|
|
* a filecore boot block on the disk. If a boot block is validated then
|
|
|
|
* it is used to locate the partition table. If the boot block is not
|
|
|
|
* validated, it is assumed that the whole disk is NetBSD.
|
|
|
|
*
|
|
|
|
* The basic algorithm is:
|
|
|
|
*
|
|
|
|
* for (each byte in block, excluding checksum) {
|
|
|
|
* sum += byte;
|
|
|
|
* if (sum > 255)
|
|
|
|
* sum -= 255;
|
|
|
|
* }
|
|
|
|
*
|
|
|
|
* That's equivalent to summing all of the bytes in the block
|
|
|
|
* (excluding the checksum byte, of course), then calculating the
|
|
|
|
* checksum as "cksum = sum - ((sum - 1) / 255) * 255)". That
|
|
|
|
* expression may or may not yield a faster checksum function,
|
|
|
|
* but it's easier to reason about.
|
|
|
|
*
|
|
|
|
* Note that if you have a block filled with bytes of a single
|
|
|
|
* value "X" (regardless of that value!) and calculate the cksum
|
|
|
|
* of the block (excluding the checksum byte), you will _always_
|
|
|
|
* end up with a checksum of X. (Do the math; that can be derived
|
|
|
|
* from the checksum calculation function!) That means that
|
|
|
|
* blocks which contain bytes which all have the same value will
|
|
|
|
* always checksum properly. That's a _very_ unlikely occurence
|
|
|
|
* (probably impossible, actually) for a valid filecore boot block,
|
|
|
|
* so we treat such blocks as invalid.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
filecore_bbchecksum(bb)
|
|
|
|
void *bb;
|
2005-02-27 01:58:54 +03:00
|
|
|
{
|
1998-08-14 07:26:12 +04:00
|
|
|
u_char *bootblock = bb;
|
|
|
|
u_char byte0, accum_diff;
|
|
|
|
u_int sum;
|
|
|
|
int i;
|
2005-02-27 01:58:54 +03:00
|
|
|
|
1998-08-14 07:26:12 +04:00
|
|
|
sum = 0;
|
|
|
|
accum_diff = 0;
|
|
|
|
byte0 = bootblock[0];
|
2005-02-27 01:58:54 +03:00
|
|
|
|
1998-08-14 07:26:12 +04:00
|
|
|
/*
|
|
|
|
* Sum the contents of the block, keeping track of whether
|
|
|
|
* or not all bytes are the same. If 'accum_diff' ends up
|
|
|
|
* being zero, all of the bytes are, in fact, the same.
|
|
|
|
*/
|
|
|
|
for (i = 0; i < 511; ++i) {
|
|
|
|
sum += bootblock[i];
|
|
|
|
accum_diff |= bootblock[i] ^ byte0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check to see if the checksum byte is the same as the
|
|
|
|
* rest of the bytes, too. (Note that if all of the bytes
|
|
|
|
* are the same except the checksum, a checksum compare
|
|
|
|
* won't succeed, but that's not our problem.)
|
|
|
|
*/
|
|
|
|
accum_diff |= bootblock[i] ^ byte0;
|
|
|
|
sum = (sum - ((sum - 1) / 255) * 255);
|
2005-02-27 01:58:54 +03:00
|
|
|
|
1998-08-14 07:26:12 +04:00
|
|
|
/*
|
|
|
|
* If all bytes in block are the same
|
|
|
|
* or the checksum does not match ; call it invalid.
|
|
|
|
*/
|
|
|
|
if (accum_diff == 0 || sum != bootblock[511])
|
|
|
|
return -1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
mode_t
|
|
|
|
filecore_mode(ip)
|
|
|
|
struct filecore_node *ip;
|
|
|
|
{
|
1998-08-14 22:04:04 +04:00
|
|
|
mode_t m = 0;
|
|
|
|
int rf = 0;
|
1998-08-14 07:26:12 +04:00
|
|
|
|
|
|
|
if ((ip->i_dirent.attr & FILECORE_ATTR_READ) ||
|
|
|
|
(ip->i_mnt->fc_mntflags & FILECOREMNT_OWNREAD) ||
|
1998-08-14 22:04:04 +04:00
|
|
|
(ip->i_dirent.attr & FILECORE_ATTR_DIR))
|
|
|
|
rf = 1;
|
1998-08-14 07:26:12 +04:00
|
|
|
if (ip->i_mnt->fc_mntflags & FILECOREMNT_ALLACCESS) {
|
1998-08-14 22:04:04 +04:00
|
|
|
m |= S_IRUSR | S_IXUSR;
|
1998-08-14 07:26:12 +04:00
|
|
|
if (rf || (ip->i_dirent.attr & FILECORE_ATTR_OREAD))
|
1998-08-14 22:04:04 +04:00
|
|
|
m |= S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
|
1998-08-14 07:26:12 +04:00
|
|
|
} else if (ip->i_mnt->fc_mntflags & FILECOREMNT_OWNACCESS) {
|
1998-08-14 22:04:04 +04:00
|
|
|
if (rf) m |= S_IRUSR | S_IXUSR;
|
1998-08-14 07:26:12 +04:00
|
|
|
if (ip->i_dirent.attr & FILECORE_ATTR_OREAD)
|
1998-08-14 22:04:04 +04:00
|
|
|
m |= S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
|
1998-08-14 07:26:12 +04:00
|
|
|
} else {
|
1998-08-14 22:04:04 +04:00
|
|
|
m |= S_IRUSR | S_IXUSR;
|
|
|
|
if (rf) m |= S_IRGRP | S_IXGRP;
|
1998-08-14 07:26:12 +04:00
|
|
|
if (ip->i_dirent.attr & FILECORE_ATTR_OREAD)
|
1998-08-14 22:04:04 +04:00
|
|
|
m |= S_IROTH | S_IXOTH;
|
1998-08-14 07:26:12 +04:00
|
|
|
}
|
|
|
|
if (ip->i_dirent.attr & FILECORE_ATTR_DIR) {
|
1998-08-14 22:04:04 +04:00
|
|
|
m |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
|
|
|
|
} else
|
|
|
|
m |= S_IFREG;
|
1998-08-14 07:26:12 +04:00
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct timespec
|
|
|
|
filecore_time(ip)
|
|
|
|
struct filecore_node *ip;
|
|
|
|
{
|
|
|
|
struct timespec ts;
|
|
|
|
u_int64_t cs;
|
|
|
|
|
1998-08-14 22:04:04 +04:00
|
|
|
cs = (((u_int64_t)(ip->i_dirent.load & 0xFF)) << 32)
|
|
|
|
+ ip->i_dirent.exec - ((u_int64_t)1725772500 << 7);
|
|
|
|
ts.tv_sec = cs / 100;
|
|
|
|
ts.tv_nsec = (cs % 100) * 10000000;
|
1998-08-14 07:26:12 +04:00
|
|
|
return ts;
|
|
|
|
}
|
|
|
|
|
|
|
|
ino_t
|
|
|
|
filecore_getparent(ip)
|
|
|
|
struct filecore_node *ip;
|
|
|
|
{
|
|
|
|
struct buf *pbp;
|
|
|
|
u_int32_t addr;
|
|
|
|
u_int32_t paddr;
|
1998-08-14 22:04:04 +04:00
|
|
|
int error = 0;
|
|
|
|
int i = 0;
|
1998-08-14 07:26:12 +04:00
|
|
|
|
|
|
|
#ifdef FILECORE_DEBUG
|
1998-08-14 22:04:04 +04:00
|
|
|
printf("filecore_getparent(ino=%x)\n", ip->i_number);
|
1998-08-14 07:26:12 +04:00
|
|
|
#endif
|
|
|
|
if (ip->i_parent != -2) {
|
|
|
|
return ip->i_parent;
|
|
|
|
}
|
|
|
|
if (ip->i_number == FILECORE_ROOTINO) {
|
|
|
|
ip->i_parent = ip->i_number;
|
|
|
|
return ip->i_number;
|
|
|
|
}
|
1998-08-14 22:04:04 +04:00
|
|
|
addr = ip->i_number & FILECORE_INO_MASK;
|
1998-08-14 07:26:12 +04:00
|
|
|
/* Read directory data for parent dir to find its parent */
|
|
|
|
#ifdef FILECORE_DEBUG
|
|
|
|
printf("filecore_getparent() read parent dir contents\n");
|
|
|
|
#endif
|
1998-08-14 22:04:04 +04:00
|
|
|
error = filecore_bread(ip->i_mnt, addr, FILECORE_DIR_SIZE,
|
|
|
|
NOCRED, &pbp);
|
1999-02-10 16:14:08 +03:00
|
|
|
if (error) {
|
|
|
|
brelse(pbp);
|
1998-08-14 07:26:12 +04:00
|
|
|
return error;
|
1999-02-10 16:14:08 +03:00
|
|
|
}
|
1998-08-14 22:04:04 +04:00
|
|
|
paddr = fcdirtail(pbp->b_data)->parent1
|
|
|
|
| fcdirtail(pbp->b_data)->parent2 << 16;
|
1998-08-14 07:26:12 +04:00
|
|
|
#ifdef FILECORE_DEBUG_BR
|
1998-08-14 22:04:04 +04:00
|
|
|
printf("brelse(%p) ut1\n", pbp);
|
1998-08-14 07:26:12 +04:00
|
|
|
#endif
|
|
|
|
brelse(pbp);
|
|
|
|
|
|
|
|
/* If parent's parent is the parent then parent is root dir */
|
|
|
|
if (paddr == addr) {
|
|
|
|
ip->i_parent = FILECORE_ROOTINO;
|
|
|
|
return FILECORE_ROOTINO;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef FILECORE_DEBUG
|
|
|
|
printf("filecore_getparent() read grand-parent dir contents\n");
|
|
|
|
#endif
|
1998-08-14 22:04:04 +04:00
|
|
|
error = filecore_bread(ip->i_mnt, paddr, FILECORE_DIR_SIZE,
|
|
|
|
NOCRED, &pbp);
|
1999-02-10 16:14:08 +03:00
|
|
|
if (error) {
|
|
|
|
brelse(pbp);
|
1998-08-14 07:26:12 +04:00
|
|
|
return error;
|
1999-02-10 16:14:08 +03:00
|
|
|
}
|
1998-08-14 07:26:12 +04:00
|
|
|
while (fcdirentry(pbp->b_data,i)->addr != addr) {
|
1998-08-14 22:04:04 +04:00
|
|
|
if (fcdirentry(pbp->b_data, i++)->name[0] == 0) {
|
1998-08-14 07:26:12 +04:00
|
|
|
#ifdef FILECORE_DEBUG_BR
|
1998-08-14 22:04:04 +04:00
|
|
|
printf("brelse(%p) ut2\n", pbp);
|
1998-08-14 07:26:12 +04:00
|
|
|
#endif
|
|
|
|
brelse(pbp);
|
|
|
|
return FILECORE_ROOTINO;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#ifdef FILECORE_DEBUG_BR
|
1998-08-14 22:04:04 +04:00
|
|
|
printf("brelse(%p) ut3\n", pbp);
|
1998-08-14 07:26:12 +04:00
|
|
|
#endif
|
|
|
|
brelse(pbp);
|
1998-08-14 22:04:04 +04:00
|
|
|
ip->i_parent = paddr + (i << FILECORE_INO_INDEX);
|
|
|
|
return (paddr + (i << FILECORE_INO_INDEX));
|
1998-08-14 07:26:12 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*static char filecore_hexchar[16]="0123456789abcdef";*/
|
|
|
|
|
|
|
|
int
|
|
|
|
filecore_fn2unix(fcfn, ufn, len)
|
|
|
|
char *fcfn;
|
|
|
|
char *ufn;
|
|
|
|
u_int8_t *len;
|
|
|
|
{
|
1998-08-14 22:04:04 +04:00
|
|
|
int i = 0;
|
1998-08-14 07:26:12 +04:00
|
|
|
|
1998-08-14 22:04:04 +04:00
|
|
|
if (*fcfn == 0)
|
|
|
|
return (-1);
|
|
|
|
while (i++ < 10 && *fcfn >= ' ') {
|
|
|
|
if (*fcfn == '/')
|
|
|
|
*ufn++ = '.';
|
|
|
|
else
|
|
|
|
*ufn++ = *fcfn;
|
1998-08-14 07:26:12 +04:00
|
|
|
fcfn++;
|
|
|
|
}
|
|
|
|
/* if (ip->i_mnt->fc_mntflags & FILECOREMNT_FILETYPE) {
|
|
|
|
*ufn++ = ',';
|
1998-08-14 22:04:04 +04:00
|
|
|
*ufn++ = filecore_hexchar[(ip->i_dirent.load >> 10) & 15];
|
|
|
|
*ufn++ = filecore_hexchar[(ip->i_dirent.load >> 9) & 15];
|
|
|
|
*ufn++ = filecore_hexchar[(ip->i_dirent.load >> 8) & 15];
|
1998-08-14 07:26:12 +04:00
|
|
|
} */
|
1998-08-14 22:04:04 +04:00
|
|
|
*ufn = 0;
|
|
|
|
*len = i - 1;
|
1998-08-14 07:26:12 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
filecore_fncmp(fcfn, ufn, len)
|
|
|
|
const char *fcfn;
|
|
|
|
const char *ufn;
|
|
|
|
u_short len;
|
|
|
|
{
|
|
|
|
char f, u;
|
1998-08-14 22:04:04 +04:00
|
|
|
int i = 0;
|
1998-08-14 07:26:12 +04:00
|
|
|
|
1998-08-14 22:04:04 +04:00
|
|
|
if (*fcfn == 0 || len > 10)
|
|
|
|
return -1;
|
|
|
|
while (i++ < len) {
|
|
|
|
if (*fcfn < ' ')
|
|
|
|
return 1;
|
1998-08-14 07:26:12 +04:00
|
|
|
f = *fcfn++;
|
|
|
|
u = *ufn++;
|
1998-08-14 22:04:04 +04:00
|
|
|
if (u == '.')
|
|
|
|
u = '/';
|
|
|
|
if (u >= 'a' && u <= 'z') u -= 'a' - 'A';
|
|
|
|
if (f >= 'a' && f <= 'z') f -= 'a' - 'A';
|
|
|
|
if (f < u)
|
|
|
|
return 1;
|
|
|
|
else if (f > u)
|
|
|
|
return -1;
|
1998-08-14 07:26:12 +04:00
|
|
|
}
|
1998-08-14 22:04:04 +04:00
|
|
|
if (len == 10 || *fcfn < ' ')
|
|
|
|
return 0;
|
1998-08-14 07:26:12 +04:00
|
|
|
return -1;
|
|
|
|
}
|