1 /*- 2 * Copyright (c) 2000-2001 Boris Popov 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 */ 28 #include <sys/param.h> 29 #include <sys/systm.h> 30 #include <sys/kernel.h> 31 #include <sys/clock.h> 32 #include <sys/malloc.h> 33 #include <sys/time.h> 34 #include <sys/vnode.h> 35 #include <sys/sysctl.h> 36 #include <sys/iconv.h> 37 38 #include <netsmb/smb.h> 39 #include <netsmb/smb_conn.h> 40 #include <netsmb/smb_subr.h> 41 #include <netsmb/smb_rq.h> 42 #include <netsmb/smb_dev.h> 43 44 #include <fs/smbfs/smbfs.h> 45 #include <fs/smbfs/smbfs_node.h> 46 #include <fs/smbfs/smbfs_subr.h> 47 48 MALLOC_DEFINE(M_SMBFSDATA, "smbfs_data", "SMBFS private data"); 49 MALLOC_DEFINE(M_SMBFSCRED, "smbfs_cred", "SMBFS cred data"); 50 51 void 52 smb_time_local2server(struct timespec *tsp, int tzoff, u_long *seconds) 53 { 54 *seconds = tsp->tv_sec - tzoff * 60 /*- tz_minuteswest * 60 - 55 (wall_cmos_clock ? adjkerntz : 0)*/; 56 } 57 58 void 59 smb_time_server2local(u_long seconds, int tzoff, struct timespec *tsp) 60 { 61 tsp->tv_sec = seconds + tzoff * 60; 62 /*+ tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0)*/; 63 } 64 65 /* 66 * Number of seconds between 1970 and 1601 year 67 */ 68 static int64_t DIFF1970TO1601 = 11644473600ULL; 69 70 /* 71 * Time from server comes as UTC, so no need to use tz 72 */ 73 void 74 smb_time_NT2local(int64_t nsec, int tzoff, struct timespec *tsp) 75 { 76 smb_time_server2local(nsec / 10000000 - DIFF1970TO1601, 0, tsp); 77 } 78 79 void 80 smb_time_local2NT(struct timespec *tsp, int tzoff, int64_t *nsec) 81 { 82 u_long seconds; 83 84 smb_time_local2server(tsp, 0, &seconds); 85 *nsec = (((int64_t)(seconds) & ~1) + DIFF1970TO1601) * (int64_t)10000000; 86 } 87 88 void 89 smb_time_unix2dos(struct timespec *tsp, int tzoff, u_int16_t *ddp, 90 u_int16_t *dtp, u_int8_t *dhp) 91 { 92 struct timespec tt; 93 u_long t; 94 95 tt = *tsp; 96 smb_time_local2server(tsp, tzoff, &t); 97 tt.tv_sec = t; 98 timespec2fattime(&tt, 1, ddp, dtp, dhp); 99 } 100 101 void 102 smb_dos2unixtime(u_int dd, u_int dt, u_int dh, int tzoff, 103 struct timespec *tsp) 104 { 105 106 fattime2timespec(dd, dt, dh, 1, tsp); 107 smb_time_server2local(tsp->tv_sec, tzoff, tsp); 108 } 109 110 int 111 smbfs_fullpath(struct mbchain *mbp, struct smb_vc *vcp, struct smbnode *dnp, 112 const char *name, int nmlen) 113 { 114 int caseopt = SMB_CS_NONE; 115 int error; 116 117 if (SMB_UNICODE_STRINGS(vcp)) { 118 error = mb_put_padbyte(mbp); 119 if (error) 120 return error; 121 } 122 if (SMB_DIALECT(vcp) < SMB_DIALECT_LANMAN1_0) 123 caseopt |= SMB_CS_UPPER; 124 if (dnp != NULL) { 125 error = smb_put_dmem(mbp, vcp, dnp->n_rpath, dnp->n_rplen, 126 caseopt); 127 if (error) 128 return error; 129 if (name) { 130 /* Put the separator */ 131 if (SMB_UNICODE_STRINGS(vcp)) 132 error = mb_put_uint16le(mbp, '\\'); 133 else 134 error = mb_put_uint8(mbp, '\\'); 135 if (error) 136 return error; 137 /* Put the name */ 138 error = smb_put_dmem(mbp, vcp, name, nmlen, caseopt); 139 if (error) 140 return error; 141 } 142 } 143 /* Put NULL terminator. */ 144 if (SMB_UNICODE_STRINGS(vcp)) 145 error = mb_put_uint16le(mbp, 0); 146 else 147 error = mb_put_uint8(mbp, 0); 148 return error; 149 } 150 151 int 152 smbfs_fname_tolocal(struct smb_vc *vcp, char *name, int *nmlen, int caseopt) 153 { 154 int copt = (caseopt == SMB_CS_LOWER ? KICONV_FROM_LOWER : 155 (caseopt == SMB_CS_UPPER ? KICONV_FROM_UPPER : 0)); 156 int error = 0; 157 size_t ilen = *nmlen; 158 size_t olen; 159 char *ibuf = name; 160 char outbuf[SMB_MAXFNAMELEN]; 161 char *obuf = outbuf; 162 163 if (vcp->vc_tolocal) { 164 olen = sizeof(outbuf); 165 bzero(outbuf, sizeof(outbuf)); 166 167 /* 168 error = iconv_conv_case 169 (vcp->vc_tolocal, NULL, NULL, &obuf, &olen, copt); 170 if (error) return error; 171 */ 172 173 error = iconv_conv_case(vcp->vc_tolocal, 174 __DECONST(const char **, &ibuf), &ilen, &obuf, &olen, copt); 175 if (error && SMB_UNICODE_STRINGS(vcp)) { 176 /* 177 * If using unicode, leaving a file name as it was when 178 * convert fails will cause a problem because the file name 179 * will contain NULL. 180 * Here, put '?' and give converted file name. 181 */ 182 *obuf = '?'; 183 olen--; 184 error = 0; 185 } 186 if (!error) { 187 *nmlen = sizeof(outbuf) - olen; 188 memcpy(name, outbuf, *nmlen); 189 } 190 } 191 return error; 192 } 193 194 void * 195 smbfs_malloc_scred(void) 196 { 197 return (malloc(sizeof(struct smb_cred), M_SMBFSCRED, M_WAITOK)); 198 } 199 200 void 201 smbfs_free_scred(void *scred) 202 { 203 free(scred, M_SMBFSCRED); 204 } 205