root/compat/ultrix/ultrix_fs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. make_ultrix_mntent
  2. ultrix_sys_getmnt
  3. ultrix_sys_mount

    1 /*      $OpenBSD: ultrix_fs.c,v 1.14 2006/03/05 21:48:56 miod Exp $     */
    2 /*      $NetBSD: ultrix_fs.c,v 1.4 1996/04/07 17:23:06 jonathan Exp $   */
    3 
    4 /*
    5  * Copyright (c) 1995
    6  *      Jonathan Stone (hereinafter referred to as the author)
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. The name of the author may not be used to endorse or promote products
   17  *    derived from this software without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  */
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/malloc.h>
   35 #include <sys/exec.h>
   36 #include <sys/namei.h>
   37 #include <sys/mount.h>
   38 #include <net/if.h>
   39 #include <netinet/in.h>
   40 
   41 #include <nfs/rpcv2.h>
   42 #include <nfs/nfsproto.h>
   43 #include <nfs/nfs.h>
   44 
   45 #include <sys/syscallargs.h>
   46 #include <compat/ultrix/ultrix_syscallargs.h>
   47 
   48 #include <uvm/uvm_extern.h>
   49 
   50 #define ULTRIX_MAXPATHLEN       1024
   51 
   52 /**
   53  ** Ultrix filesystem operations: mount(), getmnt().
   54  ** These are included purely so one can place an (ECOFF or ELF)
   55  ** NetBSD/pmax kernel in an Ultrix root filesystem, boot it,
   56  ** and over-write the Ultrix root parition with NetBSD binaries.
   57  **/
   58 
   59 /*
   60  * Ultrix file system data structure, as modified by
   61  * Ultrix getmntent(). This  structure is padded to 2560 bytes, for
   62  * compatibility with the size the Ultrix kernel and user apps expect.
   63  */
   64 struct ultrix_fs_data {
   65         u_int32_t       ufsd_flags;     /* how mounted */
   66         u_int32_t       ufsd_mtsize;    /* max transfer size in bytes */
   67         u_int32_t       ufsd_otsize;    /* optimal transfer size in bytes */
   68         u_int32_t       ufsd_bsize;     /* fs block size (bytes) for vm code */
   69         u_int32_t       ufsd_fstype;    /* see ../h/fs_types.h  */
   70         u_int32_t       ufsd_gtot;      /* total number of gnodes */
   71         u_int32_t       ufsd_gfree;     /* # of free gnodes */
   72         u_int32_t       ufsd_btot;      /* total number of 1K blocks */
   73         u_int32_t       ufsd_bfree;     /* # of free 1K blocks */
   74         u_int32_t       ufsd_bfreen;    /* user consumable 1K blocks */
   75         u_int32_t       ufsd_pgthresh;  /* min size in bytes before paging*/
   76         int32_t         ufsd_uid;       /* uid that mounted me */
   77         int16_t         ufsd_dev;       /* major/minor of fs */
   78         int16_t         ufsd_exroot;    /* root mapping from exports */
   79         char            ufsd_devname[ULTRIX_MAXPATHLEN + 4]; /* name of dev */
   80         char            ufsd_path[ULTRIX_MAXPATHLEN + 4]; /* name of mnt point */
   81         u_int32_t       ufsd_nupdate;   /* number of writes */
   82         u_int32_t       ufsd_pad[112];  /* pad to 2560 bytes. */
   83 };
   84 
   85 /*
   86  * Get statistics on mounted filesystems.
   87  */
   88 #if 0
   89 struct ultrix_getmnt_args {
   90         int32_t *start;
   91         struct ultrix_fs_data *buf;
   92         int32_t bufsize;
   93         int32_t mode;
   94         char *path;
   95 };
   96 
   97 #endif
   98 /*
   99  * Ultrix getmnt() flags.
  100  * The operation getmnt() should perform is incoded in the flag
  101  * argument.  There are two independent attributes.
  102  *
  103  * ULTRIX_NOSTAT_xxx will never hang, but it may not return
  104  * up-to-date statistics. (For NFS clients, it returns whatever is
  105  * in the cache.) ULTRIX_STAT_xxx returns up-to-date info but may
  106  * hang (e.g., on dead NFS servers).
  107  *
  108  * ULTRIX_xxSTAT_ONE returns statistics on just one filesystem, determined
  109  * by the parth argument.  ULTRIX_xxSTAT_MANY ignores the path argument and
  110  * returns info on as many  filesystems fit in the structure.
  111  * the start argument, which should be zero on the first call,
  112  * can be used to iterate over all filesystems.
  113  *
  114  */
  115 #define ULTRIX_NOSTAT_MANY      1
  116 #define ULTRIX_STAT_MANY        2
  117 #define ULTRIX_STAT_ONE         3
  118 #define ULTRIX_NOSTAT_ONE       4
  119 
  120 /*
  121  * Ultrix gnode-layer  filesystem codes.
  122  */
  123 #define ULTRIX_FSTYPE_UNKNOWN   0x0
  124 #define ULTRIX_FSTYPE_ULTRIX    0x1     /*  Ultrix UFS: basically 4.2bsd FFS */
  125 #define ULTRIX_FSTYPE_NFS       0x5     /*  NFS v2 */
  126 
  127 /*
  128  * Ultrix mount(2) options
  129  */
  130 #define ULTRIX_NM_RONLY    0x0001  /* mount read-only */
  131 #define ULTRIX_NM_SOFT     0x0002  /* soft mount (hard is default) */
  132 #define ULTRIX_NM_WSIZE    0x0004  /* set write size */
  133 #define ULTRIX_NM_RSIZE    0x0008  /* set read size */
  134 #define ULTRIX_NM_TIMEO    0x0010  /* set initial timeout */
  135 #define ULTRIX_NM_RETRANS  0x0020  /* set number of request retries */
  136 #define ULTRIX_NM_HOSTNAME 0x0040  /* set hostname for error printf */
  137 #define ULTRIX_NM_PGTHRESH 0x0080  /* set page threshold for exec */
  138 #define ULTRIX_NM_INT      0x0100  /* allow hard mount keyboard interrupts */
  139 #define ULTRIX_NM_NOAC     0x0200  /* don't cache attributes */
  140                                                                         
  141 
  142 /*
  143  * Construct an Ultrix getmnt() ultrix_fs_data from the native NetBSD
  144  * struct statfs.
  145  */
  146 static void
  147 make_ultrix_mntent(sp, tem)
  148         register struct statfs *sp;
  149         register struct ultrix_fs_data *tem;
  150 {
  151 
  152         bzero(tem, sizeof (*tem));
  153 
  154         tem->ufsd_flags = sp->f_flags;          /* XXX translate */
  155         tem->ufsd_mtsize = sp->f_bsize;         /* XXX max transfer size */
  156         tem->ufsd_otsize = sp->f_iosize;
  157         tem->ufsd_bsize = sp->f_bsize;
  158         /*
  159          * Translate file system type. NetBSD/1.1 has f_type zero,
  160          * and uses an fstype string instead.
  161          * For now, map types not in Ultrix (kernfs, null, procfs...)
  162          * to UFS, since Ultrix mout will try and call mount_unknown
  163          * for ULTRIX_FSTYPE_UNKNOWN, but lacks a mount_unknown binary.
  164          */
  165         tem->ufsd_fstype = ULTRIX_FSTYPE_NFS;
  166         if (strcmp(sp->f_fstypename, "ffs") == 0)
  167                 tem->ufsd_fstype = ULTRIX_FSTYPE_ULTRIX;
  168 
  169         tem->ufsd_gtot = sp->f_files;           /* total "gnodes" */
  170         tem->ufsd_gfree = sp->f_ffree;          /* free "gnodes" */
  171         tem->ufsd_btot = sp->f_blocks;          /* total 1k blocks */
  172 #ifdef needsmorethought /* XXX */
  173         /* tem->ufsd_bfree = sp->f_bfree; */    /* free 1k blocks */
  174         /* tem->ufsd_bfree = sp->f_bavail; */   /* free 1k blocks */
  175 #endif
  176 
  177         tem->ufsd_bfreen = sp->f_bavail;        /* blocks available to users */
  178         tem->ufsd_pgthresh = 0;                 /* not relevant */
  179         tem->ufsd_uid = 0;                      /* XXX kept where ?*/
  180         tem->ufsd_dev = 0;                      /* ?? */
  181         tem->ufsd_exroot  = 0;                  /* ?? */
  182         strlcpy(tem->ufsd_path, sp->f_mntonname, sizeof(tem->ufsd_path));
  183         strlcpy(tem->ufsd_devname, sp->f_mntfromname,
  184             sizeof(tem->ufsd_devname));
  185 #if 0
  186         /* In NetBSD-1.1, filesystem type is unused and always 0 */
  187         printf("mntent: %s type %d\n", tem->ufsd_devname, tem->ufsd_fstype);
  188         printf("mntent: %s tot %d free %d user%d\n",
  189          tem->ufsd_devname, sp->f_blocks, sp->f_bfree, sp->f_bavail);
  190 #endif
  191 }
  192 
  193 int
  194 ultrix_sys_getmnt(p, v, retval)
  195         struct proc *p;
  196         void *v;
  197         int *retval;
  198 {
  199         struct ultrix_sys_getmnt_args *uap = v;
  200         struct mount *mp, *nmp;
  201         struct statfs *sp;
  202         struct ultrix_fs_data *sfsp;
  203         char *path;
  204         int mntflags;
  205         int skip;
  206         int start;
  207         long count, maxcount;
  208         int error = 0;
  209 
  210         path = NULL;
  211         error = 0;
  212         maxcount = SCARG(uap, bufsize) / sizeof(struct ultrix_fs_data);
  213         sfsp = SCARG(uap, buf);
  214 
  215         if (SCARG(uap, mode) == ULTRIX_STAT_ONE ||
  216             SCARG(uap, mode) == ULTRIX_STAT_MANY)
  217                 mntflags = MNT_WAIT;
  218         else
  219                 mntflags = MNT_NOWAIT;
  220 
  221         if (SCARG(uap, mode) == ULTRIX_STAT_ONE || SCARG(uap, mode) == ULTRIX_NOSTAT_ONE) {
  222                 /*
  223                  * Only get info on mountpoints that matches the path
  224                  * provided.
  225                  */
  226                 MALLOC(path, char *, MAXPATHLEN, M_TEMP, M_WAITOK);
  227                 if ((error = copyinstr(SCARG(uap, path), path,
  228                                        MAXPATHLEN, NULL)) != 0)
  229                         goto bad;
  230                 maxcount = 1;
  231         } else {
  232                 /*
  233                  * Get info on any mountpoints, somewhat like readdir().
  234                  * Find out how many mount list entries to skip, and skip
  235                  * them.
  236                  */
  237                 if ((error = copyin((caddr_t)SCARG(uap, start), &start,
  238                                     sizeof(*SCARG(uap, start))))  != 0)
  239                         goto bad;
  240                 for (skip = start, mp = CIRCLEQ_FIRST(&mountlist);
  241                     mp != CIRCLEQ_END(&mountlist) && skip-- > 0; mp = nmp)
  242                         nmp = CIRCLEQ_NEXT(mp, mnt_list);
  243         }
  244 
  245         for (count = 0, mp = CIRCLEQ_FIRST(&mountlist);
  246             mp != CIRCLEQ_END(&mountlist) && count < maxcount; mp = nmp) {
  247                 nmp = CIRCLEQ_NEXT(mp, mnt_list);
  248                 if (sfsp != NULL) {
  249                         struct ultrix_fs_data tem;
  250                         sp = &mp->mnt_stat;
  251 
  252                         /*
  253                          * If requested, refresh the fsstat cache.
  254                          */
  255                         if ((mntflags & MNT_WAIT) != 0 &&
  256                             (error = VFS_STATFS(mp, sp, p)) != 0)
  257                                 continue;
  258 
  259                         /*
  260                          * XXX what does this do? -- cgd
  261                          */
  262                         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
  263                         if (path == NULL ||
  264                             strcmp(path, sp->f_mntonname) == 0) {
  265                                 make_ultrix_mntent(sp, &tem);
  266                                 if ((error = copyout((caddr_t)&tem, sfsp,
  267                                                      sizeof(tem))) != 0)
  268                                         goto bad;
  269                                 sfsp++;
  270                                 count++;
  271                         }
  272                 }
  273         }
  274 
  275         if (sfsp != NULL && count > maxcount)
  276                 *retval = maxcount;
  277         else
  278                 *retval = count;
  279 
  280 bad:
  281         if (path)
  282                 FREE(path, M_TEMP);
  283         return (error);
  284 }
  285 
  286 
  287 
  288 /* Old-style inet sockaddr (no len field) as passed to Ultrix mount(2) */
  289 struct osockaddr_in {
  290         short   sin_family;
  291         u_short sin_port;
  292         struct  in_addr sin_addr;
  293         char    sin_zero[8];
  294 };
  295 
  296 
  297 /*
  298  * fstype-dependent structure passed to Ultrix mount(2) when
  299  * mounting NFS filesystems
  300  */
  301 struct  ultrix_nfs_args {
  302         struct  osockaddr_in *addr;     /* file server address */
  303         void    *fh;                    /* file handle to be mounted */
  304         int     flags;                  /* flags */
  305         int     wsize;                  /* write size in bytes */
  306         int     rsize;                  /* read size in bytes */
  307         int     timeo;                  /* initial timeout in .1 secs */
  308         int     retrans;                /* times to retry send */
  309         char    *hostname;              /* server's hostname */
  310         char    *optstr;                /* string of nfs mount options*/
  311         int     gfs_flags;              /* gnode flags (ugh) */
  312         int     pg_thresh;              /* paging threshold ? */
  313 };
  314 
  315 
  316 /*
  317  * fstype-dependent structure passed to Ultrix mount(2) when
  318  * mounting local (4.2bsd FFS) filesystems
  319  */
  320 struct ultrix_ufs_args {
  321         u_long ufs_flags;               /* mount flags?*/
  322         u_long ufs_pgthresh;            /* minimum file size to page */
  323 };
  324 
  325 int
  326 ultrix_sys_mount(p, v, retval)
  327         struct proc *p;
  328         void *v;
  329         int *retval;
  330 {
  331         struct ultrix_sys_mount_args *uap = v;
  332 
  333         int error;
  334         int otype = SCARG(uap, type);
  335         char fsname[MFSNAMELEN];
  336         char * fstype;
  337         struct sys_mount_args nuap;
  338         caddr_t sg = stackgap_init(p->p_emul);
  339         caddr_t usp = stackgap_alloc(&sg, 1024 /* XXX */);
  340 
  341         bzero(&nuap, sizeof(nuap));
  342         SCARG(&nuap, flags) = 0;
  343 
  344         /*
  345          * Translate Ultrix integer mount codes for UFS and NFS to
  346          * NetBSD fstype strings.  Other Ultrix filesystem types
  347          *  (msdos, DEC ods-2) are not supported.
  348          */
  349         if (otype == ULTRIX_FSTYPE_ULTRIX)
  350                 fstype = "ufs";
  351         else if (otype == ULTRIX_FSTYPE_NFS)
  352                 fstype = "nfs";
  353         else
  354                 return (EINVAL);
  355 
  356         /* Translate the Ultrix mount-readonly option parameter */
  357         if (SCARG(uap, rdonly))
  358                 SCARG(&nuap, flags) |= MNT_RDONLY;
  359 
  360         /* Copy string-ified version of mount type back out to user space */
  361         SCARG(&nuap, type) = (char *)usp;
  362         if ((error = copyout(fstype, (void *)SCARG(&nuap, type),
  363                             strlen(fstype)+1)) != 0) {
  364                 return (error);
  365         }
  366         usp += strlen(fstype)+1;
  367 
  368 #ifdef later
  369         parse ultrix mount option string and set NetBSD flags
  370 #endif
  371         SCARG(&nuap, path) = SCARG(uap, dir);
  372 
  373         if (otype == ULTRIX_FSTYPE_ULTRIX) {
  374                 /* attempt to mount a native, rather than 4.2bsd, ffs */
  375                 struct ufs_args ua;
  376 
  377                 ua.fspec = SCARG(uap, special);
  378                 bzero(&ua.export_info, sizeof(ua.export_info));
  379                 SCARG(&nuap, data) = usp;
  380         
  381                 if ((error = copyout(&ua, SCARG(&nuap, data),
  382                                      sizeof ua)) !=0) {
  383                         return(error);
  384                 }
  385                 /*
  386                  * Ultrix mount has no MNT_UPDATE flag.
  387                  * Attempt to see if this is the root we're mounting,
  388                  * and if so, set MNT_UPDATE so we can mount / read-write.
  389                  */
  390                 fsname[0] = 0;
  391                 if ((error = copyinstr((caddr_t)SCARG(&nuap, path), fsname,
  392                                       sizeof fsname, (u_int *)0)) != 0)
  393                         return(error);
  394                 if (strcmp(fsname, "/") == 0) {
  395                         SCARG(&nuap, flags) |= MNT_UPDATE;
  396                         printf("COMPAT_ULTRIX: mount with MNT_UPDATE on %s\n",
  397                                fsname);
  398                 }
  399         } else if (otype == ULTRIX_FSTYPE_NFS) {
  400                 struct ultrix_nfs_args una;
  401                 struct nfs_args na;
  402                 struct osockaddr_in osa;
  403                 struct sockaddr_in *sap = (struct sockaddr_in *)& osa;
  404 
  405                 bzero(&osa, sizeof(osa));
  406                 bzero(&una, sizeof(una));
  407                 if ((error = copyin(SCARG(uap, data), &una, sizeof una)) !=0) {
  408                         return (error);
  409                 }
  410                 /*
  411                  * This is the only syscall boundary the
  412                  * address of the server passes, so do backwards
  413                  * compatibility on 4.3style sockaddrs here.
  414                  */
  415                 if ((error = copyin(una.addr, &osa, sizeof osa)) != 0) {
  416                         printf("ultrix_mount: nfs copyin osa\n");
  417                         return (error);
  418                 }
  419                 sap->sin_family = (u_char)osa.sin_family;
  420                 sap->sin_len = sizeof(*sap);
  421                 /* allocate space above caller's stack for nfs_args */
  422                 SCARG(&nuap, data) = usp;
  423                 usp +=  sizeof (na);
  424                 /* allocate space above caller's stack for server sockaddr */
  425                 na.version = NFS_ARGSVERSION;
  426                 na.addr = (struct sockaddr *)usp;
  427                 usp += sizeof(*sap);
  428                 na.addrlen = sap->sin_len;
  429                 na.sotype = SOCK_DGRAM;
  430                 na.proto = IPPROTO_UDP;
  431                 na.fh = una.fh;
  432                 na.fhsize = NFSX_V2FH;
  433                 na.flags = /*una.flags;*/ NFSMNT_NOCONN;
  434                 na.wsize = una.wsize;
  435                 na.rsize = una.rsize;
  436                 na.timeo = una.timeo;
  437                 na.retrans = una.retrans;
  438                 na.hostname = una.hostname;
  439                 if ((error = copyout(sap, na.addr, sizeof (*sap) )) != 0)
  440                         return (error);
  441                 if ((error = copyout(&na, SCARG(&nuap, data), sizeof na)) != 0)
  442                         return (error);
  443         }
  444         return (sys_mount(p, &nuap, retval));
  445 }

/* [<][>][^][v][top][bottom][index][help] */