smbfs_subr.c revision 278435
138776Snsouch/*- 293023Snsouch * Copyright (c) 2000-2001 Boris Popov 338776Snsouch * All rights reserved. 438776Snsouch * 538776Snsouch * Redistribution and use in source and binary forms, with or without 638776Snsouch * modification, are permitted provided that the following conditions 738776Snsouch * are met: 838776Snsouch * 1. Redistributions of source code must retain the above copyright 938776Snsouch * notice, this list of conditions and the following disclaimer. 1038776Snsouch * 2. Redistributions in binary form must reproduce the above copyright 1138776Snsouch * notice, this list of conditions and the following disclaimer in the 1238776Snsouch * documentation and/or other materials provided with the distribution. 1338776Snsouch * 1438776Snsouch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1538776Snsouch * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1638776Snsouch * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1738776Snsouch * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1838776Snsouch * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1938776Snsouch * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2038776Snsouch * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2138776Snsouch * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2238776Snsouch * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2338776Snsouch * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2438776Snsouch * SUCH DAMAGE. 2538776Snsouch * 2638776Snsouch * $FreeBSD: stable/10/sys/fs/smbfs/smbfs_subr.c 278435 2015-02-09 07:45:46Z dim $ 2738776Snsouch */ 28119419Sobrien#include <sys/param.h> 29119419Sobrien#include <sys/systm.h> 30119419Sobrien#include <sys/kernel.h> 3138776Snsouch#include <sys/clock.h> 3238776Snsouch#include <sys/malloc.h> 33162234Sjhb#include <sys/time.h> 3438776Snsouch#include <sys/vnode.h> 35162234Sjhb#include <sys/sysctl.h> 36281985Sgrembo#include <sys/iconv.h> 3738776Snsouch 3838776Snsouch#include <netsmb/smb.h> 3938776Snsouch#include <netsmb/smb_conn.h> 4038776Snsouch#include <netsmb/smb_subr.h> 41281985Sgrembo#include <netsmb/smb_rq.h> 42281985Sgrembo#include <netsmb/smb_dev.h> 43281985Sgrembo 44281985Sgrembo#include <fs/smbfs/smbfs.h> 4538776Snsouch#include <fs/smbfs/smbfs_node.h> 46162234Sjhb#include <fs/smbfs/smbfs_subr.h> 4738776Snsouch 4838776SnsouchMALLOC_DEFINE(M_SMBFSDATA, "smbfs_data", "SMBFS private data"); 4938776SnsouchMALLOC_DEFINE(M_SMBFSCRED, "smbfs_cred", "SMBFS cred data"); 5038776Snsouch 5138776Snsouchvoid 5238776Snsouchsmb_time_local2server(struct timespec *tsp, int tzoff, u_long *seconds) 53153569Sru{ 54162234Sjhb *seconds = tsp->tv_sec - tzoff * 60 /*- tz_minuteswest * 60 - 5542129Snsouch (wall_cmos_clock ? adjkerntz : 0)*/; 56281985Sgrembo} 57281985Sgrembo 58281985Sgrembovoid 59281985Sgrembosmb_time_server2local(u_long seconds, int tzoff, struct timespec *tsp) 60281985Sgrembo{ 61281985Sgrembo tsp->tv_sec = seconds + tzoff * 60; 62281985Sgrembo /*+ tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0)*/; 6338776Snsouch} 6438776Snsouch 6538776Snsouch/* 66153569Sru * Number of seconds between 1970 and 1601 year 67162234Sjhb */ 6838776Snsouchstatic int64_t DIFF1970TO1601 = 11644473600ULL; 69227843Smarius 70162237Sjhb/* 71281985Sgrembo * Time from server comes as UTC, so no need to use tz 72281985Sgrembo */ 73281985Sgrembovoid 74281985Sgrembosmb_time_NT2local(int64_t nsec, int tzoff, struct timespec *tsp) 7538776Snsouch{ 76227843Smarius smb_time_server2local(nsec / 10000000 - DIFF1970TO1601, 0, tsp); 7738776Snsouch} 7838776Snsouch 79162234Sjhbvoid 8038776Snsouchsmb_time_local2NT(struct timespec *tsp, int tzoff, int64_t *nsec) 8138776Snsouch{ 8238776Snsouch u_long seconds; 8338776Snsouch 8438776Snsouch smb_time_local2server(tsp, 0, &seconds); 85162234Sjhb *nsec = (((int64_t)(seconds) & ~1) + DIFF1970TO1601) * (int64_t)10000000; 86162234Sjhb} 8738776Snsouch 8838776Snsouchvoid 8938776Snsouchsmb_time_unix2dos(struct timespec *tsp, int tzoff, u_int16_t *ddp, 9038776Snsouch u_int16_t *dtp, u_int8_t *dhp) 9138776Snsouch{ 9238776Snsouch struct timespec tt; 9338776Snsouch u_long t; 9438776Snsouch 95162234Sjhb tt = *tsp; 9640785Snsouch smb_time_local2server(tsp, tzoff, &t); 9742129Snsouch tt.tv_sec = t; 9840785Snsouch timespec2fattime(&tt, 1, ddp, dtp, dhp); 9940785Snsouch} 10040785Snsouch 101153569Sruvoid 102153569Srusmb_dos2unixtime(u_int dd, u_int dt, u_int dh, int tzoff, 103153569Sru struct timespec *tsp) 104162234Sjhb{ 105281985Sgrembo 106162234Sjhb fattime2timespec(dd, dt, dh, 1, tsp); 107162234Sjhb smb_time_server2local(tsp->tv_sec, tzoff, tsp); 108162234Sjhb} 109281985Sgrembo 110281985Sgremboint 111281985Sgrembosmbfs_fullpath(struct mbchain *mbp, struct smb_vc *vcp, struct smbnode *dnp, 112281985Sgrembo const char *name, int nmlen) 113153569Sru{ 114153569Sru int caseopt = SMB_CS_NONE; 115153569Sru int error; 116153569Sru 117153569Sru if (SMB_UNICODE_STRINGS(vcp)) { 118162234Sjhb error = mb_put_padbyte(mbp); 119162234Sjhb if (error) 120162234Sjhb return error; 121162234Sjhb } 122162234Sjhb if (SMB_DIALECT(vcp) < SMB_DIALECT_LANMAN1_0) 123162234Sjhb caseopt |= SMB_CS_UPPER; 124162234Sjhb if (dnp != NULL) { 125162234Sjhb error = smb_put_dmem(mbp, vcp, dnp->n_rpath, dnp->n_rplen, 126162234Sjhb caseopt); 127162234Sjhb if (error) 128162234Sjhb return error; 129162234Sjhb if (name) { 130162234Sjhb /* Put the separator */ 131162234Sjhb if (SMB_UNICODE_STRINGS(vcp)) 13238776Snsouch error = mb_put_uint16le(mbp, '\\'); 133189580Simp else 13438776Snsouch error = mb_put_uint8(mbp, '\\'); 13538776Snsouch if (error) 13638776Snsouch return error; 137281985Sgrembo /* Put the name */ 138281985Sgrembo error = smb_put_dmem(mbp, vcp, name, nmlen, caseopt); 139281985Sgrembo if (error) 140281985Sgrembo return error; 141281985Sgrembo } 142281985Sgrembo } 143281985Sgrembo /* Put NULL terminator. */ 144281985Sgrembo if (SMB_UNICODE_STRINGS(vcp)) 145281985Sgrembo error = mb_put_uint16le(mbp, 0); 146281985Sgrembo else 147281985Sgrembo error = mb_put_uint8(mbp, 0); 148281985Sgrembo return error; 149281985Sgrembo} 150281985Sgrembo 151281985Sgremboint 152281985Sgrembosmbfs_fname_tolocal(struct smb_vc *vcp, char *name, int *nmlen, int caseopt) 153281985Sgrembo{ 154281985Sgrembo int copt = (caseopt == SMB_CS_LOWER ? KICONV_FROM_LOWER : 155281985Sgrembo (caseopt == SMB_CS_UPPER ? KICONV_FROM_UPPER : 0)); 156281985Sgrembo int error = 0; 157281985Sgrembo size_t ilen = *nmlen; 158281985Sgrembo size_t olen; 159281985Sgrembo char *ibuf = name; 160281985Sgrembo char outbuf[SMB_MAXFNAMELEN]; 161281985Sgrembo char *obuf = outbuf; 162281985Sgrembo 163281985Sgrembo if (vcp->vc_tolocal) { 164281985Sgrembo olen = sizeof(outbuf); 165281985Sgrembo bzero(outbuf, sizeof(outbuf)); 166281985Sgrembo 167281985Sgrembo /* 168281985Sgrembo error = iconv_conv_case 169281985Sgrembo (vcp->vc_tolocal, NULL, NULL, &obuf, &olen, copt); 170281985Sgrembo if (error) return error; 171281985Sgrembo */ 172281985Sgrembo 173281985Sgrembo error = iconv_conv_case(vcp->vc_tolocal, 174281985Sgrembo __DECONST(const char **, &ibuf), &ilen, &obuf, &olen, copt); 175281985Sgrembo if (error && SMB_UNICODE_STRINGS(vcp)) { 176281985Sgrembo /* 177281985Sgrembo * If using unicode, leaving a file name as it was when 178281985Sgrembo * convert fails will cause a problem because the file name 179281985Sgrembo * will contain NULL. 180281985Sgrembo * Here, put '?' and give converted file name. 181281985Sgrembo */ 182281985Sgrembo *obuf = '?'; 183281985Sgrembo olen--; 184281985Sgrembo error = 0; 185281985Sgrembo } 186281985Sgrembo if (!error) { 187281985Sgrembo *nmlen = sizeof(outbuf) - olen; 188281985Sgrembo memcpy(name, outbuf, *nmlen); 189281985Sgrembo } 190281985Sgrembo } 191281985Sgrembo return error; 192281985Sgrembo} 193281985Sgrembo 194281985Sgrembovoid * 195281985Sgrembosmbfs_malloc_scred(void) 196281985Sgrembo{ 197281985Sgrembo return (malloc(sizeof(struct smb_cred), M_SMBFSCRED, M_WAITOK)); 198281985Sgrembo} 199281985Sgrembo 200281985Sgrembovoid 201281985Sgrembosmbfs_free_scred(void *scred) 202281985Sgrembo{ 20393023Snsouch free(scred, M_SMBFSCRED); 204} 205