X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=fs%2Fcifs%2Fnetmisc.c;h=2bfed3f45d0f97c4d9765bd6842c07e1e39f515f;hb=f01d5e14e764b14b6bf5512678523d009254b209;hp=ce87550e918f8d33d87573677287e24d2da234e9;hpb=23e735bc7b0e1d614656881794257b4224efda3a;p=linux-2.6-omap-h63xx.git diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index ce87550e918..2bfed3f45d0 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c @@ -3,23 +3,22 @@ * * Copyright (c) International Business Machines Corp., 2002 * 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,6 +29,7 @@ #include #include #include +#include #include "cifsfs.h" #include "cifspdu.h" #include "cifsglob.h" @@ -64,22 +64,22 @@ 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}, + {ErrTooManyLinks, -EMLINK}, {0, 0} }; @@ -129,69 +129,25 @@ static const struct smb_to_posix_error mapping_table_ERRHRD[] = { /* Convert string containing dotted ip address to binary form */ /* returns 0 if invalid address */ -/* BB add address family, change rc to status flag and return union or for ipv6 */ -/* will need parent to call something like inet_pton to convert ipv6 address BB */ int -cifs_inet_pton(int address_family, char *cp,void *dst) +cifs_inet_pton(int address_family, char *cp, void *dst) { - 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; - } - - temp = *cp; - - while (TRUE) { - if (!isdigit(temp)) - return 0; - - value = 0; - digit = 0; - for (;;) { - if (isascii(temp) && isdigit(temp)) { - value = (value * 10) + temp - '0'; - temp = *++cp; - digit = 1; - } else - break; - } - - 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; + 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 ) { + ret = in6_pton(cp, -1 /* len */, dst , '\\', NULL); } - - /* 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; - - *((__be32 *)dst) = *((__be32 *) bytes) | htonl(value); - return 1; /* success */ +#ifdef CONFIG_CIFS_DEBUG2 + cFYI(1, ("address conversion returned %d for %s", ret, cp)); +#endif + if (ret > 0) + ret = 1; + return ret; } /***************************************************************************** @@ -226,7 +182,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}, { @@ -241,7 +197,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}, { @@ -311,7 +267,7 @@ 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}, { @@ -321,7 +277,7 @@ static const struct { 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}, { @@ -373,8 +329,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}, { @@ -618,8 +574,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}, { @@ -638,7 +594,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}, { @@ -769,7 +725,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++; } @@ -801,7 +757,7 @@ int map_smb_to_linux_error(struct smb_hdr *smb) { 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; @@ -812,9 +768,10 @@ 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 (cifsFYI & CIFS_RC) cifs_print_status(err); ntstatus_to_dos(err, &smberrclass, &smberrcode); } else { @@ -825,38 +782,42 @@ 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++) { 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++) { 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; } @@ -890,7 +851,7 @@ smbCalcSize_LE(struct smb_hdr *ptr) struct timespec cifs_NTtimeToUnix(u64 ntutc) { - struct timespec ts; + struct timespec ts; /* BB what about the timezone? BB */ /* Subtract the NTFS time offset, then convert to 1s intervals. */ @@ -898,7 +859,7 @@ cifs_NTtimeToUnix(u64 ntutc) t = ntutc - NTFS_TIME_OFFSET; ts.tv_nsec = do_div(t, 10000000) * 100; - ts.tv_sec = t; + ts.tv_sec = t; return ts; } @@ -909,3 +870,61 @@ cifs_UnixTimeToNT(struct timespec t) /* Convert to 100ns intervals and then add the NTFS time offset. */ return (u64) t.tv_sec * 10000000 + t.tv_nsec/100 + NTFS_TIME_OFFSET; } + +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 ts; + int sec, min, days, month, year; + SMB_TIME * st = (SMB_TIME *)&time; + SMB_DATE * sd = (SMB_DATE *)&date; + + 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)); + sec += (min * 60); + sec += 60 * 60 * 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)); + month -= 1; + days += total_days_of_prev_months[month]; + days += 3652; /* account for difference in days between 1980 and 1970 */ + year = sd->Year; + days += year * 365; + days += (year/4); /* leap year */ + /* generalized leap year calculation is more complex, ie no leap year + 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 + leap year (divisable by 400) */ + 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) + days -= ((year & 0x03) == 0) && (month < 2 ? 1 : 0); + sec += 24 * 60 * 60 * days; + + ts.tv_sec = sec; + + /* cFYI(1,("sec after cnvrt dos to unix time %d",sec)); */ + + ts.tv_nsec = 0; + return ts; +}