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 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Boris Popov. 16 * 4. Neither the name of the author nor the names of any co-contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * $FreeBSD$ 33 */ 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/kernel.h> 37 #include <sys/clock.h> 38 #include <sys/malloc.h> 39 #include <sys/time.h> 40 #include <sys/vnode.h> 41 #include <sys/sysctl.h> 42 #include <sys/iconv.h> 43 44 #include <netsmb/smb.h> 45 #include <netsmb/smb_conn.h> 46 #include <netsmb/smb_subr.h> 47 #include <netsmb/smb_rq.h> 48 #include <netsmb/smb_dev.h> 49 50 #include <fs/smbfs/smbfs.h> 51 #include <fs/smbfs/smbfs_node.h> 52 #include <fs/smbfs/smbfs_subr.h> 53 54 MALLOC_DEFINE(M_SMBFSDATA, "smbfs_data", "SMBFS private data"); 55 56 void 57 smb_time_local2server(struct timespec *tsp, int tzoff, u_long *seconds) 58 { 59 *seconds = tsp->tv_sec - tzoff * 60 /*- tz_minuteswest * 60 - 60 (wall_cmos_clock ? adjkerntz : 0)*/; 61 } 62 63 void 64 smb_time_server2local(u_long seconds, int tzoff, struct timespec *tsp) 65 { 66 tsp->tv_sec = seconds + tzoff * 60; 67 /*+ tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0)*/; 68 } 69 70 /* 71 * Number of seconds between 1970 and 1601 year 72 */ 73 static int64_t DIFF1970TO1601 = 11644473600ULL; 74 75 /* 76 * Time from server comes as UTC, so no need to use tz 77 */ 78 void 79 smb_time_NT2local(int64_t nsec, int tzoff, struct timespec *tsp) 80 { 81 smb_time_server2local(nsec / 10000000 - DIFF1970TO1601, 0, tsp); 82 } 83 84 void 85 smb_time_local2NT(struct timespec *tsp, int tzoff, int64_t *nsec) 86 { 87 u_long seconds; 88 89 smb_time_local2server(tsp, 0, &seconds); 90 *nsec = (((int64_t)(seconds) & ~1) + DIFF1970TO1601) * (int64_t)10000000; 91 } 92 93 void 94 smb_time_unix2dos(struct timespec *tsp, int tzoff, u_int16_t *ddp, 95 u_int16_t *dtp, u_int8_t *dhp) 96 { 97 struct timespec tt; 98 u_long t; 99 100 tt = *tsp; 101 smb_time_local2server(tsp, tzoff, &t); 102 tt.tv_sec = t; 103 timespec2fattime(&tt, 1, ddp, dtp, dhp); 104 } 105 106 void 107 smb_dos2unixtime(u_int dd, u_int dt, u_int dh, int tzoff, 108 struct timespec *tsp) 109 { 110 111 fattime2timespec(dd, dt, dh, 1, tsp); 112 smb_time_server2local(tsp->tv_sec, tzoff, tsp); 113 } 114 115 static int 116 smb_fphelp(struct mbchain *mbp, struct smb_vc *vcp, struct smbnode *np, 117 int caseopt) 118 { 119 struct smbmount *smp= np->n_mount; 120 struct smbnode **npp = smp->sm_npstack; 121 int i, error = 0; 122 123 /* simple_lock(&smp->sm_npslock);*/ 124 i = 0; 125 while (np->n_parent) { 126 if (i++ == SMBFS_MAXPATHCOMP) { 127 /* simple_unlock(&smp->sm_npslock);*/ 128 return ENAMETOOLONG; 129 } 130 *npp++ = np; 131 if ((np->n_flag & NREFPARENT) == 0) 132 break; 133 np = VTOSMB(np->n_parent); 134 } 135 /* if (i == 0) 136 return smb_put_dmem(mbp, vcp, "\\", 2, caseopt);*/ 137 while (i--) { 138 np = *--npp; 139 error = mb_put_uint8(mbp, '\\'); 140 if (error) 141 break; 142 error = smb_put_dmem(mbp, vcp, np->n_name, np->n_nmlen, caseopt); 143 if (error) 144 break; 145 } 146 /* simple_unlock(&smp->sm_npslock);*/ 147 return error; 148 } 149 150 int 151 smbfs_fullpath(struct mbchain *mbp, struct smb_vc *vcp, struct smbnode *dnp, 152 const char *name, int nmlen) 153 { 154 int caseopt = SMB_CS_NONE; 155 int error; 156 157 if (SMB_DIALECT(vcp) < SMB_DIALECT_LANMAN1_0) 158 caseopt |= SMB_CS_UPPER; 159 if (dnp != NULL) { 160 error = smb_fphelp(mbp, vcp, dnp, caseopt); 161 if (error) 162 return error; 163 } 164 if (name) { 165 error = mb_put_uint8(mbp, '\\'); 166 if (error) 167 return error; 168 error = smb_put_dmem(mbp, vcp, name, nmlen, caseopt); 169 if (error) 170 return error; 171 } 172 error = mb_put_uint8(mbp, 0); 173 return error; 174 } 175 176 int 177 smbfs_fname_tolocal(struct smb_vc *vcp, char *name, int *nmlen, int caseopt) 178 { 179 int copt = (caseopt == SMB_CS_LOWER ? KICONV_FROM_LOWER : 180 (caseopt == SMB_CS_UPPER ? KICONV_FROM_UPPER : 0)); 181 int error = 0; 182 size_t ilen = *nmlen; 183 size_t olen; 184 char *ibuf = name; 185 char outbuf[SMB_MAXFNAMELEN]; 186 char *obuf = outbuf; 187 188 if (vcp->vc_tolocal) { 189 olen = sizeof(outbuf); 190 bzero(outbuf, sizeof(outbuf)); 191 192 /* 193 error = iconv_conv_case 194 (vcp->vc_tolocal, NULL, NULL, &obuf, &olen, copt); 195 if (error) return error; 196 */ 197 198 error = iconv_conv_case 199 (vcp->vc_tolocal, (const char **)&ibuf, &ilen, &obuf, &olen, copt); 200 if (!error) { 201 *nmlen = sizeof(outbuf) - olen; 202 memcpy(name, outbuf, *nmlen); 203 } 204 } 205 return error; 206 } 207