1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2012, Joyent, Inc. All rights reserved. 24 */ 25 26 /* 27 * This is a simple test program to exercise the hyprlofs ioctls. This is 28 * not designed as a full featured CLI and only does minimal error checking 29 * and reporting. 30 */ 31 #include <stdio.h> 32 #include <unistd.h> 33 #include <stdlib.h> 34 #include <sys/types.h> 35 #include <sys/stat.h> 36 #include <fcntl.h> 37 #include <libgen.h> 38 #include <strings.h> 39 #include <sys/errno.h> 40 #include <sys/fs/hyprlofs.h> 41 42 extern int errno; 43 44 char *usage = "usage: <fs path> add [<file name> <alias>]+\n" 45 " <fs path> addl [<file name>]+\n" 46 " <fs path> rm [<alias>]+\n" 47 " <fs path> clear" 48 " <fs path> get"; 49 50 typedef enum { 51 CMD_ADD, 52 CMD_RM, 53 CMD_CLR, 54 CMD_ADDL, 55 CMD_GET 56 } cmd_t; 57 58 static int 59 get_entries(int fd) 60 { 61 int err; 62 int i; 63 hyprlofs_curr_entries_t e; 64 hyprlofs_curr_entry_t *ep; 65 66 e.hce_cnt = 0; 67 e.hce_entries = NULL; 68 69 err = ioctl(fd, HYPRLOFS_GET_ENTRIES, &e); 70 if (err != 0 && errno != E2BIG) { 71 perror("ioctl"); 72 return (1); 73 } 74 75 if (err == 0) { 76 (void) printf("success, but no entries\n"); 77 return (0); 78 } 79 80 /* 81 * E2BIG is what we expect when there are existing mappings 82 * since the current cnt is still returned in that case. 83 */ 84 (void) printf("cnt: %d\n", e.hce_cnt); 85 86 /* alloc array and call again, then print array */ 87 if ((ep = (hyprlofs_curr_entry_t *) 88 malloc(sizeof (hyprlofs_curr_entry_t) * e.hce_cnt)) == NULL) { 89 (void) fprintf(stderr, "out of memory\n"); 90 exit(1); 91 } 92 93 e.hce_entries = ep; 94 errno = 0; 95 if (ioctl(fd, HYPRLOFS_GET_ENTRIES, &e) != 0) { 96 /* 97 * Not handling an increase here. We would need to free and 98 * start over to do that, but ok for a test program. 99 */ 100 perror("ioctl"); 101 free(ep); 102 return (1); 103 } 104 for (i = 0; i < e.hce_cnt; i++) 105 (void) printf("%s %s\n", ep[i].hce_path, ep[i].hce_name); 106 107 free(ep); 108 return (0); 109 } 110 111 int 112 main(int argc, char **argv) 113 { 114 int i, ap; 115 cmd_t cmd; 116 int cnt = 0; 117 int fd; 118 int rv = 0; 119 hyprlofs_entry_t *e; 120 hyprlofs_entries_t ents; 121 122 if (argc < 3) { 123 (void) fprintf(stderr, "%s\n", usage); 124 exit(1); 125 } 126 127 if ((fd = open(argv[1], O_RDONLY)) < 0) { 128 perror("can't open hyprlofs mount"); 129 exit(1); 130 } 131 132 if (strcmp(argv[2], "add") == 0) { 133 cmd = CMD_ADD; 134 } else if (strcmp(argv[2], "rm") == 0) { 135 cmd = CMD_RM; 136 } else if (strcmp(argv[2], "clear") == 0) { 137 cmd = CMD_CLR; 138 } else if (strcmp(argv[2], "addl") == 0) { 139 cmd = CMD_ADDL; 140 } else if (strcmp(argv[2], "get") == 0) { 141 cmd = CMD_GET; 142 } else { 143 (void) fprintf(stderr, "%s\n", usage); 144 exit(1); 145 } 146 147 /* Count up the number of parameters. The arg format varies w/ cmd */ 148 switch (cmd) { 149 case CMD_ADD: 150 for (i = 3; i < argc; i++) { 151 /* argv[i] is the file path */ 152 153 /* The next arg is the alias */ 154 if (++i >= argc) { 155 (void) fprintf(stderr, "missing alias for %s\n", 156 argv[i - 1]); 157 exit(1); 158 } 159 160 cnt++; 161 } 162 break; 163 case CMD_ADDL: 164 cnt = argc - 3; 165 break; 166 case CMD_RM: 167 cnt = argc - 3; 168 break; 169 case CMD_CLR: /*FALLTHRU*/ 170 case CMD_GET: 171 if (argc > 3) { 172 (void) fprintf(stderr, "%s\n", usage); 173 exit(1); 174 } 175 break; 176 } 177 178 if (cnt > 0) { 179 if ((e = (hyprlofs_entry_t *)malloc(sizeof (hyprlofs_entry_t) * 180 cnt)) == NULL) { 181 (void) fprintf(stderr, "out of memory\n"); 182 exit(1); 183 } 184 } 185 186 /* 187 * Format up the args. 188 * We only setup the path member for the add cmd. 189 * We won't run this loop for the clear cmd. 190 * The addl command is special since we use basename to get the alias. 191 */ 192 for (i = 0, ap = 3; i < cnt; i++, ap++) { 193 if (cmd == CMD_ADDL) { 194 e[i].hle_path = argv[ap]; 195 e[i].hle_plen = strlen(e[i].hle_path); 196 197 e[i].hle_name = basename(argv[ap]); 198 e[i].hle_nlen = strlen(e[i].hle_name); 199 200 continue; 201 } 202 203 if (cmd == CMD_ADD) { 204 e[i].hle_path = argv[ap++]; 205 e[i].hle_plen = strlen(e[i].hle_path); 206 } 207 208 e[i].hle_name = argv[ap]; 209 e[i].hle_nlen = strlen(e[i].hle_name); 210 } 211 212 ents.hle_entries = e; 213 ents.hle_len = cnt; 214 215 switch (cmd) { 216 case CMD_ADD: /*FALLTHRU*/ 217 case CMD_ADDL: 218 if (ioctl(fd, HYPRLOFS_ADD_ENTRIES, &ents) < 0) { 219 perror("ioctl"); 220 rv = 1; 221 } 222 break; 223 case CMD_RM: 224 if (ioctl(fd, HYPRLOFS_RM_ENTRIES, &ents) < 0) { 225 perror("ioctl"); 226 rv = 1; 227 } 228 break; 229 case CMD_CLR: 230 if (ioctl(fd, HYPRLOFS_RM_ALL) < 0) { 231 perror("ioctl"); 232 rv = 1; 233 } 234 break; 235 case CMD_GET: 236 rv = get_entries(fd); 237 break; 238 } 239 240 (void) close(fd); 241 if (cnt > 0) 242 free(e); 243 return (rv); 244 }