pc_subr.c revision 264a6e7478846334593be7663fb6b1a8f37784a0
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 1980 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#ifndef KERNEL
#define KERNEL
#endif
#include <sys/sysmacros.h>
#include <sys/byteorder.h>
/*
* Convert time between DOS formats:
* - years since 1980
* and the UNIX format (seconds since 01/01/1970, 00:00:00 UT).
*
* Timezones are adjusted for via mount option arg (secondswest),
* but daylight savings time corrections are not made. Calculated
* time may therefore end up being wrong by an hour, but this:
* a) will happen as well if media is interchanged between
* two DOS/Windows-based systems that use different
* timezone settings
* b) is the best option we have unless we decide to put
* a full ctime(3C) framework into the kernel, including
* all conversion tables - AND keeping them current ...
*/
/*
* Macros/Definitons required to convert between DOS-style and
* UNIX-style time recording.
* DOS year zero is 1980.
*/
static int daysinmonth[] =
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
#define YEAR_ZERO 1980
#define FAT_ENDOFTIME \
#define FAT_ENDOFDATE \
#define leap_year(y) \
(((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
static int
days_in_year(int y)
{
}
static int
days_in_month(int m, int y)
{
if (m == 2 && leap_year(y))
return (29);
else
return (daysinmonth[m-1]);
}
/*
* Convert time from UNIX to DOS format.
* Return EOVERFLOW in case no valid DOS time representation
* exists for the given UNIX time.
*/
int
{
if (unixtime <= 0) {
/*
* "before beginning of all time" for DOS ...
*/
return (EOVERFLOW);
}
year++)
/*
* "past end of all time" for DOS - can happen
* on a 64bit kernel via utimes() syscall ...
*/
return (EOVERFLOW);
}
month++)
return (0);
}
/*
* Convert time from DOS to UNIX time format.
* Since FAT timestamps cannot be expressed in 32bit time_t,
* the calculation is performed using 64bit values. It's up to
* the caller to decide what to do for out-of-UNIX-range values.
*/
void
{
/*
* Basic sanity checks. The FAT timestamp bitfields allow for
*/
month = 1;
day = 1;
}
"d/m/y %d/%d/%d, h:m:s %d:%d:%d",
return;
}
while (month > 1) {
month--;
}
year--;
}
/*
* For FAT, the beginning of all time is 01/01/1980,
* and years are counted relative to that.
* We adjust this base value by the timezone offset
* that is passed in to pcfs at mount time.
*/
/*
* FAT epoch is past UNIX epoch - negative UNIX times
* cannot result from the conversion.
*/
}
/*
* Determine whether a character is valid for a pc 8.3 file system file name.
* The Windows 95 Resource Kit claims that these are valid:
* uppercase letters and numbers
* blank
* ASCII characters greater than 127
* $%'-_@~`!()^#&
* Long file names can also have
* lowercase letters
* +,;=[].
*/
int
pc_valid_lfn_char(char c)
{
char *cp;
int n;
static char valtab[] = {
"+,;=[].$#&@!%()-{}<>`_^~|' "
};
if (c >= 'a' && c <= 'z')
return (1);
if (c >= 'A' && c <= 'Z')
return (1);
if (c >= '0' && c <= '9')
return (1);
n = sizeof (valtab);
while (n--) {
if (c == *cp++)
return (1);
}
return (0);
}
int
pc_valid_long_fn(char *namep)
{
char *tmp;
if (!pc_valid_lfn_char(*tmp))
return (0);
return (0);
return (1);
}
int
{
int i;
char c;
i = PCFNAMESIZE;
while (i-- && ((c = *fname) != ' ')) {
if (!(c == '.' || pc_validchar(c))) {
return (-1);
}
if (foldcase)
else
*tp++ = c;
fname++;
}
if (*ext != ' ') {
*tp++ = '.';
i = PCFEXTSIZE;
while (i-- && ((c = *ext) != ' ')) {
if (!pc_validchar(c)) {
return (-1);
}
if (foldcase)
else
*tp++ = c;
ext++;
}
}
*tp = '\0';
return (0);
}