Module Name:    src
Committed By:   martin
Date:           Mon Sep  1 09:09:47 UTC 2014

Modified Files:
        src/sys/fs/msdosfs: msdosfs_conv.c
        src/usr.sbin/makefs/msdos: Makefile.inc

Log Message:
Make msdosfs time conversion use the y/m/d/h/m/s conversion functions
from clock_subr.c and compile that into the userland (and tools)
makefs as well.


To generate a diff of this commit:
cvs rdiff -u -r1.9 -r1.10 src/sys/fs/msdosfs/msdosfs_conv.c
cvs rdiff -u -r1.5 -r1.6 src/usr.sbin/makefs/msdos/Makefile.inc

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/fs/msdosfs/msdosfs_conv.c
diff -u src/sys/fs/msdosfs/msdosfs_conv.c:1.9 src/sys/fs/msdosfs/msdosfs_conv.c:1.10
--- src/sys/fs/msdosfs/msdosfs_conv.c:1.9	Sat Jan 26 16:51:51 2013
+++ src/sys/fs/msdosfs/msdosfs_conv.c	Mon Sep  1 09:09:47 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: msdosfs_conv.c,v 1.9 2013/01/26 16:51:51 christos Exp $	*/
+/*	$NetBSD: msdosfs_conv.c,v 1.10 2014/09/01 09:09:47 martin Exp $	*/
 
 /*-
  * Copyright (C) 1995, 1997 Wolfgang Solfrank.
@@ -52,7 +52,7 @@
 #endif
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: msdosfs_conv.c,v 1.9 2013/01/26 16:51:51 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: msdosfs_conv.c,v 1.10 2014/09/01 09:09:47 martin Exp $");
 
 /*
  * System include files.
@@ -66,9 +66,11 @@ __KERNEL_RCSID(0, "$NetBSD: msdosfs_conv
 #include <sys/vnode.h>
 #else
 #include <stdio.h>
+#include <string.h>
 #include <dirent.h>
 #include <sys/queue.h>
 #endif
+#include <dev/clock_subr.h>
 
 /*
  * MSDOSFS include files.
@@ -77,29 +79,15 @@ __KERNEL_RCSID(0, "$NetBSD: msdosfs_conv
 #include <fs/msdosfs/denode.h>
 
 /*
- * Days in each month in a regular year.
- */
-u_short const regyear[] = {
-	31, 28, 31, 30, 31, 30,
-	31, 31, 30, 31, 30, 31
-};
-
-/*
- * Days in each month in a leap year.
+ * The number of seconds between Jan 1, 1970 and Jan 1, 1980. In that
+ * interval there were 8 regular years and 2 leap years.
  */
-u_short const leapyear[] = {
-	31, 29, 31, 30, 31, 30,
-	31, 31, 30, 31, 30, 31
-};
-
+#define	DOSBIASYEAR	1980
+#define	SECONDSTO1980	(((8 * 365) + (2 * 366)) * (24 * 60 * 60))
 /*
- * Variables used to remember parts of the last time conversion.  Maybe we
- * can avoid a full conversion.
+ * msdos fs can not store dates beyound the year 2234
  */
-u_long lasttime;
-u_long lastday;
-u_short lastddate;
-u_short lastdtime;
+#define DOSMAXYEAR	((DD_YEAR_MASK >> DD_YEAR_SHIFT) + DOSBIASYEAR)
 
 /*
  * Convert the unix version of time to dos's idea of time to be used in
@@ -109,74 +97,51 @@ void
 unix2dostime(const struct timespec *tsp, int gmtoff, u_int16_t *ddp, u_int16_t *dtp, u_int8_t *dhp)
 {
 	u_long t;
-	u_long days;
-	u_long inc;
-	u_long year;
-	u_long month;
-	const u_short *months;
+	struct clock_ymdhms ymd;
+
+	t = tsp->tv_sec + gmtoff; /* time zone correction */
 
 	/*
-	 * If the time from the last conversion is the same as now, then
-	 * skip the computations and use the saved result.
+	 * DOS timestamps can not represent dates before 1980.
+	 */
+	if (t < SECONDSTO1980)
+		goto invalid_dos_date;
+
+	/*
+	 * DOS granularity is 2 seconds
 	 */
-	t = tsp->tv_sec + gmtoff; /* time zone correction */
 	t &= ~1;
-	if (lasttime != t) {
-		lasttime = t;
-		lastdtime = (((t / 2) % 30) << DT_2SECONDS_SHIFT)
+
+	/*
+	 * Convert to year/month/day/.. format
+	 */
+	clock_secs_to_ymdhms(t, &ymd);
+	if (ymd.dt_year > DOSMAXYEAR)
+		goto invalid_dos_date;
+
+	/*
+	 * 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)
 		    + (((t / 60) % 60) << DT_MINUTES_SHIFT)
 		    + (((t / 3600) % 24) << DT_HOURS_SHIFT);
+	return;
 
-		/*
-		 * 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.
-		 */
-		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;
-		}
-	}
+invalid_dos_date:
+	*ddp = 0;
 	if (dtp)
-		*dtp = lastdtime;
+		*dtp = 0;
 	if (dhp)
-		*dhp = (tsp->tv_sec & 1) * 100 + tsp->tv_nsec / 10000000;
-
-	*ddp = lastddate;
+		*dhp = 0;
 }
 
 /*
- * The number of seconds between Jan 1, 1970 and Jan 1, 1980. In that
- * interval there were 8 regular years and 2 leap years.
- */
-#define	SECONDSTO1980	(((8 * 365) + (2 * 366)) * (24 * 60 * 60))
-
-u_short lastdosdate;
-u_long lastseconds;
-
-/*
  * 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.
@@ -184,11 +149,8 @@ u_long lastseconds;
 void
 dos2unixtime(u_int dd, u_int dt, u_int dh, int gmtoff, struct timespec *tsp)
 {
-	u_long seconds;
-	u_long m, month;
-	u_long y, year;
-	u_long days;
-	const u_short *months;
+	time_t seconds;
+	struct clock_ymdhms ymd;
 
 	if (dd == 0) {
 		/*
@@ -198,37 +160,18 @@ dos2unixtime(u_int dd, u_int dt, u_int d
 		tsp->tv_nsec = 0;
 		return;
 	}
-	seconds = ((dt & DT_2SECONDS_MASK) >> DT_2SECONDS_SHIFT) * 2
-	    + ((dt & DT_MINUTES_MASK) >> DT_MINUTES_SHIFT) * 60
-	    + ((dt & DT_HOURS_MASK) >> DT_HOURS_SHIFT) * 3600
-	    + dh / 100;
-	/*
-	 * If the year, month, and day from the last conversion are the
-	 * same then use the saved value.
-	 */
-	if (lastdosdate != dd) {
-		lastdosdate = dd;
-		days = 0;
-		year = (dd & DD_YEAR_MASK) >> DD_YEAR_SHIFT;
-		for (y = 0; y < year; y++)
-			days += y & 0x03 ? 365 : 366;
-		months = year & 0x03 ? regyear : leapyear;
-		/*
-		 * Prevent going from 0 to 0xffffffff in the following
-		 * loop.
-		 */
-		month = (dd & DD_MONTH_MASK) >> DD_MONTH_SHIFT;
-		if (month == 0) {
-			printf("%s: month value out of range (%ld)\n",
-			    __func__, month);
-			month = 1;
-		}
-		for (m = 0; m < month - 1; m++)
-			days += months[m];
-		days += ((dd & DD_DAY_MASK) >> DD_DAY_SHIFT) - 1;
-		lastseconds = (days * 24 * 60 * 60) + SECONDSTO1980;
-	}
-	tsp->tv_sec = seconds + lastseconds;
+
+	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);
+
+	tsp->tv_sec = seconds;
 	tsp->tv_sec -= gmtoff;	/* time zone correction */
 	tsp->tv_nsec = (dh % 100) * 10000000;
 }

Index: src/usr.sbin/makefs/msdos/Makefile.inc
diff -u src/usr.sbin/makefs/msdos/Makefile.inc:1.5 src/usr.sbin/makefs/msdos/Makefile.inc:1.6
--- src/usr.sbin/makefs/msdos/Makefile.inc:1.5	Sat Jan 26 16:50:46 2013
+++ src/usr.sbin/makefs/msdos/Makefile.inc	Mon Sep  1 09:09:47 2014
@@ -1,10 +1,10 @@
-#	$NetBSD: Makefile.inc,v 1.5 2013/01/26 16:50:46 christos Exp $
+#	$NetBSD: Makefile.inc,v 1.6 2014/09/01 09:09:47 martin Exp $
 #
 
 MSDOS=	${NETBSDSRCDIR}/sys/fs/msdosfs
 MSDOS_NEWFS=	${NETBSDSRCDIR}/sbin/newfs_msdos
 
-.PATH:	${.CURDIR}/msdos ${MSDOS} ${MSDOS_NEWFS}
+.PATH:	${.CURDIR}/msdos ${MSDOS} ${MSDOS_NEWFS} ${NETBSDSRCDIR}/sys/dev
 
 CPPFLAGS+= -DMSDOS_EI -I${MSDOS} -I${MSDOS_NEWFS}
 .if !defined(HOSTPROGNAME)
@@ -13,3 +13,4 @@ CPPFLAGS+= -I${NETBSDSRCDIR}/sys
 
 SRCS+= mkfs_msdos.c msdosfs_fat.c msdosfs_conv.c msdosfs_vfsops.c
 SRCS+= msdosfs_lookup.c msdosfs_denode.c msdosfs_vnops.c
+SRCS+= clock_subr.c

Reply via email to