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