zipios++  2.0.2
Zipios++ – a small C++ library that provides easy access to .zip files.
dostime.c
Go to the documentation of this file.
1 /*
2  dostime.c - routines for converting UNIX time to MS-DOS time and vice versa.
3 
4  Various Copyrights:
5 
6  First written by Mark Adler, Richard B. Wales, Jean-loup Gailly,
7  Kai Uwe Rommel, Onno van der Linden and Igor Mandrichenko (1990-1997).
8  Tweaked further by Bryan Burns (1999).
9  Redesigned with full error checks by Alexis Wilke (2015).
10 
11  This program is free software; you can redistribute it and/or
12  modify it under the terms of the GNU General Public License
13  as published by the Free Software Foundation; either version 2
14  of the License, or (at your option) any later version.
15 
16  This program is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU General Public License for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with this program; if not, write to the Free Software
23  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 */
25 
57 #include "dostime.h"
58 
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <string.h>
62 
63 
82 {
83  // Jan 1, 1980 00:00:00 is the minimum
84  return 0x00210000;
85 }
86 
87 
106 {
107  // Dec 31, 2107 23:59:59 is the maximum
108  return 0xFF9FBF7D;
109 }
110 
111 
132 {
133  struct tm t; /* argument for mktime() */
134 
135  memset(&t, 0, sizeof(t));
136 
137  t.tm_isdst = -1; /* let mktime() determine if DST is in effect */
138  /* Convert DOS time to UNIX time_t format */
139  t.tm_sec = (((int)dostime << 1) & 0x3E);
140  t.tm_min = (((int)dostime >> 5) & 0x3F);
141  t.tm_hour = (((int)dostime >> 11) & 0x1F);
142  t.tm_mday = (((int)dostime >> 16) & 0x1F);
143  t.tm_mon = (((int)dostime >> 21) & 0x0F) - 1;
144  t.tm_year = (((int)dostime >> 25) & 0x7F) + 80;
145 
146  if(t.tm_year < 80 || t.tm_year > 207
147  || t.tm_mon < 0 || t.tm_mon > 11
148  || t.tm_mday < 1 || t.tm_mday > 31
149  || t.tm_hour < 0 || t.tm_hour > 23
150  || t.tm_min < 0 || t.tm_min > 59
151  || t.tm_sec < 0 || t.tm_sec > 59)
152  {
153  return -1;
154  }
155 
156  // A full round trip between Unix date to DOS and back to Unix works
157  // as is (without worry about the current timezone) because the DOS
158  // format makes use of localdate() and that's 1 to 1 compatible with
159  // mktime() which expects a local date too.
160  return mktime(&t);
161 }
162 
163 
164 /* \brief Convert a broken up date to a DOS date.
165  *
166  * Convert the date y/n/d and time h:m:s to a four byte DOS date and
167  * time (date in high two bytes, time in low two bytes allowing magnitude
168  * comparison).
169  *
170  * The function returns zero if the month, day, hour, minute, second are
171  * out of range.
172  *
173  * \todo
174  * The dostime_t type is 32 bits, although if it were 64 bits we would
175  * never have an overflow with the maximum. However, the Zip archive
176  * format only supports 32 bits as far as I know.
177  *
178  * \param[in] year The year.
179  * \param[in] month The month.
180  * \param[in] day The day.
181  * \param[in] hour The hour.
182  * \param[in] minute The minute.
183  * \param[in] second The second.
184  *
185  * \return The date parameters transformed in a DOS time value or zero if the
186  * date is considered invalid.
187  */
188 dostime_t dostime(int year, int month, int day, int hour, int minute, int second)
189 {
190  if(year < 1980 || year > 2107
191  || month < 1 || month > 12
192  || day < 1 || day > 31
193  || hour < 0 || hour > 23
194  || minute < 0 || minute > 59
195  || second < 0 || second > 59)
196  {
197  return 0;
198  }
199 
200  return (((dostime_t) year - 1980) << 25)
201  | (((dostime_t) month ) << 21)
202  | (((dostime_t) day ) << 16)
203  | (((dostime_t) hour ) << 11)
204  | (((dostime_t) minute ) << 5)
205  | (((dostime_t) second ) >> 1); // 1 every other second
206 }
207 
208 
219 dostime_t unix2dostime(time_t unix_time)
220 {
221  time_t even_time;
222  struct tm *s; /* result of localtime() */
223 
224  even_time = (unix_time + 1) & ~1; /* Round up to even seconds. */
225  s = localtime(&even_time); /* Use local time since MSDOS does. */
226  return dostime(s->tm_year + 1900, s->tm_mon + 1, s->tm_mday,
227  s->tm_hour, s->tm_min, s->tm_sec);
228 }
229 
230 
231 // Local Variables:
232 // mode: cpp
233 // indent-tabs-mode: nil
234 // c-basic-offset: 4
235 // tab-width: 4
236 // End:
237 
238 // vim: ts=4 sw=4 et
dostime_t maxdostime()
Return the maximum possible value .
Definition: dostime.c:105
dostime_t unix2dostime(time_t unix_time)
Convert a Unix date to a DOS date.
Definition: dostime.c:219
uint32_t dostime_t
Definition: dostime.h:50
dostime_t dostime(int year, int month, int day, int hour, int minute, int second)
Definition: dostime.c:188
time_t dos2unixtime(dostime_t dostime)
Convert a DOS time to a Unix time.
Definition: dostime.c:131
Definitions for the MS-DOS to Unix time conversions.
dostime_t mindostime()
Return the minimum possible value.
Definition: dostime.c:81