]>
git.saurik.com Git - apple/libc.git/blob - stdtime/getdate.c
2 * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
28 #include <sys/types.h>
33 DATEMSK_NOT_DEFINED
= 1,
43 #define DATEMSK "DATEMSK"
44 #define TM_SEC_SET 0x01
45 #define TM_MIN_SET 0x02
46 #define TM_HOUR_SET 0x04
47 #define TM_MDAY_SET 0x01
48 #define TM_MON_SET 0x02
49 #define TM_YEAR_SET 0x04
52 static const struct tm tmundef
= {
67 * Call strptime() on each line of the DATEMSK file, and manipulate the
68 * resulting tm structure.
71 getdate(const char *str
)
74 struct tm
*now
, *result
= NULL
;
77 int bufsiz
, offset
, len
, dateset
, timeset
, saveerrno
, wday_set
, save_mon
;
80 char *file
= getenv(DATEMSK
);
83 getdate_err
= DATEMSK_NOT_DEFINED
;
87 if((fp
= fopen(file
, "r")) == NULL
) {
88 getdate_err
= CANT_OPEN
;
93 if(fstat(fileno(fp
), &st
) < 0) {
94 getdate_err
= CANT_FSTAT
;
97 if((st
.st_mode
& S_IFMT
) != S_IFREG
) {
98 getdate_err
= NOT_FILE
;
101 if((buf
= malloc(bufsiz
= BUFSIZ
)) == NULL
) {
102 getdate_err
= OUT_OF_MEMORY
;
108 if(fgets(buf
+ offset
, bufsiz
- offset
, fp
) == NULL
) {
110 getdate_err
= IO_ERROR
;
114 getdate_err
= NO_MATCH
;
118 } else if((len
= strlen(buf
)) == bufsiz
- 1
119 && buf
[len
- 1] != '\n') {
120 char *newptr
= realloc(buf
, (bufsiz
+= BUFSIZ
));
122 getdate_err
= OUT_OF_MEMORY
;
129 if(buf
[len
- 1] == '\n')
132 if(strptime(str
, buf
, &tm
) == NULL
) {
138 dateset
= timeset
= 0;
139 if(tm
.tm_sec
!= UNDEFINED
)
140 timeset
|= TM_SEC_SET
;
141 if(tm
.tm_min
!= UNDEFINED
)
142 timeset
|= TM_MIN_SET
;
143 if(tm
.tm_hour
!= UNDEFINED
)
144 timeset
|= TM_HOUR_SET
;
145 if(tm
.tm_mday
!= UNDEFINED
)
146 dateset
|= TM_MDAY_SET
;
147 if(tm
.tm_mon
!= UNDEFINED
)
148 dateset
|= TM_MON_SET
;
149 if(tm
.tm_year
!= UNDEFINED
)
150 dateset
|= TM_YEAR_SET
;
151 wday_set
= tm
.tm_wday
;
155 tm
.tm_sec
= now
->tm_sec
;
156 tm
.tm_min
= now
->tm_min
;
157 tm
.tm_hour
= now
->tm_hour
;
161 tm
.tm_hour
= now
->tm_hour
;
162 tm
.tm_min
= now
->tm_min
;
163 if(tm
.tm_sec
< now
->tm_sec
)
168 tm
.tm_hour
= now
->tm_hour
;
169 if(tm
.tm_min
< now
->tm_min
)
174 case TM_MIN_SET
| TM_SEC_SET
:
175 tm
.tm_hour
= now
->tm_hour
;
176 if((60 * tm
.tm_min
+ tm
.tm_sec
)
177 < (60 * now
->tm_min
+ now
->tm_sec
))
186 case TM_HOUR_SET
| TM_SEC_SET
:
190 case TM_HOUR_SET
| TM_MIN_SET
:
197 tm
.tm_mday
= now
->tm_mday
;
198 if(tm
.tm_hour
< now
->tm_hour
)
200 tm
.tm_mon
= now
->tm_mon
;
201 tm
.tm_year
= now
->tm_year
;
205 tm
.tm_year
= now
->tm_year
;
206 tm
.tm_mon
= now
->tm_mon
;
207 if(tm
.tm_mday
< now
->tm_mday
)
212 case TM_MON_SET
| TM_MDAY_SET
:
213 tm
.tm_year
= now
->tm_year
;
214 if(tm
.tm_mon
< now
->tm_mon
)
216 if(!(dateset
& TM_MDAY_SET
))
221 case TM_YEAR_SET
| TM_MON_SET
:
222 if(!(dateset
& TM_MON_SET
))
227 case TM_YEAR_SET
| TM_MDAY_SET
:
228 tm
.tm_mon
= now
->tm_mon
;
229 if(tm
.tm_mday
< now
->tm_mday
)
234 tm
.tm_wday
= now
->tm_wday
;
235 tm
.tm_gmtoff
= now
->tm_gmtoff
; /* XXX: can't grok timezones */
237 save_mon
= tm
.tm_mon
;
238 if(mktime(&tm
) == (time_t)-1) {
239 getdate_err
= INVALID_DATE
;
241 } else if ((dateset
& TM_MON_SET
) && (tm
.tm_mon
!= save_mon
)) { /* Did mktime fixup an overflow date? */
242 getdate_err
= INVALID_DATE
;
245 if(wday_set
!= UNDEFINED
&&
246 (dateset
!= (TM_YEAR_SET
| TM_MON_SET
| TM_MDAY_SET
))) {
248 * We got back a week day, but not enough information to resolve it
249 * to a specific day, so we need to push forward the time to the
250 * correct wday. <rdar://problem/27439823>
252 int delta
= wday_set
- tm
.tm_wday
;
257 if(mktime(&tm
) == (time_t)-1) {
258 getdate_err
= INVALID_DATE
;