1*b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * linux/fs/isofs/util.c
41da177e4SLinus Torvalds */
51da177e4SLinus Torvalds
6e4a93be6SOscar Forner Martinez #include <linux/time.h>
794f2f715SAl Viro #include "isofs.h"
81da177e4SLinus Torvalds
91da177e4SLinus Torvalds /*
101da177e4SLinus Torvalds * We have to convert from a MM/DD/YY format to the Unix ctime format.
111da177e4SLinus Torvalds * We have to take into account leap years and all of that good stuff.
121da177e4SLinus Torvalds * Unfortunately, the kernel does not have the information on hand to
131da177e4SLinus Torvalds * take into account daylight savings time, but it shouldn't matter.
141da177e4SLinus Torvalds * The time stored should be localtime (with or without DST in effect),
151da177e4SLinus Torvalds * and the timezone offset should hold the offset required to get back
161da177e4SLinus Torvalds * to GMT. Thus we should always be correct.
171da177e4SLinus Torvalds */
181da177e4SLinus Torvalds
iso_date(u8 * p,int flag)1934be4dbfSArnd Bergmann int iso_date(u8 *p, int flag)
201da177e4SLinus Torvalds {
211da177e4SLinus Torvalds int year, month, day, hour, minute, second, tz;
22e4a93be6SOscar Forner Martinez int crtime;
231da177e4SLinus Torvalds
24e4a93be6SOscar Forner Martinez year = p[0];
251da177e4SLinus Torvalds month = p[1];
261da177e4SLinus Torvalds day = p[2];
271da177e4SLinus Torvalds hour = p[3];
281da177e4SLinus Torvalds minute = p[4];
291da177e4SLinus Torvalds second = p[5];
301da177e4SLinus Torvalds if (flag == 0) tz = p[6]; /* High sierra has no time zone */
311da177e4SLinus Torvalds else tz = 0;
321da177e4SLinus Torvalds
331da177e4SLinus Torvalds if (year < 0) {
341da177e4SLinus Torvalds crtime = 0;
351da177e4SLinus Torvalds } else {
36e4a93be6SOscar Forner Martinez crtime = mktime64(year+1900, month, day, hour, minute, second);
371da177e4SLinus Torvalds
381da177e4SLinus Torvalds /* sign extend */
391da177e4SLinus Torvalds if (tz & 0x80)
401da177e4SLinus Torvalds tz |= (-1 << 8);
411da177e4SLinus Torvalds
421da177e4SLinus Torvalds /*
431da177e4SLinus Torvalds * The timezone offset is unreliable on some disks,
441da177e4SLinus Torvalds * so we make a sanity check. In no case is it ever
451da177e4SLinus Torvalds * more than 13 hours from GMT, which is 52*15min.
461da177e4SLinus Torvalds * The time is always stored in localtime with the
471da177e4SLinus Torvalds * timezone offset being what get added to GMT to
481da177e4SLinus Torvalds * get to localtime. Thus we need to subtract the offset
491da177e4SLinus Torvalds * to get to true GMT, which is what we store the time
501da177e4SLinus Torvalds * as internally. On the local system, the user may set
511da177e4SLinus Torvalds * their timezone any way they wish, of course, so GMT
521da177e4SLinus Torvalds * gets converted back to localtime on the receiving
531da177e4SLinus Torvalds * system.
541da177e4SLinus Torvalds *
551da177e4SLinus Torvalds * NOTE: mkisofs in versions prior to mkisofs-1.10 had
561da177e4SLinus Torvalds * the sign wrong on the timezone offset. This has now
571da177e4SLinus Torvalds * been corrected there too, but if you are getting screwy
581da177e4SLinus Torvalds * results this may be the explanation. If enough people
591da177e4SLinus Torvalds * complain, a user configuration option could be added
601da177e4SLinus Torvalds * to add the timezone offset in with the wrong sign
611da177e4SLinus Torvalds * for 'compatibility' with older discs, but I cannot see how
621da177e4SLinus Torvalds * it will matter that much.
631da177e4SLinus Torvalds *
641da177e4SLinus Torvalds * Thanks to kuhlmav@elec.canterbury.ac.nz (Volker Kuhlmann)
651da177e4SLinus Torvalds * for pointing out the sign error.
661da177e4SLinus Torvalds */
671da177e4SLinus Torvalds if (-52 <= tz && tz <= 52)
681da177e4SLinus Torvalds crtime -= tz * 15 * 60;
691da177e4SLinus Torvalds }
701da177e4SLinus Torvalds return crtime;
711da177e4SLinus Torvalds }
72