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

Cache object: 1776083b5f04f78216366c2df14b2581


[ 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.