diff options
author | natano <natano@openbsd.org> | 2016-10-16 18:55:10 +0000 |
---|---|---|
committer | natano <natano@openbsd.org> | 2016-10-16 18:55:10 +0000 |
commit | 800675fd518c005c025d67872fc39b8bb63cd684 (patch) | |
tree | 2b32a88d6e8c68e93247af9d233b108f77d14efe /usr.sbin/makefs | |
parent | Fix bpf_catchpacket comment. (diff) | |
download | wireguard-openbsd-800675fd518c005c025d67872fc39b8bb63cd684.tar.xz wireguard-openbsd-800675fd518c005c025d67872fc39b8bb63cd684.zip |
Replace fs/msdosfs/{msdosfs_conv.c,direntry.h} with stripped-down
versions from our own tree. This allows to remove the clock_subr.c
tentacle.
Diffstat (limited to 'usr.sbin/makefs')
-rw-r--r-- | usr.sbin/makefs/Makefile | 1 | ||||
-rw-r--r-- | usr.sbin/makefs/fs/msdosfs/clock_subr.c | 193 | ||||
-rw-r--r-- | usr.sbin/makefs/fs/msdosfs/clock_subr.h | 111 | ||||
-rw-r--r-- | usr.sbin/makefs/fs/msdosfs/denode.h | 4 | ||||
-rw-r--r-- | usr.sbin/makefs/fs/msdosfs/direntry.h | 80 | ||||
-rw-r--r-- | usr.sbin/makefs/fs/msdosfs/msdosfs_conv.c | 850 | ||||
-rw-r--r-- | usr.sbin/makefs/fs/msdosfs/msdosfs_lookup.c | 6 | ||||
-rw-r--r-- | usr.sbin/makefs/fs/msdosfs/msdosfsmount.h | 9 | ||||
-rw-r--r-- | usr.sbin/makefs/msdos.c | 36 | ||||
-rw-r--r-- | usr.sbin/makefs/msdos/msdosfs_vfsops.c | 8 | ||||
-rw-r--r-- | usr.sbin/makefs/msdos/msdosfs_vnops.c | 22 | ||||
-rw-r--r-- | usr.sbin/makefs/sys/clock.h | 89 |
12 files changed, 256 insertions, 1153 deletions
diff --git a/usr.sbin/makefs/Makefile b/usr.sbin/makefs/Makefile index 23e46fb3500..29d70f353da 100644 --- a/usr.sbin/makefs/Makefile +++ b/usr.sbin/makefs/Makefile @@ -21,7 +21,6 @@ SRCS+= buf.c mkfs.c # msdos SRCS+= mkfs_msdos.c msdosfs_fat.c msdosfs_conv.c msdosfs_vfsops.c SRCS+= msdosfs_lookup.c msdosfs_denode.c msdosfs_vnops.c msdosfs_unicode.c -SRCS+= clock_subr.c MAN= makefs.8 diff --git a/usr.sbin/makefs/fs/msdosfs/clock_subr.c b/usr.sbin/makefs/fs/msdosfs/clock_subr.c deleted file mode 100644 index c145b9d86d0..00000000000 --- a/usr.sbin/makefs/fs/msdosfs/clock_subr.c +++ /dev/null @@ -1,193 +0,0 @@ -/* $NetBSD: clock_subr.c,v 1.27 2016/08/15 15:51:39 jakllsch Exp $ */ - -/* - * Copyright (c) 1988 University of Utah. - * Copyright (c) 1982, 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * the Systems Programming Group of the University of Utah Computer - * Science Department. - * - * 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. 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. - * - * from: Utah $Hdr: clock.c 1.18 91/01/21$ - * - * @(#)clock.c 8.2 (Berkeley) 1/12/94 - */ - -/* - * Generic routines to convert between a POSIX date - * (seconds since 1/1/1970) and yr/mo/day/hr/min/sec - * Derived from arch/hp300/hp300/clock.c - */ - -#include <stdint.h> -#include <string.h> -#include <time.h> -#include <errno.h> - -#include "../sys/clock.h" -#include <fs/msdosfs/clock_subr.h> /* XXX */ - -#define FEBRUARY 2 - -/* for easier alignment: - * time from the epoch to 2001 (there were 8 leap years): */ -#define DAYSTO2001 (365*31+8) - -/* 4 year intervals include 1 leap year */ -#define DAYS4YEARS (365*4+1) - -/* 100 year intervals include 24 leap years */ -#define DAYS100YEARS (365*100+24) - -/* 400 year intervals include 97 leap years */ -#define DAYS400YEARS (365*400+97) - -time_t -clock_ymdhms_to_secs(struct clock_ymdhms *dt) -{ - uint64_t secs, i, year, days; - - year = dt->dt_year; - - /* - * Compute days since start of time - * First from years, then from months. - */ - if (year < POSIX_BASE_YEAR) - return -1; - days = 0; - if (is_leap_year(year) && dt->dt_mon > FEBRUARY) - days++; - - if (year < 2001) { - /* simple way for early years */ - for (i = POSIX_BASE_YEAR; i < year; i++) - days += days_per_year(i); - } else { - /* years are properly aligned */ - days += DAYSTO2001; - year -= 2001; - - i = year / 400; - days += i * DAYS400YEARS; - year -= i * 400; - - i = year / 100; - days += i * DAYS100YEARS; - year -= i * 100; - - i = year / 4; - days += i * DAYS4YEARS; - year -= i * 4; - - for (i = dt->dt_year-year; i < dt->dt_year; i++) - days += days_per_year(i); - } - - - /* Months */ - for (i = 1; i < dt->dt_mon; i++) - days += days_in_month(i); - days += (dt->dt_day - 1); - - /* Add hours, minutes, seconds. */ - secs = (((uint64_t)days - * 24 + dt->dt_hour) - * 60 + dt->dt_min) - * 60 + dt->dt_sec; - - if ((time_t)secs < 0 || secs > INT64_MAX) - return -1; - return secs; -} - -int -clock_secs_to_ymdhms(time_t secs, struct clock_ymdhms *dt) -{ - int leap; - uint64_t i; - time_t days; - time_t rsec; /* remainder seconds */ - - if (secs < 0) - return EINVAL; - - days = secs / SECS_PER_DAY; - rsec = secs % SECS_PER_DAY; - - /* Day of week (Note: 1/1/1970 was a Thursday) */ - dt->dt_wday = (days + 4) % 7; - - if (days >= DAYSTO2001) { - days -= DAYSTO2001; - dt->dt_year = 2001; - - i = days / DAYS400YEARS; - days -= i*DAYS400YEARS; - dt->dt_year += i*400; - - i = days / DAYS100YEARS; - days -= i*DAYS100YEARS; - dt->dt_year += i*100; - - i = days / DAYS4YEARS; - days -= i*DAYS4YEARS; - dt->dt_year += i*4; - - for (i = dt->dt_year; days >= days_per_year(i); i++) - days -= days_per_year(i); - dt->dt_year = i; - } else { - /* Subtract out whole years, counting them in i. */ - for (i = POSIX_BASE_YEAR; days >= days_per_year(i); i++) - days -= days_per_year(i); - dt->dt_year = i; - } - - /* Subtract out whole months, counting them in i. */ - for (leap = 0, i = 1; days >= days_in_month(i)+leap; i++) { - days -= days_in_month(i)+leap; - if (i == 1 && is_leap_year(dt->dt_year)) - leap = 1; - else - leap = 0; - } - dt->dt_mon = i; - - /* Days are what is left over (+1) from all that. */ - dt->dt_day = days + 1; - - /* Hours, minutes, seconds are easy */ - dt->dt_hour = rsec / SECS_PER_HOUR; - rsec = rsec % SECS_PER_HOUR; - dt->dt_min = rsec / SECS_PER_MINUTE; - rsec = rsec % SECS_PER_MINUTE; - dt->dt_sec = rsec; - - return 0; -} diff --git a/usr.sbin/makefs/fs/msdosfs/clock_subr.h b/usr.sbin/makefs/fs/msdosfs/clock_subr.h deleted file mode 100644 index 861097aa0c4..00000000000 --- a/usr.sbin/makefs/fs/msdosfs/clock_subr.h +++ /dev/null @@ -1,111 +0,0 @@ -/* $NetBSD: clock_subr.h,v 1.25 2014/11/20 16:26:34 christos Exp $ */ - -/*- - * Copyright (c) 1996 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Gordon W. Ross - * - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -#ifndef _DEV_CLOCK_SUBR_H_ -#define _DEV_CLOCK_SUBR_H_ - -#include <sys/clock.h> - -/* - * "POSIX time" to/from "YY/MM/DD/hh/mm/ss" - */ -struct clock_ymdhms { - uint64_t dt_year; - uint8_t dt_mon; - uint8_t dt_day; - uint8_t dt_wday; /* Day of week */ - uint8_t dt_hour; - uint8_t dt_min; - uint8_t dt_sec; -}; - -time_t clock_ymdhms_to_secs(struct clock_ymdhms *); -int clock_secs_to_ymdhms(time_t, struct clock_ymdhms *); - -/* - * BCD to binary and binary to BCD. - */ -static inline unsigned int -bcdtobin(unsigned int bcd) -{ - return ((bcd >> 4) & 0x0f) * 10 + (bcd & 0x0f); -} - -static inline unsigned int -bintobcd(unsigned int bin) -{ - return (((bin / 10) << 4) & 0xf0) | (bin % 10); -} - -/* - * Interface to time-of-day clock devices. - * - * todr_gettime: convert time-of-day clock into a `struct timeval' - * todr_settime: set time-of-day clock from a `struct timeval' - * - * (this is probably not so useful:) - * todr_setwen: provide a machine-dependent TOD clock write-enable callback - * function which takes one boolean argument: - * 1 to enable writes; 0 to disable writes. - */ -struct timeval; -struct todr_chip_handle { - void *cookie; /* Device specific data */ - void *bus_cookie; /* Bus specific data */ - time_t base_time; /* Base time (e.g. rootfs time) */ - - int (*todr_gettime)(struct todr_chip_handle *, struct timeval *); - int (*todr_settime)(struct todr_chip_handle *, struct timeval *); - int (*todr_gettime_ymdhms)(struct todr_chip_handle *, - struct clock_ymdhms *); - int (*todr_settime_ymdhms)(struct todr_chip_handle *, - struct clock_ymdhms *); - int (*todr_setwen)(struct todr_chip_handle *, int); - -}; -typedef struct todr_chip_handle *todr_chip_handle_t; - -#define todr_wenable(ct, v) if ((ct)->todr_setwen) \ - ((*(ct)->todr_setwen)(ct, v)) - -/* - * Probably these should evolve into internal routines in kern_todr.c. - */ -extern int todr_gettime(todr_chip_handle_t, struct timeval *); -extern int todr_settime(todr_chip_handle_t, struct timeval *); - -/* - * Machine-dependent function that machine-independent RTC drivers can - * use to register their todr_chip_handle_t with inittodr()/resettodr(). - */ -void todr_attach(todr_chip_handle_t); - -#endif /* _DEV_CLOCK_SUBR_H_ */ diff --git a/usr.sbin/makefs/fs/msdosfs/denode.h b/usr.sbin/makefs/fs/msdosfs/denode.h index 324cf074f79..e60909fbac9 100644 --- a/usr.sbin/makefs/fs/msdosfs/denode.h +++ b/usr.sbin/makefs/fs/msdosfs/denode.h @@ -210,7 +210,7 @@ struct denode { #define DE_INTERNALIZE(dep, dp) \ (memcpy((dep)->de_Name, (dp)->deName, 11), \ (dep)->de_Attributes = (dp)->deAttributes, \ - (dep)->de_CHun = (dp)->deCHundredth, \ + (dep)->de_CHun = (dp)->deCTimeHundredth, \ (dep)->de_CTime = getushort((dp)->deCTime), \ (dep)->de_CDate = getushort((dp)->deCDate), \ (dep)->de_ADate = getushort((dp)->deADate), \ @@ -227,7 +227,7 @@ struct denode { #define DE_EXTERNALIZE(dp, dep) \ (memcpy((dp)->deName, (dep)->de_Name, 11), \ (dp)->deAttributes = (dep)->de_Attributes, \ - (dp)->deCHundredth = (dep)->de_CHun, \ + (dp)->deCTimeHundredth = (dep)->de_CHun, \ putushort((dp)->deCTime, (dep)->de_CTime), \ putushort((dp)->deCDate, (dep)->de_CDate), \ putushort((dp)->deADate, (dep)->de_ADate), \ diff --git a/usr.sbin/makefs/fs/msdosfs/direntry.h b/usr.sbin/makefs/fs/msdosfs/direntry.h index 858a09f7504..87857424ad0 100644 --- a/usr.sbin/makefs/fs/msdosfs/direntry.h +++ b/usr.sbin/makefs/fs/msdosfs/direntry.h @@ -1,4 +1,5 @@ -/* $NetBSD: direntry.h,v 1.11 2016/02/01 02:59:33 christos Exp $ */ +/* $OpenBSD: direntry.h,v 1.2 2016/10/16 18:55:10 natano Exp $ */ +/* $NetBSD: direntry.h,v 1.13 1997/10/17 11:23:45 ws Exp $ */ /*- * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. @@ -46,19 +47,17 @@ * * October 1992 */ -#ifndef _MSDOSFS_DIRENTRY_H_ -#define _MSDOSFS_DIRENTRY_H_ /* * Structure of a dos directory entry. */ struct direntry { - uint8_t deName[8]; /* filename, blank filled */ + u_int8_t deName[8]; /* filename, blank filled */ #define SLOT_EMPTY 0x00 /* slot has never been used */ #define SLOT_E5 0x05 /* the real value is 0xe5 */ #define SLOT_DELETED 0xe5 /* file in this slot deleted */ - uint8_t deExtension[3]; /* extension, blank filled */ - uint8_t deAttributes; /* file attributes */ + u_int8_t deExtension[3]; /* extension, blank filled */ + u_int8_t deAttributes; /* file attributes */ #define ATTR_NORMAL 0x00 /* normal file */ #define ATTR_READONLY 0x01 /* file is readonly */ #define ATTR_HIDDEN 0x02 /* file is hidden */ @@ -66,39 +65,35 @@ struct direntry { #define ATTR_VOLUME 0x08 /* entry is a volume label */ #define ATTR_DIRECTORY 0x10 /* entry is a directory name */ #define ATTR_ARCHIVE 0x20 /* file is new or modified */ - uint8_t deReserved; /* reserved */ - uint8_t deCHundredth; /* hundredth of seconds in CTime */ - uint8_t deCTime[2]; /* create time */ - uint8_t deCDate[2]; /* create date */ - uint8_t deADate[2]; /* access date */ - uint8_t deHighClust[2]; /* high bytes of cluster number */ - uint8_t deMTime[2]; /* last update time */ - uint8_t deMDate[2]; /* last update date */ - uint8_t deStartCluster[2]; /* starting cluster of file */ - uint8_t deFileSize[4]; /* size of file in bytes */ + u_int8_t deLowerCase; /* case for base and extension */ +#define CASE_LOWER_BASE 0x08 /* base is lower case */ +#define CASE_LOWER_EXT 0x10 /* extension is lower case */ + u_int8_t deCTimeHundredth; /* create time, 1/100th of a sec */ + u_int8_t deCTime[2]; /* create time */ + u_int8_t deCDate[2]; /* create date */ + u_int8_t deADate[2]; /* access date */ + u_int8_t deHighClust[2]; /* high byte of cluster number */ + u_int8_t deMTime[2]; /* last update time */ + u_int8_t deMDate[2]; /* last update date */ + u_int8_t deStartCluster[2]; /* starting cluster of file */ + u_int8_t deFileSize[4]; /* size of file in bytes */ }; -static __inline uint8_t -msdos_dirchar(const struct direntry *de, size_t i) { - return i < sizeof(de->deName) ? de->deName[i] : - de->deExtension[i - sizeof(de->deName)]; -} - /* * Structure of a Win95 long name directory entry */ struct winentry { - uint8_t weCnt; + u_int8_t weCnt; #define WIN_LAST 0x40 #define WIN_CNT 0x3f - uint8_t wePart1[10]; - uint8_t weAttributes; + u_int8_t wePart1[10]; + u_int8_t weAttributes; #define ATTR_WIN95 0x0f - uint8_t weReserved1; - uint8_t weChksum; - uint8_t wePart2[12]; - uint16_t weReserved2; - uint8_t wePart3[4]; + u_int8_t weReserved1; + u_int8_t weChksum; + u_int8_t wePart2[12]; + u_int16_t weReserved2; + u_int8_t wePart3[4]; }; #define WIN_CHARS 13 /* Number of chars per winentry */ @@ -126,20 +121,11 @@ struct winentry { #define DD_YEAR_MASK 0xFE00 /* year - 1980 */ #define DD_YEAR_SHIFT 9 -struct dirent; -void unix2dostime(const struct timespec *tsp, int gmtoff, uint16_t *ddp, - uint16_t *dtp, uint8_t *dhp); -void dos2unixtime(unsigned int dd, unsigned int dt, unsigned int dh, - int gmtoff, struct timespec *tsp); -int dos2unixfn(unsigned char dn[11], unsigned char *un, int lower); -int unix2dosfn(const unsigned char *un, unsigned char dn[12], int unlen, - unsigned int gen); -int unix2winfn(const unsigned char *un, int unlen, struct winentry *wep, - int cnt, int chksum, int utf8); -int winChkName(const unsigned char *un, int unlen, struct winentry *wep, - int chksum, int utf8); -int win2unixfn(struct winentry *wep, struct dirent *dp, int chksum, - uint16_t *namlen, int utf8); -uint8_t winChksum(uint8_t *name); -int winSlotCnt(const unsigned char *un, int unlen, int utf8); -#endif /* _MSDOSFS_DIRENTRY_H_ */ +void unix2dostime(struct timespec *tsp, int minuteswest, u_int16_t *ddp, + u_int16_t *dtp, u_int8_t *dhp); +int unix2dosfn(u_char *un, u_char dn[12], int unlen, u_int gen); +int unix2winfn(u_char *un, int unlen, struct winentry *wep, int cnt, + int chksum); +int winChkName(u_char *un, int unlen, struct winentry *wep, int chksum); +u_int8_t winChksum(u_int8_t *name); +int winSlotCnt(u_char *un, int unlen); diff --git a/usr.sbin/makefs/fs/msdosfs/msdosfs_conv.c b/usr.sbin/makefs/fs/msdosfs/msdosfs_conv.c index b2550c2b110..788fafd181d 100644 --- a/usr.sbin/makefs/fs/msdosfs/msdosfs_conv.c +++ b/usr.sbin/makefs/fs/msdosfs/msdosfs_conv.c @@ -1,4 +1,5 @@ -/* $NetBSD: msdosfs_conv.c,v 1.17 2016/06/30 09:34:01 nonaka Exp $ */ +/* $OpenBSD: msdosfs_conv.c,v 1.2 2016/10/16 18:55:10 natano Exp $ */ +/* $NetBSD: msdosfs_conv.c,v 1.24 1997/10/17 11:23:54 ws Exp $ */ /*- * Copyright (C) 1995, 1997 Wolfgang Solfrank. @@ -45,23 +46,16 @@ * any damages caused by this software. * * October 1992 - * */ -#include <assert.h> -#define KASSERT(x) assert(x) - /* * System include files. */ #include <sys/param.h> #include <sys/time.h> -#include <sys/endian.h> -#include <stdio.h> -#include <string.h> -#include <dirent.h> -#include <sys/queue.h> -#include <fs/msdosfs/clock_subr.h> /* XXX */ +#include <sys/dirent.h> +#include <sys/vnode.h> +#include <sys/lock.h> /* * MSDOSFS include files. @@ -69,118 +63,107 @@ #include <fs/msdosfs/direntry.h> #include <fs/msdosfs/denode.h> -static int invalidname(const u_int16_t *, int); - -static int ucs2utf8(const u_int16_t *, u_int8_t *, int); -static int utf8ucs2(const u_int8_t *, int, u_int16_t *); - -static int ucs2utf8str(const u_int16_t *, int, u_int8_t *, int); -static int utf8ucs2str(const u_int8_t *, int, u_int16_t *, int); -static int ucs2char8str(const u_int16_t *, int, u_int8_t *, int); -static int char8ucs2str(const u_int8_t *, int, u_int16_t *, int); - -static void ucs2pad(u_int16_t *, int, int); - -static u_int16_t ucs2fold(u_int16_t); -static int ucs2match(u_int16_t *, u_int16_t *, int n); -static int char8match(u_int16_t *, u_int16_t *, int n); +/* + * Days in each month in a regular year. + */ +const u_short regyear[] = { + 31, 28, 31, 30, 31, 30, + 31, 31, 30, 31, 30, 31 +}; /* - * The number of seconds between Jan 1, 1970 and Jan 1, 1980. In that - * interval there were 8 regular years and 2 leap years. + * Days in each month in a leap year. */ -#define DOSBIASYEAR 1980 -#define SECONDSTO1980 (((8 * 365) + (2 * 366)) * (24 * 60 * 60)) +const u_short leapyear[] = { + 31, 29, 31, 30, 31, 30, + 31, 31, 30, 31, 30, 31 +}; + /* - * msdos fs can not store dates beyound the year 2234 + * Variables used to remember parts of the last time conversion. Maybe we + * can avoid a full conversion. */ -#define DOSMAXYEAR ((DD_YEAR_MASK >> DD_YEAR_SHIFT) + DOSBIASYEAR) +time_t lasttime; +uint32_t lastday; +u_short lastddate; +u_short lastdtime; /* * Convert the unix version of time to dos's idea of time to be used in * file timestamps. The passed in unix time is assumed to be in GMT. */ void -unix2dostime(const struct timespec *tsp, int gmtoff, u_int16_t *ddp, u_int16_t *dtp, u_int8_t *dhp) +unix2dostime(struct timespec *tsp, int minuteswest, u_int16_t *ddp, + u_int16_t *dtp, u_int8_t *dhp) { - u_long t; - struct clock_ymdhms ymd; - - t = tsp->tv_sec + gmtoff; /* time zone correction */ - - /* - * DOS timestamps can not represent dates before 1980. - */ - if (t < SECONDSTO1980) - goto invalid_dos_date; + time_t t; + uint32_t days; + uint32_t inc; + uint32_t year; + uint32_t month; + const u_short *months; /* - * DOS granularity is 2 seconds + * If the time from the last conversion is the same as now, then + * skip the computations and use the saved result. */ + t = tsp->tv_sec - (minuteswest * 60) + /* +- daylight saving time correction */ ; t &= ~1; - /* - * Convert to year/month/day/.. format + * Before 1/1/1980 there is only a timeless void. After 12/31/2107 + * there is only Cthulhu. */ - clock_secs_to_ymdhms(t, &ymd); - if (ymd.dt_year > DOSMAXYEAR) - goto invalid_dos_date; +#define DOSEPOCH 315532800LL +#define DOSENDTIME 4354775999LL + if (t < DOSEPOCH || t > DOSENDTIME) + t = DOSEPOCH; - /* - * Now transform to DOS format - */ - *ddp = (ymd.dt_day << DD_DAY_SHIFT) - + (ymd.dt_mon << DD_MONTH_SHIFT) - + ((ymd.dt_year - DOSBIASYEAR) << DD_YEAR_SHIFT); - if (dhp) - *dhp = (tsp->tv_sec & 1) * 100 + tsp->tv_nsec / 10000000; - if (dtp) - *dtp = (((t / 2) % 30) << DT_2SECONDS_SHIFT) + if (lasttime != t) { + lasttime = t; + lastdtime = (((t / 2) % 30) << DT_2SECONDS_SHIFT) + (((t / 60) % 60) << DT_MINUTES_SHIFT) + (((t / 3600) % 24) << DT_HOURS_SHIFT); - return; - -invalid_dos_date: - *ddp = 0; - if (dtp) - *dtp = 0; - if (dhp) - *dhp = 0; -} - -/* - * Convert from dos' idea of time to unix'. This will probably only be - * called from the stat(), and fstat() system calls and so probably need - * not be too efficient. - */ -void -dos2unixtime(u_int dd, u_int dt, u_int dh, int gmtoff, struct timespec *tsp) -{ - time_t seconds; - struct clock_ymdhms ymd; - if (dd == 0) { /* - * Uninitialized field, return the epoch. + * If the number of days since 1970 is the same as the last + * time we did the computation then skip all this leap year + * and month stuff. */ - tsp->tv_sec = 0; - tsp->tv_nsec = 0; - return; + days = t / (24 * 60 * 60); + if (days != lastday) { + lastday = days; + for (year = 1970;; year++) { + inc = year & 0x03 ? 365 : 366; + if (days < inc) + break; + days -= inc; + } + months = year & 0x03 ? regyear : leapyear; + for (month = 0; month < 12; month++) { + if (days < months[month]) + break; + days -= months[month]; + } + lastddate = ((days + 1) << DD_DAY_SHIFT) + + ((month + 1) << DD_MONTH_SHIFT); + /* + * Remember dos's idea of time is relative to 1980. + * unix's is relative to 1970. If somehow we get a + * time before 1980 then don't give totally crazy + * results. + */ + if (year > 1980) + lastddate += (year - 1980) << DD_YEAR_SHIFT; + } } - memset(&ymd, 0, sizeof(ymd)); - ymd.dt_year = ((dd & DD_YEAR_MASK) >> DD_YEAR_SHIFT) + 1980 ; - ymd.dt_mon = ((dd & DD_MONTH_MASK) >> DD_MONTH_SHIFT); - ymd.dt_day = ((dd & DD_DAY_MASK) >> DD_DAY_SHIFT); - ymd.dt_hour = (dt & DT_HOURS_MASK) >> DT_HOURS_SHIFT; - ymd.dt_min = (dt & DT_MINUTES_MASK) >> DT_MINUTES_SHIFT; - ymd.dt_sec = ((dt & DT_2SECONDS_MASK) >> DT_2SECONDS_SHIFT) * 2; - - seconds = clock_ymdhms_to_secs(&ymd); + if (dtp != NULL) + *dtp = lastdtime; + if (dhp != NULL) + *dhp = (tsp->tv_sec & 1) * 100 + tsp->tv_nsec / 10000000; - tsp->tv_sec = seconds; - tsp->tv_sec -= gmtoff; /* time zone correction */ - tsp->tv_nsec = (dh % 100) * 10000000; + *ddp = lastddate; } static const u_char @@ -189,18 +172,18 @@ unix2dos[256] = { 0, 0, 0, 0, 0, 0, 0, 0, /* 08-0f */ 0, 0, 0, 0, 0, 0, 0, 0, /* 10-17 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 18-1f */ - 0, '!', 0, '#', '$', '%', '&', '\'', /* 20-27 */ - '(', ')', 0, '+', 0, '-', 0, 0, /* 28-2f */ - '0', '1', '2', '3', '4', '5', '6', '7', /* 30-37 */ - '8', '9', 0, 0, 0, 0, 0, 0, /* 38-3f */ - '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 40-47 */ - 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', /* 48-4f */ - 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', /* 50-57 */ - 'X', 'Y', 'Z', 0, 0, 0, '^', '_', /* 58-5f */ - '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 60-67 */ - 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', /* 68-6f */ - 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', /* 70-77 */ - 'X', 'Y', 'Z', '{', 0, '}', '~', 0, /* 78-7f */ + 0, 0x21, 0, 0x23, 0x24, 0x25, 0x26, 0x27, /* 20-27 */ + 0x28, 0x29, 0, 0, 0, 0x2d, 0, 0, /* 28-2f */ + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 30-37 */ + 0x38, 0x39, 0, 0, 0, 0, 0, 0, /* 38-3f */ + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 40-47 */ + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 48-4f */ + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 50-57 */ + 0x58, 0x59, 0x5a, 0, 0, 0, 0x5e, 0x5f, /* 58-5f */ + 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 60-67 */ + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 68-6f */ + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 70-77 */ + 0x58, 0x59, 0x5a, 0x7b, 0, 0x7d, 0x7e, 0, /* 78-7f */ 0, 0, 0, 0, 0, 0, 0, 0, /* 80-87 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 88-8f */ 0, 0, 0, 0, 0, 0, 0, 0, /* 90-97 */ @@ -220,59 +203,23 @@ unix2dos[256] = { }; static const u_char -dos2unix[256] = { - '?', '?', '?', '?', '?', '?', '?', '?', /* 00-07 */ - '?', '?', '?', '?', '?', '?', '?', '?', /* 08-0f */ - '?', '?', '?', '?', '?', '?', '?', '?', /* 10-17 */ - '?', '?', '?', '?', '?', '?', '?', '?', /* 18-1f */ - ' ', '!', '"', '#', '$', '%', '&', '\'', /* 20-27 */ - '(', ')', '*', '+', ',', '-', '.', '/', /* 28-2f */ - '0', '1', '2', '3', '4', '5', '6', '7', /* 30-37 */ - '8', '9', ':', ';', '<', '=', '>', '?', /* 38-3f */ - '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 40-47 */ - 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', /* 48-4f */ - 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', /* 50-57 */ - 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', /* 58-5f */ - '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', /* 60-67 */ - 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', /* 68-6f */ - 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', /* 70-77 */ - 'x', 'y', 'z', '{', '|', '}', '~', 0x7f, /* 78-7f */ - 0xc7, 0xfc, 0xe9, 0xe2, 0xe4, 0xe0, 0xe5, 0xe7, /* 80-87 */ - 0xea, 0xeb, 0xe8, 0xef, 0xee, 0xec, 0xc4, 0xc5, /* 88-8f */ - 0xc9, 0xe6, 0xc6, 0xf4, 0xf6, 0xf2, 0xfb, 0xf9, /* 90-97 */ - 0xff, 0xd6, 0xdc, 0xf8, 0xa3, 0xd8, 0xd7, '?', /* 98-9f */ - 0xe1, 0xed, 0xf3, 0xfa, 0xf1, 0xd1, 0xaa, 0xba, /* a0-a7 */ - 0xbf, 0xae, 0xac, 0xbd, 0xbc, 0xa1, 0xab, 0xbb, /* a8-af */ - '?', '?', '?', '?', '?', 0xc1, 0xc2, 0xc0, /* b0-b7 */ - 0xa9, '?', '?', '?', '?', 0xa2, 0xa5, '?', /* b8-bf */ - '?', '?', '?', '?', '?', '?', 0xe3, 0xc3, /* c0-c7 */ - '?', '?', '?', '?', '?', '?', '?', 0xa4, /* c8-cf */ - 0xf0, 0xd0, 0xca, 0xcb, 0xc8, '?', 0xcd, 0xce, /* d0-d7 */ - 0xcf, '?', '?', '?', '?', 0xa6, 0xcc, '?', /* d8-df */ - 0xd3, 0xdf, 0xd4, 0xd2, 0xf5, 0xd5, 0xb5, 0xfe, /* e0-e7 */ - 0xde, 0xda, 0xdb, 0xd9, 0xfd, 0xdd, 0xaf, 0x3f, /* e8-ef */ - 0xad, 0xb1, '?', 0xbe, 0xb6, 0xa7, 0xf7, 0xb8, /* f0-f7 */ - 0xb0, 0xa8, 0xb7, 0xb9, 0xb3, 0xb2, '?', '?', /* f8-ff */ -}; - -static const u_char u2l[256] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 00-07 */ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 08-0f */ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 10-17 */ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 18-1f */ - ' ', '!', '"', '#', '$', '%', '&', '\'', /* 20-27 */ - '(', ')', '*', '+', ',', '-', '.', '/', /* 28-2f */ - '0', '1', '2', '3', '4', '5', '6', '7', /* 30-37 */ - '8', '9', ':', ';', '<', '=', '>', '?', /* 38-3f */ - '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', /* 40-47 */ - 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', /* 48-4f */ - 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', /* 50-57 */ - 'x', 'y', 'z', '[', '\\', ']', '^', '_', /* 58-5f */ - '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', /* 60-67 */ - 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', /* 68-6f */ - 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', /* 70-77 */ - 'x', 'y', 'z', '{', '|', '}', '~', 0x7f, /* 78-7f */ + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 20-27 */ + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 28-2f */ + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 30-37 */ + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 38-3f */ + 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 40-47 */ + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 48-4f */ + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 50-57 */ + 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 58-5f */ + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 60-67 */ + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 68-6f */ + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 70-77 */ + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 78-7f */ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 80-87 */ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 88-8f */ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 90-97 */ @@ -299,63 +246,6 @@ u2l[256] = { */ /* - * Convert a DOS filename to a unix filename. And, return the number of - * characters in the resulting unix filename excluding the terminating - * null. - */ -int -dos2unixfn(u_char dn[11], u_char *un, int lower) -{ - int i, j; - int thislong = 1; - u_char c; - - /* - * If first char of the filename is SLOT_E5 (0x05), then the real - * first char of the filename should be 0xe5. But, they couldn't - * just have a 0xe5 mean 0xe5 because that is used to mean a freed - * directory slot. Another dos quirk. - */ - if (*dn == SLOT_E5) - c = dos2unix[0xe5]; - else - c = dos2unix[*dn]; - *un++ = lower ? u2l[c] : c; - - /* - * Copy the rest into the unix filename string, ignoring - * trailing blanks. - */ - - for (j=7; (j >= 0) && (dn[j] == ' '); j--) - ; - - for (i = 1; i <= j; i++) { - c = dos2unix[dn[i]]; - *un++ = lower ? u2l[c] : c; - thislong++; - } - dn += 8; - - /* - * Now, if there is an extension then put in a period and copy in - * the extension. - */ - if (*dn != ' ') { - *un++ = '.'; - thislong++; - for (i = 0; i < 3 && *dn != ' '; i++) { - c = dos2unix[*dn++]; - *un++ = lower ? u2l[c] : c; - thislong++; - } - } - *un++ = 0; - - return (thislong); -} - -/* * Convert a unix filename to a DOS filename according to Win95 rules. * If applicable and gen is not 0, it is inserted into the converted * filename as a generation number. @@ -367,13 +257,12 @@ dos2unixfn(u_char dn[11], u_char *un, int lower) * 3 if conversion was successful and generation number was inserted */ int -unix2dosfn(const u_char *un, u_char dn[12], int unlen, u_int gen) +unix2dosfn(u_char *un, u_char dn[11], int unlen, u_int gen) { int i, j, l; int conv = 1; - const u_char *cp, *dp, *dp1; - u_char gentext[6], *wcp; - int shortlen; + u_char *cp, *dp, *dp1; + u_char gentext[6]; /* * Fill the dos filename string with blanks. These are DOS's pad @@ -381,7 +270,6 @@ unix2dosfn(const u_char *un, u_char dn[12], int unlen, u_int gen) */ for (i = 0; i < 11; i++) dn[i] = ' '; - dn[11] = 0; /* * The filenames "." and ".." are handled specially, since they @@ -453,17 +341,11 @@ unix2dosfn(const u_char *un, u_char dn[12], int unlen, u_int gen) dp++; } - shortlen = (dp - un) <= 8; - /* * Now convert the rest of the name */ for (i = j = 0; un < dp && j < 8; i++, j++, un++) { - if ((*un == ' ') && shortlen) - dn[j] = ' '; - else - dn[j] = unix2dos[*un]; - if ((*un != dn[j]) + if (*un != (dn[j] = unix2dos[*un]) && conv != 3) conv = 2; if (!dn[j]) { @@ -500,17 +382,16 @@ unix2dosfn(const u_char *un, u_char dn[12], int unlen, u_int gen) /* * Now insert the generation number into the filename part */ - for (wcp = gentext + sizeof(gentext); wcp > gentext && gen; gen /= 10) - *--wcp = gen % 10 + '0'; + for (cp = gentext + sizeof(gentext); cp > gentext && gen; gen /= 10) + *--cp = gen % 10 + '0'; if (gen) return 0; for (i = 8; dn[--i] == ' ';); - i++; - if (gentext + sizeof(gentext) - wcp + 1 > 8 - i) - i = 8 - (gentext + sizeof(gentext) - wcp + 1); + if (gentext + sizeof(gentext) - cp + 1 > 8 - i) + i = 8 - (gentext + sizeof(gentext) - cp + 1); dn[i++] = '~'; - while (wcp < gentext + sizeof(gentext)) - dn[i++] = *wcp++; + while (cp < gentext + sizeof(gentext)) + dn[i++] = *cp++; return 3; } @@ -520,34 +401,23 @@ unix2dosfn(const u_char *un, u_char dn[12], int unlen, u_int gen) * i.e. doesn't consist solely of blanks and dots */ int -unix2winfn(const u_char *un, int unlen, struct winentry *wep, int cnt, int chksum, int utf8) +unix2winfn(u_char *un, int unlen, struct winentry *wep, int cnt, int chksum) { - u_int16_t wn[WIN_MAXLEN], *p; - int i, len; - const u_char *cp; + u_int8_t *cp; + int i; /* * Drop trailing blanks and dots */ - for (cp = un + unlen; unlen > 0; unlen--) - if (*--cp != ' ' && *cp != '.') - break; - - /* - * Offset of this entry - */ - i = (cnt - 1) * WIN_CHARS; + for (cp = un + unlen; *--cp == ' ' || *cp == '.'; unlen--); - /* - * Translate UNIX name to ucs-2 - */ - len = utf8 ? utf8ucs2str(un, unlen, wn, WIN_MAXLEN) : char8ucs2str(un, unlen, wn, WIN_MAXLEN); - ucs2pad(wn, len, WIN_MAXLEN); + un += (cnt - 1) * WIN_CHARS; + unlen -= (cnt - 1) * WIN_CHARS; /* * Initialize winentry to some useful default */ - memset(wep, 0xff, sizeof(*wep)); + for (cp = (u_int8_t *)wep, i = sizeof(*wep); --i >= 0; *cp++ = 0xff); wep->weCnt = cnt; wep->weAttributes = ATTR_WIN95; wep->weReserved1 = 0; @@ -555,18 +425,33 @@ unix2winfn(const u_char *un, int unlen, struct winentry *wep, int cnt, int chksu wep->weReserved2 = 0; /* - * Store name segment into directory entry + * Now convert the filename parts */ - p = &wn[i]; - memcpy(wep->wePart1, p, sizeof(wep->wePart1)); - p += sizeof(wep->wePart1) / sizeof(*p); - memcpy(wep->wePart2, p, sizeof(wep->wePart2)); - p += sizeof(wep->wePart2) / sizeof(*p); - memcpy(wep->wePart3, p, sizeof(wep->wePart3)); - - if (len > i + WIN_CHARS) - return 1; + for (cp = wep->wePart1, i = sizeof(wep->wePart1)/2; --i >= 0;) { + if (--unlen < 0) + goto done; + *cp++ = *un++; + *cp++ = 0; + } + for (cp = wep->wePart2, i = sizeof(wep->wePart2)/2; --i >= 0;) { + if (--unlen < 0) + goto done; + *cp++ = *un++; + *cp++ = 0; + } + for (cp = wep->wePart3, i = sizeof(wep->wePart3)/2; --i >= 0;) { + if (--unlen < 0) + goto done; + *cp++ = *un++; + *cp++ = 0; + } + if (!unlen) + wep->weCnt |= WIN_LAST; + return unlen; +done: + *cp++ = 0; + *cp++ = 0; wep->weCnt |= WIN_LAST; return 0; } @@ -576,16 +461,15 @@ unix2winfn(const u_char *un, int unlen, struct winentry *wep, int cnt, int chksu * Returns the checksum or -1 if no match */ int -winChkName(const u_char *un, int unlen, struct winentry *wep, int chksum, int utf8) +winChkName(u_char *un, int unlen, struct winentry *wep, int chksum) { - u_int16_t wn[WIN_MAXLEN], *p; - u_int16_t buf[WIN_CHARS]; - int i, len; + u_int8_t *cp; + int i; /* * First compare checksums */ - if (wep->weCnt & WIN_LAST) + if (wep->weCnt&WIN_LAST) chksum = wep->weChksum; else if (chksum != wep->weChksum) chksum = -1; @@ -595,110 +479,44 @@ winChkName(const u_char *un, int unlen, struct winentry *wep, int chksum, int ut /* * Offset of this entry */ - i = ((wep->weCnt & WIN_CNT) - 1) * WIN_CHARS; - - /* - * Translate UNIX name to ucs-2 - */ - len = utf8 ? utf8ucs2str(un, unlen, wn, WIN_MAXLEN) : char8ucs2str(un, unlen, wn, WIN_MAXLEN); - ucs2pad(wn, len, WIN_MAXLEN); - - if (i >= len + 1) - return -1; - if ((wep->weCnt & WIN_LAST) && (len - i > WIN_CHARS)) - return -1; - - /* - * Fetch name segment from directory entry - */ - p = &buf[0]; - memcpy(p, wep->wePart1, sizeof(wep->wePart1)); - p += sizeof(wep->wePart1) / sizeof(*p); - memcpy(p, wep->wePart2, sizeof(wep->wePart2)); - p += sizeof(wep->wePart2) / sizeof(*p); - memcpy(p, wep->wePart3, sizeof(wep->wePart3)); - - /* - * And compare name segment - */ - if (! (utf8 ? ucs2match(&wn[i], buf, WIN_CHARS) : char8match(&wn[i], buf, WIN_CHARS))) - return -1; - - return chksum; -} - -/* - * Convert Win95 filename to dirbuf. - * Returns the checksum or -1 if impossible - */ -int -win2unixfn(struct winentry *wep, struct dirent *dp, int chksum, - uint16_t *namlen, int utf8) -{ - u_int16_t wn[WIN_CHARS], *p; - u_int8_t buf[WIN_CHARS*3]; - int len; - - if ((wep->weCnt & WIN_CNT) > howmany(WIN_MAXLEN, WIN_CHARS) - || !(wep->weCnt & WIN_CNT)) - return -1; - - /* - * First compare checksums - */ - if (wep->weCnt & WIN_LAST) { - chksum = wep->weChksum; - *namlen = 0; - } else if (chksum != wep->weChksum) - chksum = -1; - if (chksum == -1) + i = ((wep->weCnt&WIN_CNT) - 1) * WIN_CHARS; + if ((unlen -= i) <= 0) return -1; + un += i; - /* - * Fetch name segment from directory entry - */ - p = &wn[0]; - memcpy(p, wep->wePart1, sizeof(wep->wePart1)); - p += sizeof(wep->wePart1) / sizeof(*p); - memcpy(p, wep->wePart2, sizeof(wep->wePart2)); - p += sizeof(wep->wePart2) / sizeof(*p); - memcpy(p, wep->wePart3, sizeof(wep->wePart3)); - - /* - * Don't allow slashes in UNIX names. Discard that entry. - */ - if (invalidname(wn, WIN_CHARS)) + if ((wep->weCnt&WIN_LAST) && unlen > WIN_CHARS) return -1; /* - * Translate ucs-2 to UNIX name - */ - len = utf8 ? ucs2utf8str(wn, WIN_CHARS, buf, sizeof(buf)) - : ucs2char8str(wn, WIN_CHARS, buf, sizeof(buf)); - - KASSERT(len >= 0); - KASSERT((size_t)len <= MIN(sizeof(buf), sizeof(dp->d_name)-1)); - - /* - * Prepend name segment to directory entry - * - * This ignores the slot number from the windows entry but - * assumes that segments are read in reverse order. - * - * The UCS-2 name (up to 255 chars) can overflow the UNIX - * directory entry (up to 511 bytes). Trailing characters - * are silently discarded. This could also end in multiple - * files using the same (truncated) name. + * Compare the name parts */ - *namlen += len; - if (*namlen > sizeof(dp->d_name) - 1) - *namlen = sizeof(dp->d_name) - 1; - - KASSERT(*namlen >= len); - - memmove(&dp->d_name[len], &dp->d_name[0], *namlen - len); - memcpy(dp->d_name, buf, len); - + for (cp = wep->wePart1, i = sizeof(wep->wePart1)/2; --i >= 0;) { + if (--unlen < 0) { + if (!*cp++ && !*cp) + return chksum; + return -1; + } + if (u2l[*cp++] != u2l[*un++] || *cp++) + return -1; + } + for (cp = wep->wePart2, i = sizeof(wep->wePart2)/2; --i >= 0;) { + if (--unlen < 0) { + if (!*cp++ && !*cp) + return chksum; + return -1; + } + if (u2l[*cp++] != u2l[*un++] || *cp++) + return -1; + } + for (cp = wep->wePart3, i = sizeof(wep->wePart3)/2; --i >= 0;) { + if (--unlen < 0) { + if (!*cp++ && !*cp) + return chksum; + return -1; + } + if (u2l[*cp++] != u2l[*un++] || *cp++) + return -1; + } return chksum; } @@ -712,7 +530,7 @@ winChksum(u_int8_t *name) u_int8_t s; for (s = 0, i = 11; --i >= 0; s += *name++) - s = (s << 7) | (s >> 1); + s = (s << 7)|(s >> 1); return s; } @@ -720,304 +538,12 @@ winChksum(u_int8_t *name) * Determine the number of slots necessary for Win95 names */ int -winSlotCnt(const u_char *un, int unlen, int utf8) -{ - const u_char *cp; - int len; - - /* - * Drop trailing blanks and dots - */ - for (cp = un + unlen; unlen > 0; unlen--) - if (*--cp != ' ' && *cp != '.') - break; - - len = utf8 ? utf8ucs2str(un, unlen, NULL, WIN_MAXLEN) : unlen; - - return howmany(len, WIN_CHARS); -} - -/* - * Scan windows name for characters that must not - * appear in a UNIX filename - */ -static int -invalidname(const u_int16_t *in, int n) -{ - while (n-- > 0) { - if (*in++ == '/') - return 1; - } - - return 0; -} - -/* - * Convert UCS-2 character into UTF-8 - * return number of output bytes or 0 if output - * buffer is too short - */ -static int -ucs2utf8(const u_int16_t *in, u_int8_t *out, int n) -{ - uint16_t inch = le16toh(in[0]); - - if (inch <= 0x007f) { - if (n < 1) return 0; - if (out) - *out++ = inch; - return 1; - } else if (inch <= 0x07ff) { - if (n < 2) return 0; - if (out) { - *out++ = 0xc0 | (inch >> 6); - *out++ = 0x80 | (inch & 0x3f); - } - return 2; - } else { - if (n < 3) return 0; - if (out) { - *out++ = 0xe0 | (inch >> 12); - *out++ = 0x80 | ((inch >> 6) & 0x3f); - *out++ = 0x80 | (inch & 0x3f); - } - return 3; - } -} - - -/* - * Convert UTF-8 bytes into UCS-2 character - * return number of input bytes, 0 if input - * is too short and -1 if input is invalid - */ -static int -utf8ucs2(const u_int8_t *in, int n, u_int16_t *out) -{ - uint16_t outch; - - if (n < 1) return 0; - - if (in[0] <= 0x7f) { - outch = in[0]; - if (out) - *out = htole16(outch); - return 1; - } else if (in[0] <= 0xdf) { - if (n < 2) return 0; - outch = (in[0] & 0x1f) << 6 | (in[1] & 0x3f); - if (out) - *out = htole16(outch); - return 2; - } else if (in[0] <= 0xef) { - if (n < 3) return 0; - outch = (in[0] & 0x1f) << 12 | (in[1] & 0x3f) << 6 | (in[2] & 0x3f); - if (out) - *out = htole16(outch); - return 3; - } - - return -1; -} - -/* - * Convert UCS-2 string into UTF-8 string - * return total number of output bytes - */ -static int -ucs2utf8str(const u_int16_t *in, int n, u_int8_t *out, int m) -{ - u_int8_t *p; - int outlen; - - p = out; - while (n > 0 && *in != 0) { - outlen = ucs2utf8(in, out ? p : out, m); - if (outlen == 0) - break; - p += outlen; - m -= outlen; - in += 1; - n -= 1; - } - - return p - out; -} - -/* - * Convert UTF8 string into UCS-2 string - * return total number of output chacters - */ -static int -utf8ucs2str(const u_int8_t *in, int n, u_int16_t *out, int m) +winSlotCnt(u_char *un, int unlen) { - u_int16_t *p; - int inlen; - - p = out; - while (n > 0 && *in != 0) { - if (m < 1) + for (un += unlen; unlen > 0; unlen--) + if (*--un != ' ' && *un != '.') break; - inlen = utf8ucs2(in, n, out ? p : out); - if (inlen <= 0) - break; - in += inlen; - n -= inlen; - p += 1; - m -= 1; - } - - return p - out; -} - -/* - * Convert UCS-2 string into 8bit character string - * return total number of output bytes - */ -static int -ucs2char8str(const u_int16_t *in, int n, u_int8_t *out, int m) -{ - u_int8_t *p; - u_int16_t inch; - - p = out; - while (n > 0 && in[0] != 0) { - if (m < 1) - break; - inch = le16toh(in[0]); - if (inch > 255) - break; - if (p) - p[0] = inch; - p += 1; - m -= 1; - in += 1; - n -= 1; - } - - return p - out; -} - -/* - * Convert 8bit character string into UCS-2 string - * return total number of output chacters - */ -static int -char8ucs2str(const u_int8_t *in, int n, u_int16_t *out, int m) -{ - u_int16_t *p; - - p = out; - while (n > 0 && in[0] != 0) { - if (m < 1) - break; - if (p) - p[0] = htole16(in[0]); - p += 1; - m -= 1; - in += 1; - n -= 1; - } - - return p - out; -} - -static void -ucs2pad(u_int16_t *buf, int len, int size) -{ - - if (len < size-1) - buf[len++] = 0x0000; - while (len < size) - buf[len++] = 0xffff; -} - -/* - * Fold UCS-2 character to uppercase - */ -static u_int16_t -ucs2fold(u_int16_t w) -{ - int low,high,mid; - u_int16_t check; - extern const u_int16_t msdosfs_unicode_foldmap[]; - extern size_t msdosfs_unicode_foldmap_entries; - - w = le16toh(w); - - low = 0; - high = msdosfs_unicode_foldmap_entries / 2; - while (low < high) { - mid = (low + high)/2; - check = msdosfs_unicode_foldmap[2*mid+0]; - - if (w == check) { - w = msdosfs_unicode_foldmap[2*mid+1]; - break; - } - - if (w < check) - high = mid; - else - low = mid+1; - } - - w = le16toh(w); - - return w; -} - -/* - * Compare two UCS-2 strings case-insensitive - * - * uses the Unicode case folding table - */ -static int -ucs2match(u_int16_t *w1, u_int16_t *w2, int n) -{ - u_int16_t u1, u2; - - while (n > 0) { - if (*w1 == 0 || *w2 == 0) - return *w1 == *w2; - u1 = ucs2fold(*w1); - u2 = ucs2fold(*w2); - if (u1 != u2) - return 0; - ++w1; - ++w2; - --n; - } - - return 1; -} - -/* - * Compare two 8bit char conversions case-insensitive - * - * uses the DOS case folding table - */ -static int -char8match(u_int16_t *w1, u_int16_t *w2, int n) -{ - u_int16_t u1, u2; - - while (n > 0) { - u1 = le16toh(*w1); - u2 = le16toh(*w2); - if (u1 == 0 || u2 == 0) - return u1 == u2; - if (u1 > 255 || u2 > 255) - return 0; - u1 = u2l[u1 & 0xff]; - u2 = u2l[u2 & 0xff]; - if (u1 != u2) - return 0; - ++w1; - ++w2; - --n; - } - - return 1; + if (unlen > WIN_MAXLEN) + return 0; + return howmany(unlen, WIN_CHARS); } - diff --git a/usr.sbin/makefs/fs/msdosfs/msdosfs_lookup.c b/usr.sbin/makefs/fs/msdosfs/msdosfs_lookup.c index dfc3d070236..cf6303c0297 100644 --- a/usr.sbin/makefs/fs/msdosfs/msdosfs_lookup.c +++ b/usr.sbin/makefs/fs/msdosfs/msdosfs_lookup.c @@ -168,8 +168,7 @@ createde(struct denode *dep, struct denode *ddep, struct denode **depp, struct c fndoffset -= sizeof(struct direntry); } if (!unix2winfn(un, unlen, (struct winentry *)ndep, - wcnt, chksum, - ddep->de_pmp->pm_flags & MSDOSFSMNT_UTF8)) + wcnt, chksum)) break; } } @@ -557,8 +556,7 @@ uniqdosname(struct denode *dep, struct componentname *cnp, u_char *cp) /* * Generate DOS name with generation number */ - if (!unix2dosfn((const u_char *)cnp->cn_nameptr, cp, - cnp->cn_namelen, gen)) + if (!unix2dosfn(cnp->cn_nameptr, cp, cnp->cn_namelen, gen)) return gen == 1 ? EINVAL : EEXIST; /* diff --git a/usr.sbin/makefs/fs/msdosfs/msdosfsmount.h b/usr.sbin/makefs/fs/msdosfs/msdosfsmount.h index 9b4399bd8d8..a6371bde2cb 100644 --- a/usr.sbin/makefs/fs/msdosfs/msdosfsmount.h +++ b/usr.sbin/makefs/fs/msdosfs/msdosfsmount.h @@ -59,21 +59,16 @@ #define MSDOSFSMNT_NOWIN95 4 /* Completely ignore Win95 entries */ #define MSDOSFSMNT_GEMDOSFS 8 /* This is a GEMDOS-flavour */ #define MSDOSFSMNT_VERSIONED 16 /* Struct is versioned */ -#define MSDOSFSMNT_UTF8 32 /* Use UTF8 filenames */ /* All flags above: */ #define MSDOSFSMNT_MNTOPT \ (MSDOSFSMNT_SHORTNAME|MSDOSFSMNT_LONGNAME|MSDOSFSMNT_NOWIN95 \ - |MSDOSFSMNT_GEMDOSFS|MSDOSFSMNT_VERSIONED|MSDOSFSMNT_UTF8) + |MSDOSFSMNT_GEMDOSFS|MSDOSFSMNT_VERSIONED) #define MSDOSFSMNT_RONLY 0x80000000 /* mounted read-only */ #define MSDOSFSMNT_WAITONFAT 0x40000000 /* mounted synchronous */ #define MSDOSFS_FATMIRROR 0x20000000 /* FAT is mirrored */ -#define MSDOSFSMNT_BITS "\177\20" \ - "b\00shortname\0b\01longname\0b\02nowin95\0b\03gemdosfs\0b\04mntversioned\0" \ - "b\05utf8\0b\037ronly\0b\036waitonfat\0b\035fatmirror\0" - /* * Layout of the mount control block for a MSDOSFS file system. @@ -87,7 +82,7 @@ struct msdosfsmount { for files */ mode_t pm_dirmask; /* mask to and with file protection bits for directories */ - int pm_gmtoff; /* offset from UTC in seconds */ + int pm_minuteswest; /* of Greenwitch */ struct vnode *pm_devvp; /* vnode for block device mntd */ struct bpb50 pm_bpb; /* BIOS parameter blk for this fs */ u_long pm_FATsecs; /* actual number of FAT sectors */ diff --git a/usr.sbin/makefs/msdos.c b/usr.sbin/makefs/msdos.c index 002c4910a09..a8c409e8bac 100644 --- a/usr.sbin/makefs/msdos.c +++ b/usr.sbin/makefs/msdos.c @@ -54,15 +54,10 @@ static int msdos_populate_dir(const char *, struct denode *, fsnode *, fsnode *, fsinfo_t *); -struct msdos_options_ex { - struct msdos_options options; - bool utf8; -}; - void msdos_prep_opts(fsinfo_t *fsopts) { - struct msdos_options_ex *msdos_opt = ecalloc(1, sizeof(*msdos_opt)); + struct msdos_options *msdos_opt = ecalloc(1, sizeof(*msdos_opt)); const option_t msdos_options[] = { #define AOPT(_opt, _type, _name, _min, _desc) { \ .letter = _opt, \ @@ -72,7 +67,7 @@ msdos_prep_opts(fsinfo_t *fsopts) (sizeof(_type) == 1 ? OPT_INT8 : \ (sizeof(_type) == 2 ? OPT_INT16 : \ (sizeof(_type) == 4 ? OPT_INT32 : OPT_INT64)))), \ - .value = &msdos_opt->options._name, \ + .value = &msdos_opt->_name, \ .minimum = _min, \ .maximum = sizeof(_type) == 1 ? 0xff : \ (sizeof(_type) == 2 ? 0xffff : \ @@ -81,8 +76,6 @@ msdos_prep_opts(fsinfo_t *fsopts) }, ALLOPTS #undef AOPT - { 'U', "utf8", &msdos_opt->utf8, OPT_BOOL, - 0, 1, "Use UTF8 names" }, { .name = NULL } }; @@ -129,11 +122,10 @@ msdos_parse_opts(const char *option, fsinfo_t *fsopts) void msdos_makefs(const char *image, const char *dir, fsnode *root, fsinfo_t *fsopts) { - struct msdos_options_ex *msdos_opt = fsopts->fs_specific; + struct msdos_options *msdos_opt = fsopts->fs_specific; struct vnode vp, rootvp; struct timeval start; struct msdosfsmount *pmp; - uint32_t flags; assert(image != NULL); assert(dir != NULL); @@ -144,36 +136,32 @@ msdos_makefs(const char *image, const char *dir, fsnode *root, fsinfo_t *fsopts) * XXX: pick up other options from the msdos specific ones? * Is minsize right here? */ - msdos_opt->options.create_size = MAX(msdos_opt->options.create_size, + msdos_opt->create_size = MAX(msdos_opt->create_size, fsopts->minsize); - msdos_opt->options.offset = fsopts->offset; - if (msdos_opt->options.bytes_per_sector == 0) { + msdos_opt->offset = fsopts->offset; + if (msdos_opt->bytes_per_sector == 0) { if (fsopts->sectorsize == -1) fsopts->sectorsize = 512; - msdos_opt->options.bytes_per_sector = fsopts->sectorsize; + msdos_opt->bytes_per_sector = fsopts->sectorsize; } else if (fsopts->sectorsize == -1) { - fsopts->sectorsize = msdos_opt->options.bytes_per_sector; - } else if (fsopts->sectorsize != msdos_opt->options.bytes_per_sector) { + fsopts->sectorsize = msdos_opt->bytes_per_sector; + } else if (fsopts->sectorsize != msdos_opt->bytes_per_sector) { err(1, "inconsistent sectorsize -S %u" "!= -o bytes_per_sector %u", - fsopts->sectorsize, msdos_opt->options.bytes_per_sector); + fsopts->sectorsize, msdos_opt->bytes_per_sector); } /* create image */ printf("Creating `%s'\n", image); TIMER_START(start); - if (mkfs_msdos(image, NULL, &msdos_opt->options) == -1) + if (mkfs_msdos(image, NULL, msdos_opt) == -1) return; TIMER_RESULTS(start, "mkfs_msdos"); fsopts->fd = open(image, O_RDWR); vp.fs = fsopts; - flags = 0; - if (msdos_opt->utf8) - flags |= MSDOSFSMNT_UTF8; - - if ((pmp = msdosfs_mount(&vp, flags)) == NULL) + if ((pmp = msdosfs_mount(&vp, 0)) == NULL) err(1, "msdosfs_mount"); if (msdosfs_root(pmp, &rootvp) != 0) diff --git a/usr.sbin/makefs/msdos/msdosfs_vfsops.c b/usr.sbin/makefs/msdos/msdosfs_vfsops.c index e5453753cfc..a8614854906 100644 --- a/usr.sbin/makefs/msdos/msdosfs_vfsops.c +++ b/usr.sbin/makefs/msdos/msdosfs_vfsops.c @@ -46,6 +46,7 @@ */ #include <sys/param.h> +#include <sys/time.h> #include <ffs/buf.h> @@ -85,6 +86,7 @@ msdosfs_mount(struct vnode *devvp, int flags) int ronly = 0, error, tmp; int bsize; struct msdos_options *m = devvp->fs->fs_specific; + struct timezone tz; uint64_t psize = m->create_size; unsigned secsize = 512; @@ -127,6 +129,12 @@ msdosfs_mount(struct vnode *devvp, int flags) pmp->pm_Heads = getushort(b50->bpbHeads); pmp->pm_Media = b50->bpbMedia; + if (gettimeofday(NULL, &tz) == -1) { + error = errno; + goto error_exit; + } + pmp->pm_minuteswest = tz.tz_minuteswest; + DPRINTF(("%s(BytesPerSec=%u, ResSectors=%u, FATs=%d, RootDirEnts=%u, " "Sectors=%u, FATsecs=%lu, SecPerTrack=%u, Heads=%u, Media=%u)\n", __func__, pmp->pm_BytesPerSec, pmp->pm_ResSectors, pmp->pm_FATs, diff --git a/usr.sbin/makefs/msdos/msdosfs_vnops.c b/usr.sbin/makefs/msdos/msdosfs_vnops.c index c166715f7e3..c1a33ba32d0 100644 --- a/usr.sbin/makefs/msdos/msdosfs_vnops.c +++ b/usr.sbin/makefs/msdos/msdosfs_vnops.c @@ -94,8 +94,8 @@ msdosfs_times(struct msdosfsmount *pmp, struct denode *dep, { struct timespec at = st->st_atimespec; struct timespec mt = st->st_mtimespec; - unix2dostime(&at, pmp->pm_gmtoff, &dep->de_ADate, NULL, NULL); - unix2dostime(&mt, pmp->pm_gmtoff, &dep->de_MDate, &dep->de_MTime, NULL); + unix2dostime(&at, pmp->pm_minuteswest, &dep->de_ADate, NULL, NULL); + unix2dostime(&mt, pmp->pm_minuteswest, &dep->de_MDate, &dep->de_MTime, NULL); } /* @@ -135,20 +135,17 @@ msdosfs_findslot(struct denode *dp, struct componentname *cnp) pmp = dp->de_pmp; - switch (unix2dosfn((const u_char *)cnp->cn_nameptr, dosfilename, - cnp->cn_namelen, 0)) { + switch (unix2dosfn(cnp->cn_nameptr, dosfilename, cnp->cn_namelen, 0)) { case 0: return (EINVAL); case 1: break; case 2: - wincnt = winSlotCnt((const u_char *)cnp->cn_nameptr, - cnp->cn_namelen, pmp->pm_flags & MSDOSFSMNT_UTF8) + 1; + wincnt = winSlotCnt(cnp->cn_nameptr, cnp->cn_namelen) + 1; break; case 3: olddos = 0; - wincnt = winSlotCnt((const u_char *)cnp->cn_nameptr, - cnp->cn_namelen, pmp->pm_flags & MSDOSFSMNT_UTF8) + 1; + wincnt = winSlotCnt(cnp->cn_nameptr, cnp->cn_namelen) + 1; break; } @@ -229,11 +226,10 @@ msdosfs_findslot(struct denode *dp, struct componentname *cnp) if (pmp->pm_flags & MSDOSFSMNT_SHORTNAME) continue; - chksum = winChkName((const u_char *)cnp->cn_nameptr, + chksum = winChkName(cnp->cn_nameptr, cnp->cn_namelen, (struct winentry *)dep, - chksum, - pmp->pm_flags & MSDOSFSMNT_UTF8); + chksum); continue; } @@ -572,7 +568,7 @@ msdosfs_mkdire(const char *path, struct denode *pdep, fsnode *node) { putushort(denp[0].deStartCluster, newcluster); putushort(denp[0].deCDate, ndirent.de_CDate); putushort(denp[0].deCTime, ndirent.de_CTime); - denp[0].deCHundredth = ndirent.de_CHun; + denp[0].deCTimeHundredth = ndirent.de_CHun; putushort(denp[0].deADate, ndirent.de_ADate); putushort(denp[0].deMDate, ndirent.de_MDate); putushort(denp[0].deMTime, ndirent.de_MTime); @@ -584,7 +580,7 @@ msdosfs_mkdire(const char *path, struct denode *pdep, fsnode *node) { putushort(denp[1].deStartCluster, pcl); putushort(denp[1].deCDate, ndirent.de_CDate); putushort(denp[1].deCTime, ndirent.de_CTime); - denp[1].deCHundredth = ndirent.de_CHun; + denp[1].deCTimeHundredth = ndirent.de_CHun; putushort(denp[1].deADate, ndirent.de_ADate); putushort(denp[1].deMDate, ndirent.de_MDate); putushort(denp[1].deMTime, ndirent.de_MTime); diff --git a/usr.sbin/makefs/sys/clock.h b/usr.sbin/makefs/sys/clock.h deleted file mode 100644 index da61df67af9..00000000000 --- a/usr.sbin/makefs/sys/clock.h +++ /dev/null @@ -1,89 +0,0 @@ -/* $NetBSD: clock.h,v 1.3 2014/11/17 17:11:29 christos Exp $ */ - -/*- - * Copyright (c) 1996 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Gordon W. Ross - * - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -#ifndef _SYS_CLOCK_H_ -#define _SYS_CLOCK_H_ - -/* Some handy constants. */ -#define SECS_PER_MINUTE 60 -#define SECS_PER_HOUR 3600 -#define SECS_PER_DAY 86400 -#define DAYS_PER_COMMON_YEAR 365 -#define DAYS_PER_LEAP_YEAR 366 -#define SECS_PER_COMMON_YEAR (SECS_PER_DAY * DAYS_PER_COMMON_YEAR) -#define SECS_PER_LEAP_YEAR (SECS_PER_DAY * DAYS_PER_LEAP_YEAR) - -/* Traditional POSIX base year */ -#define POSIX_BASE_YEAR 1970 - -/* Some handy functions */ -static inline int -days_in_month(int m) -{ - switch (m) { - case 2: - return 28; - case 4: case 6: case 9: case 11: - return 30; - case 1: case 3: case 5: case 7: case 8: case 10: case 12: - return 31; - default: - return -1; - } -} - -/* - * This inline avoids some unnecessary modulo operations - * as compared with the usual macro: - * ( ((year % 4) == 0 && - * (year % 100) != 0) || - * ((year % 400) == 0) ) - * It is otherwise equivalent. - */ -static inline int -is_leap_year(uint64_t year) -{ - if ((year & 3) != 0) - return 0; - - if (__predict_false((year % 100) != 0)) - return 1; - - return __predict_false((year % 400) == 0); -} - -static inline int -days_per_year(uint64_t year) -{ - return is_leap_year(year) ? DAYS_PER_LEAP_YEAR : DAYS_PER_COMMON_YEAR; -} - -#endif /* _SYS_CLOCK_H_ */ |