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 static int 111 smb_fphelp(struct mbchain *mbp, struct smb_vc *vcp, struct smbnode *np, 112 int caseopt) 113 { 114 struct smbmount *smp= np->n_mount; 115 struct smbnode **npp = smp->sm_npstack; 116 int i, error = 0; 117 118 /* simple_lock(&smp->sm_npslock);*/ 119 i = 0; 120 while (np->n_parent) { 121 if (i++ == SMBFS_MAXPATHCOMP) { 122 /* simple_unlock(&smp->sm_npslock);*/ 123 return ENAMETOOLONG; 124 } 125 *npp++ = np; 126 if ((np->n_flag & NREFPARENT) == 0) 127 break; 128 np = VTOSMB(np->n_parent); 129 } 130 /* if (i == 0) 131 return smb_put_dmem(mbp, vcp, "\\", 2, caseopt);*/ 132 while (i--) { 133 np = *--npp; 134 if (SMB_UNICODE_STRINGS(vcp)) 135 error = mb_put_uint16le(mbp, '\\'); 136 else 137 error = mb_put_uint8(mbp, '\\'); 138 if (error) 139 break; 140 error = smb_put_dmem(mbp, vcp, np->n_name, np->n_nmlen, caseopt); 141 if (error) 142 break; 143 } 144 /* simple_unlock(&smp->sm_npslock);*/ 145 return error; 146 } 147 148 int 149 smbfs_fullpath(struct mbchain *mbp, struct smb_vc *vcp, struct smbnode *dnp, 150 const char *name, int nmlen) 151 { 152 int caseopt = SMB_CS_NONE; 153 int error; 154 155 if (SMB_UNICODE_STRINGS(vcp)) { 156 error = mb_put_padbyte(mbp); 157 if (error) 158 return error; 159 } 160 if (SMB_DIALECT(vcp) < SMB_DIALECT_LANMAN1_0) 161 caseopt |= SMB_CS_UPPER; 162 if (dnp != NULL) { 163 error = smb_fphelp(mbp, vcp, dnp, caseopt); 164 if (error) 165 return error; 166 } 167 if (name) { 168 if (SMB_UNICODE_STRINGS(vcp)) 169 error = mb_put_uint16le(mbp, '\\'); 170 else 171 error = mb_put_uint8(mbp, '\\'); 172 if (error) 173 return error; 174 error = smb_put_dmem(mbp, vcp, name, nmlen, caseopt); 175 if (error) 176 return error; 177 } 178 error = mb_put_uint8(mbp, 0); 179 if (SMB_UNICODE_STRINGS(vcp) && error == 0) 180 error = mb_put_uint8(mbp, 0); 181 return error; 182 } 183 184 int 185 smbfs_fname_tolocal(struct smb_vc *vcp, char *name, int *nmlen, int caseopt) 186 { 187 int copt = (caseopt == SMB_CS_LOWER ? KICONV_FROM_LOWER : 188 (caseopt == SMB_CS_UPPER ? KICONV_FROM_UPPER : 0)); 189 int error = 0; 190 size_t ilen = *nmlen; 191 size_t olen; 192 char *ibuf = name; 193 char outbuf[SMB_MAXFNAMELEN]; 194 char *obuf = outbuf; 195 196 if (vcp->vc_tolocal) { 197 olen = sizeof(outbuf); 198 bzero(outbuf, sizeof(outbuf)); 199 200 /* 201 error = iconv_conv_case 202 (vcp->vc_tolocal, NULL, NULL, &obuf, &olen, copt); 203 if (error) return error; 204 */ 205 206 error = iconv_conv_case 207 (vcp->vc_tolocal, (const char **)&ibuf, &ilen, &obuf, &olen, copt); 208 if (error && SMB_UNICODE_STRINGS(vcp)) { 209 /* 210 * If using unicode, leaving a file name as it was when 211 * convert fails will cause a problem because the file name 212 * will contain NULL. 213 * Here, put '?' and give converted file name. 214 */ 215 *obuf = '?'; 216 olen--; 217 error = 0; 218 } 219 if (!error) { 220 *nmlen = sizeof(outbuf) - olen; 221 memcpy(name, outbuf, *nmlen); 222 } 223 } 224 return error; 225 } 226 227 void * 228 smbfs_malloc_scred(void) 229 { 230 return (malloc(sizeof(struct smb_cred), M_SMBFSCRED, M_WAITOK)); 231 } 232 233 void 234 smbfs_free_scred(void *scred) 235 { 236 free(scred, M_SMBFSCRED); 237 } 238