1139776Simp/*- 2206361Sjoel * Copyright (c) 2000-2001 Boris Popov 375374Sbp * All rights reserved. 475374Sbp * 575374Sbp * Redistribution and use in source and binary forms, with or without 675374Sbp * modification, are permitted provided that the following conditions 775374Sbp * are met: 875374Sbp * 1. Redistributions of source code must retain the above copyright 975374Sbp * notice, this list of conditions and the following disclaimer. 1075374Sbp * 2. Redistributions in binary form must reproduce the above copyright 1175374Sbp * notice, this list of conditions and the following disclaimer in the 1275374Sbp * documentation and/or other materials provided with the distribution. 1375374Sbp * 1475374Sbp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1575374Sbp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1675374Sbp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1775374Sbp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1875374Sbp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1975374Sbp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2075374Sbp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2175374Sbp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2275374Sbp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2375374Sbp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2475374Sbp * SUCH DAMAGE. 2575374Sbp * 2675374Sbp * $FreeBSD$ 2775374Sbp */ 2875374Sbp#include <sys/param.h> 2975374Sbp#include <sys/systm.h> 3075374Sbp#include <sys/kernel.h> 31163652Sphk#include <sys/clock.h> 3275374Sbp#include <sys/malloc.h> 3375374Sbp#include <sys/time.h> 3475374Sbp#include <sys/vnode.h> 3575374Sbp#include <sys/sysctl.h> 3675374Sbp#include <sys/iconv.h> 3775374Sbp 3875374Sbp#include <netsmb/smb.h> 3975374Sbp#include <netsmb/smb_conn.h> 4075374Sbp#include <netsmb/smb_subr.h> 4175374Sbp#include <netsmb/smb_rq.h> 4275374Sbp#include <netsmb/smb_dev.h> 4375374Sbp 4475374Sbp#include <fs/smbfs/smbfs.h> 4575374Sbp#include <fs/smbfs/smbfs_node.h> 4675374Sbp#include <fs/smbfs/smbfs_subr.h> 4775374Sbp 48151897SrwatsonMALLOC_DEFINE(M_SMBFSDATA, "smbfs_data", "SMBFS private data"); 4975374Sbp 5075374Sbpvoid 5175374Sbpsmb_time_local2server(struct timespec *tsp, int tzoff, u_long *seconds) 5275374Sbp{ 53110299Sphk *seconds = tsp->tv_sec - tzoff * 60 /*- tz_minuteswest * 60 - 5475374Sbp (wall_cmos_clock ? adjkerntz : 0)*/; 5575374Sbp} 5675374Sbp 5775374Sbpvoid 5875374Sbpsmb_time_server2local(u_long seconds, int tzoff, struct timespec *tsp) 5975374Sbp{ 6075374Sbp tsp->tv_sec = seconds + tzoff * 60; 61110299Sphk /*+ tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0)*/; 6275374Sbp} 6375374Sbp 6475374Sbp/* 6575374Sbp * Number of seconds between 1970 and 1601 year 6675374Sbp */ 67145974Sanholtstatic int64_t DIFF1970TO1601 = 11644473600ULL; 6875374Sbp 6975374Sbp/* 7075374Sbp * Time from server comes as UTC, so no need to use tz 7175374Sbp */ 7275374Sbpvoid 7375374Sbpsmb_time_NT2local(int64_t nsec, int tzoff, struct timespec *tsp) 7475374Sbp{ 7575374Sbp smb_time_server2local(nsec / 10000000 - DIFF1970TO1601, 0, tsp); 7675374Sbp} 7775374Sbp 7875374Sbpvoid 7975374Sbpsmb_time_local2NT(struct timespec *tsp, int tzoff, int64_t *nsec) 8075374Sbp{ 8175374Sbp u_long seconds; 8275374Sbp 8375374Sbp smb_time_local2server(tsp, 0, &seconds); 8475374Sbp *nsec = (((int64_t)(seconds) & ~1) + DIFF1970TO1601) * (int64_t)10000000; 8575374Sbp} 8675374Sbp 8775374Sbpvoid 8875374Sbpsmb_time_unix2dos(struct timespec *tsp, int tzoff, u_int16_t *ddp, 8975374Sbp u_int16_t *dtp, u_int8_t *dhp) 9075374Sbp{ 91163652Sphk struct timespec tt; 92163652Sphk u_long t; 9375374Sbp 94163652Sphk tt = *tsp; 9575374Sbp smb_time_local2server(tsp, tzoff, &t); 96163652Sphk tt.tv_sec = t; 97163652Sphk timespec2fattime(&tt, 1, ddp, dtp, dhp); 9875374Sbp} 9975374Sbp 10075374Sbpvoid 10175374Sbpsmb_dos2unixtime(u_int dd, u_int dt, u_int dh, int tzoff, 10275374Sbp struct timespec *tsp) 10375374Sbp{ 10475374Sbp 105163652Sphk fattime2timespec(dd, dt, dh, 1, tsp); 106163652Sphk smb_time_server2local(tsp->tv_sec, tzoff, tsp); 10775374Sbp} 10875374Sbp 10975374Sbpstatic int 11075374Sbpsmb_fphelp(struct mbchain *mbp, struct smb_vc *vcp, struct smbnode *np, 11175374Sbp int caseopt) 11275374Sbp{ 11375374Sbp struct smbmount *smp= np->n_mount; 11475374Sbp struct smbnode **npp = smp->sm_npstack; 11575374Sbp int i, error = 0; 11675374Sbp 11775374Sbp/* simple_lock(&smp->sm_npslock);*/ 11875374Sbp i = 0; 11975374Sbp while (np->n_parent) { 12075374Sbp if (i++ == SMBFS_MAXPATHCOMP) { 12175374Sbp/* simple_unlock(&smp->sm_npslock);*/ 12275374Sbp return ENAMETOOLONG; 12375374Sbp } 12475374Sbp *npp++ = np; 125116338Stjr if ((np->n_flag & NREFPARENT) == 0) 126116338Stjr break; 127107821Stjr np = VTOSMB(np->n_parent); 12875374Sbp } 12975374Sbp/* if (i == 0) 13075374Sbp return smb_put_dmem(mbp, vcp, "\\", 2, caseopt);*/ 13175374Sbp while (i--) { 13275374Sbp np = *--npp; 133230196Skevlo if (SMB_UNICODE_STRINGS(vcp)) 134230196Skevlo error = mb_put_uint16le(mbp, '\\'); 135230196Skevlo else 136230196Skevlo error = mb_put_uint8(mbp, '\\'); 13775374Sbp if (error) 13875374Sbp break; 13975374Sbp error = smb_put_dmem(mbp, vcp, np->n_name, np->n_nmlen, caseopt); 14075374Sbp if (error) 14175374Sbp break; 14275374Sbp } 14375374Sbp/* simple_unlock(&smp->sm_npslock);*/ 14475374Sbp return error; 14575374Sbp} 14675374Sbp 14775374Sbpint 14875374Sbpsmbfs_fullpath(struct mbchain *mbp, struct smb_vc *vcp, struct smbnode *dnp, 14975374Sbp const char *name, int nmlen) 15075374Sbp{ 15175374Sbp int caseopt = SMB_CS_NONE; 15275374Sbp int error; 15375374Sbp 154230196Skevlo if (SMB_UNICODE_STRINGS(vcp)) { 155230196Skevlo error = mb_put_padbyte(mbp); 156230196Skevlo if (error) 157230196Skevlo return error; 158230196Skevlo } 15975374Sbp if (SMB_DIALECT(vcp) < SMB_DIALECT_LANMAN1_0) 16075374Sbp caseopt |= SMB_CS_UPPER; 16175374Sbp if (dnp != NULL) { 16275374Sbp error = smb_fphelp(mbp, vcp, dnp, caseopt); 16375374Sbp if (error) 16475374Sbp return error; 16575374Sbp } 16675374Sbp if (name) { 167230196Skevlo if (SMB_UNICODE_STRINGS(vcp)) 168230196Skevlo error = mb_put_uint16le(mbp, '\\'); 169230196Skevlo else 170230196Skevlo error = mb_put_uint8(mbp, '\\'); 17175374Sbp if (error) 17275374Sbp return error; 17375374Sbp error = smb_put_dmem(mbp, vcp, name, nmlen, caseopt); 17475374Sbp if (error) 17575374Sbp return error; 17675374Sbp } 17775374Sbp error = mb_put_uint8(mbp, 0); 178230196Skevlo if (SMB_UNICODE_STRINGS(vcp) && error == 0) 179230196Skevlo error = mb_put_uint8(mbp, 0); 18075374Sbp return error; 18175374Sbp} 18275374Sbp 18375374Sbpint 184145872Stakawatasmbfs_fname_tolocal(struct smb_vc *vcp, char *name, int *nmlen, int caseopt) 18575374Sbp{ 186145872Stakawata int copt = (caseopt == SMB_CS_LOWER ? KICONV_FROM_LOWER : 187145872Stakawata (caseopt == SMB_CS_UPPER ? KICONV_FROM_UPPER : 0)); 188145872Stakawata int error = 0; 189145900Stakawata size_t ilen = *nmlen; 190145900Stakawata size_t olen; 191145872Stakawata char *ibuf = name; 192145872Stakawata char outbuf[SMB_MAXFNAMELEN]; 193145872Stakawata char *obuf = outbuf; 194145872Stakawata 195145872Stakawata if (vcp->vc_tolocal) { 196145872Stakawata olen = sizeof(outbuf); 197145872Stakawata bzero(outbuf, sizeof(outbuf)); 198145872Stakawata 199145872Stakawata /* 200145872Stakawata error = iconv_conv_case 201145872Stakawata (vcp->vc_tolocal, NULL, NULL, &obuf, &olen, copt); 202145872Stakawata if (error) return error; 203145872Stakawata */ 204145872Stakawata 205145872Stakawata error = iconv_conv_case 206145872Stakawata (vcp->vc_tolocal, (const char **)&ibuf, &ilen, &obuf, &olen, copt); 207230196Skevlo if (error && SMB_UNICODE_STRINGS(vcp)) { 208230196Skevlo /* 209230196Skevlo * If using unicode, leaving a file name as it was when 210230196Skevlo * convert fails will cause a problem because the file name 211230196Skevlo * will contain NULL. 212230196Skevlo * Here, put '?' and give converted file name. 213230196Skevlo */ 214230196Skevlo *obuf = '?'; 215230196Skevlo olen--; 216230196Skevlo error = 0; 217230196Skevlo } 218145872Stakawata if (!error) { 219145872Stakawata *nmlen = sizeof(outbuf) - olen; 220145872Stakawata memcpy(name, outbuf, *nmlen); 221145872Stakawata } 222145872Stakawata } 223145872Stakawata return error; 22475374Sbp} 225