1164829Srodrigc/*- 21558Srgrimes * Copyright (c) 1992, 1993, 1994 3164829Srodrigc * The Regents of the University of California. 4164829Srodrigc * Copyright (c) 2005, 2006 Masanori Ozawa <ozawa@ongs.co.jp>, ONGS Inc. 5164829Srodrigc * Copyright (c) 2006 Daichi Goto <daichi@freebsd.org> 6164829Srodrigc * All rights reserved. 71558Srgrimes * 81558Srgrimes * This code is derived from software donated to Berkeley by 91558Srgrimes * Jan-Simon Pendry. 101558Srgrimes * 111558Srgrimes * Redistribution and use in source and binary forms, with or without 121558Srgrimes * modification, are permitted provided that the following conditions 131558Srgrimes * are met: 141558Srgrimes * 1. Redistributions of source code must retain the above copyright 151558Srgrimes * notice, this list of conditions and the following disclaimer. 161558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 171558Srgrimes * notice, this list of conditions and the following disclaimer in the 181558Srgrimes * documentation and/or other materials provided with the distribution. 191558Srgrimes * 4. Neither the name of the University nor the names of its contributors 201558Srgrimes * may be used to endorse or promote products derived from this software 211558Srgrimes * without specific prior written permission. 221558Srgrimes * 231558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 241558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 251558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 261558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 271558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 281558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 291558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 301558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 311558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 321558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 331558Srgrimes * SUCH DAMAGE. 341558Srgrimes */ 351558Srgrimes 361558Srgrimes#ifndef lint 3728629Sstevestatic const char copyright[] = 381558Srgrimes"@(#) Copyright (c) 1992, 1993, 1994\n\ 391558Srgrimes The Regents of the University of California. All rights reserved.\n"; 401558Srgrimes#endif /* not lint */ 411558Srgrimes 421558Srgrimes#ifndef lint 4328629Ssteve#if 0 441558Srgrimesstatic char sccsid[] = "@(#)mount_union.c 8.5 (Berkeley) 3/27/94"; 4528629Ssteve#else 4628629Sstevestatic const char rcsid[] = 4750476Speter "$FreeBSD$"; 4828629Ssteve#endif 491558Srgrimes#endif /* not lint */ 501558Srgrimes 511558Srgrimes#include <sys/param.h> 521558Srgrimes#include <sys/mount.h> 53101829Smux#include <sys/uio.h> 54164829Srodrigc#include <sys/errno.h> 551558Srgrimes 561558Srgrimes#include <err.h> 571558Srgrimes#include <stdio.h> 581558Srgrimes#include <stdlib.h> 591558Srgrimes#include <string.h> 6015770Swollman#include <sysexits.h> 611558Srgrimes#include <unistd.h> 62164829Srodrigc#include <grp.h> 63164829Srodrigc#include <pwd.h> 641558Srgrimes 651558Srgrimes#include "mntopts.h" 661558Srgrimes 67164829Srodrigcstatic int 68164829Srodrigcsubdir(const char *p, const char *dir) 69164829Srodrigc{ 70164829Srodrigc int l; 711558Srgrimes 72164829Srodrigc l = strlen(dir); 73164829Srodrigc if (l <= 1) 74164829Srodrigc return (1); 751558Srgrimes 76164829Srodrigc if ((strncmp(p, dir, l) == 0) && (p[l] == '/' || p[l] == '\0')) 77164829Srodrigc return (1); 78164829Srodrigc 79164829Srodrigc return (0); 80164829Srodrigc} 81164829Srodrigc 82164829Srodrigcstatic void 83164829Srodrigcusage(void) 841558Srgrimes{ 85164829Srodrigc (void)fprintf(stderr, 86164829Srodrigc "usage: mount_unionfs [-o options] directory uniondir\n"); 87164829Srodrigc exit(EX_USAGE); 88164829Srodrigc} 891558Srgrimes 90164829Srodrigcstatic void 91164829Srodrigcparse_gid(const char *s, char *buf, size_t bufsize) 92164829Srodrigc{ 93164829Srodrigc struct group *gr; 94164829Srodrigc char *inval; 95164829Srodrigc 96164829Srodrigc if ((gr = getgrnam(s)) != NULL) 97164829Srodrigc snprintf(buf, bufsize, "%d", gr->gr_gid); 98164829Srodrigc else { 99164829Srodrigc strtol(s, &inval, 10); 100164829Srodrigc if (*inval != 0) { 101164829Srodrigc errx(EX_NOUSER, "unknown group id: %s", s); 102164829Srodrigc usage(); 103164829Srodrigc } else { 104164829Srodrigc strncpy(buf, s, bufsize); 105164829Srodrigc } 106164829Srodrigc } 107164829Srodrigc} 108164829Srodrigc 109164875Smaximstatic void 110164829Srodrigcparse_uid(const char *s, char *buf, size_t bufsize) 111164829Srodrigc{ 112164829Srodrigc struct passwd *pw; 113164829Srodrigc char *inval; 114164829Srodrigc 115164829Srodrigc if ((pw = getpwnam(s)) != NULL) 116164829Srodrigc snprintf(buf, bufsize, "%d", pw->pw_uid); 117164829Srodrigc else { 118164829Srodrigc strtol(s, &inval, 10); 119164829Srodrigc if (*inval != 0) { 120164829Srodrigc errx(EX_NOUSER, "unknown user id: %s", s); 121164829Srodrigc usage(); 122164829Srodrigc } else { 123164829Srodrigc strncpy(buf, s, bufsize); 124164829Srodrigc } 125164829Srodrigc } 126164829Srodrigc} 127164829Srodrigc 128164829Srodrigcint 129164829Srodrigcmain(int argc, char *argv[]) 130164829Srodrigc{ 131164829Srodrigc struct iovec *iov; 132164829Srodrigc int ch, mntflags, iovlen; 133164829Srodrigc char source [MAXPATHLEN], target[MAXPATHLEN], errmsg[255]; 134164829Srodrigc char uid_str[20], gid_str[20]; 135166684Srodrigc char fstype[] = "unionfs"; 136164829Srodrigc char *p, *val; 137164829Srodrigc 138164829Srodrigc iov = NULL; 139164829Srodrigc iovlen = 0; 1401558Srgrimes mntflags = 0; 141164829Srodrigc memset(errmsg, 0, sizeof(errmsg)); 142164829Srodrigc 143164829Srodrigc while ((ch = getopt(argc, argv, "bo:")) != -1) { 1441558Srgrimes switch (ch) { 1451558Srgrimes case 'b': 146164829Srodrigc printf("\n -b is deprecated. Use \"-o below\" instead\n"); 147164829Srodrigc build_iovec(&iov, &iovlen, "below", NULL, 0); 1481558Srgrimes break; 1491558Srgrimes case 'o': 150164829Srodrigc p = strchr(optarg, '='); 151164829Srodrigc val = NULL; 152164829Srodrigc if (p != NULL) { 153164829Srodrigc *p = '\0'; 154164829Srodrigc val = p + 1; 155165788Srodrigc if (strcmp(optarg, "gid") == 0) { 156164829Srodrigc parse_gid(val, gid_str, sizeof(gid_str)); 157164829Srodrigc val = gid_str; 158164829Srodrigc } 159165788Srodrigc else if (strcmp(optarg, "uid") == 0) { 160164829Srodrigc parse_uid(val, uid_str, sizeof(uid_str)); 161164829Srodrigc val = uid_str; 162164829Srodrigc } 163164829Srodrigc } 164164829Srodrigc build_iovec(&iov, &iovlen, optarg, val, (size_t)-1); 1651558Srgrimes break; 1661558Srgrimes case '?': 1671558Srgrimes default: 1681558Srgrimes usage(); 1691558Srgrimes /* NOTREACHED */ 1701558Srgrimes } 171164829Srodrigc } 1721558Srgrimes argc -= optind; 1731558Srgrimes argv += optind; 1741558Srgrimes 1751558Srgrimes if (argc != 2) 1761558Srgrimes usage(); 1771558Srgrimes 17852055Sphk /* resolve both target and source with realpath(3) */ 17952055Sphk (void)checkpath(argv[0], target); 18052055Sphk (void)checkpath(argv[1], source); 1811558Srgrimes 18225275Sdfr if (subdir(target, source) || subdir(source, target)) 18325275Sdfr errx(EX_USAGE, "%s (%s) and %s (%s) are not distinct paths", 184164829Srodrigc argv[0], target, argv[1], source); 18525275Sdfr 186166684Srodrigc build_iovec(&iov, &iovlen, "fstype", fstype, (size_t)-1); 187164829Srodrigc build_iovec(&iov, &iovlen, "fspath", source, (size_t)-1); 188164829Srodrigc build_iovec(&iov, &iovlen, "from", target, (size_t)-1); 189164829Srodrigc build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg)); 190164829Srodrigc 191164829Srodrigc if (nmount(iov, iovlen, mntflags)) 192164829Srodrigc err(EX_OSERR, "%s: %s", source, errmsg); 1931558Srgrimes exit(0); 1941558Srgrimes} 195