X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=fs%2Fcifs%2Fnetmisc.c;h=bd6d6895730d885442f5715e7d4c4e3e693ce333;hb=cf6e693212263d33c5882e4653df89a2fca4c0c4;hp=53e304d59544cbeddff71ea909904ad084106d42;hpb=5858ae44e289ac6c809af3fe81b9a6ed41914d41;p=safe%2Fjmp%2Flinux-2.6 diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index 53e304d..bd6d689 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c @@ -1,25 +1,24 @@ /* * fs/cifs/netmisc.c * - * Copyright (c) International Business Machines Corp., 2002 + * Copyright (c) International Business Machines Corp., 2002,2008 * Author(s): Steve French (sfrench@us.ibm.com) - * + * * Error mapping routines from Samba libsmb/errormap.c * Copyright (C) Andrew Tridgell 2001 * - * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software + * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ @@ -30,9 +29,7 @@ #include #include #include -#ifdef CONFIG_CIFS_EXPERIMENTAL #include -#endif #include "cifsfs.h" #include "cifspdu.h" #include "cifsglob.h" @@ -67,22 +64,23 @@ static const struct smb_to_posix_error mapping_table_ERRDOS[] = { {ERRbadshare, -ETXTBSY}, {ERRlock, -EACCES}, {ERRunsup, -EINVAL}, - {ERRnosuchshare,-ENXIO}, + {ERRnosuchshare, -ENXIO}, {ERRfilexists, -EEXIST}, {ERRinvparm, -EINVAL}, {ERRdiskfull, -ENOSPC}, {ERRinvname, -ENOENT}, - {ERRinvlevel,-EOPNOTSUPP}, + {ERRinvlevel, -EOPNOTSUPP}, {ERRdirnotempty, -ENOTEMPTY}, {ERRnotlocked, -ENOLCK}, {ERRcancelviolation, -ENOLCK}, {ERRalreadyexists, -EEXIST}, {ERRmoredata, -EOVERFLOW}, - {ERReasnotsupported,-EOPNOTSUPP}, + {ERReasnotsupported, -EOPNOTSUPP}, {ErrQuota, -EDQUOT}, {ErrNotALink, -ENOLINK}, - {ERRnetlogonNotStarted,-ENOPROTOOPT}, - {ErrTooManyLinks,-EMLINK}, + {ERRnetlogonNotStarted, -ENOPROTOOPT}, + {ERRsymlink, -EOPNOTSUPP}, + {ErrTooManyLinks, -EMLINK}, {0, 0} }; @@ -117,10 +115,16 @@ static const struct smb_to_posix_error mapping_table_ERRSRV[] = { {ERRusempx, -EIO}, {ERRusestd, -EIO}, {ERR_NOTIFY_ENUM_DIR, -ENOBUFS}, - {ERRaccountexpired, -EACCES}, + {ERRnoSuchUser, -EACCES}, +/* {ERRaccountexpired, -EACCES}, {ERRbadclient, -EACCES}, {ERRbadLogonTime, -EACCES}, - {ERRpasswordExpired, -EACCES}, + {ERRpasswordExpired, -EACCES},*/ + {ERRaccountexpired, -EKEYEXPIRED}, + {ERRbadclient, -EACCES}, + {ERRbadLogonTime, -EACCES}, + {ERRpasswordExpired, -EKEYEXPIRED}, + {ERRnosupport, -EINVAL}, {0, 0} }; @@ -129,89 +133,72 @@ static const struct smb_to_posix_error mapping_table_ERRHRD[] = { {0, 0} }; -/* Convert string containing dotted ip address to binary form */ -/* returns 0 if invalid address */ - -int -cifs_inet_pton(int address_family, char *cp,void *dst) +/* + * Convert a string containing text IPv4 or IPv6 address to binary form. + * + * Returns 0 on failure. + */ +static int +cifs_inet_pton(const int address_family, const char *cp, void *dst) { -#ifdef CONFIG_CIFS_EXPERIMENTAL int ret = 0; /* calculate length by finding first slash or NULL */ - /* BB Should we convert '/' slash to '\' here since it seems already done - before this */ - if( address_family == AF_INET ){ - ret = in4_pton(cp, -1 /* len */, dst , '\\', NULL); - } else if( address_family == AF_INET6 ){ + if (address_family == AF_INET) + ret = in4_pton(cp, -1 /* len */, dst, '\\', NULL); + else if (address_family == AF_INET6) ret = in6_pton(cp, -1 /* len */, dst , '\\', NULL); - } -#ifdef CONFIG_CIFS_DEBUG2 - cFYI(1,("address conversion returned %d for %s", ret, cp)); -#endif + + cFYI(DBG2, ("address conversion returned %d for %s", ret, cp)); if (ret > 0) ret = 1; return ret; -#else - int value; - int digit; - int i; - char temp; - char bytes[4]; - char *end = bytes; - static const int addr_class_max[4] = - { 0xffffffff, 0xffffff, 0xffff, 0xff }; - - if(address_family != AF_INET) - return -EAFNOSUPPORT; +} - for (i = 0; i < 4; i++) { - bytes[i] = 0; +/* + * Try to convert a string to an IPv4 address and then attempt to convert + * it to an IPv6 address if that fails. Set the family field if either + * succeeds. If it's an IPv6 address and it has a '%' sign in it, try to + * treat the part following it as a numeric sin6_scope_id. + * + * Returns 0 on failure. + */ +int +cifs_convert_address(char *src, void *dst) +{ + int rc; + char *pct, *endp; + struct sockaddr_in *s4 = (struct sockaddr_in *) dst; + struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) dst; + + /* IPv4 address */ + if (cifs_inet_pton(AF_INET, src, &s4->sin_addr.s_addr)) { + s4->sin_family = AF_INET; + return 1; } - temp = *cp; + /* temporarily terminate string */ + pct = strchr(src, '%'); + if (pct) + *pct = '\0'; - while (TRUE) { - if (!isdigit(temp)) - return 0; + rc = cifs_inet_pton(AF_INET6, src, &s6->sin6_addr.s6_addr); - value = 0; - digit = 0; - for (;;) { - if (isascii(temp) && isdigit(temp)) { - value = (value * 10) + temp - '0'; - temp = *++cp; - digit = 1; - } else - break; - } + /* repair temp termination (if any) and make pct point to scopeid */ + if (pct) + *pct++ = '%'; - if (temp == '.') { - if ((end > bytes + 2) || (value > 255)) - return 0; - *end++ = value; - temp = *++cp; - } else if (temp == ':') { - cFYI(1,("IPv6 addresses not supported for CIFS mounts yet")); - return -1; - } else - break; - } + if (!rc) + return rc; - /* check for last characters */ - if (temp != '\0' && (!isascii(temp) || !isspace(temp))) - if (temp != '\\') { - if (temp != '/') - return 0; - else - (*cp = '\\'); /* switch the slash the expected way */ - } - if (value > addr_class_max[end - bytes]) - return 0; + s6->sin6_family = AF_INET6; + if (pct) { + s6->sin6_scope_id = (u32) simple_strtoul(pct, &endp, 0); + if (!*pct || *endp) + return 0; + } - *((__be32 *)dst) = *((__be32 *) bytes) | htonl(value); - return 1; /* success */ -#endif /* EXPERIMENTAL */ + return rc; } /***************************************************************************** @@ -246,7 +233,7 @@ static const struct { ERRHRD, ERRgeneral, NT_STATUS_UNRECOGNIZED_MEDIA}, { ERRDOS, 27, NT_STATUS_NONEXISTENT_SECTOR}, /* { This NT error code was 'sqashed' - from NT_STATUS_MORE_PROCESSING_REQUIRED to NT_STATUS_OK + from NT_STATUS_MORE_PROCESSING_REQUIRED to NT_STATUS_OK during the session setup } */ { ERRDOS, ERRnomem, NT_STATUS_NO_MEMORY}, { @@ -261,7 +248,7 @@ static const struct { ERRDOS, 193, NT_STATUS_INVALID_FILE_FOR_SECTION}, { ERRDOS, ERRnoaccess, NT_STATUS_ALREADY_COMMITTED}, /* { This NT error code was 'sqashed' - from NT_STATUS_ACCESS_DENIED to NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE + from NT_STATUS_ACCESS_DENIED to NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE during the session setup } */ { ERRDOS, ERRnoaccess, NT_STATUS_ACCESS_DENIED}, { @@ -281,7 +268,8 @@ static const struct { ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_MIX}, { ERRHRD, ERRgeneral, NT_STATUS_INVALID_QUOTA_LOWER}, { ERRHRD, ERRgeneral, NT_STATUS_DISK_CORRUPT_ERROR}, { - ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_INVALID}, { /* mapping changed since shell does lookup on * and expects file not found */ + /* mapping changed since shell does lookup on * expects FileNotFound */ + ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_INVALID}, { ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND}, { ERRDOS, ERRalreadyexists, NT_STATUS_OBJECT_NAME_COLLISION}, { ERRHRD, ERRgeneral, NT_STATUS_HANDLE_NOT_WAITABLE}, { @@ -331,17 +319,17 @@ static const struct { ERRHRD, ERRgeneral, NT_STATUS_INVALID_ACCOUNT_NAME}, { ERRHRD, ERRgeneral, NT_STATUS_USER_EXISTS}, /* { This NT error code was 'sqashed' - from NT_STATUS_NO_SUCH_USER to NT_STATUS_LOGON_FAILURE + from NT_STATUS_NO_SUCH_USER to NT_STATUS_LOGON_FAILURE during the session setup } */ { - ERRDOS, ERRnoaccess, NT_STATUS_NO_SUCH_USER}, { + ERRDOS, ERRnoaccess, NT_STATUS_NO_SUCH_USER}, { /* could map to 2238 */ ERRHRD, ERRgeneral, NT_STATUS_GROUP_EXISTS}, { ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_GROUP}, { ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_GROUP}, { ERRHRD, ERRgeneral, NT_STATUS_MEMBER_NOT_IN_GROUP}, { ERRHRD, ERRgeneral, NT_STATUS_LAST_ADMIN}, /* { This NT error code was 'sqashed' - from NT_STATUS_WRONG_PASSWORD to NT_STATUS_LOGON_FAILURE + from NT_STATUS_WRONG_PASSWORD to NT_STATUS_LOGON_FAILURE during the session setup } */ { ERRSRV, ERRbadpw, NT_STATUS_WRONG_PASSWORD}, { @@ -349,10 +337,10 @@ static const struct { ERRHRD, ERRgeneral, NT_STATUS_PASSWORD_RESTRICTION}, { ERRDOS, ERRnoaccess, NT_STATUS_LOGON_FAILURE}, { ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, { - ERRSRV, 2241, NT_STATUS_INVALID_LOGON_HOURS}, { - ERRSRV, 2240, NT_STATUS_INVALID_WORKSTATION}, { + ERRSRV, ERRbadLogonTime, NT_STATUS_INVALID_LOGON_HOURS}, { + ERRSRV, ERRbadclient, NT_STATUS_INVALID_WORKSTATION}, { ERRSRV, ERRpasswordExpired, NT_STATUS_PASSWORD_EXPIRED}, { - ERRSRV, 2239, NT_STATUS_ACCOUNT_DISABLED}, { + ERRSRV, ERRaccountexpired, NT_STATUS_ACCOUNT_DISABLED}, { ERRHRD, ERRgeneral, NT_STATUS_NONE_MAPPED}, { ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, { ERRHRD, ERRgeneral, NT_STATUS_LUIDS_EXHAUSTED}, { @@ -393,8 +381,8 @@ static const struct { ERRHRD, ERRgeneral, NT_STATUS_FILE_INVALID}, { ERRHRD, ERRgeneral, NT_STATUS_ALLOTTED_SPACE_EXCEEDED}, /* { This NT error code was 'sqashed' - from NT_STATUS_INSUFFICIENT_RESOURCES to NT_STATUS_INSUFF_SERVER_RESOURCES - during the session setup } */ + from NT_STATUS_INSUFFICIENT_RESOURCES to + NT_STATUS_INSUFF_SERVER_RESOURCES during the session setup } */ { ERRDOS, ERRnomem, NT_STATUS_INSUFFICIENT_RESOURCES}, { ERRDOS, ERRbadpath, NT_STATUS_DFS_EXIT_PATH_FOUND}, { @@ -638,8 +626,8 @@ static const struct { ERRDOS, 19, NT_STATUS_TOO_LATE}, { ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_LSA_SECRET}, /* { This NT error code was 'sqashed' - from NT_STATUS_NO_TRUST_SAM_ACCOUNT to NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE - during the session setup } */ + from NT_STATUS_NO_TRUST_SAM_ACCOUNT to + NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE during the session setup } */ { ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_SAM_ACCOUNT}, { ERRDOS, ERRnoaccess, NT_STATUS_TRUSTED_DOMAIN_FAILURE}, { @@ -649,7 +637,7 @@ static const struct { ERRDOS, ERRnoaccess, NT_STATUS_TRUST_FAILURE}, { ERRHRD, ERRgeneral, NT_STATUS_MUTANT_LIMIT_EXCEEDED}, { ERRDOS, ERRnetlogonNotStarted, NT_STATUS_NETLOGON_NOT_STARTED}, { - ERRSRV, 2239, NT_STATUS_ACCOUNT_EXPIRED}, { + ERRSRV, ERRaccountexpired, NT_STATUS_ACCOUNT_EXPIRED}, { ERRHRD, ERRgeneral, NT_STATUS_POSSIBLE_DEADLOCK}, { ERRHRD, ERRgeneral, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT}, { ERRHRD, ERRgeneral, NT_STATUS_REMOTE_SESSION_LIMIT}, { @@ -658,7 +646,7 @@ static const struct { ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT}, { ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT}, /* { This NT error code was 'sqashed' - from NT_STATUS_DOMAIN_TRUST_INCONSISTENT to NT_STATUS_LOGON_FAILURE + from NT_STATUS_DOMAIN_TRUST_INCONSISTENT to NT_STATUS_LOGON_FAILURE during the session setup } */ { ERRDOS, ERRnoaccess, NT_STATUS_DOMAIN_TRUST_INCONSISTENT}, { @@ -775,6 +763,7 @@ static const struct { ERRDOS, ERRnoaccess, 0xc000028f}, { ERRDOS, ERRnoaccess, 0xc0000290}, { ERRDOS, ERRbadfunc, 0xc000029c}, { + ERRDOS, ERRsymlink, NT_STATUS_STOPPED_ON_SYMLINK}, { ERRDOS, ERRinvlevel, 0x007c0001}, }; /***************************************************************************** @@ -789,7 +778,7 @@ cifs_print_status(__u32 status_code) if (((nt_errs[idx].nt_errcode) & 0xFFFFFF) == (status_code & 0xFFFFFF)) { printk(KERN_NOTICE "Status code returned 0x%08x %s\n", - status_code,nt_errs[idx].nt_errstr); + status_code, nt_errs[idx].nt_errstr); } idx++; } @@ -798,7 +787,7 @@ cifs_print_status(__u32 status_code) static void -ntstatus_to_dos(__u32 ntstatus, __u8 * eclass, __u16 * ecode) +ntstatus_to_dos(__u32 ntstatus, __u8 *eclass, __u16 *ecode) { int i; if (ntstatus == 0) { @@ -818,10 +807,10 @@ ntstatus_to_dos(__u32 ntstatus, __u8 * eclass, __u16 * ecode) } int -map_smb_to_linux_error(struct smb_hdr *smb) +map_smb_to_linux_error(struct smb_hdr *smb, int logErr) { unsigned int i; - int rc = -EIO; /* if transport error smb error may not be set */ + int rc = -EIO; /* if transport error smb error may not be set */ __u8 smberrclass; __u16 smberrcode; @@ -832,9 +821,12 @@ map_smb_to_linux_error(struct smb_hdr *smb) return 0; if (smb->Flags2 & SMBFLG2_ERR_STATUS) { - /* translate the newer STATUS codes to old style errors and then to POSIX errors */ + /* translate the newer STATUS codes to old style SMB errors + * and then to POSIX errors */ __u32 err = le32_to_cpu(smb->Status.CifsError); - if(cifsFYI & CIFS_RC) + if (logErr && (err != (NT_STATUS_MORE_PROCESSING_REQUIRED))) + cifs_print_status(err); + else if (cifsFYI & CIFS_RC) cifs_print_status(err); ntstatus_to_dos(err, &smberrclass, &smberrcode); } else { @@ -845,38 +837,44 @@ map_smb_to_linux_error(struct smb_hdr *smb) /* old style errors */ /* DOS class smb error codes - map DOS */ - if (smberrclass == ERRDOS) { /* one byte field no need to byte reverse */ + if (smberrclass == ERRDOS) { + /* 1 byte field no need to byte reverse */ for (i = 0; i < - sizeof (mapping_table_ERRDOS) / - sizeof (struct smb_to_posix_error); i++) { + sizeof(mapping_table_ERRDOS) / + sizeof(struct smb_to_posix_error); i++) { if (mapping_table_ERRDOS[i].smb_err == 0) break; - else if (mapping_table_ERRDOS[i].smb_err == smberrcode) { + else if (mapping_table_ERRDOS[i].smb_err == + smberrcode) { rc = mapping_table_ERRDOS[i].posix_code; break; } - /* else try the next error mapping one to see if it will match */ + /* else try next error mapping one to see if match */ } - } else if (smberrclass == ERRSRV) { /* server class of error codes */ + } else if (smberrclass == ERRSRV) { + /* server class of error codes */ for (i = 0; i < - sizeof (mapping_table_ERRSRV) / - sizeof (struct smb_to_posix_error); i++) { + sizeof(mapping_table_ERRSRV) / + sizeof(struct smb_to_posix_error); i++) { if (mapping_table_ERRSRV[i].smb_err == 0) break; - else if (mapping_table_ERRSRV[i].smb_err == smberrcode) { + else if (mapping_table_ERRSRV[i].smb_err == + smberrcode) { rc = mapping_table_ERRSRV[i].posix_code; break; } - /* else try the next error mapping one to see if it will match */ + /* else try next error mapping to see if match */ } } /* else ERRHRD class errors or junk - return EIO */ - cFYI(1, (" !!Mapping smb error code %d to POSIX err %d !!", smberrcode,rc)); + cFYI(1, ("Mapping smb error code %d to POSIX err %d", + smberrcode, rc)); - /* generic corrective action e.g. reconnect SMB session on ERRbaduid could be added */ + /* generic corrective action e.g. reconnect SMB session on + * ERRbaduid could be added */ return rc; } @@ -888,14 +886,14 @@ map_smb_to_linux_error(struct smb_hdr *smb) unsigned int smbCalcSize(struct smb_hdr *ptr) { - return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) + + return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) + 2 /* size of the bcc field */ + BCC(ptr)); } unsigned int smbCalcSize_LE(struct smb_hdr *ptr) { - return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) + + return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) + 2 /* size of the bcc field */ + le16_to_cpu(BCC_LE(ptr))); } @@ -903,22 +901,22 @@ smbCalcSize_LE(struct smb_hdr *ptr) #define NTFS_TIME_OFFSET ((u64)(369*365 + 89) * 24 * 3600 * 10000000) - /* - * Convert the NT UTC (based 1601-01-01, in hundred nanosecond units) - * into Unix UTC (based 1970-01-01, in seconds). - */ +/* + * Convert the NT UTC (based 1601-01-01, in hundred nanosecond units) + * into Unix UTC (based 1970-01-01, in seconds). + */ struct timespec -cifs_NTtimeToUnix(u64 ntutc) +cifs_NTtimeToUnix(__le64 ntutc) { - struct timespec ts; + struct timespec ts; /* BB what about the timezone? BB */ /* Subtract the NTFS time offset, then convert to 1s intervals. */ u64 t; - t = ntutc - NTFS_TIME_OFFSET; + t = le64_to_cpu(ntutc) - NTFS_TIME_OFFSET; ts.tv_nsec = do_div(t, 10000000) * 100; - ts.tv_sec = t; + ts.tv_sec = t; return ts; } @@ -933,33 +931,32 @@ cifs_UnixTimeToNT(struct timespec t) static int total_days_of_prev_months[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; - -__le64 cnvrtDosCifsTm(__u16 date, __u16 time) -{ - return cpu_to_le64(cifs_UnixTimeToNT(cnvrtDosUnixTm(date, time))); -} - -struct timespec cnvrtDosUnixTm(__u16 date, __u16 time) +struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, int offset) { struct timespec ts; int sec, min, days, month, year; - SMB_TIME * st = (SMB_TIME *)&time; - SMB_DATE * sd = (SMB_DATE *)&date; + u16 date = le16_to_cpu(le_date); + u16 time = le16_to_cpu(le_time); + SMB_TIME *st = (SMB_TIME *)&time; + SMB_DATE *sd = (SMB_DATE *)&date; - cFYI(1,("date %d time %d",date, time)); + cFYI(1, ("date %d time %d", date, time)); sec = 2 * st->TwoSeconds; min = st->Minutes; - if((sec > 59) || (min > 59)) - cERROR(1,("illegal time min %d sec %d", min, sec)); + if ((sec > 59) || (min > 59)) + cERROR(1, ("illegal time min %d sec %d", min, sec)); sec += (min * 60); sec += 60 * 60 * st->Hours; - if(st->Hours > 24) - cERROR(1,("illegal hours %d",st->Hours)); + if (st->Hours > 24) + cERROR(1, ("illegal hours %d", st->Hours)); days = sd->Day; month = sd->Month; - if((days > 31) || (month > 12)) - cERROR(1,("illegal date, month %d day: %d", month, days)); + if ((days > 31) || (month > 12)) { + cERROR(1, ("illegal date, month %d day: %d", month, days)); + if (month > 12) + month = 12; + } month -= 1; days += total_days_of_prev_months[month]; days += 3652; /* account for difference in days between 1980 and 1970 */ @@ -970,20 +967,20 @@ struct timespec cnvrtDosUnixTm(__u16 date, __u16 time) for years/100 except for years/400, but since the maximum number for DOS year is 2**7, the last year is 1980+127, which means we need only consider 2 special case years, ie the years 2000 and 2100, and only - adjust for the lack of leap year for the year 2100, as 2000 was a + adjust for the lack of leap year for the year 2100, as 2000 was a leap year (divisable by 400) */ - if(year >= 120) /* the year 2100 */ + if (year >= 120) /* the year 2100 */ days = days - 1; /* do not count leap year for the year 2100 */ /* adjust for leap year where we are still before leap day */ - if(year != 120) + if (year != 120) days -= ((year & 0x03) == 0) && (month < 2 ? 1 : 0); - sec += 24 * 60 * 60 * days; + sec += 24 * 60 * 60 * days; - ts.tv_sec = sec; + ts.tv_sec = sec + offset; /* cFYI(1,("sec after cnvrt dos to unix time %d",sec)); */ ts.tv_nsec = 0; return ts; -} +}