Exemplo n.º 1
0
static int
update_mp(struct mount *mp, struct msdosfs_args *argp)
{
	struct msdosfsmount *pmp = VFSTOMSDOSFS(mp);
	int error;
        char cs_local[ICONV_CSNMAXLEN];
        char cs_dos[ICONV_CSNMAXLEN];

	pmp->pm_gid = argp->gid;
	pmp->pm_uid = argp->uid;
	pmp->pm_mask = argp->mask & ALLPERMS;
	pmp->pm_flags |= argp->flags & MSDOSFSMNT_MNTOPT;
	if (pmp->pm_flags & MSDOSFSMNT_KICONV && msdos_iconv) {
		bcopy(argp->cs_local, cs_local, sizeof(cs_local));
		bcopy(argp->cs_dos, cs_dos, sizeof(cs_dos));
		kprintf("local: %s dos: %s\n",argp->cs_local, argp->cs_dos);
		error = msdos_iconv->open(cs_local, ENCODING_UNICODE, &pmp->pm_w2u);
		if(error)
			return error;
		error = msdos_iconv->open(ENCODING_UNICODE, cs_local, &pmp->pm_u2w);
		if(error)
			return error;
		error = msdos_iconv->open(cs_dos, cs_local, &pmp->pm_u2d);
		if(error)
			return error;
		error = msdos_iconv->open(cs_local, cs_dos, &pmp->pm_d2u);
		if(error)
			return error;
	}

	if (pmp->pm_flags & MSDOSFSMNT_NOWIN95)
		pmp->pm_flags |= MSDOSFSMNT_SHORTNAME;
	else if (!(pmp->pm_flags &
	    (MSDOSFSMNT_SHORTNAME | MSDOSFSMNT_LONGNAME))) {
		struct vnode *rootvp;

		/*
		 * Try to divine whether to support Win'95 long filenames
		 */
		if (FAT32(pmp))
			pmp->pm_flags |= MSDOSFSMNT_LONGNAME;
		else {
			if ((error = msdosfs_root(mp, &rootvp)) != 0)
				return error;
			pmp->pm_flags |= findwin95(VTODE(rootvp))
				? MSDOSFSMNT_LONGNAME
					: MSDOSFSMNT_SHORTNAME;
			vput(rootvp);
		}
	}
	return 0;
}
Exemplo n.º 2
0
static int
update_mp(struct mount *mp, struct msdosfs_args *argp)
{
	struct msdosfsmount *pmp = VFSTOMSDOSFS(mp);
	int error;

	pmp->pm_gid = argp->gid;
	pmp->pm_uid = argp->uid;
	pmp->pm_mask = argp->mask & ALLPERMS;
	pmp->pm_dirmask = argp->dirmask & ALLPERMS;
	pmp->pm_gmtoff = argp->gmtoff;
	pmp->pm_flags |= argp->flags & MSDOSFSMNT_MNTOPT;

	/*
	 * GEMDOS knows nothing about win95 long filenames
	 */
	if (pmp->pm_flags & MSDOSFSMNT_GEMDOSFS)
		pmp->pm_flags |= MSDOSFSMNT_NOWIN95;

	if (pmp->pm_flags & MSDOSFSMNT_NOWIN95)
		pmp->pm_flags |= MSDOSFSMNT_SHORTNAME;
	else if (!(pmp->pm_flags &
	    (MSDOSFSMNT_SHORTNAME | MSDOSFSMNT_LONGNAME))) {
		struct vnode *rtvp;

		/*
		 * Try to divine whether to support Win'95 long filenames
		 */
		if (FAT32(pmp))
			pmp->pm_flags |= MSDOSFSMNT_LONGNAME;
		else {
			if ((error = msdosfs_root(mp, &rtvp)) != 0)
				return error;
			pmp->pm_flags |= findwin95(VTODE(rtvp))
				? MSDOSFSMNT_LONGNAME
					: MSDOSFSMNT_SHORTNAME;
			vput(rtvp);
		}
	}

	mp->mnt_stat.f_namemax = MSDOSFS_NAMEMAX(pmp);

	return 0;
}
Exemplo n.º 3
0
/*
 * mp - path - addr in user space of mount point (ie /usr or whatever) 
 * data - addr in user space of mount params including the name of the block
 * special file to treat as a filesystem. 
 */
int
msdosfs_mount(struct mount *mp, const char *path, void *data,
    struct nameidata *ndp, struct proc *p)
{
	struct vnode *devvp;	  /* vnode for blk device to mount */
	struct msdosfs_args args; /* will hold data from mount request */
	/* msdosfs specific mount control block */
	struct msdosfsmount *pmp = NULL;
	size_t size;
	int error, flags;
	mode_t accessmode;
	char *fspec = NULL;

	error = copyin(data, &args, sizeof(struct msdosfs_args));
	if (error)
		return (error);

	/*
	 * If updating, check whether changing from read-only to
	 * read/write; if there is no device name, that's all we do.
	 */
	if (mp->mnt_flag & MNT_UPDATE) {
		pmp = VFSTOMSDOSFS(mp);
		error = 0;
		if (!(pmp->pm_flags & MSDOSFSMNT_RONLY) &&
		    (mp->mnt_flag & MNT_RDONLY)) {
			flags = WRITECLOSE;
			if (mp->mnt_flag & MNT_FORCE)
				flags |= FORCECLOSE;
			error = vflush(mp, NULLVP, flags);
		}
		if (!error && (mp->mnt_flag & MNT_RELOAD))
			/* not yet implemented */
			error = EOPNOTSUPP;
		if (error)
			return (error);
		if ((pmp->pm_flags & MSDOSFSMNT_RONLY) &&
		    (mp->mnt_flag & MNT_WANTRDWR)) {
			/*
			 * If upgrade to read-write by non-root, then verify
			 * that user has necessary permissions on the device.
			 */
			if (suser(p, 0) != 0) {
				devvp = pmp->pm_devvp;
				vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
				error = VOP_ACCESS(devvp, VREAD | VWRITE,
						   p->p_ucred, p);
				VOP_UNLOCK(devvp, 0, p);
				if (error)
					return (error);
			}
			pmp->pm_flags &= ~MSDOSFSMNT_RONLY;
		}
		if (args.fspec == 0) {
#ifdef	__notyet__		/* doesn't work correctly with current mountd	XXX */
			if (args.flags & MSDOSFSMNT_MNTOPT) {
				pmp->pm_flags &= ~MSDOSFSMNT_MNTOPT;
				pmp->pm_flags |= args.flags & MSDOSFSMNT_MNTOPT;
				if (pmp->pm_flags & MSDOSFSMNT_NOWIN95)
					pmp->pm_flags |= MSDOSFSMNT_SHORTNAME;
			}
#endif
			/*
			 * Process export requests.
			 */
			return (vfs_export(mp, &pmp->pm_export, 
			    &args.export_info));
		}
	}

	/*
	 * Not an update, or updating the name: look up the name
	 * and verify that it refers to a sensible block device.
	 */
	fspec = malloc(MNAMELEN, M_MOUNT, M_WAITOK);
	error = copyinstr(args.fspec, fspec, MNAMELEN - 1, &size);
	if (error)
		goto error;
	disk_map(fspec, fspec, MNAMELEN, DM_OPENBLCK);

	NDINIT(ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, fspec, p);
	if ((error = namei(ndp)) != 0)
		goto error;

	devvp = ndp->ni_vp;

	if (devvp->v_type != VBLK) {
		error = ENOTBLK;
		goto error_devvp;
	}
	if (major(devvp->v_rdev) >= nblkdev) {
		error = ENXIO;
		goto error_devvp;
	}

	/*
	 * If mount by non-root, then verify that user has necessary
	 * permissions on the device.
	 */
	if (suser(p, 0) != 0) {
		accessmode = VREAD;
		if ((mp->mnt_flag & MNT_RDONLY) == 0)
			accessmode |= VWRITE;
		vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
		error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p);
		VOP_UNLOCK(devvp, 0, p);
		if (error)
			goto error_devvp;
	}

	if ((mp->mnt_flag & MNT_UPDATE) == 0)
		error = msdosfs_mountfs(devvp, mp, p, &args);
	else {
		if (devvp != pmp->pm_devvp)
			error = EINVAL;	/* XXX needs translation */
		else
			vrele(devvp);
	}
	if (error)
		goto error_devvp;

	pmp = VFSTOMSDOSFS(mp);
	pmp->pm_gid = args.gid;
	pmp->pm_uid = args.uid;
	pmp->pm_mask = args.mask;
	pmp->pm_flags |= args.flags & MSDOSFSMNT_MNTOPT;

	if (pmp->pm_flags & MSDOSFSMNT_NOWIN95)
		pmp->pm_flags |= MSDOSFSMNT_SHORTNAME;
	else if (!(pmp->pm_flags &
	    (MSDOSFSMNT_SHORTNAME | MSDOSFSMNT_LONGNAME))) {
		struct vnode *rvp;
		
		/*
		 * Try to divine whether to support Win'95 long filenames
		 */
		if (FAT32(pmp))
		        pmp->pm_flags |= MSDOSFSMNT_LONGNAME;
		else {
		        if ((error = msdosfs_root(mp, &rvp)) != 0) {
			        msdosfs_unmount(mp, MNT_FORCE, p);
			        goto error;
			}
			pmp->pm_flags |= findwin95(VTODE(rvp))
			     ? MSDOSFSMNT_LONGNAME
			     : MSDOSFSMNT_SHORTNAME;
			vput(rvp);
		}
	}
	(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
	bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);

	size = strlcpy(mp->mnt_stat.f_mntfromname, fspec, MNAMELEN - 1);
	bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
	bcopy(&args, &mp->mnt_stat.mount_info.msdosfs_args, sizeof(args));
#ifdef MSDOSFS_DEBUG
	printf("msdosfs_mount(): mp %x, pmp %x, inusemap %x\n", mp,
	    pmp, pmp->pm_inusemap);
#endif
	return (0);

error_devvp:
	vrele(devvp);

error:
	if (fspec)
		free(fspec, M_MOUNT);

	return (error);
}