1139776Simp/*- 274062Sbp * Copyright (c) 1999, 2001 Boris Popov 351852Sbp * All rights reserved. 451852Sbp * 551852Sbp * Redistribution and use in source and binary forms, with or without 651852Sbp * modification, are permitted provided that the following conditions 751852Sbp * are met: 851852Sbp * 1. Redistributions of source code must retain the above copyright 951852Sbp * notice, this list of conditions and the following disclaimer. 1051852Sbp * 2. Redistributions in binary form must reproduce the above copyright 1151852Sbp * notice, this list of conditions and the following disclaimer in the 1251852Sbp * documentation and/or other materials provided with the distribution. 1351852Sbp * 1451852Sbp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1551852Sbp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1651852Sbp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1751852Sbp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1851852Sbp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1951852Sbp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2051852Sbp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2151852Sbp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2251852Sbp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2351852Sbp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2451852Sbp * SUCH DAMAGE. 2551852Sbp * 2651852Sbp * $FreeBSD$ 2751852Sbp */ 2851852Sbp#include <sys/param.h> 2951852Sbp#include <sys/systm.h> 3051852Sbp#include <sys/kernel.h> 31176708Sattilio#include <sys/lock.h> 32102821Siedowse#include <sys/lockmgr.h> 3351852Sbp#include <sys/malloc.h> 34162970Sphk#include <sys/clock.h> 3551852Sbp#include <sys/time.h> 3651852Sbp 3751852Sbp#include <netncp/ncp.h> 3851852Sbp#include <netncp/ncp_conn.h> 3951852Sbp#include <netncp/ncp_ncp.h> 4051852Sbp#include <netncp/ncp_subr.h> 4151852Sbp#include <netncp/ncp_rq.h> 4251852Sbp#include <netncp/nwerror.h> 4351852Sbp 4477223Sru#include <fs/nwfs/nwfs.h> 4577223Sru#include <fs/nwfs/nwfs_node.h> 4677223Sru#include <fs/nwfs/nwfs_subr.h> 4751852Sbp 4874062Sbp#define NCP_INFOSZ (sizeof(struct nw_entry_info) - 257) 4974062Sbp 50151897SrwatsonMALLOC_DEFINE(M_NWFSDATA, "nwfs_data", "NWFS private data"); 5151852Sbp 5274062Sbpstatic int 5374062Sbpncp_extract_file_info(struct nwmount *nmp, struct ncp_rq *rqp, 5474062Sbp struct nw_entry_info *target, int withname) 5574062Sbp{ 5674062Sbp u_int8_t name_len; 5751852Sbp 5874062Sbp md_get_mem(&rqp->rp, (caddr_t)target, NCP_INFOSZ, MB_MSYSTEM); 5974062Sbp if (!withname) 6074062Sbp return 0; 6174062Sbp md_get_uint8(&rqp->rp, &name_len); 6251852Sbp target->nameLen = name_len; 6374062Sbp md_get_mem(&rqp->rp, (caddr_t)target->entryName, name_len, MB_MSYSTEM); 6451852Sbp target->entryName[name_len] = '\0'; 6551852Sbp ncp_path2unix(target->entryName, target->entryName, name_len, &nmp->m.nls); 6674062Sbp return 0; 6751852Sbp} 6851852Sbp 6951852Sbpint 7083366Sjulianncp_initsearch(struct vnode *dvp, struct thread *td, struct ucred *cred) 7151852Sbp{ 7251852Sbp struct nwmount *nmp = VTONWFS(dvp); 7351852Sbp struct ncp_conn *conn = NWFSTOCONN(nmp); 7451852Sbp struct nwnode *np = VTONW(dvp); 7574062Sbp struct ncp_rq *rqp; 7651852Sbp u_int8_t volnum = nmp->n_volume; 7751852Sbp u_int32_t dirent = np->n_fid.f_id; 7851852Sbp int error; 7951852Sbp 8051852Sbp NCPNDEBUG("vol=%d,dir=%d\n", volnum, dirent); 8183366Sjulian error = ncp_rq_alloc(87, conn, td, cred, &rqp); 8274062Sbp if (error) 8374062Sbp return error; 8474062Sbp mb_put_uint8(&rqp->rq, 2); /* subfunction */ 8574062Sbp mb_put_uint8(&rqp->rq, nmp->name_space); 8674062Sbp mb_put_uint8(&rqp->rq, 0); /* reserved */ 8751852Sbp ncp_rq_dbase_path(rqp, volnum, dirent, 0, NULL, NULL); 8874062Sbp rqp->nr_minrplen = sizeof(np->n_seq); 8974062Sbp error = ncp_request(rqp); 9074062Sbp if (error) 9174062Sbp return error; 9274062Sbp md_get_mem(&rqp->rp, (caddr_t)&np->n_seq, sizeof(np->n_seq), MB_MSYSTEM); 9374062Sbp ncp_rq_done(rqp); 9474062Sbp return 0; 9551852Sbp} 9651852Sbp 9751852Sbpint 9851852Sbpncp_search_for_file_or_subdir(struct nwmount *nmp, 9951852Sbp struct nw_search_seq *seq, 10051852Sbp struct nw_entry_info *target, 10183366Sjulian struct thread *td,struct ucred *cred) 10251852Sbp{ 10351852Sbp struct ncp_conn *conn = NWFSTOCONN(nmp); 10474062Sbp struct ncp_rq *rqp; 10551852Sbp int error; 10651852Sbp 10783366Sjulian error = ncp_rq_alloc(87, conn, td, cred, &rqp); 10874062Sbp if (error) 10974062Sbp return error; 11074062Sbp mb_put_uint8(&rqp->rq, 3); /* subfunction */ 11174062Sbp mb_put_uint8(&rqp->rq, nmp->name_space); 11274062Sbp mb_put_uint8(&rqp->rq, 0); /* data stream */ 11374062Sbp mb_put_uint16le(&rqp->rq, 0xffff); /* Search attribs */ 11474062Sbp mb_put_uint32le(&rqp->rq, IM_ALL); /* return info mask */ 11574062Sbp mb_put_mem(&rqp->rq, (caddr_t)seq, 9, MB_MSYSTEM); 11674062Sbp mb_put_uint8(&rqp->rq, 2); /* 2 byte pattern */ 11774062Sbp mb_put_uint8(&rqp->rq, 0xff); /* following is a wildcard */ 11874062Sbp mb_put_uint8(&rqp->rq, '*'); 11974062Sbp rqp->nr_minrplen = sizeof(*seq) + 1 + NCP_INFOSZ + 1; 12074062Sbp error = ncp_request(rqp); 12174062Sbp if (error) 12274062Sbp return error; 12374062Sbp md_get_mem(&rqp->rp, (caddr_t)seq, sizeof(*seq), MB_MSYSTEM); 12474062Sbp md_get_uint8(&rqp->rp, NULL); /* skip */ 12574062Sbp error = ncp_extract_file_info(nmp, rqp, target, 1); 12674062Sbp ncp_rq_done(rqp); 12751852Sbp return error; 12851852Sbp} 12951852Sbp 13051852Sbp/* 13151852Sbp * Returns information for a (one-component) name relative to the specified 13251852Sbp * directory. 13351852Sbp */ 13451852Sbpint 13551852Sbpncp_obtain_info(struct nwmount *nmp, u_int32_t dirent, 13651852Sbp int namelen, char *path, struct nw_entry_info *target, 13783366Sjulian struct thread *td,struct ucred *cred) 13851852Sbp{ 13951852Sbp struct ncp_conn *conn=NWFSTOCONN(nmp); 14074062Sbp struct ncp_rq *rqp; 14151852Sbp int error; 14251852Sbp u_char volnum = nmp->n_volume, ns; 14351852Sbp 14451852Sbp if (target == NULL) { 14551852Sbp NCPFATAL("target == NULL\n"); 14651852Sbp return EINVAL; 14751852Sbp } 14851852Sbp ns = (path == NULL || path[0] == 0) ? NW_NS_DOS : nmp->name_space; 14983366Sjulian error = ncp_rq_alloc(87, conn, td, cred, &rqp); 15074062Sbp if (error) 15174062Sbp return error; 15274062Sbp mb_put_uint8(&rqp->rq, 6); /* subfunction */ 15374062Sbp mb_put_uint8(&rqp->rq, ns); 15474062Sbp mb_put_uint8(&rqp->rq, ns); /* DestNameSpace */ 15574062Sbp mb_put_uint16le(&rqp->rq, 0xff); /* get all */ 15674062Sbp mb_put_uint32le(&rqp->rq, IM_ALL); 15751852Sbp ncp_rq_dbase_path(rqp, volnum, dirent, namelen, path, &nmp->m.nls); 15874062Sbp error = ncp_request(rqp); 15974062Sbp if (error) 16074062Sbp return error; 16174062Sbp error = ncp_extract_file_info(nmp, rqp, target, path != NULL); 16274062Sbp ncp_rq_done(rqp); 16351852Sbp return error; 16451852Sbp} 16551852Sbp/* 16651852Sbp * lookup name pointed by cnp in directory dvp and return file info in np. 16751852Sbp * May be I should create a little cache, but another way is to minimize 16851852Sbp * number of calls, on other hand, in multiprocess environment ... 16951852Sbp */ 17051852Sbpint 17151852Sbpncp_lookup(struct vnode *dvp, int len, char *name, struct nw_entry_info *fap, 17283366Sjulian struct thread *td,struct ucred *cred) 17351852Sbp{ 17451852Sbp struct nwmount *nmp; 175146115Skan struct nwnode *dnp; 17651852Sbp int error; 17751852Sbp 17851852Sbp if (!dvp || dvp->v_type != VDIR) { 17951852Sbp nwfs_printf("dvp is NULL or not a directory.\n"); 18051852Sbp return (ENOENT); 18151852Sbp } 182146115Skan dnp = VTONW(dvp); 18351852Sbp nmp = VTONWFS(dvp); 18451852Sbp 18551852Sbp if (len == 1 && name[0] == '.') { 18674064Sbp if (dnp->n_flag & NVOLUME) { 18751852Sbp error = ncp_obtain_info(nmp, dnp->n_fid.f_id, 0, NULL, 18883366Sjulian fap, td, cred); 18951852Sbp } else { 19051852Sbp error = ncp_obtain_info(nmp, dnp->n_fid.f_parent, 19183366Sjulian dnp->n_nmlen, dnp->n_name, fap, td, cred); 19251852Sbp } 19351852Sbp return error; 19451852Sbp } else if (len == 2 && name[0] == '.' && name[1] == '.') { 19587599Sobrien printf("%s: knows NOTHING about '..'\n", __func__); 19651852Sbp return EIO; 19751852Sbp } else { 19851852Sbp error = ncp_obtain_info(nmp, dnp->n_fid.f_id, 19983366Sjulian len, name, fap, td, cred); 20051852Sbp } 20151852Sbp return error; 20251852Sbp} 20351852Sbp 20451852Sbpstatic void ConvertToNWfromDWORD(u_int32_t sfd, ncp_fh *fh); 20551852Sbpstatic void 20651852SbpConvertToNWfromDWORD(u_int32_t sfd, ncp_fh *fh) { 20751852Sbp fh->val1 = (fh->val.val32 = sfd); 20851852Sbp return; 20951852Sbp} 21051852Sbp 21151852Sbp/* 21251852Sbp * If both dir and name are NULL, then in target there's already a looked-up 21351852Sbp * entry that wants to be opened. 21451852Sbp */ 21551852Sbpint 21651852Sbpncp_open_create_file_or_subdir(struct nwmount *nmp,struct vnode *dvp,int namelen, 21751852Sbp char *name, int open_create_mode, u_int32_t create_attributes, 21851852Sbp int desired_acc_rights, struct ncp_open_info *nop, 21983366Sjulian struct thread *td,struct ucred *cred) 22051852Sbp{ 22151852Sbp 22251852Sbp struct ncp_conn *conn=NWFSTOCONN(nmp); 22374062Sbp struct ncp_rq *rqp; 22451852Sbp u_int16_t search_attribs = SA_ALL & (~SA_SUBDIR_FILES); 22551852Sbp u_int8_t volnum; 22651852Sbp u_int32_t dirent; 22751852Sbp int error; 22851852Sbp 22983366Sjulian error = ncp_rq_alloc(87, conn, td, cred, &rqp); 23074062Sbp if (error) 23174062Sbp return error; 23251852Sbp volnum = nmp->n_volume; 23351852Sbp dirent = VTONW(dvp)->n_fid.f_id; 23451852Sbp if ((create_attributes & aDIR) != 0) { 23551852Sbp search_attribs |= SA_SUBDIR_FILES; 23651852Sbp } 23774062Sbp mb_put_uint8(&rqp->rq, 1);/* subfunction */ 23874062Sbp mb_put_uint8(&rqp->rq, nmp->name_space); 23974062Sbp mb_put_uint8(&rqp->rq, open_create_mode); 24074062Sbp mb_put_uint16le(&rqp->rq, search_attribs); 24174062Sbp mb_put_uint32le(&rqp->rq, IM_ALL); 24274062Sbp mb_put_uint32le(&rqp->rq, create_attributes); 24351852Sbp /* 24451852Sbp * The desired acc rights seem to be the inherited rights mask for 24551852Sbp * directories 24651852Sbp */ 24774062Sbp mb_put_uint16le(&rqp->rq, desired_acc_rights); 24851852Sbp ncp_rq_dbase_path(rqp, volnum, dirent, namelen, name, &nmp->m.nls); 24974062Sbp error = ncp_request(rqp); 25074062Sbp if (error) { 25174062Sbp if (error == NWE_FILE_NO_CREATE_PRIV) 25274062Sbp error = EACCES; 25374062Sbp return error; 25474062Sbp } 25574062Sbp md_get_uint32le(&rqp->rp, &nop->origfh); 25674062Sbp md_get_uint8(&rqp->rp, &nop->action); 25774062Sbp md_get_uint8(&rqp->rp, NULL); /* skip */ 25874062Sbp error = ncp_extract_file_info(nmp, rqp, &nop->fattr, 1); 25974062Sbp ncp_rq_done(rqp); 26051852Sbp ConvertToNWfromDWORD(nop->origfh, &nop->fh); 26151852Sbp return error; 26251852Sbp} 26351852Sbp 26451852Sbpint 26583366Sjulianncp_close_file(struct ncp_conn *conn, ncp_fh *fh,struct thread *td,struct ucred *cred) 26674062Sbp{ 26774062Sbp struct ncp_rq *rqp; 26851852Sbp int error; 26951852Sbp 27083366Sjulian error = ncp_rq_alloc(66, conn, td, cred, &rqp); 27174062Sbp if (error) 27274062Sbp return error; 27374062Sbp mb_put_uint8(&rqp->rq, 0); 27474062Sbp mb_put_mem(&rqp->rq, (caddr_t)fh, 6, MB_MSYSTEM); 27574062Sbp error = ncp_request(rqp); 27674062Sbp if (error) 27774062Sbp return error; 27874062Sbp ncp_rq_done(rqp); 27951852Sbp return error; 28051852Sbp} 28151852Sbp 28251852Sbpint 28351852Sbpncp_DeleteNSEntry(struct nwmount *nmp, u_int32_t dirent, 28483366Sjulian int namelen,char *name,struct thread *td,struct ucred *cred) 28551852Sbp{ 28674062Sbp struct ncp_rq *rqp; 28751852Sbp int error; 28851852Sbp struct ncp_conn *conn=NWFSTOCONN(nmp); 28951852Sbp 29083366Sjulian error = ncp_rq_alloc(87, conn, td, cred, &rqp); 29174062Sbp if (error) 29274062Sbp return error; 29374062Sbp mb_put_uint8(&rqp->rq, 8); /* subfunction */ 29474062Sbp mb_put_uint8(&rqp->rq, nmp->name_space); 29574062Sbp mb_put_uint8(&rqp->rq, 0); /* reserved */ 29674062Sbp mb_put_uint16le(&rqp->rq, SA_ALL); /* search attribs: all */ 29751852Sbp ncp_rq_dbase_path(rqp, nmp->n_volume, dirent, namelen, name, &nmp->m.nls); 29874062Sbp error = ncp_request(rqp); 29974062Sbp if (!error) 30074062Sbp ncp_rq_done(rqp); 30151852Sbp return error; 30251852Sbp} 30351852Sbp 30451852Sbpint 30551852Sbpncp_nsrename(struct ncp_conn *conn, int volume, int ns, int oldtype, 30651852Sbp struct ncp_nlstables *nt, 30751852Sbp nwdirent fdir, char *old_name, int oldlen, 30851852Sbp nwdirent tdir, char *new_name, int newlen, 30983366Sjulian struct thread *td, struct ucred *cred) 31051852Sbp{ 31174062Sbp struct ncp_rq *rqp; 31251852Sbp int error; 31351852Sbp 31483366Sjulian error = ncp_rq_alloc(87, conn, td, cred, &rqp); 31574062Sbp if (error) 31674062Sbp return error; 31774062Sbp mb_put_uint8(&rqp->rq, 4); 31874062Sbp mb_put_uint8(&rqp->rq, ns); 31974062Sbp mb_put_uint8(&rqp->rq, 1); /* RRenameToMySelf */ 32074062Sbp mb_put_uint16le(&rqp->rq, oldtype); 32151852Sbp /* source Handle Path */ 32274062Sbp mb_put_uint8(&rqp->rq, volume); 32374062Sbp mb_put_mem(&rqp->rq, (c_caddr_t)&fdir, sizeof(fdir), MB_MSYSTEM); 32474062Sbp mb_put_uint8(&rqp->rq, 1); 32574062Sbp mb_put_uint8(&rqp->rq, 1); /* 1 source component */ 32651852Sbp /* dest Handle Path */ 32774062Sbp mb_put_uint8(&rqp->rq, volume); 32874062Sbp mb_put_mem(&rqp->rq, (c_caddr_t)&tdir, sizeof(tdir), MB_MSYSTEM); 32974062Sbp mb_put_uint8(&rqp->rq, 1); 33074062Sbp mb_put_uint8(&rqp->rq, 1); /* 1 destination component */ 33151852Sbp ncp_rq_pathstring(rqp, oldlen, old_name, nt); 33251852Sbp ncp_rq_pathstring(rqp, newlen, new_name, nt); 33374062Sbp error = ncp_request(rqp); 33474062Sbp if (!error) 33574062Sbp ncp_rq_done(rqp); 33651852Sbp return error; 33751852Sbp} 33851852Sbp 33951852Sbpint 34051852Sbpncp_modify_file_or_subdir_dos_info(struct nwmount *nmp, struct vnode *vp, 34151852Sbp u_int32_t info_mask, 34251852Sbp struct nw_modify_dos_info *info, 34383366Sjulian struct thread *td,struct ucred *cred) 34451852Sbp{ 34551852Sbp struct nwnode *np=VTONW(vp); 34674062Sbp struct ncp_rq *rqp; 34751852Sbp u_int8_t volnum = nmp->n_volume; 34851852Sbp u_int32_t dirent = np->n_fid.f_id; 34951852Sbp struct ncp_conn *conn=NWFSTOCONN(nmp); 35051852Sbp int error; 35151852Sbp 35283366Sjulian error = ncp_rq_alloc(87, conn, td, cred, &rqp); 35374062Sbp if (error) 35474062Sbp return error; 35574062Sbp mb_put_uint8(&rqp->rq, 7); /* subfunction */ 35674062Sbp mb_put_uint8(&rqp->rq, nmp->name_space); 35774062Sbp mb_put_uint8(&rqp->rq, 0); /* reserved */ 35874062Sbp mb_put_uint16le(&rqp->rq, SA_ALL); /* search attribs: all */ 35974062Sbp mb_put_uint32le(&rqp->rq, info_mask); 36074062Sbp mb_put_mem(&rqp->rq, (caddr_t)info, sizeof(*info), MB_MSYSTEM); 36151852Sbp ncp_rq_dbase_path(rqp, volnum, dirent, 0, NULL, NULL); 36274062Sbp error = ncp_request(rqp); 36374062Sbp if (!error) 36474062Sbp ncp_rq_done(rqp); 36551852Sbp return error; 36651852Sbp} 36751852Sbp 36851852Sbpint 36983366Sjulianncp_setattr(vp, vap, cred, td) 37066539Sbp struct vnode *vp; 37166539Sbp struct vattr *vap; 37251852Sbp struct ucred *cred; 37383366Sjulian struct thread *td; 37451852Sbp{ 37551852Sbp struct nwmount *nmp=VTONWFS(vp); 37651852Sbp struct nwnode *np=VTONW(vp); 37751852Sbp struct ncp_open_info nwn; 37851852Sbp struct ncp_conn *conn=NWFSTOCONN(nmp); 37951852Sbp struct nw_modify_dos_info info; 38074062Sbp struct ncp_rq *rqp; 38151852Sbp int error = 0, info_mask; 38251852Sbp 38351852Sbp if (vap->va_size != VNOVAL) { 38451852Sbp error = ncp_open_create_file_or_subdir(nmp, vp, 0, NULL, OC_MODE_OPEN, 0, 38583366Sjulian AR_WRITE | AR_READ, &nwn,td,cred); 38674062Sbp if (error) 38774062Sbp return error; 38883366Sjulian error = ncp_rq_alloc(73, conn, td, cred, &rqp); 38974062Sbp if (error) { 39083366Sjulian ncp_close_file(conn, &nwn.fh, td, cred); 39174062Sbp return error; 39274062Sbp } 39374062Sbp mb_put_uint8(&rqp->rq, 0); 39474062Sbp mb_put_mem(&rqp->rq, (caddr_t)&nwn.fh, 6, MB_MSYSTEM); 39574062Sbp mb_put_uint32be(&rqp->rq, vap->va_size); 39674062Sbp mb_put_uint16be(&rqp->rq, 0); 39774062Sbp error = ncp_request(rqp); 39851852Sbp np->n_vattr.va_size = np->n_size = vap->va_size; 39974062Sbp if (!error) 40074062Sbp ncp_rq_done(rqp); 40183366Sjulian ncp_close_file(conn, &nwn.fh, td, cred); 40274062Sbp if (error) 40374062Sbp return error; 40451852Sbp } 40551852Sbp info_mask = 0; 40651852Sbp bzero(&info, sizeof(info)); 40751852Sbp 40851852Sbp if (vap->va_mtime.tv_sec != VNOVAL) { 40951852Sbp info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE); 41059034Sbp ncp_unix2dostime(&vap->va_mtime, nmp->m.tz, &info.modifyDate, &info.modifyTime, NULL); 41151852Sbp } 41251852Sbp if (vap->va_atime.tv_sec != VNOVAL) { 41351852Sbp info_mask |= (DM_LAST_ACCESS_DATE); 41459034Sbp ncp_unix2dostime(&vap->va_atime, nmp->m.tz, &info.lastAccessDate, NULL, NULL); 41551852Sbp } 41651852Sbp if (info_mask) { 41783366Sjulian error = ncp_modify_file_or_subdir_dos_info(nmp, vp, info_mask, &info,td,cred); 41851852Sbp } 41951852Sbp return (error); 42051852Sbp} 42151852Sbp 42251852Sbpint 42351852Sbpncp_get_volume_info_with_number(struct ncp_conn *conn, 42474062Sbp int n, struct ncp_volume_info *target, 42583366Sjulian struct thread *td,struct ucred *cred) 42674062Sbp{ 42774062Sbp struct ncp_rq *rqp; 42874062Sbp u_int32_t tmp32; 42974062Sbp u_int8_t len; 43074062Sbp int error; 43151852Sbp 43283366Sjulian error = ncp_rq_alloc_subfn(22, 44, conn, td, cred, &rqp); 43374062Sbp if (error) 43474062Sbp return error; 43574062Sbp mb_put_uint8(&rqp->rq,n); 43674062Sbp error = ncp_request(rqp); 43774062Sbp if (error) 43874062Sbp return error; 43974062Sbp md_get_uint32le(&rqp->rp, &target->total_blocks); 44074062Sbp md_get_uint32le(&rqp->rp, &target->free_blocks); 44174062Sbp md_get_uint32le(&rqp->rp, &target->purgeable_blocks); 44274062Sbp md_get_uint32le(&rqp->rp, &target->not_yet_purgeable_blocks); 44374062Sbp md_get_uint32le(&rqp->rp, &target->total_dir_entries); 44474062Sbp md_get_uint32le(&rqp->rp, &target->available_dir_entries); 44574062Sbp md_get_uint32le(&rqp->rp, &tmp32); 44674062Sbp md_get_uint8(&rqp->rp, &target->sectors_per_block); 44751852Sbp bzero(&target->volume_name, sizeof(target->volume_name)); 44874062Sbp md_get_uint8(&rqp->rp, &len); 44951852Sbp if (len > NCP_VOLNAME_LEN) { 45051852Sbp error = ENAMETOOLONG; 45151852Sbp } else { 45274062Sbp md_get_mem(&rqp->rp, (caddr_t)&target->volume_name, len, MB_MSYSTEM); 45351852Sbp } 45474062Sbp ncp_rq_done(rqp); 45551852Sbp return error; 45651852Sbp} 45751852Sbp 45851852Sbpint 45951852Sbpncp_get_namespaces(struct ncp_conn *conn, u_int32_t volume, int *nsf, 46083366Sjulian struct thread *td,struct ucred *cred) 46174062Sbp{ 46274062Sbp struct ncp_rq *rqp; 46351852Sbp int error; 46451852Sbp u_int8_t ns; 46551852Sbp u_int16_t nscnt; 46651852Sbp 46783366Sjulian error = ncp_rq_alloc(87, conn, td, cred, &rqp); 46874062Sbp if (error) 46974062Sbp return error; 47074062Sbp mb_put_uint8(&rqp->rq, 24); /* Subfunction: Get Loaded Name Spaces */ 47174062Sbp mb_put_uint16le(&rqp->rq, 0); /* reserved */ 47274062Sbp mb_put_uint8(&rqp->rq, volume); 47374062Sbp error = ncp_request(rqp); 47474062Sbp if (error) 47574062Sbp return error; 47674062Sbp md_get_uint16le(&rqp->rp, &nscnt); 47751852Sbp *nsf = 0; 47851852Sbp while (nscnt-- > 0) { 47974062Sbp md_get_uint8(&rqp->rp, &ns); 48051852Sbp *nsf |= 1 << ns; 48151852Sbp } 48274062Sbp ncp_rq_done(rqp); 48351852Sbp return error; 48451852Sbp} 48551852Sbp 48651852Sbpint 48751852Sbpncp_lookup_volume(struct ncp_conn *conn, char *volname, 48851852Sbp u_char *volNum, u_int32_t *dirEnt, 48983366Sjulian struct thread *td,struct ucred *cred) 49051852Sbp{ 49174062Sbp struct ncp_rq *rqp; 49274062Sbp u_int32_t tmp32; 49351852Sbp int error; 49451852Sbp 49551852Sbp NCPNDEBUG("looking up vol %s\n", volname); 49683366Sjulian error = ncp_rq_alloc(87, conn, td, cred, &rqp); 49774062Sbp if (error) 49874062Sbp return error; 49974062Sbp mb_put_uint8(&rqp->rq, 22); /* Subfunction: Generate dir handle */ 50074062Sbp mb_put_uint8(&rqp->rq, 0); /* src name space */ 50174062Sbp mb_put_uint8(&rqp->rq, 0); /* dst name space, always zero */ 50274062Sbp mb_put_uint16le(&rqp->rq, 0); /* dstNSIndicator (Jn) */ 50351852Sbp 50474062Sbp mb_put_uint8(&rqp->rq, 0); /* faked volume number */ 50574062Sbp mb_put_uint32be(&rqp->rq, 0); /* faked dir_base */ 50674062Sbp mb_put_uint8(&rqp->rq, 0xff); /* Don't have a dir_base */ 50774062Sbp mb_put_uint8(&rqp->rq, 1); /* 1 path component */ 50851852Sbp ncp_rq_pstring(rqp, volname); 50974062Sbp error = ncp_request(rqp); 51074062Sbp if (error) 51174062Sbp return error; 51274062Sbp md_get_uint32le(&rqp->rp, &tmp32); 51374062Sbp md_get_uint32le(&rqp->rp, dirEnt); 51474062Sbp md_get_uint8(&rqp->rp, volNum); 51574062Sbp ncp_rq_done(rqp); 51651852Sbp return error; 51751852Sbp} 51851852Sbp 51951852Sbp/* 520163651Sphk * XXX: I think the timezone in struct nwfs_args is truly bogus, especially 521163651Sphk * XXX: considering that nwfs_mount(8) picks this up from the kernel in 522163651Sphk * XXX: the first place. Since I can't test this, I won't attempt to fix it. 523163651Sphk * XXX: /phk 52451852Sbp */ 52551852Sbp 52651852Sbpvoid 52759034Sbpncp_unix2dostime(tsp, tzoff, ddp, dtp, dhp) 52851852Sbp struct timespec *tsp; 52959034Sbp int tzoff; 53051852Sbp u_int16_t *ddp; 53151852Sbp u_int16_t *dtp; 53251852Sbp u_int8_t *dhp; 53351852Sbp{ 534163651Sphk struct timespec t; 53551852Sbp 536163651Sphk t = *tsp; 537163651Sphk 538163651Sphk t.tv_sec = - tzoff * 60 - utc_offset(); 539163651Sphk timespec2fattime(&t, 1, ddp, dtp, dhp); 54051852Sbp} 54151852Sbp 54251852Sbpvoid 54359034Sbpncp_dos2unixtime(dd, dt, dh, tzoff, tsp) 54451852Sbp u_int dd; 54551852Sbp u_int dt; 54651852Sbp u_int dh; 54759034Sbp int tzoff; 54851852Sbp struct timespec *tsp; 54951852Sbp{ 55051852Sbp 551163651Sphk fattime2timespec(dd, dt, dh, 1, tsp); 552163651Sphk tsp->tv_sec += tzoff * 60 + utc_offset(); 55351852Sbp} 554