11558Srgrimes/*
21558Srgrimes * Copyright (c) 1992, 1993, 1994
31558Srgrimes *      The Regents of the University of California.  All rights reserved.
41558Srgrimes *
51558Srgrimes * This code is derived from software contributed to Berkeley
61558Srgrimes * by Pace Willisson (pace@blitz.com).  The Rock Ridge Extension
71558Srgrimes * Support code is derived from software contributed to Berkeley
81558Srgrimes * by Atsushi Murai (amurai@spec.co.jp).
91558Srgrimes *
101558Srgrimes * Redistribution and use in source and binary forms, with or without
111558Srgrimes * modification, are permitted provided that the following conditions
121558Srgrimes * are met:
131558Srgrimes * 1. Redistributions of source code must retain the above copyright
141558Srgrimes *    notice, this list of conditions and the following disclaimer.
151558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
161558Srgrimes *    notice, this list of conditions and the following disclaimer in the
171558Srgrimes *    documentation and/or other materials provided with the distribution.
181558Srgrimes * 4. Neither the name of the University nor the names of its contributors
191558Srgrimes *    may be used to endorse or promote products derived from this software
201558Srgrimes *    without specific prior written permission.
211558Srgrimes *
221558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
231558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
241558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
251558Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
261558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
271558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
281558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
291558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
301558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
311558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
321558Srgrimes * SUCH DAMAGE.
331558Srgrimes *
3423680Speter *      @(#)mount_cd9660.c	8.7 (Berkeley) 5/1/95
351558Srgrimes */
361558Srgrimes
371558Srgrimes#ifndef lint
38122080Strhodesstatic const char copyright[] =
39121861Strhodes"@(#) Copyright (c) 1992, 1993, 1994\n\
40121861Strhodes        The Regents of the University of California.  All rights reserved.\n";
41121861Strhodes#endif /* not lint */
42121861Strhodes
43121861Strhodes#ifndef lint
4415770Swollman/*
4523680Speterstatic char sccsid[] = "@(#)mount_cd9660.c	8.7 (Berkeley) 5/1/95";
4615770Swollman*/
4715770Swollmanstatic const char rcsid[] =
4850476Speter  "$FreeBSD: releng/10.3/sbin/mount_cd9660/mount_cd9660.c 247856 2013-03-05 22:41:35Z jkim $";
491558Srgrimes#endif /* not lint */
501558Srgrimes
5125286Sjoerg#include <sys/cdio.h>
5225286Sjoerg#include <sys/file.h>
531558Srgrimes#include <sys/param.h>
541558Srgrimes#include <sys/mount.h>
55120492Sfjoe#include <sys/module.h>
56120492Sfjoe#include <sys/iconv.h>
57122080Strhodes#include <sys/linker.h>
581558Srgrimes
5990868Smike#include <arpa/inet.h>
6090868Smike
611558Srgrimes#include <err.h>
6271652Sbsd#include <errno.h>
631558Srgrimes#include <stdlib.h>
641558Srgrimes#include <stdio.h>
651558Srgrimes#include <string.h>
6615770Swollman#include <sysexits.h>
671558Srgrimes#include <unistd.h>
681558Srgrimes
691558Srgrimes#include "mntopts.h"
701558Srgrimes
71227081Sedstatic struct mntopt mopts[] = {
721558Srgrimes	MOPT_STDOPTS,
731558Srgrimes	MOPT_UPDATE,
74147242Sdelphij	MOPT_END
751558Srgrimes};
761558Srgrimes
77152355Srodrigcstatic int	get_ssector(const char *dev);
78152808Savatarstatic int	set_charset(struct iovec **, int *iovlen, const char *);
7925286Sjoergvoid	usage(void);
801558Srgrimes
811558Srgrimesint
8225286Sjoergmain(int argc, char **argv)
831558Srgrimes{
84152355Srodrigc	struct iovec *iov;
85152355Srodrigc	int iovlen;
86247856Sjkim	int ch, mntflags;
87152355Srodrigc	char *dev, *dir, *p, *val, mntpath[MAXPATHLEN];
88101274Smux	int verbose;
89152355Srodrigc	int ssector;		/* starting sector, 0 for 1st session */
90152355Srodrigc	char fstype[] = "cd9660";
911558Srgrimes
92152355Srodrigc	iov = NULL;
93152355Srodrigc	iovlen = 0;
94247856Sjkim	mntflags = verbose = 0;
95152355Srodrigc	ssector = -1;
96152355Srodrigc
97120492Sfjoe	while ((ch = getopt(argc, argv, "begjo:rs:vC:")) != -1)
981558Srgrimes		switch (ch) {
9974097Sbp		case 'b':
100152355Srodrigc			build_iovec(&iov, &iovlen, "brokenjoliet", NULL, (size_t)-1);
10174097Sbp			break;
1021558Srgrimes		case 'e':
103152355Srodrigc			build_iovec(&iov, &iovlen, "extatt", NULL, (size_t)-1);
1041558Srgrimes			break;
1051558Srgrimes		case 'g':
106152355Srodrigc			build_iovec(&iov, &iovlen, "gens", NULL, (size_t)-1);
1071558Srgrimes			break;
10845773Sdcs		case 'j':
109152355Srodrigc			build_iovec(&iov, &iovlen, "nojoliet", NULL, (size_t)-1);
11045773Sdcs			break;
1111558Srgrimes		case 'o':
112247856Sjkim			getmntopts(optarg, mopts, &mntflags, NULL);
113152355Srodrigc			p = strchr(optarg, '=');
114152355Srodrigc			val = NULL;
115152355Srodrigc			if (p != NULL) {
116152355Srodrigc				*p = '\0';
117152355Srodrigc				val = p + 1;
118152355Srodrigc			}
119152355Srodrigc			build_iovec(&iov, &iovlen, optarg, val, (size_t)-1);
1201558Srgrimes			break;
1211558Srgrimes		case 'r':
122152355Srodrigc			build_iovec(&iov, &iovlen, "norrip", NULL, (size_t)-1);
1231558Srgrimes			break;
12425286Sjoerg		case 's':
125152355Srodrigc			ssector = atoi(optarg);
12625286Sjoerg			break;
12725286Sjoerg		case 'v':
12825286Sjoerg			verbose++;
12925286Sjoerg			break;
130120492Sfjoe		case 'C':
131152808Savatar			if (set_charset(&iov, &iovlen, optarg) == -1)
132120492Sfjoe				err(EX_OSERR, "cd9660_iconv");
133152355Srodrigc			build_iovec(&iov, &iovlen, "kiconv", NULL, (size_t)-1);
134120492Sfjoe			break;
1351558Srgrimes		case '?':
1361558Srgrimes		default:
1371558Srgrimes			usage();
1381558Srgrimes		}
1391558Srgrimes	argc -= optind;
1401558Srgrimes	argv += optind;
1411558Srgrimes
1421558Srgrimes	if (argc != 2)
1431558Srgrimes		usage();
1441558Srgrimes
1451558Srgrimes	dev = argv[0];
1461558Srgrimes	dir = argv[1];
1471558Srgrimes
14852055Sphk	/*
14952055Sphk	 * Resolve the mountpoint with realpath(3) and remove unnecessary
15052055Sphk	 * slashes from the devicename if there are any.
15152055Sphk	 */
152230226Sjh	if (checkpath(dir, mntpath) != 0)
153230226Sjh		err(1, "%s", mntpath);
15452055Sphk	(void)rmslashes(dev, dev);
15552055Sphk
156152355Srodrigc	if (ssector == -1) {
15725286Sjoerg		/*
15825286Sjoerg		 * The start of the session has not been specified on
15925286Sjoerg		 * the command line.  If we can successfully read the
16025286Sjoerg		 * TOC of a CD-ROM, use the last data track we find.
16125286Sjoerg		 * Otherwise, just use 0, in order to mount the very
16225286Sjoerg		 * first session.  This is compatible with the
16325286Sjoerg		 * historic behaviour of mount_cd9660(8).  If the user
16425286Sjoerg		 * has specified -s <ssector> above, we don't get here
16525286Sjoerg		 * and leave the user's will.
16625286Sjoerg		 */
167152355Srodrigc		if ((ssector = get_ssector(dev)) == -1) {
16825286Sjoerg			if (verbose)
16925286Sjoerg				printf("could not determine starting sector, "
17025286Sjoerg				       "using very first session\n");
171152355Srodrigc			ssector = 0;
17225286Sjoerg		} else if (verbose)
173152355Srodrigc			printf("using starting sector %d\n", ssector);
17425286Sjoerg	}
175152355Srodrigc	mntflags |= MNT_RDONLY;
176152355Srodrigc	build_iovec(&iov, &iovlen, "fstype", fstype, (size_t)-1);
177152355Srodrigc	build_iovec(&iov, &iovlen, "fspath", mntpath, (size_t)-1);
178152355Srodrigc	build_iovec(&iov, &iovlen, "from", dev, (size_t)-1);
179153531Savatar	build_iovec_argf(&iov, &iovlen, "ssector", "%d", ssector);
18025286Sjoerg
181152355Srodrigc	if (nmount(iov, iovlen, mntflags) < 0)
182152355Srodrigc		err(1, "%s", dev);
1831558Srgrimes	exit(0);
1841558Srgrimes}
1851558Srgrimes
1861558Srgrimesvoid
18725286Sjoergusage(void)
1881558Srgrimes{
1891558Srgrimes	(void)fprintf(stderr,
190137672Sru"usage: mount_cd9660 [-begjrv] [-C charset] [-o options] [-s startsector]\n"
191137672Sru"                    special node\n");
19215770Swollman	exit(EX_USAGE);
1931558Srgrimes}
19425286Sjoerg
195152355Srodrigcstatic int
19625286Sjoergget_ssector(const char *dev)
19725286Sjoerg{
19825286Sjoerg	struct ioc_toc_header h;
19925286Sjoerg	struct ioc_read_toc_entry t;
20025286Sjoerg	struct cd_toc_entry toc_buffer[100];
20125286Sjoerg	int fd, ntocentries, i;
20225286Sjoerg
20325286Sjoerg	if ((fd = open(dev, O_RDONLY)) == -1)
20425286Sjoerg		return -1;
20525286Sjoerg	if (ioctl(fd, CDIOREADTOCHEADER, &h) == -1) {
20625286Sjoerg		close(fd);
20725286Sjoerg		return -1;
20825286Sjoerg	}
20925286Sjoerg
21025286Sjoerg	ntocentries = h.ending_track - h.starting_track + 1;
21125286Sjoerg	if (ntocentries > 100) {
21225286Sjoerg		/* unreasonable, only 100 allowed */
21325286Sjoerg		close(fd);
21425286Sjoerg		return -1;
21525286Sjoerg	}
21625286Sjoerg	t.address_format = CD_LBA_FORMAT;
21725286Sjoerg	t.starting_track = 0;
21825286Sjoerg	t.data_len = ntocentries * sizeof(struct cd_toc_entry);
21925286Sjoerg	t.data = toc_buffer;
22025286Sjoerg
22125286Sjoerg	if (ioctl(fd, CDIOREADTOCENTRYS, (char *) &t) == -1) {
22225286Sjoerg		close(fd);
22325286Sjoerg		return -1;
22425286Sjoerg	}
22525286Sjoerg	close(fd);
22625286Sjoerg
22725286Sjoerg	for (i = ntocentries - 1; i >= 0; i--)
22825286Sjoerg		if ((toc_buffer[i].control & 4) != 0)
22925286Sjoerg			/* found a data track */
23025286Sjoerg			break;
23125286Sjoerg	if (i < 0)
23225286Sjoerg		return -1;
23325286Sjoerg
23425286Sjoerg	return ntohl(toc_buffer[i].addr.lba);
23525286Sjoerg}
236120492Sfjoe
237152355Srodrigcstatic int
238152808Savatarset_charset(struct iovec **iov, int *iovlen, const char *localcs)
239120492Sfjoe{
240120492Sfjoe	int error;
241152355Srodrigc	char *cs_disk;	/* disk charset for Joliet cs conversion */
242152355Srodrigc	char *cs_local;	/* local charset for Joliet cs conversion */
243120492Sfjoe
244152355Srodrigc	cs_disk = NULL;
245152355Srodrigc	cs_local = NULL;
246152355Srodrigc
247120492Sfjoe	if (modfind("cd9660_iconv") < 0)
248120492Sfjoe		if (kldload("cd9660_iconv") < 0 || modfind("cd9660_iconv") < 0) {
249120492Sfjoe			warnx( "cannot find or load \"cd9660_iconv\" kernel module");
250120492Sfjoe			return (-1);
251120492Sfjoe		}
252120492Sfjoe
253152355Srodrigc	if ((cs_disk = malloc(ICONV_CSNMAXLEN)) == NULL)
254120492Sfjoe		return (-1);
255199584Snetchild	if ((cs_local = malloc(ICONV_CSNMAXLEN)) == NULL) {
256199584Snetchild		free(cs_disk);
257120492Sfjoe		return (-1);
258199584Snetchild	}
259152355Srodrigc	strncpy(cs_disk, ENCODING_UNICODE, ICONV_CSNMAXLEN);
260152355Srodrigc	strncpy(cs_local, kiconv_quirkcs(localcs, KICONV_VENDOR_MICSFT),
261120492Sfjoe	    ICONV_CSNMAXLEN);
262152355Srodrigc	error = kiconv_add_xlat16_cspairs(cs_disk, cs_local);
263120492Sfjoe	if (error)
264120492Sfjoe		return (-1);
265152355Srodrigc
266152808Savatar	build_iovec(iov, iovlen, "cs_disk", cs_disk, (size_t)-1);
267152808Savatar	build_iovec(iov, iovlen, "cs_local", cs_local, (size_t)-1);
268120492Sfjoe
269120492Sfjoe	return (0);
270120492Sfjoe}
271