mt.c (256281) | mt.c (280438) |
---|---|
1/* 2 * Copyright (c) 1980, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 12 unchanged lines hidden (view full) --- 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ | 1/* 2 * Copyright (c) 1980, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 12 unchanged lines hidden (view full) --- 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ |
29/*- 30 * Copyright (c) 2013, 2014, 2015 Spectra Logic Corporation 31 * All rights reserved. 32 * 33 * Redistribution and use in source and binary forms, with or without 34 * modification, are permitted provided that the following conditions 35 * are met: 36 * 1. Redistributions of source code must retain the above copyright 37 * notice, this list of conditions, and the following disclaimer, 38 * without modification. 39 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 40 * substantially similar to the "NO WARRANTY" disclaimer below 41 * ("Disclaimer") and any redistribution must be conditioned upon 42 * including a substantially similar Disclaimer requirement for further 43 * binary redistribution. 44 * 45 * NO WARRANTY 46 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 47 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 48 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 49 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 50 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 54 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 55 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 56 * POSSIBILITY OF SUCH DAMAGES. 57 * 58 * Authors: Ken Merry (Spectra Logic Corporation) 59 */ |
|
29 30#ifndef lint 31static const char copyright[] = 32"@(#) Copyright (c) 1980, 1993\n\ 33 The Regents of the University of California. All rights reserved.\n"; 34#endif /* not lint */ 35 36#ifndef lint 37#if 0 38static char sccsid[] = "@(#)mt.c 8.2 (Berkeley) 5/4/95"; 39#endif 40#endif /* not lint */ 41 42#include <sys/cdefs.h> | 60 61#ifndef lint 62static const char copyright[] = 63"@(#) Copyright (c) 1980, 1993\n\ 64 The Regents of the University of California. All rights reserved.\n"; 65#endif /* not lint */ 66 67#ifndef lint 68#if 0 69static char sccsid[] = "@(#)mt.c 8.2 (Berkeley) 5/4/95"; 70#endif 71#endif /* not lint */ 72 73#include <sys/cdefs.h> |
43__FBSDID("$FreeBSD: stable/10/usr.bin/mt/mt.c 228619 2011-12-17 02:23:30Z dim $"); | 74__FBSDID("$FreeBSD: stable/10/usr.bin/mt/mt.c 280438 2015-03-24 14:36:10Z ken $"); |
44 45/* 46 * mt -- 47 * magnetic tape manipulation program 48 */ 49#include <sys/types.h> 50#include <sys/ioctl.h> 51#include <sys/mtio.h> | 75 76/* 77 * mt -- 78 * magnetic tape manipulation program 79 */ 80#include <sys/types.h> 81#include <sys/ioctl.h> 82#include <sys/mtio.h> |
83#include <sys/queue.h> 84#include <sys/sbuf.h> |
|
52 53#include <ctype.h> 54#include <err.h> 55#include <fcntl.h> 56#include <stdio.h> 57#include <stdlib.h> 58#include <string.h> 59#include <unistd.h> | 85 86#include <ctype.h> 87#include <err.h> 88#include <fcntl.h> 89#include <stdio.h> 90#include <stdlib.h> 91#include <string.h> 92#include <unistd.h> |
93#include <stdint.h> 94#include <errno.h> 95#include <bsdxml.h> 96#include <mtlib.h> |
|
60 | 97 |
98#include <cam/cam.h> 99#include <cam/cam_ccb.h> 100#include <cam/cam_periph.h> 101#include <cam/scsi/scsi_all.h> 102#include <cam/scsi/scsi_sa.h> 103 |
|
61/* the appropriate sections of <sys/mtio.h> are also #ifdef'd for FreeBSD */ 62/* c_flags */ 63#define NEED_2ARGS 0x01 64#define ZERO_ALLOWED 0x02 65#define IS_DENSITY 0x04 66#define DISABLE_THIS 0x08 67#define IS_COMP 0x10 | 104/* the appropriate sections of <sys/mtio.h> are also #ifdef'd for FreeBSD */ 105/* c_flags */ 106#define NEED_2ARGS 0x01 107#define ZERO_ALLOWED 0x02 108#define IS_DENSITY 0x04 109#define DISABLE_THIS 0x08 110#define IS_COMP 0x10 |
111#define USE_GETOPT 0x20 |
|
68 69#ifndef TRUE 70#define TRUE 1 71#endif 72#ifndef FALSE 73#define FALSE 0 74#endif | 112 113#ifndef TRUE 114#define TRUE 1 115#endif 116#ifndef FALSE 117#define FALSE 0 118#endif |
119#ifndef MAX 120#define MAX(a, b) (a > b) ? a : b 121#endif 122#define MT_PLURAL(a) (a == 1) ? "" : "s" |
|
75 | 123 |
124typedef enum { 125 MT_CMD_NONE = MTLOAD + 1, 126 MT_CMD_PROTECT, 127 MT_CMD_GETDENSITY 128} mt_commands; 129 |
|
76static const struct commands { 77 const char *c_name; 78 unsigned long c_code; 79 int c_ronly; 80 int c_flags; 81} com[] = { 82 { "bsf", MTBSF, 1, 0 }, 83 { "bsr", MTBSR, 1, 0 }, 84 /* XXX FreeBSD considered "eof" dangerous, since it's being 85 confused with "eom" (and is an alias for "weof" anyway) */ 86 { "eof", MTWEOF, 0, DISABLE_THIS }, 87 { "fsf", MTFSF, 1, 0 }, 88 { "fsr", MTFSR, 1, 0 }, 89 { "offline", MTOFFL, 1, 0 }, | 130static const struct commands { 131 const char *c_name; 132 unsigned long c_code; 133 int c_ronly; 134 int c_flags; 135} com[] = { 136 { "bsf", MTBSF, 1, 0 }, 137 { "bsr", MTBSR, 1, 0 }, 138 /* XXX FreeBSD considered "eof" dangerous, since it's being 139 confused with "eom" (and is an alias for "weof" anyway) */ 140 { "eof", MTWEOF, 0, DISABLE_THIS }, 141 { "fsf", MTFSF, 1, 0 }, 142 { "fsr", MTFSR, 1, 0 }, 143 { "offline", MTOFFL, 1, 0 }, |
144 { "load", MTLOAD, 1, 0 }, |
|
90 { "rewind", MTREW, 1, 0 }, 91 { "rewoffl", MTOFFL, 1, 0 }, | 145 { "rewind", MTREW, 1, 0 }, 146 { "rewoffl", MTOFFL, 1, 0 }, |
92 { "status", MTNOP, 1, 0 }, | 147 { "ostatus", MTNOP, 1, 0 }, |
93 { "weof", MTWEOF, 0, ZERO_ALLOWED }, | 148 { "weof", MTWEOF, 0, ZERO_ALLOWED }, |
149 { "weofi", MTWEOFI, 0, ZERO_ALLOWED }, |
|
94 { "erase", MTERASE, 0, ZERO_ALLOWED}, 95 { "blocksize", MTSETBSIZ, 0, NEED_2ARGS|ZERO_ALLOWED }, 96 { "density", MTSETDNSTY, 0, NEED_2ARGS|ZERO_ALLOWED|IS_DENSITY }, 97 { "eom", MTEOD, 1, 0 }, 98 { "eod", MTEOD, 1, 0 }, 99 { "smk", MTWSS, 0, 0 }, 100 { "wss", MTWSS, 0, 0 }, 101 { "fss", MTFSS, 1, 0 }, --- 4 unchanged lines hidden (view full) --- 106 { "rdspos", MTIOCRDSPOS, 0, 0 }, 107 { "sethpos", MTIOCHLOCATE, 0, NEED_2ARGS|ZERO_ALLOWED }, 108 { "setspos", MTIOCSLOCATE, 0, NEED_2ARGS|ZERO_ALLOWED }, 109 { "errstat", MTIOCERRSTAT, 0, 0 }, 110 { "setmodel", MTIOCSETEOTMODEL, 0, NEED_2ARGS|ZERO_ALLOWED }, 111 { "seteotmodel", MTIOCSETEOTMODEL, 0, NEED_2ARGS|ZERO_ALLOWED }, 112 { "getmodel", MTIOCGETEOTMODEL, 0, 0 }, 113 { "geteotmodel", MTIOCGETEOTMODEL, 0, 0 }, | 150 { "erase", MTERASE, 0, ZERO_ALLOWED}, 151 { "blocksize", MTSETBSIZ, 0, NEED_2ARGS|ZERO_ALLOWED }, 152 { "density", MTSETDNSTY, 0, NEED_2ARGS|ZERO_ALLOWED|IS_DENSITY }, 153 { "eom", MTEOD, 1, 0 }, 154 { "eod", MTEOD, 1, 0 }, 155 { "smk", MTWSS, 0, 0 }, 156 { "wss", MTWSS, 0, 0 }, 157 { "fss", MTFSS, 1, 0 }, --- 4 unchanged lines hidden (view full) --- 162 { "rdspos", MTIOCRDSPOS, 0, 0 }, 163 { "sethpos", MTIOCHLOCATE, 0, NEED_2ARGS|ZERO_ALLOWED }, 164 { "setspos", MTIOCSLOCATE, 0, NEED_2ARGS|ZERO_ALLOWED }, 165 { "errstat", MTIOCERRSTAT, 0, 0 }, 166 { "setmodel", MTIOCSETEOTMODEL, 0, NEED_2ARGS|ZERO_ALLOWED }, 167 { "seteotmodel", MTIOCSETEOTMODEL, 0, NEED_2ARGS|ZERO_ALLOWED }, 168 { "getmodel", MTIOCGETEOTMODEL, 0, 0 }, 169 { "geteotmodel", MTIOCGETEOTMODEL, 0, 0 }, |
170 { "rblim", MTIOCRBLIM, 0, 0}, 171 { "getdensity", MT_CMD_GETDENSITY, 0, USE_GETOPT}, 172 { "status", MTIOCEXTGET, 0, USE_GETOPT }, 173 { "locate", MTIOCEXTLOCATE, 0, USE_GETOPT }, 174 { "param", MTIOCPARAMGET, 0, USE_GETOPT }, 175 { "protect", MT_CMD_PROTECT, 0, USE_GETOPT }, |
|
114 { NULL, 0, 0, 0 } 115}; 116 | 176 { NULL, 0, 0, 0 } 177}; 178 |
179 |
|
117static const char *getblksiz(int); 118static void printreg(const char *, u_int, const char *); 119static void status(struct mtget *); 120static void usage(void); | 180static const char *getblksiz(int); 181static void printreg(const char *, u_int, const char *); 182static void status(struct mtget *); 183static void usage(void); |
121static void st_status(struct mtget *); 122static int stringtodens(const char *s); 123static const char *denstostring(int d); 124static int denstobp(int d, int bpi); | 184const char *get_driver_state_str(int dsreg); 185static void st_status (struct mtget *); 186static int mt_locate(int argc, char **argv, int mtfd, const char *tape); 187static int nstatus_print(int argc, char **argv, char *xml_str, 188 struct mt_status_data *status_data); 189static int mt_xml_cmd(unsigned long cmd, int argc, char **argv, int mtfd, 190 const char *tape); 191static int mt_print_density_entry(struct mt_status_entry *density_root, int indent); 192static int mt_print_density_report(struct mt_status_entry *report_root, int indent); 193static int mt_print_density(struct mt_status_entry *density_root, int indent); 194static int mt_getdensity(int argc, char **argv, char *xml_str, 195 struct mt_status_data *status_data); 196static int mt_set_param(int mtfd, struct mt_status_data *status_data, 197 char *param_name, char *param_value); 198static int mt_protect(int argc, char **argv, int mtfd, 199 struct mt_status_data *status_data); 200static int mt_param(int argc, char **argv, int mtfd, char *xml_str, 201 struct mt_status_data *status_data); 202static const char *denstostring (int d); |
125static u_int32_t stringtocomp(const char *s); 126static const char *comptostring(u_int32_t comp); 127static void warn_eof(void); 128 129int 130main(int argc, char *argv[]) 131{ 132 const struct commands *comp; 133 struct mtget mt_status; 134 struct mtop mt_com; 135 int ch, len, mtfd; 136 const char *p, *tape; 137 | 203static u_int32_t stringtocomp(const char *s); 204static const char *comptostring(u_int32_t comp); 205static void warn_eof(void); 206 207int 208main(int argc, char *argv[]) 209{ 210 const struct commands *comp; 211 struct mtget mt_status; 212 struct mtop mt_com; 213 int ch, len, mtfd; 214 const char *p, *tape; 215 |
216 bzero(&mt_com, sizeof(mt_com)); 217 |
|
138 if ((tape = getenv("TAPE")) == NULL) 139 tape = DEFTAPE; 140 141 while ((ch = getopt(argc, argv, "f:t:")) != -1) 142 switch(ch) { 143 case 'f': 144 case 't': 145 tape = optarg; 146 break; 147 case '?': | 218 if ((tape = getenv("TAPE")) == NULL) 219 tape = DEFTAPE; 220 221 while ((ch = getopt(argc, argv, "f:t:")) != -1) 222 switch(ch) { 223 case 'f': 224 case 't': 225 tape = optarg; 226 break; 227 case '?': |
148 default: | |
149 usage(); | 228 usage(); |
229 break; 230 default: 231 break; |
|
150 } 151 argc -= optind; 152 argv += optind; 153 | 232 } 233 argc -= optind; 234 argv += optind; 235 |
154 if (argc < 1 || argc > 2) | 236 if (argc < 1) |
155 usage(); 156 157 len = strlen(p = *argv++); 158 for (comp = com;; comp++) { 159 if (comp->c_name == NULL) 160 errx(1, "%s: unknown command", p); 161 if (strncmp(p, comp->c_name, len) == 0) 162 break; 163 } 164 if((comp->c_flags & NEED_2ARGS) && argc != 2) 165 usage(); 166 if(comp->c_flags & DISABLE_THIS) { 167 warn_eof(); 168 } | 237 usage(); 238 239 len = strlen(p = *argv++); 240 for (comp = com;; comp++) { 241 if (comp->c_name == NULL) 242 errx(1, "%s: unknown command", p); 243 if (strncmp(p, comp->c_name, len) == 0) 244 break; 245 } 246 if((comp->c_flags & NEED_2ARGS) && argc != 2) 247 usage(); 248 if(comp->c_flags & DISABLE_THIS) { 249 warn_eof(); 250 } |
251 if (comp->c_flags & USE_GETOPT) { 252 argc--; 253 optind = 0; 254 } 255 |
|
169 if ((mtfd = open(tape, comp->c_ronly ? O_RDONLY : O_RDWR)) < 0) 170 err(1, "%s", tape); 171 if (comp->c_code != MTNOP) { 172 mt_com.mt_op = comp->c_code; 173 if (*argv) { 174 if (!isdigit(**argv) && 175 (comp->c_flags & IS_DENSITY)) { 176 const char *dcanon; | 256 if ((mtfd = open(tape, comp->c_ronly ? O_RDONLY : O_RDWR)) < 0) 257 err(1, "%s", tape); 258 if (comp->c_code != MTNOP) { 259 mt_com.mt_op = comp->c_code; 260 if (*argv) { 261 if (!isdigit(**argv) && 262 (comp->c_flags & IS_DENSITY)) { 263 const char *dcanon; |
177 mt_com.mt_count = stringtodens(*argv); | 264 mt_com.mt_count = mt_density_num(*argv); |
178 if (mt_com.mt_count == 0) 179 errx(1, "%s: unknown density", *argv); 180 dcanon = denstostring(mt_com.mt_count); 181 if (strcmp(dcanon, *argv) != 0) 182 printf( 183 "Using \"%s\" as an alias for %s\n", 184 *argv, dcanon); 185 p = ""; 186 } else if (!isdigit(**argv) && 187 (comp->c_flags & IS_COMP)) { 188 189 mt_com.mt_count = stringtocomp(*argv); 190 if ((u_int32_t)mt_com.mt_count == 0xf0f0f0f0) 191 errx(1, "%s: unknown compression", 192 *argv); 193 p = ""; | 265 if (mt_com.mt_count == 0) 266 errx(1, "%s: unknown density", *argv); 267 dcanon = denstostring(mt_com.mt_count); 268 if (strcmp(dcanon, *argv) != 0) 269 printf( 270 "Using \"%s\" as an alias for %s\n", 271 *argv, dcanon); 272 p = ""; 273 } else if (!isdigit(**argv) && 274 (comp->c_flags & IS_COMP)) { 275 276 mt_com.mt_count = stringtocomp(*argv); 277 if ((u_int32_t)mt_com.mt_count == 0xf0f0f0f0) 278 errx(1, "%s: unknown compression", 279 *argv); 280 p = ""; |
194 } else { | 281 } else if ((comp->c_flags & USE_GETOPT) == 0) { |
195 char *q; 196 /* allow for hex numbers; useful for density */ 197 mt_com.mt_count = strtol(*argv, &q, 0); 198 p = q; 199 } | 282 char *q; 283 /* allow for hex numbers; useful for density */ 284 mt_com.mt_count = strtol(*argv, &q, 0); 285 p = q; 286 } |
200 if ((mt_com.mt_count <= 201 ((comp->c_flags & ZERO_ALLOWED)? -1: 0) 202 && ((comp->c_flags & IS_COMP) == 0) 203 ) || *p) | 287 if (((comp->c_flags & USE_GETOPT) == 0) 288 && (((mt_com.mt_count <= 289 ((comp->c_flags & ZERO_ALLOWED)? -1: 0)) 290 && ((comp->c_flags & IS_COMP) == 0)) 291 || *p)) |
204 errx(1, "%s: illegal count", *argv); 205 } 206 else 207 mt_com.mt_count = 1; 208 switch (comp->c_code) { 209 case MTIOCERRSTAT: 210 { 211 unsigned int i; --- 72 unchanged lines hidden (view full) --- 284 err(2, "%s", tape); 285 (void)printf("%s: old model was %u filemar%s at EOT\n", 286 tape, om, (om > 1)? "ks" : "k"); 287 (void)printf("%s: new model is %u filemar%s at EOT\n", 288 tape, nm, (nm > 1)? "ks" : "k"); 289 exit(0); 290 /* NOTREACHED */ 291 } | 292 errx(1, "%s: illegal count", *argv); 293 } 294 else 295 mt_com.mt_count = 1; 296 switch (comp->c_code) { 297 case MTIOCERRSTAT: 298 { 299 unsigned int i; --- 72 unchanged lines hidden (view full) --- 372 err(2, "%s", tape); 373 (void)printf("%s: old model was %u filemar%s at EOT\n", 374 tape, om, (om > 1)? "ks" : "k"); 375 (void)printf("%s: new model is %u filemar%s at EOT\n", 376 tape, nm, (nm > 1)? "ks" : "k"); 377 exit(0); 378 /* NOTREACHED */ 379 } |
380 case MTIOCRBLIM: 381 { 382 struct mtrblim rblim; 383 384 bzero(&rblim, sizeof(rblim)); 385 386 if (ioctl(mtfd, MTIOCRBLIM, (caddr_t)&rblim) < 0) 387 err(2, "%s", tape); 388 (void)printf("%s:\n" 389 " min blocksize %u byte%s\n" 390 " max blocksize %u byte%s\n" 391 " granularity %u byte%s\n", 392 tape, rblim.min_block_length, 393 MT_PLURAL(rblim.min_block_length), 394 rblim.max_block_length, 395 MT_PLURAL(rblim.max_block_length), 396 (1 << rblim.granularity), 397 MT_PLURAL((1 << rblim.granularity))); 398 exit(0); 399 /* NOTREACHED */ 400 } 401 case MTIOCPARAMGET: 402 case MTIOCEXTGET: 403 case MT_CMD_PROTECT: 404 case MT_CMD_GETDENSITY: 405 { 406 int retval = 0; 407 408 retval = mt_xml_cmd(comp->c_code, argc, argv, mtfd, 409 tape); 410 411 exit(retval); 412 } 413 case MTIOCEXTLOCATE: 414 { 415 int retval = 0; 416 417 retval = mt_locate(argc, argv, mtfd, tape); 418 419 exit(retval); 420 } |
|
292 default: 293 break; 294 } 295 if (ioctl(mtfd, MTIOCTOP, &mt_com) < 0) 296 err(1, "%s: %s", tape, comp->c_name); 297 } else { 298 if (ioctl(mtfd, MTIOCGET, &mt_status) < 0) 299 err(1, NULL); --- 76 unchanged lines hidden (view full) --- 376 377static void 378usage(void) 379{ 380 (void)fprintf(stderr, "usage: mt [-f device] command [count]\n"); 381 exit(1); 382} 383 | 421 default: 422 break; 423 } 424 if (ioctl(mtfd, MTIOCTOP, &mt_com) < 0) 425 err(1, "%s: %s", tape, comp->c_name); 426 } else { 427 if (ioctl(mtfd, MTIOCGET, &mt_status) < 0) 428 err(1, NULL); --- 76 unchanged lines hidden (view full) --- 505 506static void 507usage(void) 508{ 509 (void)fprintf(stderr, "usage: mt [-f device] command [count]\n"); 510 exit(1); 511} 512 |
384static const struct densities { 385 int dens; 386 int bpmm; 387 int bpi; 388 const char *name; 389} dens[] = { 390 /* 391 * Taken from T10 Project 997D 392 * SCSI-3 Stream Device Commands (SSC) 393 * Revision 11, 4-Nov-97 394 */ 395 /*Num. bpmm bpi Reference */ 396 { 0x1, 32, 800, "X3.22-1983" }, 397 { 0x2, 63, 1600, "X3.39-1986" }, 398 { 0x3, 246, 6250, "X3.54-1986" }, 399 { 0x5, 315, 8000, "X3.136-1986" }, 400 { 0x6, 126, 3200, "X3.157-1987" }, 401 { 0x7, 252, 6400, "X3.116-1986" }, 402 { 0x8, 315, 8000, "X3.158-1987" }, 403 { 0x9, 491, 37871, "X3.180" }, 404 { 0xA, 262, 6667, "X3B5/86-199" }, 405 { 0xB, 63, 1600, "X3.56-1986" }, 406 { 0xC, 500, 12690, "HI-TC1" }, 407 { 0xD, 999, 25380, "HI-TC2" }, 408 { 0xF, 394, 10000, "QIC-120" }, 409 { 0x10, 394, 10000, "QIC-150" }, 410 { 0x11, 630, 16000, "QIC-320" }, 411 { 0x12, 2034, 51667, "QIC-1350" }, 412 { 0x13, 2400, 61000, "X3B5/88-185A" }, 413 { 0x14, 1703, 43245, "X3.202-1991" }, 414 { 0x15, 1789, 45434, "ECMA TC17" }, 415 { 0x16, 394, 10000, "X3.193-1990" }, 416 { 0x17, 1673, 42500, "X3B5/91-174" }, 417 { 0x18, 1673, 42500, "X3B5/92-50" }, 418 { 0x19, 2460, 62500, "DLTapeIII" }, 419 { 0x1A, 3214, 81633, "DLTapeIV(20GB)" }, 420 { 0x1B, 3383, 85937, "DLTapeIV(35GB)" }, 421 { 0x1C, 1654, 42000, "QIC-385M" }, 422 { 0x1D, 1512, 38400, "QIC-410M" }, 423 { 0x1E, 1385, 36000, "QIC-1000C" }, 424 { 0x1F, 2666, 67733, "QIC-2100C" }, 425 { 0x20, 2666, 67733, "QIC-6GB(M)" }, 426 { 0x21, 2666, 67733, "QIC-20GB(C)" }, 427 { 0x22, 1600, 40640, "QIC-2GB(C)" }, 428 { 0x23, 2666, 67733, "QIC-875M" }, 429 { 0x24, 2400, 61000, "DDS-2" }, 430 { 0x25, 3816, 97000, "DDS-3" }, 431 { 0x26, 3816, 97000, "DDS-4" }, 432 { 0x27, 3056, 77611, "Mammoth" }, 433 { 0x28, 1491, 37871, "X3.224" }, 434 { 0x41, 3868, 98250, "DLTapeIV(40GB)" }, 435 { 0x48, 5236, 133000, "SDLTapeI(110)" }, 436 { 0x49, 7598, 193000, "SDLTapeI(160)" }, 437 { 0, 0, 0, NULL } 438}; 439 | |
440static const struct compression_types { 441 u_int32_t comp_number; 442 const char *name; 443} comp_types[] = { 444 { 0x00, "none" }, 445 { 0x00, "off" }, 446 { 0x10, "IDRC" }, 447 { 0x20, "DCLZ" }, 448 { 0xffffffff, "enable" }, 449 { 0xffffffff, "on" }, 450 { 0xf0f0f0f0, NULL} 451}; 452 453static const char * 454denstostring(int d) 455{ 456 static char buf[20]; | 513static const struct compression_types { 514 u_int32_t comp_number; 515 const char *name; 516} comp_types[] = { 517 { 0x00, "none" }, 518 { 0x00, "off" }, 519 { 0x10, "IDRC" }, 520 { 0x20, "DCLZ" }, 521 { 0xffffffff, "enable" }, 522 { 0xffffffff, "on" }, 523 { 0xf0f0f0f0, NULL} 524}; 525 526static const char * 527denstostring(int d) 528{ 529 static char buf[20]; |
457 const struct densities *sd; | 530 const char *name = mt_density_name(d); |
458 | 531 |
459 /* densities 0 and 0x7f are handled as special cases */ 460 if (d == 0) 461 return "default"; 462 if (d == 0x7f) 463 return "same"; 464 for (sd = dens; sd->dens; sd++) 465 if (sd->dens == d) 466 break; 467 if (sd->dens == 0) | 532 if (name == NULL) |
468 sprintf(buf, "0x%02x", d); 469 else | 533 sprintf(buf, "0x%02x", d); 534 else |
470 sprintf(buf, "0x%02x:%s", d, sd->name); | 535 sprintf(buf, "0x%02x:%s", d, name); |
471 return buf; 472} 473 | 536 return buf; 537} 538 |
474/* 475 * Given a specific density number, return either the bits per inch or bits 476 * per millimeter for the given density. 477 */ 478static int 479denstobp(int d, int bpi) 480{ 481 const struct densities *sd; 482 483 for (sd = dens; sd->dens; sd++) 484 if (sd->dens == d) 485 break; 486 if (sd->dens == 0) 487 return(0); 488 else { 489 if (bpi) 490 return(sd->bpi); 491 else 492 return(sd->bpmm); 493 } 494} 495 496static int 497stringtodens(const char *s) 498{ 499 const struct densities *sd; 500 size_t l = strlen(s); 501 502 for (sd = dens; sd->dens; sd++) 503 if (strncasecmp(sd->name, s, l) == 0) 504 break; 505 return sd->dens; 506} 507 508 | |
509static const char * 510getblksiz(int bs) 511{ 512 static char buf[25]; 513 if (bs == 0) 514 return "variable"; 515 else { 516 sprintf(buf, "%d bytes", bs); --- 31 unchanged lines hidden (view full) --- 548 549 for (ct = comp_types; ct->name; ct++) 550 if (strncasecmp(ct->name, s, l) == 0) 551 break; 552 553 return(ct->comp_number); 554} 555 | 539static const char * 540getblksiz(int bs) 541{ 542 static char buf[25]; 543 if (bs == 0) 544 return "variable"; 545 else { 546 sprintf(buf, "%d bytes", bs); --- 31 unchanged lines hidden (view full) --- 578 579 for (ct = comp_types; ct->name; ct++) 580 if (strncasecmp(ct->name, s, l) == 0) 581 break; 582 583 return(ct->comp_number); 584} 585 |
586static struct driver_state { 587 int dsreg; 588 const char *desc; 589} driver_states[] = { 590 { MTIO_DSREG_REST, "at rest" }, 591 { MTIO_DSREG_RBSY, "Communicating with drive" }, 592 { MTIO_DSREG_WR, "Writing" }, 593 { MTIO_DSREG_FMK, "Writing Filemarks" }, 594 { MTIO_DSREG_ZER, "Erasing" }, 595 { MTIO_DSREG_RD, "Reading" }, 596 { MTIO_DSREG_FWD, "Spacing Forward" }, 597 { MTIO_DSREG_REV, "Spacing Reverse" }, 598 { MTIO_DSREG_POS, "Hardware Positioning (direction unknown)" }, 599 { MTIO_DSREG_REW, "Rewinding" }, 600 { MTIO_DSREG_TEN, "Retensioning" }, 601 { MTIO_DSREG_UNL, "Unloading" }, 602 { MTIO_DSREG_LD, "Loading" }, 603}; 604 605const char * 606get_driver_state_str(int dsreg) 607{ 608 unsigned int i; 609 610 for (i = 0; i < (sizeof(driver_states)/sizeof(driver_states[0])); i++) { 611 if (driver_states[i].dsreg == dsreg) 612 return (driver_states[i].desc); 613 } 614 615 return (NULL); 616} 617 |
|
556static void 557st_status(struct mtget *bp) 558{ 559 printf("Mode Density Blocksize bpi " 560 "Compression\n" 561 "Current: %-17s %-12s %-7d %s\n" 562 "---------available modes---------\n" 563 "0: %-17s %-12s %-7d %s\n" 564 "1: %-17s %-12s %-7d %s\n" 565 "2: %-17s %-12s %-7d %s\n" 566 "3: %-17s %-12s %-7d %s\n", 567 denstostring(bp->mt_density), getblksiz(bp->mt_blksiz), | 618static void 619st_status(struct mtget *bp) 620{ 621 printf("Mode Density Blocksize bpi " 622 "Compression\n" 623 "Current: %-17s %-12s %-7d %s\n" 624 "---------available modes---------\n" 625 "0: %-17s %-12s %-7d %s\n" 626 "1: %-17s %-12s %-7d %s\n" 627 "2: %-17s %-12s %-7d %s\n" 628 "3: %-17s %-12s %-7d %s\n", 629 denstostring(bp->mt_density), getblksiz(bp->mt_blksiz), |
568 denstobp(bp->mt_density, TRUE), comptostring(bp->mt_comp), | 630 mt_density_bp(bp->mt_density, TRUE), comptostring(bp->mt_comp), |
569 denstostring(bp->mt_density0), getblksiz(bp->mt_blksiz0), | 631 denstostring(bp->mt_density0), getblksiz(bp->mt_blksiz0), |
570 denstobp(bp->mt_density0, TRUE), comptostring(bp->mt_comp0), | 632 mt_density_bp(bp->mt_density0, TRUE), comptostring(bp->mt_comp0), |
571 denstostring(bp->mt_density1), getblksiz(bp->mt_blksiz1), | 633 denstostring(bp->mt_density1), getblksiz(bp->mt_blksiz1), |
572 denstobp(bp->mt_density1, TRUE), comptostring(bp->mt_comp1), | 634 mt_density_bp(bp->mt_density1, TRUE), comptostring(bp->mt_comp1), |
573 denstostring(bp->mt_density2), getblksiz(bp->mt_blksiz2), | 635 denstostring(bp->mt_density2), getblksiz(bp->mt_blksiz2), |
574 denstobp(bp->mt_density2, TRUE), comptostring(bp->mt_comp2), | 636 mt_density_bp(bp->mt_density2, TRUE), comptostring(bp->mt_comp2), |
575 denstostring(bp->mt_density3), getblksiz(bp->mt_blksiz3), | 637 denstostring(bp->mt_density3), getblksiz(bp->mt_blksiz3), |
576 denstobp(bp->mt_density3, TRUE), comptostring(bp->mt_comp3)); | 638 mt_density_bp(bp->mt_density3, TRUE), comptostring(bp->mt_comp3)); |
577 578 if (bp->mt_dsreg != MTIO_DSREG_NIL) { | 639 640 if (bp->mt_dsreg != MTIO_DSREG_NIL) { |
579 auto char foo[32]; | |
580 const char sfmt[] = "Current Driver State: %s.\n"; 581 printf("---------------------------------\n"); | 641 const char sfmt[] = "Current Driver State: %s.\n"; 642 printf("---------------------------------\n"); |
582 switch (bp->mt_dsreg) { 583 case MTIO_DSREG_REST: 584 printf(sfmt, "at rest"); | 643 const char *state_str; 644 645 state_str = get_driver_state_str(bp->mt_dsreg); 646 if (state_str == NULL) { 647 char foo[32]; 648 (void) sprintf(foo, "Unknown state 0x%x", bp->mt_dsreg); 649 printf(sfmt, foo); 650 } else { 651 printf(sfmt, state_str); 652 } 653 } 654 if (bp->mt_resid == 0 && bp->mt_fileno == (daddr_t) -1 && 655 bp->mt_blkno == (daddr_t) -1) 656 return; 657 printf("---------------------------------\n"); 658 printf("File Number: %d\tRecord Number: %d\tResidual Count %d\n", 659 bp->mt_fileno, bp->mt_blkno, bp->mt_resid); 660} 661 662static int 663mt_locate(int argc, char **argv, int mtfd, const char *tape) 664{ 665 struct mtlocate mtl; 666 uint64_t logical_id = 0; 667 mt_locate_dest_type dest_type = MT_LOCATE_DEST_FILE; 668 int eod = 0, explicit = 0, immediate = 0; 669 int64_t partition = 0; 670 int block_addr_set = 0, partition_set = 0, file_set = 0, set_set = 0; 671 int c, retval; 672 673 retval = 0; 674 bzero(&mtl, sizeof(mtl)); 675 676 while ((c = getopt(argc, argv, "b:eEf:ip:s:")) != -1) { 677 switch (c) { 678 case 'b': 679 /* Block address */ 680 logical_id = strtoull(optarg, NULL, 0); 681 dest_type = MT_LOCATE_DEST_OBJECT; 682 block_addr_set = 1; |
585 break; | 683 break; |
586 case MTIO_DSREG_RBSY: 587 printf(sfmt, "Communicating with drive"); | 684 case 'e': 685 /* end of data */ 686 eod = 1; 687 dest_type = MT_LOCATE_DEST_EOD; |
588 break; | 688 break; |
589 case MTIO_DSREG_WR: 590 printf(sfmt, "Writing"); | 689 case 'E': 690 /* 691 * XXX KDM explicit address mode. Should we even 692 * allow this, since the driver doesn't operate in 693 * explicit address mode? 694 */ 695 explicit = 1; |
591 break; | 696 break; |
592 case MTIO_DSREG_FMK: 593 printf(sfmt, "Writing Filemarks"); | 697 case 'f': 698 /* file number */ 699 logical_id = strtoull(optarg, NULL, 0); 700 dest_type = MT_LOCATE_DEST_FILE; 701 file_set = 1; |
594 break; | 702 break; |
595 case MTIO_DSREG_ZER: 596 printf(sfmt, "Erasing"); | 703 case 'i': 704 /* 705 * Immediate address mode. XXX KDM do we want to 706 * implement this? The other commands in the 707 * tape driver will need to be able to handle this. 708 */ 709 immediate = 1; |
597 break; | 710 break; |
598 case MTIO_DSREG_RD: 599 printf(sfmt, "Reading"); | 711 case 'p': 712 /* 713 * Change partition to the given partition. 714 */ 715 partition = strtol(optarg, NULL, 0); 716 partition_set = 1; |
600 break; | 717 break; |
601 case MTIO_DSREG_FWD: 602 printf(sfmt, "Spacing Forward"); | 718 case 's': 719 /* Go to the given set mark */ 720 logical_id = strtoull(optarg, NULL, 0); 721 dest_type = MT_LOCATE_DEST_SET; 722 set_set = 1; |
603 break; | 723 break; |
604 case MTIO_DSREG_REV: 605 printf(sfmt, "Spacing Reverse"); | 724 default: |
606 break; | 725 break; |
607 case MTIO_DSREG_POS: 608 printf(sfmt, 609 "Hardware Positioning (direction unknown)"); | 726 } 727 } 728 729 /* 730 * These options are mutually exclusive. The user may only specify 731 * one. 732 */ 733 if ((block_addr_set + file_set + eod + set_set) != 1) 734 errx(1, "You must specify only one of -b, -f, -e, or -s"); 735 736 mtl.dest_type = dest_type; 737 switch (dest_type) { 738 case MT_LOCATE_DEST_OBJECT: 739 case MT_LOCATE_DEST_FILE: 740 case MT_LOCATE_DEST_SET: 741 mtl.logical_id = logical_id; 742 break; 743 case MT_LOCATE_DEST_EOD: 744 break; 745 } 746 747 if (immediate != 0) 748 mtl.flags |= MT_LOCATE_FLAG_IMMED; 749 750 if (partition_set != 0) { 751 mtl.flags |= MT_LOCATE_FLAG_CHANGE_PART; 752 mtl.partition = partition; 753 } 754 755 if (explicit != 0) 756 mtl.block_address_mode = MT_LOCATE_BAM_EXPLICIT; 757 else 758 mtl.block_address_mode = MT_LOCATE_BAM_IMPLICIT; 759 760 if (ioctl(mtfd, MTIOCEXTLOCATE, &mtl) == -1) 761 err(1, "MTIOCEXTLOCATE ioctl failed on %s", tape); 762 763 return (retval); 764} 765 766typedef enum { 767 MT_PERIPH_NAME = 0, 768 MT_UNIT_NUMBER = 1, 769 MT_VENDOR = 2, 770 MT_PRODUCT = 3, 771 MT_REVISION = 4, 772 MT_COMPRESSION_SUPPORTED = 5, 773 MT_COMPRESSION_ENABLED = 6, 774 MT_COMPRESSION_ALGORITHM = 7, 775 MT_MEDIA_DENSITY = 8, 776 MT_MEDIA_BLOCKSIZE = 9, 777 MT_CALCULATED_FILENO = 10, 778 MT_CALCULATED_REL_BLKNO = 11, 779 MT_REPORTED_FILENO = 12, 780 MT_REPORTED_BLKNO = 13, 781 MT_PARTITION = 14, 782 MT_BOP = 15, 783 MT_EOP = 16, 784 MT_BPEW = 17, 785 MT_DSREG = 18, 786 MT_RESID = 19, 787 MT_FIXED_MODE = 20, 788 MT_SERIAL_NUM = 21, 789 MT_MAXIO = 22, 790 MT_CPI_MAXIO = 23, 791 MT_MAX_BLK = 24, 792 MT_MIN_BLK = 25, 793 MT_BLK_GRAN = 26, 794 MT_MAX_EFF_IOSIZE = 27 795} status_item_index; 796 797static struct mt_status_items { 798 const char *name; 799 struct mt_status_entry *entry; 800} req_status_items[] = { 801 { "periph_name", NULL }, 802 { "unit_number", NULL }, 803 { "vendor", NULL }, 804 { "product", NULL }, 805 { "revision", NULL }, 806 { "compression_supported", NULL }, 807 { "compression_enabled", NULL }, 808 { "compression_algorithm", NULL }, 809 { "media_density", NULL }, 810 { "media_blocksize", NULL }, 811 { "calculated_fileno", NULL }, 812 { "calculated_rel_blkno", NULL }, 813 { "reported_fileno", NULL }, 814 { "reported_blkno", NULL }, 815 { "partition", NULL }, 816 { "bop", NULL }, 817 { "eop", NULL }, 818 { "bpew", NULL }, 819 { "dsreg", NULL }, 820 { "residual", NULL }, 821 { "fixed_mode", NULL }, 822 { "serial_num", NULL }, 823 { "maxio", NULL }, 824 { "cpi_maxio", NULL }, 825 { "max_blk", NULL }, 826 { "min_blk", NULL }, 827 { "blk_gran", NULL }, 828 { "max_effective_iosize", NULL } 829}; 830 831int 832nstatus_print(int argc, char **argv, char *xml_str, 833 struct mt_status_data *status_data) 834{ 835 unsigned int i; 836 int64_t calculated_fileno, calculated_rel_blkno; 837 int64_t rep_fileno, rep_blkno, partition, resid; 838 char block_str[32]; 839 const char *dens_str; 840 int dsreg, bop, eop, bpew; 841 int xml_dump = 0; 842 size_t dens_len; 843 unsigned int field_width; 844 int verbose = 0; 845 int c; 846 847 while ((c = getopt(argc, argv, "xv")) != -1) { 848 switch (c) { 849 case 'x': 850 xml_dump = 1; |
610 break; | 851 break; |
611 case MTIO_DSREG_REW: 612 printf(sfmt, "Rewinding"); | 852 case 'v': 853 verbose = 1; |
613 break; | 854 break; |
614 case MTIO_DSREG_TEN: 615 printf(sfmt, "Retensioning"); | 855 default: |
616 break; | 856 break; |
617 case MTIO_DSREG_UNL: 618 printf(sfmt, "Unloading"); | 857 } 858 } 859 860 if (xml_dump != 0) { 861 printf("%s", xml_str); 862 return (0); 863 } 864 865 for (i = 0; i < (sizeof(req_status_items)/sizeof(req_status_items[0])); 866 i++) { 867 char *name; 868 869 name = __DECONST(char *, req_status_items[i].name); 870 req_status_items[i].entry = mt_status_entry_find(status_data, 871 name); 872 if (req_status_items[i].entry == NULL) { 873 errx(1, "Cannot find status entry %s", 874 req_status_items[i].name); 875 } 876 } 877 878 printf("Drive: %s%ju: <%s %s %s> Serial Number: %s\n", 879 req_status_items[MT_PERIPH_NAME].entry->value, 880 (uintmax_t)req_status_items[MT_UNIT_NUMBER].entry->value_unsigned, 881 req_status_items[MT_VENDOR].entry->value, 882 req_status_items[MT_PRODUCT].entry->value, 883 req_status_items[MT_REVISION].entry->value, 884 (req_status_items[MT_SERIAL_NUM].entry->value) ? 885 req_status_items[MT_SERIAL_NUM].entry->value : "none"); 886 printf("---------------------------------\n"); 887 888 /* 889 * We check to see whether we're in fixed mode or not, and don't 890 * just believe the blocksize. If the SILI bit is turned on, the 891 * blocksize will be set to 4, even though we're doing variable 892 * length (well, multiples of 4) blocks. 893 */ 894 if (req_status_items[MT_FIXED_MODE].entry->value_signed == 0) 895 snprintf(block_str, sizeof(block_str), "variable"); 896 else 897 snprintf(block_str, sizeof(block_str), "%s", 898 getblksiz(req_status_items[ 899 MT_MEDIA_BLOCKSIZE].entry->value_unsigned)); 900 901 dens_str = denstostring(req_status_items[ 902 MT_MEDIA_DENSITY].entry->value_unsigned); 903 if (dens_str == NULL) 904 dens_len = 0; 905 else 906 dens_len = strlen(dens_str); 907 field_width = MAX(dens_len, 17); 908 printf("Mode %-*s Blocksize bpi Compression\n" 909 "Current: %-*s %-12s %-7d ", 910 field_width, "Density", field_width, dens_str, block_str, 911 mt_density_bp(req_status_items[ 912 MT_MEDIA_DENSITY].entry->value_unsigned, TRUE)); 913 914 if (req_status_items[MT_COMPRESSION_SUPPORTED].entry->value_signed == 0) 915 printf("unsupported\n"); 916 else if (req_status_items[ 917 MT_COMPRESSION_ENABLED].entry->value_signed == 0) 918 printf("disabled\n"); 919 else { 920 printf("enabled (%s)\n", 921 comptostring(req_status_items[ 922 MT_COMPRESSION_ALGORITHM].entry->value_unsigned)); 923 } 924 925 dsreg = req_status_items[MT_DSREG].entry->value_signed; 926 if (dsreg != MTIO_DSREG_NIL) { 927 const char sfmt[] = "Current Driver State: %s.\n"; 928 printf("---------------------------------\n"); 929 const char *state_str; 930 931 state_str = get_driver_state_str(dsreg); 932 if (state_str == NULL) { 933 char foo[32]; 934 (void) sprintf(foo, "Unknown state 0x%x", dsreg); 935 printf(sfmt, foo); 936 } else { 937 printf(sfmt, state_str); 938 } 939 } 940 resid = req_status_items[MT_RESID].entry->value_signed; 941 calculated_fileno = req_status_items[ 942 MT_CALCULATED_FILENO].entry->value_signed; 943 calculated_rel_blkno = req_status_items[ 944 MT_CALCULATED_REL_BLKNO].entry->value_signed; 945 rep_fileno = req_status_items[ 946 MT_REPORTED_FILENO].entry->value_signed; 947 rep_blkno = req_status_items[ 948 MT_REPORTED_BLKNO].entry->value_signed; 949 bop = req_status_items[MT_BOP].entry->value_signed; 950 eop = req_status_items[MT_EOP].entry->value_signed; 951 bpew = req_status_items[MT_BPEW].entry->value_signed; 952 partition = req_status_items[MT_PARTITION].entry->value_signed; 953 954 printf("---------------------------------\n"); 955 printf("Partition: %3jd Calc File Number: %3jd " 956 " Calc Record Number: %jd\n" 957 "Residual: %3jd Reported File Number: %3jd " 958 "Reported Record Number: %jd\n", partition, calculated_fileno, 959 calculated_rel_blkno, resid, rep_fileno, rep_blkno); 960 961 printf("Flags: "); 962 if (bop > 0 || eop > 0 || bpew > 0) { 963 int need_comma = 0; 964 965 if (bop > 0) { 966 printf("BOP"); 967 need_comma = 1; 968 } 969 if (eop > 0) { 970 if (need_comma != 0) 971 printf(","); 972 printf("EOP"); 973 need_comma = 1; 974 } 975 if (bpew > 0) { 976 if (need_comma != 0) 977 printf(","); 978 printf("BPEW"); 979 need_comma = 1; 980 } 981 } else { 982 printf("None"); 983 } 984 printf("\n"); 985 if (verbose != 0) { 986 printf("---------------------------------\n"); 987 printf("Tape I/O parameters:\n"); 988 for (i = MT_MAXIO; i <= MT_MAX_EFF_IOSIZE; i++) { 989 printf(" %s (%s): %ju bytes\n", 990 req_status_items[i].entry->desc, 991 req_status_items[i].name, 992 req_status_items[i].entry->value_unsigned); 993 } 994 } 995 996 return (0); 997} 998 999int 1000mt_xml_cmd(unsigned long cmd, int argc, char **argv, int mtfd, const char *tape) 1001{ 1002 struct mt_status_data status_data; 1003#if 0 1004 struct mt_status_entry *entry; 1005#endif 1006 char *xml_str; 1007 int retval; 1008 unsigned long ioctl_cmd; 1009 1010 switch (cmd) { 1011 case MT_CMD_PROTECT: 1012 case MTIOCPARAMGET: 1013 ioctl_cmd = MTIOCPARAMGET; 1014 break; 1015 default: 1016 ioctl_cmd = MTIOCEXTGET; 1017 break; 1018 } 1019 1020 retval = mt_get_xml_str(mtfd, ioctl_cmd, &xml_str); 1021 if (retval != 0) 1022 err(1, "Couldn't get mt XML string"); 1023 1024 retval = mt_get_status(xml_str, &status_data); 1025 if (retval != XML_STATUS_OK) { 1026 warn("Couldn't get mt status for %s", tape); 1027 goto bailout; 1028 } 1029 1030 /* 1031 * This gets set if there are memory allocation or other errors in 1032 * our parsing of the XML. 1033 */ 1034 if (status_data.error != 0) { 1035 warnx("%s", status_data.error_str); 1036 retval = 1; 1037 goto bailout; 1038 } 1039#if 0 1040 STAILQ_FOREACH(entry, &status_data.entries, links) 1041 mt_status_tree_print(entry, 0, NULL); 1042#endif 1043 1044 switch (cmd) { 1045 case MTIOCEXTGET: 1046 retval = nstatus_print(argc, argv, xml_str, &status_data); 1047 break; 1048 case MTIOCPARAMGET: 1049 retval = mt_param(argc, argv, mtfd, xml_str, &status_data); 1050 break; 1051 case MT_CMD_PROTECT: 1052 retval = mt_protect(argc, argv, mtfd, &status_data); 1053 break; 1054 case MT_CMD_GETDENSITY: 1055 retval = mt_getdensity(argc, argv, xml_str, &status_data); 1056 break; 1057 } 1058 1059bailout: 1060 if (xml_str != NULL) 1061 free(xml_str); 1062 1063 mt_status_free(&status_data); 1064 1065 return (retval); 1066} 1067 1068static int 1069mt_set_param(int mtfd, struct mt_status_data *status_data, char *param_name, 1070 char *param_value) 1071{ 1072 struct mt_status_entry *entry; 1073 struct mtparamset param_set; 1074 1075 entry = mt_status_entry_find(status_data, 1076 __DECONST(char *, "mtparamget")); 1077 if (entry == NULL) 1078 errx(1, "Cannot find parameter root node"); 1079 1080 bzero(¶m_set, sizeof(param_set)); 1081 entry = mt_entry_find(entry, param_name); 1082 if (entry == NULL) 1083 errx(1, "Unknown parameter name \"%s\"", param_name); 1084 1085 strlcpy(param_set.value_name, param_name, sizeof(param_set.value_name)); 1086 1087 switch (entry->var_type) { 1088 case MT_TYPE_INT: 1089 param_set.value.value_signed = strtoll(param_value, NULL, 0); 1090 param_set.value_type = MT_PARAM_SET_SIGNED; 1091 param_set.value_len = entry->size; 1092 break; 1093 case MT_TYPE_UINT: 1094 param_set.value.value_unsigned = strtoull(param_value, NULL, 0); 1095 param_set.value_type = MT_PARAM_SET_UNSIGNED; 1096 param_set.value_len = entry->size; 1097 break; 1098 case MT_TYPE_STRING: { 1099 size_t param_len; 1100 1101 param_len = strlen(param_value) + 1; 1102 if (param_len > sizeof(param_set.value.value_fixed_str)) { 1103 param_set.value_type = MT_PARAM_SET_VAR_STR; 1104 param_set.value.value_var_str = param_value; 1105 } else { 1106 param_set.value_type = MT_PARAM_SET_FIXED_STR; 1107 strlcpy(param_set.value.value_fixed_str, param_value, 1108 sizeof(param_set.value.value_fixed_str)); 1109 } 1110 param_set.value_len = param_len; 1111 break; 1112 } 1113 default: 1114 errx(1, "Unknown parameter type %d for %s", entry->var_type, 1115 param_name); 1116 break; 1117 } 1118 1119 if (ioctl(mtfd, MTIOCPARAMSET, ¶m_set) == -1) 1120 err(1, "MTIOCPARAMSET"); 1121 1122 if (param_set.status != MT_PARAM_STATUS_OK) 1123 errx(1, "Failed to set %s: %s", param_name, 1124 param_set.error_str); 1125 1126 return (0); 1127} 1128 1129 1130typedef enum { 1131 MT_PP_LBP_R, 1132 MT_PP_LBP_W, 1133 MT_PP_RBDP, 1134 MT_PP_PI_LENGTH, 1135 MT_PP_PROT_METHOD 1136} mt_protect_param; 1137 1138static struct mt_protect_info { 1139 const char *name; 1140 struct mt_status_entry *entry; 1141 uint32_t value; 1142} mt_protect_list[] = { 1143 { "lbp_r", NULL, 0 }, 1144 { "lbp_w", NULL, 0 }, 1145 { "rbdp", NULL, 0 }, 1146 { "pi_length", NULL, 0 }, 1147 { "prot_method", NULL, 0 } 1148}; 1149 1150#define MT_NUM_PROTECT_PARAMS (sizeof(mt_protect_list)/sizeof(mt_protect_list[0])) 1151 1152#define MT_PROT_NAME "protection" 1153 1154static int 1155mt_protect(int argc, char **argv, int mtfd, struct mt_status_data *status_data) 1156{ 1157 int retval = 0; 1158 int do_enable = 0, do_disable = 0, do_list = 0; 1159 int rbdp_set = 0, lbp_w_set = 0, lbp_r_set = 0; 1160 int prot_method_set = 0, pi_length_set = 0; 1161 int verbose = 0; 1162 uint32_t rbdp = 0, lbp_w = 0, lbp_r = 0; 1163 uint32_t prot_method = 0, pi_length = 0; 1164 struct mt_status_entry *prot_entry, *supported_entry; 1165 struct mt_status_entry *entry; 1166 struct mtparamset params[MT_NUM_PROTECT_PARAMS]; 1167 struct mtsetlist param_list; 1168 unsigned int i; 1169 int c; 1170 1171 while ((c = getopt(argc, argv, "b:delL:m:r:vw:")) != -1) { 1172 switch (c) { 1173 case 'b': 1174 rbdp_set = 1; 1175 rbdp = strtoul(optarg, NULL, 0); 1176 if ((rbdp != 0) && (rbdp != 1)) 1177 errx(1, "valid values for -b are 0 and 1"); |
619 break; | 1178 break; |
620 case MTIO_DSREG_LD: 621 printf(sfmt, "Loading"); | 1179 case 'd': 1180 do_disable = 1; |
622 break; | 1181 break; |
1182 case 'e': 1183 do_enable = 1; 1184 break; 1185 case 'l': 1186 do_list = 1; 1187 break; 1188 case 'L': 1189 pi_length_set = 1; 1190 pi_length = strtoul(optarg, NULL, 0); 1191 if (pi_length > SA_CTRL_DP_PI_LENGTH_MASK) 1192 errx(1, "PI length %u > maximum %u", 1193 pi_length, SA_CTRL_DP_PI_LENGTH_MASK); 1194 break; 1195 case 'm': 1196 prot_method_set = 1; 1197 prot_method = strtoul(optarg, NULL, 0); 1198 if (prot_method > SA_CTRL_DP_METHOD_MAX) 1199 errx(1, "Method %u > maximum %u", 1200 prot_method, SA_CTRL_DP_METHOD_MAX); 1201 break; 1202 case 'r': 1203 lbp_r_set = 1; 1204 lbp_r = strtoul(optarg, NULL, 0); 1205 if ((lbp_r != 0) && (lbp_r != 1)) 1206 errx(1, "valid values for -r are 0 and 1"); 1207 break; 1208 case 'v': 1209 verbose = 1; 1210 break; 1211 case 'w': 1212 lbp_w_set = 1; 1213 lbp_w = strtoul(optarg, NULL, 0); 1214 if ((lbp_w != 0) && (lbp_r != 1)) 1215 errx(1, "valid values for -r are 0 and 1"); 1216 break; |
|
623 default: | 1217 default: |
624 (void) sprintf(foo, "Unknown state 0x%x", bp->mt_dsreg); 625 printf(sfmt, foo); | |
626 break; 627 } 628 } | 1218 break; 1219 } 1220 } |
629 if (bp->mt_resid == 0 && bp->mt_fileno == (daddr_t) -1 && 630 bp->mt_blkno == (daddr_t) -1) 631 return; 632 printf("---------------------------------\n"); 633 printf("File Number: %d\tRecord Number: %d\tResidual Count %d\n", 634 bp->mt_fileno, bp->mt_blkno, bp->mt_resid); | 1221 1222 if ((rbdp_set + do_disable + do_enable + do_list + pi_length_set + 1223 prot_method_set + lbp_r_set + lbp_w_set) == 0) 1224 errx(1, "Need an argument for protect"); 1225 1226 if ((do_disable + do_enable + do_list) != 1) 1227 errx(1, "You must specify only one of -e, -d or -l"); 1228 1229 if (do_list != 0) { 1230 retval = mt_protect_print(status_data, verbose); 1231 goto bailout; 1232 } 1233 if (do_enable != 0) { 1234 /* 1235 * Enable protection, but allow the user to override 1236 * settings if he doesn't want everything turned on. 1237 */ 1238 if (rbdp_set == 0) 1239 rbdp = 1; 1240 if (lbp_w_set == 0) 1241 lbp_w = 1; 1242 if (lbp_r_set == 0) 1243 lbp_r = 1; 1244 /* 1245 * If the user doesn't override it, we default to enabling 1246 * Reed-Solomon checkums. 1247 */ 1248 if (prot_method_set == 0) 1249 prot_method = SA_CTRL_DP_REED_SOLOMON; 1250 if (pi_length_set == 0) 1251 pi_length = SA_CTRL_DP_RS_LENGTH; 1252 } else if (do_disable != 0) { 1253 /* 1254 * If the user wants to disable protection, we ignore any 1255 * other parameters he has set. Everything gets set to 0. 1256 */ 1257 rbdp = lbp_w = lbp_r = 0; 1258 prot_method = pi_length = 0; 1259 } 1260 1261 prot_entry = mt_status_entry_find(status_data, 1262 __DECONST(char *, MT_PROT_NAME)); 1263 if (prot_entry == NULL) 1264 errx(1, "Unable to find protection information status"); 1265 1266 supported_entry = mt_entry_find(prot_entry, 1267 __DECONST(char *, "protection_supported")); 1268 if (supported_entry == NULL) 1269 errx(1, "Unable to find protection support information"); 1270 1271 if (((supported_entry->var_type == MT_TYPE_INT) 1272 && (supported_entry->value_signed == 0)) 1273 || ((supported_entry->var_type == MT_TYPE_UINT) 1274 && (supported_entry->value_unsigned == 0))) 1275 errx(1, "This device does not support protection information"); 1276 1277 mt_protect_list[MT_PP_LBP_R].value = lbp_r; 1278 mt_protect_list[MT_PP_LBP_W].value = lbp_w; 1279 mt_protect_list[MT_PP_RBDP].value = rbdp; 1280 mt_protect_list[MT_PP_PI_LENGTH].value = pi_length; 1281 mt_protect_list[MT_PP_PROT_METHOD].value = prot_method; 1282 1283 bzero(¶ms, sizeof(params)); 1284 bzero(¶m_list, sizeof(param_list)); 1285 1286 /* 1287 * Go through the list and make sure that we have this parameter, 1288 * and that it is still an unsigned integer. If not, we've got a 1289 * problem. 1290 */ 1291 for (i = 0; i < MT_NUM_PROTECT_PARAMS; i++) { 1292 entry = mt_entry_find(prot_entry, 1293 __DECONST(char *, mt_protect_list[i].name)); 1294 if (entry == NULL) { 1295 errx(1, "Unable to find parameter %s", 1296 mt_protect_list[i].name); 1297 } 1298 mt_protect_list[i].entry = entry; 1299 1300 if (entry->var_type != MT_TYPE_UINT) 1301 errx(1, "Parameter %s is type %d, not unsigned, " 1302 "cannot proceed", mt_protect_list[i].name, 1303 entry->var_type); 1304 snprintf(params[i].value_name, sizeof(params[i].value_name), 1305 "%s.%s", MT_PROT_NAME, mt_protect_list[i].name); 1306 /* XXX KDM unify types here */ 1307 params[i].value_type = MT_PARAM_SET_UNSIGNED; 1308 params[i].value_len = sizeof(mt_protect_list[i].value); 1309 params[i].value.value_unsigned = mt_protect_list[i].value; 1310 1311 } 1312 param_list.num_params = MT_NUM_PROTECT_PARAMS; 1313 param_list.param_len = sizeof(params); 1314 param_list.params = params; 1315 1316 if (ioctl(mtfd, MTIOCSETLIST, ¶m_list) == -1) 1317 err(1, "error issuing MTIOCSETLIST ioctl"); 1318 1319 for (i = 0; i < MT_NUM_PROTECT_PARAMS; i++) { 1320 if (params[i].status != MT_PARAM_STATUS_OK) { 1321 warnx("%s", params[i].error_str); 1322 retval = 1; 1323 } 1324 } 1325bailout: 1326 1327 return (retval); |
635} 636 | 1328} 1329 |
1330static int 1331mt_param(int argc, char **argv, int mtfd, char *xml_str, 1332 struct mt_status_data *status_data) 1333{ 1334 int list = 0, do_set = 0, xml_dump = 0; 1335 char *param_name = NULL, *param_value = NULL; 1336 int retval = 0, quiet = 0; 1337 int c; 1338 1339 while ((c = getopt(argc, argv, "lp:qs:x")) != -1) { 1340 switch (c) { 1341 case 'l': 1342 list = 1; 1343 break; 1344 case 'p': 1345 if (param_name != NULL) { 1346 warnx("Only one paramter name may be " 1347 "specified"); 1348 retval = 1; 1349 goto bailout; 1350 } 1351 param_name = strdup(optarg); 1352 break; 1353 case 'q': 1354 quiet = 1; 1355 break; 1356 case 's': 1357 if (param_value != NULL) { 1358 warnx("Only one paramter value may be " 1359 "specified"); 1360 retval = 1; 1361 goto bailout; 1362 } 1363 param_value = strdup(optarg); 1364 do_set = 1; 1365 break; 1366 case 'x': 1367 xml_dump = 1; 1368 break; 1369 default: 1370 break; 1371 } 1372 } 1373 1374 if ((list + do_set + xml_dump) != 1) { 1375 warnx("You must specify only one of -s, -l or -x"); 1376 retval = 1; 1377 goto bailout; 1378 } 1379 1380 if (xml_dump != 0) { 1381 printf("%s", xml_str); 1382 retval = 0; 1383 goto bailout; 1384 } 1385 1386 if (do_set != 0) { 1387 if (param_name == NULL) 1388 errx(1, "You must specify -p with -s"); 1389 1390 retval = mt_set_param(mtfd, status_data, param_name, 1391 param_value); 1392 } else if (list != 0) 1393 retval = mt_param_list(status_data, param_name, quiet); 1394 1395bailout: 1396 free(param_name); 1397 free(param_value); 1398 return (retval); 1399} 1400 1401int 1402mt_print_density_entry(struct mt_status_entry *density_root, int indent) 1403{ 1404 struct mt_status_entry *entry; 1405 int retval = 0; 1406 1407 STAILQ_FOREACH(entry, &density_root->child_entries, links) { 1408 if (entry->var_type == MT_TYPE_NODE) { 1409 retval = mt_print_density_entry(entry, indent + 2); 1410 if (retval != 0) 1411 break; 1412 else 1413 continue; 1414 } 1415 if ((strcmp(entry->entry_name, "primary_density_code") == 0) 1416 || (strcmp(entry->entry_name, "secondary_density_code") == 0) 1417 || (strcmp(entry->entry_name, "density_code") == 0)) { 1418 1419 printf("%*s%s (%s): %s\n", indent, "", entry->desc ? 1420 entry->desc : "", entry->entry_name, 1421 denstostring(entry->value_unsigned)); 1422 } else if (strcmp(entry->entry_name, "density_flags") == 0) { 1423 printf("%*sMedium Access: ", indent, ""); 1424 if (entry->value_unsigned & MT_DENS_WRITE_OK) { 1425 printf("Read and Write\n"); 1426 } else { 1427 printf("Read Only\n"); 1428 } 1429 printf("%*sDefault Density: %s\n", indent, "", 1430 (entry->value_unsigned & MT_DENS_DEFLT) ? "Yes" : 1431 "No"); 1432 printf("%*sDuplicate Density: %s\n", indent, "", 1433 (entry->value_unsigned & MT_DENS_DUP) ? "Yes" : 1434 "No"); 1435 } else if (strcmp(entry->entry_name, "media_width") == 0) { 1436 printf("%*s%s (%s): %.1f mm\n", indent, "", 1437 entry->desc ? entry->desc : "", entry->entry_name, 1438 (double)((double)entry->value_unsigned / 10)); 1439 } else if (strcmp(entry->entry_name, "medium_length") == 0) { 1440 printf("%*s%s (%s): %ju m\n", indent, "", 1441 entry->desc ? entry->desc : "", entry->entry_name, 1442 (uintmax_t)entry->value_unsigned); 1443 } else if (strcmp(entry->entry_name, "capacity") == 0) { 1444 printf("%*s%s (%s): %ju MB\n", indent, "", entry->desc ? 1445 entry->desc : "", entry->entry_name, 1446 (uintmax_t)entry->value_unsigned); 1447 } else { 1448 printf("%*s%s (%s): %s\n", indent, "", entry->desc ? 1449 entry->desc : "", entry->entry_name, entry->value); 1450 } 1451 } 1452 1453 return (retval); 1454} 1455 1456int 1457mt_print_density_report(struct mt_status_entry *report_root, int indent) 1458{ 1459 struct mt_status_entry *mt_report, *media_report; 1460 struct mt_status_entry *entry; 1461 int retval = 0; 1462 1463 mt_report = mt_entry_find(report_root, 1464 __DECONST(char *, MT_MEDIUM_TYPE_REPORT_NAME)); 1465 if (mt_report == NULL) 1466 return (1); 1467 1468 media_report = mt_entry_find(report_root, 1469 __DECONST(char *, MT_MEDIA_REPORT_NAME)); 1470 if (media_report == NULL) 1471 return (1); 1472 1473 if ((mt_report->value_signed == 0) 1474 && (media_report->value_signed == 0)) { 1475 printf("%*sThis tape drive supports the following " 1476 "media densities:\n", indent, ""); 1477 } else if ((mt_report->value_signed == 0) 1478 && (media_report->value_signed != 0)) { 1479 printf("%*sThe tape currently in this drive supports " 1480 "the following media densities:\n", indent, ""); 1481 } else if ((mt_report->value_signed != 0) 1482 && (media_report->value_signed == 0)) { 1483 printf("%*sThis tape drive supports the following " 1484 "media types:\n", indent, ""); 1485 } else { 1486 printf("%*sThis tape currently in this drive supports " 1487 "the following media types:\n", indent, ""); 1488 } 1489 1490 STAILQ_FOREACH(entry, &report_root->child_entries, links) { 1491 struct mt_status_nv *nv; 1492 1493 if (strcmp(entry->entry_name, MT_DENSITY_ENTRY_NAME) != 0) 1494 continue; 1495 1496 STAILQ_FOREACH(nv, &entry->nv_list, links) { 1497 if (strcmp(nv->name, "num") != 0) 1498 continue; 1499 1500 break; 1501 } 1502 1503 indent += 2; 1504 1505 printf("%*sDensity Entry", indent, ""); 1506 if (nv != NULL) 1507 printf(" %s", nv->value); 1508 printf(":\n"); 1509 1510 retval = mt_print_density_entry(entry, indent + 2); 1511 1512 indent -= 2; 1513 } 1514 1515 return (retval); 1516} 1517 1518int 1519mt_print_density(struct mt_status_entry *density_root, int indent) 1520{ 1521 struct mt_status_entry *entry; 1522 int retval = 0; 1523 1524 /* 1525 * We should have this entry for every tape drive. This particular 1526 * value is reported via the mode page block header, not the 1527 * SCSI REPORT DENSITY SUPPORT command. 1528 */ 1529 entry = mt_entry_find(density_root, 1530 __DECONST(char *, MT_MEDIA_DENSITY_NAME)); 1531 if (entry == NULL) 1532 errx(1, "Unable to find node %s", MT_MEDIA_DENSITY_NAME); 1533 1534 printf("%*sCurrent density: %s\n", indent, "", 1535 denstostring(entry->value_unsigned)); 1536 1537 /* 1538 * It isn't an error if we don't have any density reports. Tape 1539 * drives that don't support the REPORT DENSITY SUPPORT command 1540 * won't have any; they will only have the current density entry 1541 * above. 1542 */ 1543 STAILQ_FOREACH(entry, &density_root->child_entries, links) { 1544 if (strcmp(entry->entry_name, MT_DENSITY_REPORT_NAME) != 0) 1545 continue; 1546 1547 retval = mt_print_density_report(entry, indent); 1548 } 1549 1550 return (retval); 1551} 1552 1553int 1554mt_getdensity(int argc, char **argv, char *xml_str, 1555 struct mt_status_data *status_data) 1556{ 1557 int retval = 0; 1558 int verbose = 0, xml_dump = 0; 1559 struct mt_status_entry *density_root = NULL; 1560 int c; 1561 1562 while ((c = getopt(argc, argv, "vx")) != -1) { 1563 switch (c) { 1564 case 'v': 1565 verbose = 1; 1566 break; 1567 case 'x': 1568 xml_dump = 1; 1569 break; 1570 } 1571 } 1572 1573 if (xml_dump != 0) { 1574 printf("%s", xml_str); 1575 return (0); 1576 } 1577 1578 density_root = mt_status_entry_find(status_data, 1579 __DECONST(char *, MT_DENSITY_ROOT_NAME)); 1580 if (density_root == NULL) 1581 errx(1, "Cannot find density root node %s", 1582 MT_DENSITY_ROOT_NAME); 1583 1584 retval = mt_print_density(density_root, 0); 1585 1586 return (retval); 1587} 1588 |
|
637static void 638warn_eof(void) 639{ 640 fprintf(stderr, 641 "The \"eof\" command has been disabled.\n" 642 "Use \"weof\" if you really want to write end-of-file marks,\n" 643 "or \"eom\" if you rather want to skip to the end of " 644 "recorded medium.\n"); 645 exit(1); 646} | 1589static void 1590warn_eof(void) 1591{ 1592 fprintf(stderr, 1593 "The \"eof\" command has been disabled.\n" 1594 "Use \"weof\" if you really want to write end-of-file marks,\n" 1595 "or \"eom\" if you rather want to skip to the end of " 1596 "recorded medium.\n"); 1597 exit(1); 1598} |