1 /* 2 * Copyright (c) 2007 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Matthew Dillon <dillon@backplane.com> 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 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 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 3. Neither the name of The DragonFly Project nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific, prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #include <sys/types.h> 36 #include <sys/stat.h> 37 #include <vfs/hammer/hammer_mount.h> 38 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <stdarg.h> 42 #include <stddef.h> 43 #include <unistd.h> 44 #include <string.h> 45 #include <fcntl.h> 46 #include <err.h> 47 #include <mntopts.h> 48 49 static void test_master_id(int master_id); 50 static void extract_volumes(struct hammer_mount_info *info, char **av, int ac); 51 static void free_volumes(struct hammer_mount_info *info); 52 static void usage(void); 53 54 #define hwarnx(format, args...) warnx("WARNING: "format,## args) 55 56 #define MOPT_HAMMEROPTS \ 57 { "history", 1, HMNT_NOHISTORY, 1 }, \ 58 { "master=", 0, HMNT_MASTERID, 1 }, \ 59 { "mirror", 1, HMNT_NOMIRROR, 1 } 60 61 static struct mntopt mopts[] = { MOPT_STDOPTS, MOPT_HAMMEROPTS, 62 MOPT_UPDATE, MOPT_NULL }; 63 64 int 65 main(int ac, char **av) 66 { 67 struct hammer_mount_info info; 68 struct vfsconf vfc; 69 int mount_flags = 0; 70 int init_flags = 0; 71 int error; 72 int ch; 73 char *mountpt; 74 char *ptr; 75 76 bzero(&info, sizeof(info)); 77 78 while ((ch = getopt(ac, av, "o:T:u")) != -1) { 79 switch(ch) { 80 case 'T': 81 info.asof = strtoull(optarg, NULL, 0); 82 break; 83 case 'o': 84 getmntopts(optarg, mopts, &mount_flags, &info.hflags); 85 86 /* 87 * Handle extended flags with parameters. 88 */ 89 if (info.hflags & HMNT_MASTERID) { 90 ptr = strstr(optarg, "master="); 91 if (ptr) { 92 info.master_id = strtol(ptr + 7, NULL, 0); 93 test_master_id(info.master_id); 94 } 95 } 96 if (info.hflags & HMNT_NOMIRROR) { 97 ptr = strstr(optarg, "nomirror"); 98 if (ptr) 99 info.master_id = -1; 100 } 101 break; 102 case 'u': 103 init_flags |= MNT_UPDATE; 104 break; 105 default: 106 usage(); 107 /* not reached */ 108 break; 109 } 110 } 111 ac -= optind; 112 av += optind; 113 mount_flags |= init_flags; 114 115 /* 116 * Only the mount point need be specified in update mode. 117 */ 118 if (init_flags & MNT_UPDATE) { 119 if (ac != 1) { 120 usage(); 121 /* not reached */ 122 } 123 mountpt = av[0]; 124 if (mount(vfc.vfc_name, mountpt, mount_flags, &info)) { 125 err(1, "mountpoint %s", mountpt); 126 /* not reached */ 127 } 128 exit(0); 129 } 130 131 if (ac < 2) { 132 usage(); 133 /* not reached */ 134 } 135 136 /* 137 * Mount arguments: vol [vol...] mountpt 138 */ 139 extract_volumes(&info, av, ac - 1); 140 mountpt = av[ac - 1]; 141 142 /* 143 * Load the hammer module if necessary (this bit stolen from 144 * mount_null). 145 */ 146 error = getvfsbyname("hammer", &vfc); 147 if (error && vfsisloadable("hammer")) { 148 if (vfsload("hammer") != 0) { 149 err(1, "vfsload(hammer)"); 150 /* not reached */ 151 } 152 endvfsent(); 153 error = getvfsbyname("hammer", &vfc); 154 } 155 if (error) { 156 errx(1, "hammer filesystem is not available"); 157 /* not reached */ 158 } 159 160 if (mount(vfc.vfc_name, mountpt, mount_flags, &info)) { 161 perror("mount"); 162 exit(1); 163 } 164 free_volumes(&info); 165 166 return(0); 167 } 168 169 static 170 void 171 test_master_id(int master_id) 172 { 173 switch (master_id) { 174 case 0: 175 hwarnx("A master id of 0 is the default, " 176 "explicit settings should use 1-15"); 177 break; 178 case -1: 179 hwarnx("A master id of -1 is nomirror mode, " 180 "equivalent to -o nomirror option"); 181 break; 182 case 1 ... 15: /* gcc */ 183 /* Expected values via -o master= option */ 184 break; 185 default: 186 /* This will eventually fail in hammer_vfs_mount() */ 187 hwarnx("A master id of %d is not supported", master_id); 188 break; 189 } 190 } 191 192 /* 193 * Extract a volume list 194 */ 195 static 196 void 197 extract_volumes(struct hammer_mount_info *info, char **av, int ac) 198 { 199 int idx = 0; 200 int arymax = 32; 201 char **ary, *ptr, *next, *orig; 202 203 #define _extend_ary(ary, arymax) ({ \ 204 (arymax) += 32; \ 205 realloc(ary, (arymax) * sizeof(char *)); \ 206 }) 207 ary = calloc(arymax, sizeof(char *)); 208 209 while (ac) { 210 if (idx == arymax) 211 ary = _extend_ary(ary, arymax); 212 if (strchr(*av, ':') == NULL) { 213 ary[idx++] = strdup(*av); 214 } else { 215 orig = next = strdup(*av); 216 while ((ptr = next) != NULL) { 217 if (idx == arymax) 218 ary = _extend_ary(ary, arymax); 219 if ((next = strchr(ptr, ':')) != NULL) 220 *next++ = 0; 221 ary[idx++] = strdup(ptr); 222 } 223 free(orig); 224 } 225 --ac; 226 ++av; 227 } 228 info->nvolumes = idx; 229 info->volumes = ary; 230 } 231 232 static 233 void 234 free_volumes(struct hammer_mount_info *info) 235 { 236 int i; 237 238 for (i = 0; i < info->nvolumes; i++) 239 free(info->volumes[i]); 240 free(info->volumes); 241 } 242 243 static 244 void 245 usage(void) 246 { 247 fprintf(stderr, "usage: mount_hammer [-o options] [-T transaction-id] " 248 "special ... node\n"); 249 fprintf(stderr, " mount_hammer [-o options] [-T transaction-id] " 250 "special[:special]* node\n"); 251 fprintf(stderr, " mount_hammer -u [-o options] node\n"); 252 exit(1); 253 } 254