The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/nwfs/nwfs_subr.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 1999, 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: src/sys/fs/nwfs/nwfs_subr.c,v 1.11.6.1 2005/01/31 23:25:57 imp Exp $
   33  */
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/kernel.h>
   37 #include <sys/lockmgr.h>
   38 #include <sys/malloc.h>
   39 #include <machine/clock.h>
   40 #include <sys/time.h>
   41 
   42 #include <netncp/ncp.h>
   43 #include <netncp/ncp_conn.h>
   44 #include <netncp/ncp_ncp.h>
   45 #include <netncp/ncp_subr.h>
   46 #include <netncp/ncp_rq.h>
   47 #include <netncp/nwerror.h>
   48 
   49 #include <fs/nwfs/nwfs.h>
   50 #include <fs/nwfs/nwfs_node.h>
   51 #include <fs/nwfs/nwfs_subr.h>
   52 
   53 #define NCP_INFOSZ      (sizeof(struct nw_entry_info) - 257)
   54 
   55 MALLOC_DEFINE(M_NWFSDATA, "NWFS data", "NWFS private data");
   56 
   57 static int
   58 ncp_extract_file_info(struct nwmount *nmp, struct ncp_rq *rqp,
   59         struct nw_entry_info *target, int withname)
   60 {
   61         u_int8_t name_len;
   62 
   63         md_get_mem(&rqp->rp, (caddr_t)target, NCP_INFOSZ, MB_MSYSTEM);
   64         if (!withname)
   65                 return 0;
   66         md_get_uint8(&rqp->rp, &name_len);
   67         target->nameLen = name_len;
   68         md_get_mem(&rqp->rp, (caddr_t)target->entryName, name_len, MB_MSYSTEM);
   69         target->entryName[name_len] = '\0';
   70         ncp_path2unix(target->entryName, target->entryName, name_len, &nmp->m.nls);
   71         return 0;
   72 }
   73 
   74 int
   75 ncp_initsearch(struct vnode *dvp, struct thread *td, struct ucred *cred)
   76 {
   77         struct nwmount *nmp = VTONWFS(dvp);
   78         struct ncp_conn *conn = NWFSTOCONN(nmp);
   79         struct nwnode *np = VTONW(dvp);
   80         struct ncp_rq *rqp;
   81         u_int8_t volnum = nmp->n_volume;
   82         u_int32_t dirent = np->n_fid.f_id;
   83         int error;
   84 
   85         NCPNDEBUG("vol=%d,dir=%d\n", volnum, dirent);
   86         error = ncp_rq_alloc(87, conn, td, cred, &rqp);
   87         if (error)
   88                 return error;
   89         mb_put_uint8(&rqp->rq, 2);              /* subfunction */
   90         mb_put_uint8(&rqp->rq, nmp->name_space);
   91         mb_put_uint8(&rqp->rq, 0);              /* reserved */
   92         ncp_rq_dbase_path(rqp, volnum, dirent, 0, NULL, NULL);
   93         rqp->nr_minrplen = sizeof(np->n_seq);
   94         error = ncp_request(rqp);
   95         if (error)
   96                 return error;
   97         md_get_mem(&rqp->rp, (caddr_t)&np->n_seq, sizeof(np->n_seq), MB_MSYSTEM);
   98         ncp_rq_done(rqp);
   99         return 0;
  100 }
  101 
  102 int 
  103 ncp_search_for_file_or_subdir(struct nwmount *nmp,
  104                               struct nw_search_seq *seq,
  105                               struct nw_entry_info *target,
  106                               struct thread *td,struct ucred *cred)
  107 {
  108         struct ncp_conn *conn = NWFSTOCONN(nmp);
  109         struct ncp_rq *rqp;
  110         int error;
  111 
  112         error = ncp_rq_alloc(87, conn, td, cred, &rqp);
  113         if (error)
  114                 return error;
  115         mb_put_uint8(&rqp->rq, 3);              /* subfunction */
  116         mb_put_uint8(&rqp->rq, nmp->name_space);
  117         mb_put_uint8(&rqp->rq, 0);              /* data stream */
  118         mb_put_uint16le(&rqp->rq, 0xffff);      /* Search attribs */
  119         mb_put_uint32le(&rqp->rq, IM_ALL);      /* return info mask */
  120         mb_put_mem(&rqp->rq, (caddr_t)seq, 9, MB_MSYSTEM);
  121         mb_put_uint8(&rqp->rq, 2);              /* 2 byte pattern */
  122         mb_put_uint8(&rqp->rq, 0xff);           /* following is a wildcard */
  123         mb_put_uint8(&rqp->rq, '*');
  124         rqp->nr_minrplen = sizeof(*seq) +  1 + NCP_INFOSZ + 1;
  125         error = ncp_request(rqp);
  126         if (error)
  127                 return error;
  128         md_get_mem(&rqp->rp, (caddr_t)seq, sizeof(*seq), MB_MSYSTEM);
  129         md_get_uint8(&rqp->rp, NULL);           /* skip */
  130         error = ncp_extract_file_info(nmp, rqp, target, 1);
  131         ncp_rq_done(rqp);
  132         return error;
  133 }
  134 
  135 /*
  136  * Returns information for a (one-component) name relative to the specified
  137  * directory.
  138  */
  139 int 
  140 ncp_obtain_info(struct nwmount *nmp,  u_int32_t dirent,
  141                 int namelen, char *path, struct nw_entry_info *target,
  142                 struct thread *td,struct ucred *cred)
  143 {
  144         struct ncp_conn *conn=NWFSTOCONN(nmp);
  145         struct ncp_rq *rqp;
  146         int error;
  147         u_char volnum = nmp->n_volume, ns;
  148 
  149         if (target == NULL) {
  150                 NCPFATAL("target == NULL\n");
  151                 return EINVAL;
  152         }
  153         ns = (path == NULL || path[0] == 0) ? NW_NS_DOS : nmp->name_space;
  154         error = ncp_rq_alloc(87, conn, td, cred, &rqp);
  155         if (error)
  156                 return error;
  157         mb_put_uint8(&rqp->rq, 6);      /* subfunction */
  158         mb_put_uint8(&rqp->rq, ns);
  159         mb_put_uint8(&rqp->rq, ns);     /* DestNameSpace */
  160         mb_put_uint16le(&rqp->rq, 0xff);        /* get all */
  161         mb_put_uint32le(&rqp->rq, IM_ALL);
  162         ncp_rq_dbase_path(rqp, volnum, dirent, namelen, path, &nmp->m.nls);
  163         error = ncp_request(rqp);
  164         if (error)
  165                 return error;
  166         error = ncp_extract_file_info(nmp, rqp, target, path != NULL);
  167         ncp_rq_done(rqp);
  168         return error;
  169 }
  170 /* 
  171  * lookup name pointed by cnp in directory dvp and return file info in np.
  172  * May be I should create a little cache, but another way is to minimize
  173  * number of calls, on other hand, in multiprocess environment ...
  174  */
  175 int
  176 ncp_lookup(struct vnode *dvp, int len, char *name, struct nw_entry_info *fap,
  177                 struct thread *td,struct ucred *cred)
  178 {
  179         struct nwmount *nmp;
  180         struct nwnode *dnp = VTONW(dvp);
  181         struct ncp_conn *conn;
  182         int error;
  183 
  184         if (!dvp || dvp->v_type != VDIR) {
  185                 nwfs_printf("dvp is NULL or not a directory.\n");
  186                 return (ENOENT);
  187         }
  188         nmp = VTONWFS(dvp);
  189         conn = NWFSTOCONN(nmp);
  190 
  191         if (len == 1 && name[0] == '.') {
  192                 if (dnp->n_flag & NVOLUME) {
  193                         error = ncp_obtain_info(nmp, dnp->n_fid.f_id, 0, NULL,
  194                                 fap, td, cred);
  195                 } else {
  196                         error = ncp_obtain_info(nmp, dnp->n_fid.f_parent, 
  197                                 dnp->n_nmlen, dnp->n_name, fap, td, cred);
  198                 }
  199                 return error;
  200         } else if (len == 2 && name[0] == '.' && name[1] == '.') {
  201                 printf("%s: knows NOTHING about '..'\n", __func__);
  202                 return EIO;
  203         } else {
  204                 error = ncp_obtain_info(nmp, dnp->n_fid.f_id, 
  205                         len, name, fap, td, cred);
  206         }
  207         return error;
  208 }
  209 
  210 static void ConvertToNWfromDWORD(u_int32_t sfd, ncp_fh *fh);
  211 static void 
  212 ConvertToNWfromDWORD(u_int32_t sfd, ncp_fh *fh) {
  213         fh->val1 = (fh->val.val32 = sfd);
  214         return;
  215 }
  216 
  217 /*
  218  * If both dir and name are NULL, then in target there's already a looked-up
  219  * entry that wants to be opened.
  220  */
  221 int 
  222 ncp_open_create_file_or_subdir(struct nwmount *nmp,struct vnode *dvp,int namelen,
  223             char *name, int open_create_mode, u_int32_t create_attributes,
  224             int desired_acc_rights, struct ncp_open_info *nop,
  225             struct thread *td,struct ucred *cred)
  226 {
  227         
  228         struct ncp_conn *conn=NWFSTOCONN(nmp);
  229         struct ncp_rq *rqp;
  230         u_int16_t search_attribs = SA_ALL & (~SA_SUBDIR_FILES);
  231         u_int8_t volnum;
  232         u_int32_t dirent;
  233         int error;
  234 
  235         error = ncp_rq_alloc(87, conn, td, cred, &rqp);
  236         if (error)
  237                 return error;
  238         volnum = nmp->n_volume;
  239         dirent = VTONW(dvp)->n_fid.f_id;
  240         if ((create_attributes & aDIR) != 0) {
  241                 search_attribs |= SA_SUBDIR_FILES;
  242         }
  243         mb_put_uint8(&rqp->rq, 1);/* subfunction */
  244         mb_put_uint8(&rqp->rq, nmp->name_space);
  245         mb_put_uint8(&rqp->rq, open_create_mode);
  246         mb_put_uint16le(&rqp->rq, search_attribs);
  247         mb_put_uint32le(&rqp->rq, IM_ALL);
  248         mb_put_uint32le(&rqp->rq, create_attributes);
  249         /*
  250          * The desired acc rights seem to be the inherited rights mask for
  251          * directories
  252          */
  253         mb_put_uint16le(&rqp->rq, desired_acc_rights);
  254         ncp_rq_dbase_path(rqp, volnum, dirent, namelen, name, &nmp->m.nls);
  255         error = ncp_request(rqp);
  256         if (error) {
  257                 if (error == NWE_FILE_NO_CREATE_PRIV)
  258                         error = EACCES;
  259                 return error;
  260         }
  261         md_get_uint32le(&rqp->rp, &nop->origfh);
  262         md_get_uint8(&rqp->rp, &nop->action);
  263         md_get_uint8(&rqp->rp, NULL);   /* skip */
  264         error = ncp_extract_file_info(nmp, rqp, &nop->fattr, 1);
  265         ncp_rq_done(rqp);
  266         ConvertToNWfromDWORD(nop->origfh, &nop->fh);
  267         return error;
  268 }
  269 
  270 int
  271 ncp_close_file(struct ncp_conn *conn, ncp_fh *fh,struct thread *td,struct ucred *cred)
  272 {
  273         struct ncp_rq *rqp;
  274         int error;
  275 
  276         error = ncp_rq_alloc(66, conn, td, cred, &rqp);
  277         if (error)
  278                 return error;
  279         mb_put_uint8(&rqp->rq, 0);
  280         mb_put_mem(&rqp->rq, (caddr_t)fh, 6, MB_MSYSTEM);
  281         error = ncp_request(rqp);
  282         if (error)
  283                 return error;
  284         ncp_rq_done(rqp);
  285         return error;
  286 }
  287 
  288 int
  289 ncp_DeleteNSEntry(struct nwmount *nmp, u_int32_t dirent,
  290         int namelen,char *name,struct thread *td,struct ucred *cred)
  291 {
  292         struct ncp_rq *rqp;
  293         int error;
  294         struct ncp_conn *conn=NWFSTOCONN(nmp);
  295 
  296         error = ncp_rq_alloc(87, conn, td, cred, &rqp);
  297         if (error)
  298                 return error;
  299         mb_put_uint8(&rqp->rq, 8);              /* subfunction */
  300         mb_put_uint8(&rqp->rq, nmp->name_space);
  301         mb_put_uint8(&rqp->rq, 0);              /* reserved */
  302         mb_put_uint16le(&rqp->rq, SA_ALL);      /* search attribs: all */
  303         ncp_rq_dbase_path(rqp, nmp->n_volume, dirent, namelen, name, &nmp->m.nls);
  304         error = ncp_request(rqp);
  305         if (!error)
  306                 ncp_rq_done(rqp);
  307         return error;
  308 }
  309 
  310 int 
  311 ncp_nsrename(struct ncp_conn *conn, int volume, int ns, int oldtype, 
  312         struct ncp_nlstables *nt,
  313         nwdirent fdir, char *old_name, int oldlen,
  314         nwdirent tdir, char *new_name, int newlen,
  315         struct thread *td, struct ucred *cred)
  316 {
  317         struct ncp_rq *rqp;
  318         int error;
  319 
  320         error = ncp_rq_alloc(87, conn, td, cred, &rqp);
  321         if (error)
  322                 return error;
  323         mb_put_uint8(&rqp->rq, 4);
  324         mb_put_uint8(&rqp->rq, ns);
  325         mb_put_uint8(&rqp->rq, 1);      /* RRenameToMySelf */
  326         mb_put_uint16le(&rqp->rq, oldtype);
  327         /* source Handle Path */
  328         mb_put_uint8(&rqp->rq, volume);
  329         mb_put_mem(&rqp->rq, (c_caddr_t)&fdir, sizeof(fdir), MB_MSYSTEM);
  330         mb_put_uint8(&rqp->rq, 1);
  331         mb_put_uint8(&rqp->rq, 1);      /* 1 source component */
  332         /* dest Handle Path */
  333         mb_put_uint8(&rqp->rq, volume);
  334         mb_put_mem(&rqp->rq, (c_caddr_t)&tdir, sizeof(tdir), MB_MSYSTEM);
  335         mb_put_uint8(&rqp->rq, 1);
  336         mb_put_uint8(&rqp->rq, 1);      /* 1 destination component */
  337         ncp_rq_pathstring(rqp, oldlen, old_name, nt);
  338         ncp_rq_pathstring(rqp, newlen, new_name, nt);
  339         error = ncp_request(rqp);
  340         if (!error)
  341                 ncp_rq_done(rqp);
  342         return error;
  343 }
  344 
  345 int
  346 ncp_modify_file_or_subdir_dos_info(struct nwmount *nmp, struct vnode *vp, 
  347                                 u_int32_t info_mask,
  348                                 struct nw_modify_dos_info *info,
  349                                 struct thread *td,struct ucred *cred)
  350 {
  351         struct nwnode *np=VTONW(vp);
  352         struct ncp_rq *rqp;
  353         u_int8_t volnum = nmp->n_volume;
  354         u_int32_t dirent = np->n_fid.f_id;
  355         struct ncp_conn *conn=NWFSTOCONN(nmp);
  356         int             error;
  357 
  358         error = ncp_rq_alloc(87, conn, td, cred, &rqp);
  359         if (error)
  360                 return error;
  361         mb_put_uint8(&rqp->rq, 7);      /* subfunction */
  362         mb_put_uint8(&rqp->rq, nmp->name_space);
  363         mb_put_uint8(&rqp->rq, 0);      /* reserved */
  364         mb_put_uint16le(&rqp->rq, SA_ALL);      /* search attribs: all */
  365         mb_put_uint32le(&rqp->rq, info_mask);
  366         mb_put_mem(&rqp->rq, (caddr_t)info, sizeof(*info), MB_MSYSTEM);
  367         ncp_rq_dbase_path(rqp, volnum, dirent, 0, NULL, NULL);
  368         error = ncp_request(rqp);
  369         if (!error)
  370                 ncp_rq_done(rqp);
  371         return error;
  372 }
  373 
  374 int
  375 ncp_setattr(vp, vap, cred, td)
  376         struct vnode *vp;
  377         struct vattr *vap;
  378         struct ucred *cred;
  379         struct thread *td;
  380 {
  381         struct nwmount *nmp=VTONWFS(vp);
  382         struct nwnode *np=VTONW(vp);
  383         struct ncp_open_info nwn;
  384         struct ncp_conn *conn=NWFSTOCONN(nmp);
  385         struct nw_modify_dos_info info;
  386         struct ncp_rq *rqp;
  387         int error = 0, info_mask;
  388 
  389         if (vap->va_size != VNOVAL) {
  390                 error = ncp_open_create_file_or_subdir(nmp, vp, 0, NULL, OC_MODE_OPEN, 0,
  391                                                    AR_WRITE | AR_READ, &nwn,td,cred);
  392                 if (error)
  393                         return error;
  394                 error = ncp_rq_alloc(73, conn, td, cred, &rqp);
  395                 if (error) {
  396                         ncp_close_file(conn, &nwn.fh, td, cred);
  397                         return error;
  398                 }
  399                 mb_put_uint8(&rqp->rq, 0);
  400                 mb_put_mem(&rqp->rq, (caddr_t)&nwn.fh, 6, MB_MSYSTEM);
  401                 mb_put_uint32be(&rqp->rq, vap->va_size);
  402                 mb_put_uint16be(&rqp->rq, 0);
  403                 error = ncp_request(rqp);
  404                 np->n_vattr.va_size = np->n_size = vap->va_size;
  405                 if (!error)
  406                         ncp_rq_done(rqp);
  407                 ncp_close_file(conn, &nwn.fh, td, cred);
  408                 if (error)
  409                         return error;
  410         }
  411         info_mask = 0;
  412         bzero(&info, sizeof(info));
  413 
  414         if (vap->va_mtime.tv_sec != VNOVAL) {
  415                 info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE);
  416                 ncp_unix2dostime(&vap->va_mtime, nmp->m.tz, &info.modifyDate, &info.modifyTime, NULL);
  417         }
  418         if (vap->va_atime.tv_sec != VNOVAL) {
  419                 info_mask |= (DM_LAST_ACCESS_DATE);
  420                 ncp_unix2dostime(&vap->va_atime, nmp->m.tz, &info.lastAccessDate, NULL, NULL);
  421         }
  422         if (info_mask) {
  423                 error = ncp_modify_file_or_subdir_dos_info(nmp, vp, info_mask, &info,td,cred);
  424         }
  425         return (error);
  426 }
  427 
  428 int
  429 ncp_get_volume_info_with_number(struct ncp_conn *conn, 
  430         int n, struct ncp_volume_info *target,
  431         struct thread *td,struct ucred *cred)
  432 {
  433         struct ncp_rq *rqp;
  434         u_int32_t tmp32;
  435         u_int8_t len;
  436         int error;
  437 
  438         error = ncp_rq_alloc_subfn(22, 44, conn, td, cred, &rqp);
  439         if (error)
  440                 return error;
  441         mb_put_uint8(&rqp->rq,n);
  442         error = ncp_request(rqp);
  443         if (error)
  444                 return error;
  445         md_get_uint32le(&rqp->rp, &target->total_blocks);
  446         md_get_uint32le(&rqp->rp, &target->free_blocks);
  447         md_get_uint32le(&rqp->rp, &target->purgeable_blocks);
  448         md_get_uint32le(&rqp->rp, &target->not_yet_purgeable_blocks);
  449         md_get_uint32le(&rqp->rp, &target->total_dir_entries);
  450         md_get_uint32le(&rqp->rp, &target->available_dir_entries);
  451         md_get_uint32le(&rqp->rp, &tmp32);
  452         md_get_uint8(&rqp->rp, &target->sectors_per_block);
  453         bzero(&target->volume_name, sizeof(target->volume_name));
  454         md_get_uint8(&rqp->rp, &len);
  455         if (len > NCP_VOLNAME_LEN) {
  456                 error = ENAMETOOLONG;
  457         } else {
  458                 md_get_mem(&rqp->rp, (caddr_t)&target->volume_name, len, MB_MSYSTEM);
  459         }
  460         ncp_rq_done(rqp);
  461         return error;
  462 }
  463 
  464 int
  465 ncp_get_namespaces(struct ncp_conn *conn, u_int32_t volume, int *nsf,
  466         struct thread *td,struct ucred *cred)
  467 {
  468         struct ncp_rq *rqp;
  469         int error;
  470         u_int8_t ns;
  471         u_int16_t nscnt;
  472 
  473         error = ncp_rq_alloc(87, conn, td, cred, &rqp);
  474         if (error)
  475                 return error;
  476         mb_put_uint8(&rqp->rq, 24);     /* Subfunction: Get Loaded Name Spaces */
  477         mb_put_uint16le(&rqp->rq, 0);   /* reserved */
  478         mb_put_uint8(&rqp->rq, volume);
  479         error = ncp_request(rqp);
  480         if (error)
  481                 return error;
  482         md_get_uint16le(&rqp->rp, &nscnt);
  483         *nsf = 0;
  484         while (nscnt-- > 0) {
  485                 md_get_uint8(&rqp->rp, &ns);
  486                 *nsf |= 1 << ns;
  487         }
  488         ncp_rq_done(rqp);
  489         return error;
  490 }
  491 
  492 int
  493 ncp_lookup_volume(struct ncp_conn *conn, char *volname, 
  494                 u_char *volNum, u_int32_t *dirEnt,
  495                 struct thread *td,struct ucred *cred)
  496 {
  497         struct ncp_rq *rqp;
  498         u_int32_t tmp32;
  499         int error;
  500 
  501         NCPNDEBUG("looking up vol %s\n", volname);
  502         error = ncp_rq_alloc(87, conn, td, cred, &rqp);
  503         if (error)
  504                 return error;
  505         mb_put_uint8(&rqp->rq, 22);     /* Subfunction: Generate dir handle */
  506         mb_put_uint8(&rqp->rq, 0);      /* src name space */
  507         mb_put_uint8(&rqp->rq, 0);      /* dst name space, always zero */
  508         mb_put_uint16le(&rqp->rq, 0);   /* dstNSIndicator (Jn) */
  509 
  510         mb_put_uint8(&rqp->rq, 0);      /* faked volume number */
  511         mb_put_uint32be(&rqp->rq, 0);   /* faked dir_base */
  512         mb_put_uint8(&rqp->rq, 0xff);   /* Don't have a dir_base */
  513         mb_put_uint8(&rqp->rq, 1);      /* 1 path component */
  514         ncp_rq_pstring(rqp, volname);
  515         error = ncp_request(rqp);
  516         if (error)
  517                 return error;
  518         md_get_uint32le(&rqp->rp, &tmp32);
  519         md_get_uint32le(&rqp->rp, dirEnt);
  520         md_get_uint8(&rqp->rp, volNum);
  521         ncp_rq_done(rqp);
  522         return error;
  523 }
  524 
  525 /* 
  526  * Time & date conversion routines taken from msdosfs. Although leap
  527  * year calculation is bogus, it's sufficient before 2100 :)
  528  */
  529 /*
  530  * This is the format of the contents of the deTime field in the direntry
  531  * structure.
  532  * We don't use bitfields because we don't know how compilers for
  533  * arbitrary machines will lay them out.
  534  */
  535 #define DT_2SECONDS_MASK        0x1F    /* seconds divided by 2 */
  536 #define DT_2SECONDS_SHIFT       0
  537 #define DT_MINUTES_MASK         0x7E0   /* minutes */
  538 #define DT_MINUTES_SHIFT        5
  539 #define DT_HOURS_MASK           0xF800  /* hours */
  540 #define DT_HOURS_SHIFT          11
  541 
  542 /*
  543  * This is the format of the contents of the deDate field in the direntry
  544  * structure.
  545  */
  546 #define DD_DAY_MASK             0x1F    /* day of month */
  547 #define DD_DAY_SHIFT            0
  548 #define DD_MONTH_MASK           0x1E0   /* month */
  549 #define DD_MONTH_SHIFT          5
  550 #define DD_YEAR_MASK            0xFE00  /* year - 1980 */
  551 #define DD_YEAR_SHIFT           9
  552 /*
  553  * Total number of days that have passed for each month in a regular year.
  554  */
  555 static u_short regyear[] = {
  556         31, 59, 90, 120, 151, 181,
  557         212, 243, 273, 304, 334, 365
  558 };
  559 
  560 /*
  561  * Total number of days that have passed for each month in a leap year.
  562  */
  563 static u_short leapyear[] = {
  564         31, 60, 91, 121, 152, 182,
  565         213, 244, 274, 305, 335, 366
  566 };
  567 
  568 /*
  569  * Variables used to remember parts of the last time conversion.  Maybe we
  570  * can avoid a full conversion.
  571  */
  572 static u_long  lasttime;
  573 static u_long  lastday;
  574 static u_short lastddate;
  575 static u_short lastdtime;
  576 /*
  577  * Convert the unix version of time to dos's idea of time to be used in
  578  * file timestamps. The passed in unix time is assumed to be in GMT.
  579  */
  580 void
  581 ncp_unix2dostime(tsp, tzoff, ddp, dtp, dhp)
  582         struct timespec *tsp;
  583         int tzoff;
  584         u_int16_t *ddp;
  585         u_int16_t *dtp;
  586         u_int8_t *dhp;
  587 {
  588         u_long t;
  589         u_long days;
  590         u_long inc;
  591         u_long year;
  592         u_long month;
  593         u_short *months;
  594 
  595         /*
  596          * If the time from the last conversion is the same as now, then
  597          * skip the computations and use the saved result.
  598          */
  599         t = tsp->tv_sec - tzoff * 60 - tz_minuteswest * 60 -
  600             (wall_cmos_clock ? adjkerntz : 0);
  601         t &= ~1;
  602         if (lasttime != t) {
  603                 lasttime = t;
  604                 lastdtime = (((t / 2) % 30) << DT_2SECONDS_SHIFT)
  605                     + (((t / 60) % 60) << DT_MINUTES_SHIFT)
  606                     + (((t / 3600) % 24) << DT_HOURS_SHIFT);
  607 
  608                 /*
  609                  * If the number of days since 1970 is the same as the last
  610                  * time we did the computation then skip all this leap year
  611                  * and month stuff.
  612                  */
  613                 days = t / (24 * 60 * 60);
  614                 if (days != lastday) {
  615                         lastday = days;
  616                         for (year = 1970;; year++) {
  617                                 inc = year & 0x03 ? 365 : 366;
  618                                 if (days < inc)
  619                                         break;
  620                                 days -= inc;
  621                         }
  622                         months = year & 0x03 ? regyear : leapyear;
  623                         for (month = 0; days >= months[month]; month++)
  624                                 ;
  625                         if (month > 0)
  626                                 days -= months[month - 1];
  627                         lastddate = ((days + 1) << DD_DAY_SHIFT)
  628                             + ((month + 1) << DD_MONTH_SHIFT);
  629                         /*
  630                          * Remember dos's idea of time is relative to 1980.
  631                          * unix's is relative to 1970.  If somehow we get a
  632                          * time before 1980 then don't give totally crazy
  633                          * results.
  634                          */
  635                         if (year > 1980)
  636                                 lastddate += (year - 1980) << DD_YEAR_SHIFT;
  637                 }
  638         }
  639         if (dtp)
  640                 *dtp = lastdtime;
  641         if (dhp)
  642                 *dhp = (tsp->tv_sec & 1) * 100 + tsp->tv_nsec / 10000000;
  643 
  644         *ddp = lastddate;
  645 }
  646 
  647 /*
  648  * The number of seconds between Jan 1, 1970 and Jan 1, 1980. In that
  649  * interval there were 8 regular years and 2 leap years.
  650  */
  651 #define SECONDSTO1980   (((8 * 365) + (2 * 366)) * (24 * 60 * 60))
  652 
  653 static u_short lastdosdate;
  654 static u_long  lastseconds;
  655 
  656 /*
  657  * Convert from dos' idea of time to unix'. This will probably only be
  658  * called from the stat(), and fstat() system calls and so probably need
  659  * not be too efficient.
  660  */
  661 void
  662 ncp_dos2unixtime(dd, dt, dh, tzoff, tsp)
  663         u_int dd;
  664         u_int dt;
  665         u_int dh;
  666         int tzoff;
  667         struct timespec *tsp;
  668 {
  669         u_long seconds;
  670         u_long month;
  671         u_long year;
  672         u_long days;
  673         u_short *months;
  674 
  675         if (dd == 0) {
  676                 /*
  677                  * Uninitialized field, return the epoch.
  678                  */
  679                 tsp->tv_sec = 0;
  680                 tsp->tv_nsec = 0;
  681                 return;
  682         }
  683         seconds = (((dt & DT_2SECONDS_MASK) >> DT_2SECONDS_SHIFT) << 1)
  684             + ((dt & DT_MINUTES_MASK) >> DT_MINUTES_SHIFT) * 60
  685             + ((dt & DT_HOURS_MASK) >> DT_HOURS_SHIFT) * 3600
  686             + dh / 100;
  687         /*
  688          * If the year, month, and day from the last conversion are the
  689          * same then use the saved value.
  690          */
  691         if (lastdosdate != dd) {
  692                 lastdosdate = dd;
  693                 days = 0;
  694                 year = (dd & DD_YEAR_MASK) >> DD_YEAR_SHIFT;
  695                 days = year * 365;
  696                 days += year / 4 + 1;   /* add in leap days */
  697                 if ((year & 0x03) == 0)
  698                         days--;         /* if year is a leap year */
  699                 months = year & 0x03 ? regyear : leapyear;
  700                 month = (dd & DD_MONTH_MASK) >> DD_MONTH_SHIFT;
  701                 if (month < 1 || month > 12) {
  702                         month = 1;
  703                 }
  704                 if (month > 1)
  705                         days += months[month - 2];
  706                 days += ((dd & DD_DAY_MASK) >> DD_DAY_SHIFT) - 1;
  707                 lastseconds = (days * 24 * 60 * 60) + SECONDSTO1980;
  708         }
  709         tsp->tv_sec = seconds + lastseconds + tz_minuteswest * 60 +
  710             tzoff * 60 + (wall_cmos_clock ? adjkerntz : 0);
  711         tsp->tv_nsec = (dh % 100) * 10000000;
  712 }

Cache object: f89cf790445f71d9689535916bfe1caf


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.