/* * NT level. Specially for win9x */ int smbfs_smb_setpattrNT(struct smbnode *np, u_short attr, struct timespec *mtime, struct timespec *atime, struct smb_cred *scred) { struct smb_t2rq *t2p; struct smb_share *ssp = np->n_mount->sm_share; struct smb_vc *vcp = SSTOVC(ssp); struct mbchain *mbp; int64_t tm; int error, tzoff; /* * SMB_SET_FILE_BASIC_INFO isn't supported for * SMB_TRANS2_SET_PATH_INFORMATION, * so use SMB_SET_FILE_BASIC_INFORMATION instead, * but it requires SMB_CAP_INFOLEVEL_PASSTHRU capability. */ if ((SMB_CAPS(vcp) & SMB_CAP_INFOLEVEL_PASSTHRU) == 0) return smbfs_smb_setptime2(np, mtime, atime, attr, scred); error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_PATH_INFORMATION, scred, &t2p); if (error) return error; mbp = &t2p->t2_tparam; mb_init(mbp); mb_put_uint16le(mbp, SMB_SET_FILE_BASIC_INFORMATION); mb_put_uint32le(mbp, 0); /* MBZ */ error = smbfs_fullpath(mbp, vcp, np, NULL, 0); if (error) { smb_t2_done(t2p); return error; } tzoff = vcp->vc_sopt.sv_tz; mbp = &t2p->t2_tdata; mb_init(mbp); mb_put_int64le(mbp, 0); /* creation time */ if (atime) { smb_time_local2NT(atime, tzoff, &tm); } else tm = 0; mb_put_int64le(mbp, tm); if (mtime) { smb_time_local2NT(mtime, tzoff, &tm); } else tm = 0; mb_put_int64le(mbp, tm); mb_put_int64le(mbp, tm); /* change time */ mb_put_uint32le(mbp, attr); /* attr */ mb_put_uint32le(mbp, 0); /* padding */ t2p->t2_maxpcount = 2; t2p->t2_maxdcount = 0; error = smb_t2_request(t2p); smb_t2_done(t2p); return error; }
/* * Note, win95 doesn't support this call. */ int smbfs_smb_setptime2(struct smbnode *np, struct timespec *mtime, struct timespec *atime, int attr, struct smb_cred *scred) { struct smb_t2rq *t2p; struct smb_share *ssp = np->n_mount->sm_share; struct smb_vc *vcp = SSTOVC(ssp); struct mbchain *mbp; u_int16_t date, time; int error, tzoff; error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_PATH_INFORMATION, scred, &t2p); if (error) return error; mbp = &t2p->t2_tparam; mb_init(mbp); mb_put_uint16le(mbp, SMB_INFO_STANDARD); mb_put_uint32le(mbp, 0); /* MBZ */ /* mb_put_uint8(mbp, SMB_DT_ASCII); specs incorrect */ error = smbfs_fullpath(mbp, vcp, np, NULL, 0); if (error) { smb_t2_done(t2p); return error; } tzoff = vcp->vc_sopt.sv_tz; mbp = &t2p->t2_tdata; mb_init(mbp); mb_put_uint32le(mbp, 0); /* creation time */ if (atime) smb_time_unix2dos(atime, tzoff, &date, &time, NULL); else time = date = 0; mb_put_uint16le(mbp, date); mb_put_uint16le(mbp, time); if (mtime) smb_time_unix2dos(mtime, tzoff, &date, &time, NULL); else time = date = 0; mb_put_uint16le(mbp, date); mb_put_uint16le(mbp, time); mb_put_uint32le(mbp, 0); /* file size */ mb_put_uint32le(mbp, 0); /* allocation unit size */ mb_put_uint16le(mbp, attr); /* DOS attr */ mb_put_uint32le(mbp, 0); /* EA size */ t2p->t2_maxpcount = 5 * 2; t2p->t2_maxdcount = vcp->vc_txmax; error = smb_t2_request(t2p); smb_t2_done(t2p); return error; }
static int smbfs_smb_seteof(struct smbnode *np, int64_t newsize, struct smb_cred *scred) { struct smb_t2rq *t2p; struct smb_share *ssp = np->n_mount->sm_share; struct mbchain *mbp; int error; error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_FILE_INFORMATION, scred, &t2p); if (error) return error; mbp = &t2p->t2_tparam; mb_init(mbp); mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM); mb_put_uint16le(mbp, SMB_SET_FILE_END_OF_FILE_INFO); mb_put_uint32le(mbp, 0); mbp = &t2p->t2_tdata; mb_init(mbp); mb_put_int64le(mbp, newsize); mb_put_uint32le(mbp, 0); /* padding */ mb_put_uint16le(mbp, 0); t2p->t2_maxpcount = 2; t2p->t2_maxdcount = 0; error = smb_t2_request(t2p); smb_t2_done(t2p); return error; }
/* * NT level. Specially for win9x */ int smbfs_smb_setpattrNT(struct smbnode *np, u_short attr, struct timespec *mtime, struct timespec *atime, struct smb_cred *scred) { struct smb_t2rq *t2p; struct smb_share *ssp = np->n_mount->sm_share; struct smb_vc *vcp = SSTOVC(ssp); struct mbchain *mbp; int64_t tm; int error, tzoff; error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_PATH_INFORMATION, scred, &t2p); if (error) return error; mbp = &t2p->t2_tparam; mb_init(mbp); mb_put_uint16le(mbp, SMB_SET_FILE_BASIC_INFO); mb_put_uint32le(mbp, 0); /* MBZ */ /* mb_put_uint8(mbp, SMB_DT_ASCII); specs incorrect */ error = smbfs_fullpath(mbp, vcp, np, NULL, 0); if (error) { smb_t2_done(t2p); return error; } tzoff = vcp->vc_sopt.sv_tz; mbp = &t2p->t2_tdata; mb_init(mbp); mb_put_int64le(mbp, 0); /* creation time */ if (atime) { smb_time_local2NT(atime, tzoff, &tm); } else tm = 0; mb_put_int64le(mbp, tm); if (mtime) { smb_time_local2NT(mtime, tzoff, &tm); } else tm = 0; mb_put_int64le(mbp, tm); mb_put_int64le(mbp, tm); /* change time */ mb_put_uint32le(mbp, attr); /* attr */ t2p->t2_maxpcount = 24; t2p->t2_maxdcount = 56; error = smb_t2_request(t2p); smb_t2_done(t2p); return error; }
static int smbfs_findcloseLM2(struct smbfs_fctx *ctx) { if (ctx->f_name) free(ctx->f_name, M_SMBFSDATA); if (ctx->f_t2) smb_t2_done(ctx->f_t2); if ((ctx->f_flags & SMBFS_RDD_NOCLOSE) == 0) smbfs_smb_findclose2(ctx); return 0; }
int smbfs_smb_statfs2(struct smb_share *ssp, struct statfs *sbp, struct smb_cred *scred) { struct smb_t2rq *t2p; struct mbchain *mbp; struct mdchain *mdp; u_int16_t bsize; u_int32_t units, bpu, funits; int error; error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_QUERY_FS_INFORMATION, scred, &t2p); if (error) return error; mbp = &t2p->t2_tparam; mb_init(mbp); mb_put_uint16le(mbp, SMB_INFO_ALLOCATION); t2p->t2_maxpcount = 4; t2p->t2_maxdcount = 4 * 4 + 2; error = smb_t2_request(t2p); if (error) { smb_t2_done(t2p); return error; } mdp = &t2p->t2_rdata; md_get_uint32(mdp, NULL); /* fs id */ md_get_uint32le(mdp, &bpu); md_get_uint32le(mdp, &units); md_get_uint32le(mdp, &funits); md_get_uint16le(mdp, &bsize); sbp->f_bsize = bpu * bsize; /* fundamental filesystem block size */ sbp->f_blocks= units; /* total data blocks in filesystem */ sbp->f_bfree = funits; /* free blocks in fs */ sbp->f_bavail= funits; /* free blocks avail to non-superuser */ sbp->f_files = 0xffff; /* total file nodes in filesystem */ sbp->f_ffree = 0xffff; /* free file nodes in fs */ smb_t2_done(t2p); return 0; }
static int smbfs_query_info_fs(struct smb_share *ssp, struct statfs *sbp, struct smb_cred *scred) { struct smb_t2rq *t2p; struct mbchain *mbp; struct mdchain *mdp; uint32_t bsize, bpu; int64_t units, funits; int error; error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_QUERY_FS_INFORMATION, scred, &t2p); if (error) return (error); mbp = &t2p->t2_tparam; mb_init(mbp); mb_put_uint16le(mbp, SMB_QUERY_FS_SIZE_INFO); t2p->t2_maxpcount = 2; t2p->t2_maxdcount = sizeof(int64_t) * 2 + sizeof(uint32_t) * 2; error = smb_t2_request(t2p); if (error) { smb_t2_done(t2p); return (error); } mdp = &t2p->t2_rdata; md_get_int64le(mdp, &units); md_get_int64le(mdp, &funits); md_get_uint32le(mdp, &bpu); md_get_uint32le(mdp, &bsize); sbp->f_bsize = bpu * bsize; /* fundamental filesystem block size */ sbp->f_blocks= (uint64_t)units; /* total data blocks in filesystem */ sbp->f_bfree = (uint64_t)funits;/* free blocks in fs */ sbp->f_bavail= (uint64_t)funits;/* free blocks avail to non-superuser */ sbp->f_files = 0xffff; /* total file nodes in filesystem */ sbp->f_ffree = 0xffff; /* free file nodes in fs */ smb_t2_done(t2p); return (0); }
/* * TRANS2 request implementation */ int smb_t2_alloc(struct smb_connobj *layer, u_short setup, struct smb_cred *scred, struct smb_t2rq **t2pp) { struct smb_t2rq *t2p; int error; t2p = kmalloc(sizeof(*t2p), M_SMBRQ, M_WAITOK); error = smb_t2_init(t2p, layer, setup, scred); t2p->t2_flags |= SMBT2_ALLOCED; if (error) { smb_t2_done(t2p); return error; } *t2pp = t2p; return 0; }
/* * Set DOS file attributes. * Looks like this call can be used only if SMB_CAP_NT_SMBS bit is on. */ int smbfs_smb_setfattrNT(struct smbnode *np, u_int16_t attr, struct timespec *mtime, struct timespec *atime, struct smb_cred *scred) { struct smb_t2rq *t2p; struct smb_share *ssp = np->n_mount->sm_share; struct mbchain *mbp; int64_t tm; int error, svtz; error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_FILE_INFORMATION, scred, &t2p); if (error) return error; svtz = SSTOVC(ssp)->vc_sopt.sv_tz; mbp = &t2p->t2_tparam; mb_init(mbp); mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM); mb_put_uint16le(mbp, SMB_SET_FILE_BASIC_INFO); mb_put_uint32le(mbp, 0); mbp = &t2p->t2_tdata; mb_init(mbp); mb_put_int64le(mbp, 0); /* creation time */ if (atime) { smb_time_local2NT(atime, svtz, &tm); } else tm = 0; mb_put_int64le(mbp, tm); if (mtime) { smb_time_local2NT(mtime, svtz, &tm); } else tm = 0; mb_put_int64le(mbp, tm); mb_put_int64le(mbp, tm); /* change time */ mb_put_uint16le(mbp, attr); mb_put_uint32le(mbp, 0); /* padding */ mb_put_uint16le(mbp, 0); t2p->t2_maxpcount = 2; t2p->t2_maxdcount = 0; error = smb_t2_request(t2p); smb_t2_done(t2p); return error; }
/* * TRANS2 request implementation * TRANS implementation is in the "t2" routines * NT_TRANSACTION implementation is the separate "nt" stuff */ int smb_t2_alloc(struct smb_connobj *layer, ushort_t setup, struct smb_cred *scred, struct smb_t2rq **t2pp) { struct smb_t2rq *t2p; int error; t2p = (struct smb_t2rq *)kmem_alloc(sizeof (*t2p), KM_SLEEP); if (t2p == NULL) return (ENOMEM); error = smb_t2_init(t2p, layer, &setup, 1, scred); t2p->t2_flags |= SMBT2_ALLOCED; if (error) { smb_t2_done(t2p); return (error); } *t2pp = t2p; return (0); }
/* * TRANS2_FIND_FIRST2/NEXT2, used for NT LM12 dialect */ static int smbfs_smb_trans2find2(struct smbfs_fctx *ctx) { struct smb_t2rq *t2p; struct smb_vc *vcp = SSTOVC(ctx->f_ssp); struct mbchain *mbp; struct mdchain *mdp; u_int16_t tw, flags; int error; if (ctx->f_t2) { smb_t2_done(ctx->f_t2); ctx->f_t2 = NULL; } ctx->f_flags &= ~SMBFS_RDD_GOTRNAME; flags = 8 | 2; /* <resume> | <close if EOS> */ if (ctx->f_flags & SMBFS_RDD_FINDSINGLE) { flags |= 1; /* close search after this request */ ctx->f_flags |= SMBFS_RDD_NOCLOSE; } if (ctx->f_flags & SMBFS_RDD_FINDFIRST) { error = smb_t2_alloc(SSTOCP(ctx->f_ssp), SMB_TRANS2_FIND_FIRST2, ctx->f_scred, &t2p); if (error) return error; ctx->f_t2 = t2p; mbp = &t2p->t2_tparam; mb_init(mbp); mb_put_uint16le(mbp, ctx->f_attrmask); mb_put_uint16le(mbp, ctx->f_limit); mb_put_uint16le(mbp, flags); mb_put_uint16le(mbp, ctx->f_infolevel); mb_put_uint32le(mbp, 0); error = smbfs_fullpath(mbp, vcp, ctx->f_dnp, ctx->f_wildcard, ctx->f_wclen); if (error) return error; } else { error = smb_t2_alloc(SSTOCP(ctx->f_ssp), SMB_TRANS2_FIND_NEXT2, ctx->f_scred, &t2p); if (error) return error; ctx->f_t2 = t2p; mbp = &t2p->t2_tparam; mb_init(mbp); mb_put_mem(mbp, (caddr_t)&ctx->f_Sid, 2, MB_MSYSTEM); mb_put_uint16le(mbp, ctx->f_limit); mb_put_uint16le(mbp, ctx->f_infolevel); mb_put_uint32le(mbp, 0); /* resume key */ mb_put_uint16le(mbp, flags); if (ctx->f_rname) mb_put_mem(mbp, ctx->f_rname, ctx->f_rnamelen + 1, MB_MSYSTEM); else mb_put_uint8(mbp, 0); /* resume file name */ #if 0 struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 200 * 1000; /* 200ms */ if (vcp->vc_flags & SMBC_WIN95) { /* * some implementations suggests to sleep here * for 200ms, due to the bug in the Win95. * I've didn't notice any problem, but put code * for it. */ pause("fix95", tvtohz(&tv)); } #endif } t2p->t2_maxpcount = 5 * 2; t2p->t2_maxdcount = vcp->vc_txmax; error = smb_t2_request(t2p); if (error) return error; mdp = &t2p->t2_rparam; if (ctx->f_flags & SMBFS_RDD_FINDFIRST) { if ((error = md_get_uint16(mdp, &ctx->f_Sid)) != 0) return error; ctx->f_flags &= ~SMBFS_RDD_FINDFIRST; } if ((error = md_get_uint16le(mdp, &tw)) != 0) return error; ctx->f_ecnt = tw; if ((error = md_get_uint16le(mdp, &tw)) != 0) return error; if (tw) ctx->f_flags |= SMBFS_RDD_EOF | SMBFS_RDD_NOCLOSE; if ((error = md_get_uint16le(mdp, &tw)) != 0) return error; if ((error = md_get_uint16le(mdp, &tw)) != 0) return error; if (ctx->f_ecnt == 0) { ctx->f_flags |= SMBFS_RDD_EOF | SMBFS_RDD_NOCLOSE; return ENOENT; } ctx->f_rnameofs = tw; mdp = &t2p->t2_rdata; if (mdp->md_top == NULL) { printf("bug: ecnt = %d, but data is NULL (please report)\n", ctx->f_ecnt); return ENOENT; } if (mdp->md_top->m_len == 0) { printf("bug: ecnt = %d, but m_len = 0 and m_next = %p (please report)\n", ctx->f_ecnt,mbp->mb_top->m_next); return ENOENT; } ctx->f_eofs = 0; return 0; }
int smb_usr_t2request(struct smb_share *ssp, struct smbioc_t2rq *dp, struct smb_cred *scred) { struct smb_t2rq t2, *t2p = &t2; struct mdchain *mdp; int error, len; if (dp->ioc_setupcnt > 3) return EINVAL; error = smb_t2_init(t2p, SSTOCP(ssp), dp->ioc_setup[0], scred); if (error) return error; len = t2p->t2_setupcount = dp->ioc_setupcnt; if (len > 1) t2p->t2_setupdata = dp->ioc_setup; if (dp->ioc_name) { t2p->t_name = smb_strdupin(dp->ioc_name, 128); if (t2p->t_name == NULL) { error = ENOMEM; goto bad; } } t2p->t2_maxscount = 0; t2p->t2_maxpcount = dp->ioc_rparamcnt; t2p->t2_maxdcount = dp->ioc_rdatacnt; error = smb_cpdatain(&t2p->t2_tparam, dp->ioc_tparamcnt, dp->ioc_tparam); if (error) goto bad; error = smb_cpdatain(&t2p->t2_tdata, dp->ioc_tdatacnt, dp->ioc_tdata); if (error) goto bad; error = smb_t2_request(t2p); if (error) goto bad; mdp = &t2p->t2_rparam; if (mdp->md_top) { len = m_fixhdr(mdp->md_top); if (len > dp->ioc_rparamcnt) { error = EMSGSIZE; goto bad; } dp->ioc_rparamcnt = len; error = md_get_mem(mdp, dp->ioc_rparam, len, MB_MUSER); if (error) goto bad; } else dp->ioc_rparamcnt = 0; mdp = &t2p->t2_rdata; if (mdp->md_top) { len = m_fixhdr(mdp->md_top); if (len > dp->ioc_rdatacnt) { error = EMSGSIZE; goto bad; } dp->ioc_rdatacnt = len; error = md_get_mem(mdp, dp->ioc_rdata, len, MB_MUSER); } else dp->ioc_rdatacnt = 0; bad: if (t2p->t_name) smb_strfree(t2p->t_name); smb_t2_done(t2p); return error; }
static int smbfs_smb_qpathinfo(struct smbnode *np, struct smbfattr *fap, struct smb_cred *scred, short infolevel) { struct smb_share *ssp = np->n_mount->sm_share; struct smb_vc *vcp = SSTOVC(ssp); struct smb_t2rq *t2p; int error, svtz, timesok = 1; struct mbchain *mbp; struct mdchain *mdp; u_int16_t date, time, wattr; int64_t lint; u_int32_t size, dattr; error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_QUERY_PATH_INFORMATION, scred, &t2p); if (error) return error; mbp = &t2p->t2_tparam; mb_init(mbp); if (!infolevel) { if (SMB_DIALECT(vcp) < SMB_DIALECT_NTLM0_12) infolevel = SMB_QUERY_FILE_STANDARD; else infolevel = SMB_QUERY_FILE_BASIC_INFO; } mb_put_uint16le(mbp, infolevel); mb_put_uint32le(mbp, 0); /* mb_put_uint8(mbp, SMB_DT_ASCII); specs are wrong */ error = smbfs_fullpath(mbp, vcp, np, NULL, 0); if (error) { smb_t2_done(t2p); return error; } t2p->t2_maxpcount = 2; t2p->t2_maxdcount = vcp->vc_txmax; error = smb_t2_request(t2p); if (error) { smb_t2_done(t2p); if (infolevel == SMB_QUERY_FILE_STANDARD || error != EINVAL) return error; return smbfs_smb_qpathinfo(np, fap, scred, SMB_QUERY_FILE_STANDARD); } mdp = &t2p->t2_rdata; svtz = vcp->vc_sopt.sv_tz; switch (infolevel) { case SMB_QUERY_FILE_STANDARD: timesok = 0; md_get_uint16le(mdp, NULL); md_get_uint16le(mdp, NULL); /* creation time */ md_get_uint16le(mdp, &date); md_get_uint16le(mdp, &time); /* access time */ if (date || time) { timesok++; smb_dos2unixtime(date, time, 0, svtz, &fap->fa_atime); } md_get_uint16le(mdp, &date); md_get_uint16le(mdp, &time); /* modify time */ if (date || time) { timesok++; smb_dos2unixtime(date, time, 0, svtz, &fap->fa_mtime); } md_get_uint32le(mdp, &size); fap->fa_size = size; md_get_uint32(mdp, NULL); /* allocation size */ md_get_uint16le(mdp, &wattr); fap->fa_attr = wattr; break; case SMB_QUERY_FILE_BASIC_INFO: timesok = 0; md_get_int64(mdp, NULL); /* creation time */ md_get_int64le(mdp, &lint); if (lint) { timesok++; smb_time_NT2local(lint, svtz, &fap->fa_atime); } md_get_int64le(mdp, &lint); if (lint) { timesok++; smb_time_NT2local(lint, svtz, &fap->fa_mtime); } md_get_int64le(mdp, &lint); if (lint) { timesok++; smb_time_NT2local(lint, svtz, &fap->fa_ctime); } md_get_uint32le(mdp, &dattr); fap->fa_attr = dattr; md_get_uint32(mdp, NULL); /* XXX could use ALL_INFO to get size */ break; default: SMBERROR("unexpected info level %d\n", infolevel); error = EINVAL; } smb_t2_done(t2p); /* * if all times are zero (observed with FAT on NT4SP6) * then fall back to older info level */ if (!timesok) { if (infolevel != SMB_QUERY_FILE_STANDARD) return smbfs_smb_qpathinfo(np, fap, scred, SMB_QUERY_FILE_STANDARD); error = EINVAL; } return error; }
int smbfs_smb_statvfs(struct smb_share *ssp, struct statvfs *sbp, struct smb_cred *scred) { unsigned long bsize; /* Block (allocation unit) size */ unsigned long bavail, bfree; /* * The SMB request work with notion of sector size and * allocation units. Allocation unit is what 'block' * means in Unix context, sector size might be HW sector size. */ if (SMB_DIALECT(SSTOVC(ssp)) >= SMB_DIALECT_LANMAN2_0) { struct smb_t2rq *t2p; struct mbchain *mbp; struct mdchain *mdp; u_int16_t secsz; u_int32_t units, bpu, funits; int error; error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_QUERY_FS_INFORMATION, scred, &t2p); if (error) return error; mbp = &t2p->t2_tparam; mb_init(mbp); mb_put_uint16le(mbp, SMB_INFO_ALLOCATION); t2p->t2_maxpcount = 4; t2p->t2_maxdcount = 4 * 4 + 2; error = smb_t2_request(t2p); if (error) { smb_t2_done(t2p); return error; } mdp = &t2p->t2_rdata; md_get_uint32(mdp, NULL); /* fs id */ md_get_uint32le(mdp, &bpu); /* Number of sectors per unit */ md_get_uint32le(mdp, &units); /* Total number of units */ md_get_uint32le(mdp, &funits); /* Number of available units */ md_get_uint16le(mdp, &secsz); /* Number of bytes per sector */ smb_t2_done(t2p); bsize = bpu * secsz; bavail = units; bfree = funits; } else { struct smb_rq *rqp; struct mdchain *mdp; u_int16_t units, bpu, secsz, funits; int error; error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_QUERY_INFORMATION_DISK, scred, &rqp); if (error) return error; smb_rq_wstart(rqp); smb_rq_wend(rqp); smb_rq_bstart(rqp); smb_rq_bend(rqp); error = smb_rq_simple(rqp); if (error) { smb_rq_done(rqp); return error; } smb_rq_getreply(rqp, &mdp); md_get_uint16le(mdp, &units); /* Total units per server */ md_get_uint16le(mdp, &bpu); /* Blocks per allocation unit */ md_get_uint16le(mdp, &secsz); /* Block size (in bytes) */ md_get_uint16le(mdp, &funits); /* Number of free units */ smb_rq_done(rqp); bsize = bpu * secsz; bavail = units; bfree = funits; } sbp->f_bsize = bsize; /* fundamental file system block size */ sbp->f_frsize = bsize; /* fundamental file system frag size */ sbp->f_iosize = bsize; /* optimal I/O size */ sbp->f_blocks = bavail; /* total data blocks in file system */ sbp->f_bfree = bfree; /* free blocks in fs */ sbp->f_bresvd = 0; /* reserved blocks in fs */ sbp->f_bavail= bfree; /* free blocks avail to non-superuser */ sbp->f_files = 0xffff; /* total file nodes in file system */ sbp->f_ffree = 0xffff; /* free file nodes to non-superuser */ sbp->f_favail = 0xffff; /* free file nodes in fs */ sbp->f_fresvd = 0; /* reserved file nodes in fs */ return 0; }