mtlib.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781
  1. /*-
  2. * Copyright (c) 2013, 2014, 2015 Spectra Logic Corporation
  3. * 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
  9. * notice, this list of conditions, and the following disclaimer,
  10. * without modification.
  11. * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  12. * substantially similar to the "NO WARRANTY" disclaimer below
  13. * ("Disclaimer") and any redistribution must be conditioned upon
  14. * including a substantially similar Disclaimer requirement for further
  15. * binary redistribution.
  16. *
  17. * NO WARRANTY
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  21. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22. * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  23. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  24. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  25. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  26. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  27. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  28. * POSSIBILITY OF SUCH DAMAGES.
  29. *
  30. * Authors: Ken Merry (Spectra Logic Corporation)
  31. */
  32. #include <sys/types.h>
  33. #include <sys/ioctl.h>
  34. #include <sys/mtio.h>
  35. #include <sys/queue.h>
  36. #include <sys/sbuf.h>
  37. #include <ctype.h>
  38. #include <err.h>
  39. #include <fcntl.h>
  40. #include <stdio.h>
  41. #include <stdlib.h>
  42. #include <string.h>
  43. #include <unistd.h>
  44. #include <stdint.h>
  45. #include <errno.h>
  46. #include <bsdxml.h>
  47. #include <mtlib.h>
  48. /*
  49. * Called at the start of each XML element, and includes the list of
  50. * attributes for the element.
  51. */
  52. void
  53. mt_start_element(void *user_data, const char *name, const char **attr)
  54. {
  55. int i;
  56. struct mt_status_data *mtinfo;
  57. struct mt_status_entry *entry;
  58. mtinfo = (struct mt_status_data *)user_data;
  59. if (mtinfo->error != 0)
  60. return;
  61. mtinfo->level++;
  62. if ((u_int)mtinfo->level >= (sizeof(mtinfo->cur_sb) /
  63. sizeof(mtinfo->cur_sb[0]))) {
  64. mtinfo->error = 1;
  65. snprintf(mtinfo->error_str, sizeof(mtinfo->error_str),
  66. "%s: too many nesting levels, %zd max", __func__,
  67. sizeof(mtinfo->cur_sb) / sizeof(mtinfo->cur_sb[0]));
  68. return;
  69. }
  70. mtinfo->cur_sb[mtinfo->level] = sbuf_new_auto();
  71. if (mtinfo->cur_sb[mtinfo->level] == NULL) {
  72. mtinfo->error = 1;
  73. snprintf(mtinfo->error_str, sizeof(mtinfo->error_str),
  74. "%s: Unable to allocate sbuf", __func__);
  75. return;
  76. }
  77. entry = malloc(sizeof(*entry));
  78. if (entry == NULL) {
  79. mtinfo->error = 1;
  80. snprintf(mtinfo->error_str, sizeof(mtinfo->error_str),
  81. "%s: unable to allocate %zd bytes", __func__,
  82. sizeof(*entry));
  83. return;
  84. }
  85. bzero(entry, sizeof(*entry));
  86. STAILQ_INIT(&entry->nv_list);
  87. STAILQ_INIT(&entry->child_entries);
  88. entry->entry_name = strdup(name);
  89. mtinfo->cur_entry[mtinfo->level] = entry;
  90. if (mtinfo->cur_entry[mtinfo->level - 1] == NULL) {
  91. STAILQ_INSERT_TAIL(&mtinfo->entries, entry, links);
  92. } else {
  93. STAILQ_INSERT_TAIL(
  94. &mtinfo->cur_entry[mtinfo->level - 1]->child_entries,
  95. entry, links);
  96. entry->parent = mtinfo->cur_entry[mtinfo->level - 1];
  97. }
  98. for (i = 0; attr[i] != NULL; i+=2) {
  99. struct mt_status_nv *nv;
  100. int need_nv;
  101. need_nv = 0;
  102. if (strcmp(attr[i], "size") == 0) {
  103. entry->size = strtoull(attr[i+1], NULL, 0);
  104. } else if (strcmp(attr[i], "type") == 0) {
  105. if (strcmp(attr[i+1], "int") == 0) {
  106. entry->var_type = MT_TYPE_INT;
  107. } else if (strcmp(attr[i+1], "uint") == 0) {
  108. entry->var_type = MT_TYPE_UINT;
  109. } else if (strcmp(attr[i+1], "str") == 0) {
  110. entry->var_type = MT_TYPE_STRING;
  111. } else if (strcmp(attr[i+1], "node") == 0) {
  112. entry->var_type = MT_TYPE_NODE;
  113. } else {
  114. need_nv = 1;
  115. }
  116. } else if (strcmp(attr[i], "fmt") == 0) {
  117. entry->fmt = strdup(attr[i+1]);
  118. } else if (strcmp(attr[i], "desc") == 0) {
  119. entry->desc = strdup(attr[i+1]);
  120. } else {
  121. need_nv = 1;
  122. }
  123. if (need_nv != 0) {
  124. nv = malloc(sizeof(*nv));
  125. if (nv == NULL) {
  126. mtinfo->error = 1;
  127. snprintf(mtinfo->error_str,
  128. sizeof(mtinfo->error_str),
  129. "%s: error allocating %zd bytes",
  130. __func__, sizeof(*nv));
  131. }
  132. bzero(nv, sizeof(*nv));
  133. nv->name = strdup(attr[i]);
  134. nv->value = strdup(attr[i+1]);
  135. STAILQ_INSERT_TAIL(&entry->nv_list, nv, links);
  136. }
  137. }
  138. }
  139. /*
  140. * Called on XML element close.
  141. */
  142. void
  143. mt_end_element(void *user_data, const char *name)
  144. {
  145. struct mt_status_data *mtinfo;
  146. char *str;
  147. mtinfo = (struct mt_status_data *)user_data;
  148. if (mtinfo->error != 0)
  149. return;
  150. if (mtinfo->cur_sb[mtinfo->level] == NULL) {
  151. mtinfo->error = 1;
  152. snprintf(mtinfo->error_str, sizeof(mtinfo->error_str),
  153. "%s: no valid sbuf at level %d (name %s)", __func__,
  154. mtinfo->level, name);
  155. return;
  156. }
  157. sbuf_finish(mtinfo->cur_sb[mtinfo->level]);
  158. str = strdup(sbuf_data(mtinfo->cur_sb[mtinfo->level]));
  159. if (str == NULL) {
  160. mtinfo->error = 1;
  161. snprintf(mtinfo->error_str, sizeof(mtinfo->error_str),
  162. "%s can't allocate %zd bytes for string", __func__,
  163. sbuf_len(mtinfo->cur_sb[mtinfo->level]));
  164. return;
  165. }
  166. if (strlen(str) == 0) {
  167. free(str);
  168. str = NULL;
  169. }
  170. if (str != NULL) {
  171. struct mt_status_entry *entry;
  172. entry = mtinfo->cur_entry[mtinfo->level];
  173. switch(entry->var_type) {
  174. case MT_TYPE_INT:
  175. entry->value_signed = strtoll(str, NULL, 0);
  176. break;
  177. case MT_TYPE_UINT:
  178. entry->value_unsigned = strtoull(str, NULL, 0);
  179. break;
  180. default:
  181. break;
  182. }
  183. }
  184. mtinfo->cur_entry[mtinfo->level]->value = str;
  185. sbuf_delete(mtinfo->cur_sb[mtinfo->level]);
  186. mtinfo->cur_sb[mtinfo->level] = NULL;
  187. mtinfo->cur_entry[mtinfo->level] = NULL;
  188. mtinfo->level--;
  189. }
  190. /*
  191. * Called to handle character strings in the current element.
  192. */
  193. void
  194. mt_char_handler(void *user_data, const XML_Char *str, int len)
  195. {
  196. struct mt_status_data *mtinfo;
  197. mtinfo = (struct mt_status_data *)user_data;
  198. if (mtinfo->error != 0)
  199. return;
  200. sbuf_bcat(mtinfo->cur_sb[mtinfo->level], str, len);
  201. }
  202. void
  203. mt_status_tree_sbuf(struct sbuf *sb, struct mt_status_entry *entry, int indent,
  204. void (*sbuf_func)(struct sbuf *sb, struct mt_status_entry *entry,
  205. void *arg), void *arg)
  206. {
  207. struct mt_status_nv *nv;
  208. struct mt_status_entry *entry2;
  209. if (sbuf_func != NULL) {
  210. sbuf_func(sb, entry, arg);
  211. } else {
  212. sbuf_printf(sb, "%*sname: %s, value: %s, fmt: %s, size: %zd, "
  213. "type: %d, desc: %s\n", indent, "", entry->entry_name,
  214. entry->value, entry->fmt, entry->size, entry->var_type,
  215. entry->desc);
  216. STAILQ_FOREACH(nv, &entry->nv_list, links) {
  217. sbuf_printf(sb, "%*snv: name: %s, value: %s\n",
  218. indent + 1, "", nv->name, nv->value);
  219. }
  220. }
  221. STAILQ_FOREACH(entry2, &entry->child_entries, links)
  222. mt_status_tree_sbuf(sb, entry2, indent + 2, sbuf_func, arg);
  223. }
  224. void
  225. mt_status_tree_print(struct mt_status_entry *entry, int indent,
  226. void (*print_func)(struct mt_status_entry *entry, void *arg), void *arg)
  227. {
  228. if (print_func != NULL) {
  229. struct mt_status_entry *entry2;
  230. print_func(entry, arg);
  231. STAILQ_FOREACH(entry2, &entry->child_entries, links)
  232. mt_status_tree_print(entry2, indent + 2, print_func,
  233. arg);
  234. } else {
  235. struct sbuf *sb;
  236. sb = sbuf_new_auto();
  237. if (sb == NULL)
  238. return;
  239. mt_status_tree_sbuf(sb, entry, indent, NULL, NULL);
  240. sbuf_finish(sb);
  241. printf("%s", sbuf_data(sb));
  242. sbuf_delete(sb);
  243. }
  244. }
  245. /*
  246. * Given a parameter name in the form "foo" or "foo.bar.baz", traverse the
  247. * tree looking for the parameter (the first case) or series of parameters
  248. * (second case).
  249. */
  250. struct mt_status_entry *
  251. mt_entry_find(struct mt_status_entry *entry, char *name)
  252. {
  253. struct mt_status_entry *entry2;
  254. char *tmpname = NULL, *tmpname2 = NULL, *tmpstr = NULL;
  255. tmpname = strdup(name);
  256. if (tmpname == NULL)
  257. goto bailout;
  258. /* Save a pointer so we can free this later */
  259. tmpname2 = tmpname;
  260. tmpstr = strsep(&tmpname, ".");
  261. /*
  262. * Is this the entry we're looking for? Or do we have further
  263. * child entries that we need to grab?
  264. */
  265. if (strcmp(entry->entry_name, tmpstr) == 0) {
  266. if (tmpname == NULL) {
  267. /*
  268. * There are no further child entries to find. We
  269. * have a complete match.
  270. */
  271. free(tmpname2);
  272. return (entry);
  273. } else {
  274. /*
  275. * There are more child entries that we need to find.
  276. * Fall through to the recursive search off of this
  277. * entry, below. Use tmpname, which will contain
  278. * everything after the first period.
  279. */
  280. name = tmpname;
  281. }
  282. }
  283. /*
  284. * Recursively look for further entries.
  285. */
  286. STAILQ_FOREACH(entry2, &entry->child_entries, links) {
  287. struct mt_status_entry *entry3;
  288. entry3 = mt_entry_find(entry2, name);
  289. if (entry3 != NULL) {
  290. free(tmpname2);
  291. return (entry3);
  292. }
  293. }
  294. bailout:
  295. free(tmpname2);
  296. return (NULL);
  297. }
  298. struct mt_status_entry *
  299. mt_status_entry_find(struct mt_status_data *status_data, char *name)
  300. {
  301. struct mt_status_entry *entry, *entry2;
  302. STAILQ_FOREACH(entry, &status_data->entries, links) {
  303. entry2 = mt_entry_find(entry, name);
  304. if (entry2 != NULL)
  305. return (entry2);
  306. }
  307. return (NULL);
  308. }
  309. void
  310. mt_status_entry_free(struct mt_status_entry *entry)
  311. {
  312. struct mt_status_entry *entry2, *entry3;
  313. struct mt_status_nv *nv, *nv2;
  314. STAILQ_FOREACH_SAFE(entry2, &entry->child_entries, links, entry3) {
  315. STAILQ_REMOVE(&entry->child_entries, entry2, mt_status_entry,
  316. links);
  317. mt_status_entry_free(entry2);
  318. }
  319. free(entry->entry_name);
  320. free(entry->value);
  321. free(entry->fmt);
  322. free(entry->desc);
  323. STAILQ_FOREACH_SAFE(nv, &entry->nv_list, links, nv2) {
  324. STAILQ_REMOVE(&entry->nv_list, nv, mt_status_nv, links);
  325. free(nv->name);
  326. free(nv->value);
  327. free(nv);
  328. }
  329. free(entry);
  330. }
  331. void
  332. mt_status_free(struct mt_status_data *status_data)
  333. {
  334. struct mt_status_entry *entry, *entry2;
  335. STAILQ_FOREACH_SAFE(entry, &status_data->entries, links, entry2) {
  336. STAILQ_REMOVE(&status_data->entries, entry, mt_status_entry,
  337. links);
  338. mt_status_entry_free(entry);
  339. }
  340. }
  341. void
  342. mt_entry_sbuf(struct sbuf *sb, struct mt_status_entry *entry, char *fmt)
  343. {
  344. switch(entry->var_type) {
  345. case MT_TYPE_INT:
  346. if (fmt != NULL)
  347. sbuf_printf(sb, fmt, (intmax_t)entry->value_signed);
  348. else
  349. sbuf_printf(sb, "%jd",
  350. (intmax_t)entry->value_signed);
  351. break;
  352. case MT_TYPE_UINT:
  353. if (fmt != NULL)
  354. sbuf_printf(sb, fmt, (uintmax_t)entry->value_unsigned);
  355. else
  356. sbuf_printf(sb, "%ju",
  357. (uintmax_t)entry->value_unsigned);
  358. break;
  359. default:
  360. if (fmt != NULL)
  361. sbuf_printf(sb, fmt, entry->value);
  362. else
  363. sbuf_printf(sb, "%s", entry->value);
  364. break;
  365. }
  366. }
  367. void
  368. mt_param_parent_print(struct mt_status_entry *entry,
  369. struct mt_print_params *print_params)
  370. {
  371. if (entry->parent != NULL)
  372. mt_param_parent_print(entry->parent, print_params);
  373. if (((print_params->flags & MT_PF_INCLUDE_ROOT) == 0)
  374. && (strcmp(entry->entry_name, print_params->root_name) == 0))
  375. return;
  376. printf("%s.", entry->entry_name);
  377. }
  378. void
  379. mt_param_parent_sbuf(struct sbuf *sb, struct mt_status_entry *entry,
  380. struct mt_print_params *print_params)
  381. {
  382. if (entry->parent != NULL)
  383. mt_param_parent_sbuf(sb, entry->parent, print_params);
  384. if (((print_params->flags & MT_PF_INCLUDE_ROOT) == 0)
  385. && (strcmp(entry->entry_name, print_params->root_name) == 0))
  386. return;
  387. sbuf_printf(sb, "%s.", entry->entry_name);
  388. }
  389. void
  390. mt_param_entry_sbuf(struct sbuf *sb, struct mt_status_entry *entry, void *arg)
  391. {
  392. struct mt_print_params *print_params;
  393. print_params = (struct mt_print_params *)arg;
  394. /*
  395. * We don't want to print nodes.
  396. */
  397. if (entry->var_type == MT_TYPE_NODE)
  398. return;
  399. if ((print_params->flags & MT_PF_FULL_PATH)
  400. && (entry->parent != NULL))
  401. mt_param_parent_sbuf(sb, entry->parent, print_params);
  402. sbuf_printf(sb, "%s: %s", entry->entry_name, entry->value);
  403. if ((print_params->flags & MT_PF_VERBOSE)
  404. && (entry->desc != NULL)
  405. && (strlen(entry->desc) > 0))
  406. sbuf_printf(sb, " (%s)", entry->desc);
  407. sbuf_printf(sb, "\n");
  408. }
  409. void
  410. mt_param_entry_print(struct mt_status_entry *entry, void *arg)
  411. {
  412. struct mt_print_params *print_params;
  413. print_params = (struct mt_print_params *)arg;
  414. /*
  415. * We don't want to print nodes.
  416. */
  417. if (entry->var_type == MT_TYPE_NODE)
  418. return;
  419. if ((print_params->flags & MT_PF_FULL_PATH)
  420. && (entry->parent != NULL))
  421. mt_param_parent_print(entry->parent, print_params);
  422. printf("%s: %s", entry->entry_name, entry->value);
  423. if ((print_params->flags & MT_PF_VERBOSE)
  424. && (entry->desc != NULL)
  425. && (strlen(entry->desc) > 0))
  426. printf(" (%s)", entry->desc);
  427. printf("\n");
  428. }
  429. int
  430. mt_protect_print(struct mt_status_data *status_data, int verbose)
  431. {
  432. struct mt_status_entry *entry;
  433. const char *prot_name = MT_PROTECTION_NAME;
  434. struct mt_print_params print_params;
  435. snprintf(print_params.root_name, sizeof(print_params.root_name),
  436. MT_PARAM_ROOT_NAME);
  437. print_params.flags = MT_PF_FULL_PATH;
  438. if (verbose != 0)
  439. print_params.flags |= MT_PF_VERBOSE;
  440. entry = mt_status_entry_find(status_data, __DECONST(char *,prot_name));
  441. if (entry == NULL)
  442. return (1);
  443. mt_status_tree_print(entry, 0, mt_param_entry_print, &print_params);
  444. return (0);
  445. }
  446. int
  447. mt_param_list(struct mt_status_data *status_data, char *param_name, int quiet)
  448. {
  449. struct mt_status_entry *entry;
  450. struct mt_print_params print_params;
  451. char root_name[20];
  452. snprintf(root_name, sizeof(root_name), "mtparamget");
  453. strlcpy(print_params.root_name, root_name,
  454. sizeof(print_params.root_name));
  455. print_params.flags = MT_PF_FULL_PATH;
  456. if (quiet == 0)
  457. print_params.flags |= MT_PF_VERBOSE;
  458. if (param_name != NULL) {
  459. entry = mt_status_entry_find(status_data, param_name);
  460. if (entry == NULL)
  461. return (1);
  462. mt_param_entry_print(entry, &print_params);
  463. return (0);
  464. } else {
  465. entry = mt_status_entry_find(status_data, root_name);
  466. STAILQ_FOREACH(entry, &status_data->entries, links)
  467. mt_status_tree_print(entry, 0, mt_param_entry_print,
  468. &print_params);
  469. }
  470. return (0);
  471. }
  472. static struct densities {
  473. int dens;
  474. int bpmm;
  475. int bpi;
  476. const char *name;
  477. } dens[] = {
  478. /*
  479. * Taken from T10 Project 997D
  480. * SCSI-3 Stream Device Commands (SSC)
  481. * Revision 11, 4-Nov-97
  482. *
  483. * LTO 1-6 definitions obtained from the eighth edition of the
  484. * IBM TotalStorage LTO Ultrium Tape Drive SCSI Reference
  485. * (July 2007) and the second edition of the IBM System Storage LTO
  486. * Tape Drive SCSI Reference (February 13, 2013).
  487. *
  488. * IBM 3592 definitions obtained from second edition of the IBM
  489. * System Storage Tape Drive 3592 SCSI Reference (May 25, 2012).
  490. *
  491. * DAT-72 and DAT-160 bpi values taken from "HP StorageWorks DAT160
  492. * tape drive white paper", dated June 2007.
  493. *
  494. * DAT-160 / SDLT220 density code (0x48) conflict information
  495. * found here:
  496. *
  497. * http://h20564.www2.hp.com/hpsc/doc/public/display?docId=emr_na-c01065117&sp4ts.oid=429311
  498. * (Document ID c01065117)
  499. */
  500. /*Num. bpmm bpi Reference */
  501. { 0x1, 32, 800, "X3.22-1983" },
  502. { 0x2, 63, 1600, "X3.39-1986" },
  503. { 0x3, 246, 6250, "X3.54-1986" },
  504. { 0x5, 315, 8000, "X3.136-1986" },
  505. { 0x6, 126, 3200, "X3.157-1987" },
  506. { 0x7, 252, 6400, "X3.116-1986" },
  507. { 0x8, 315, 8000, "X3.158-1987" },
  508. { 0x9, 491, 37871, "X3.180" },
  509. { 0xA, 262, 6667, "X3B5/86-199" },
  510. { 0xB, 63, 1600, "X3.56-1986" },
  511. { 0xC, 500, 12690, "HI-TC1" },
  512. { 0xD, 999, 25380, "HI-TC2" },
  513. { 0xF, 394, 10000, "QIC-120" },
  514. { 0x10, 394, 10000, "QIC-150" },
  515. { 0x11, 630, 16000, "QIC-320" },
  516. { 0x12, 2034, 51667, "QIC-1350" },
  517. { 0x13, 2400, 61000, "X3B5/88-185A" },
  518. { 0x14, 1703, 43245, "X3.202-1991" },
  519. { 0x15, 1789, 45434, "ECMA TC17" },
  520. { 0x16, 394, 10000, "X3.193-1990" },
  521. { 0x17, 1673, 42500, "X3B5/91-174" },
  522. { 0x18, 1673, 42500, "X3B5/92-50" },
  523. { 0x19, 2460, 62500, "DLTapeIII" },
  524. { 0x1A, 3214, 81633, "DLTapeIV(20GB)" },
  525. { 0x1B, 3383, 85937, "DLTapeIV(35GB)" },
  526. { 0x1C, 1654, 42000, "QIC-385M" },
  527. { 0x1D, 1512, 38400, "QIC-410M" },
  528. { 0x1E, 1385, 36000, "QIC-1000C" },
  529. { 0x1F, 2666, 67733, "QIC-2100C" },
  530. { 0x20, 2666, 67733, "QIC-6GB(M)" },
  531. { 0x21, 2666, 67733, "QIC-20GB(C)" },
  532. { 0x22, 1600, 40640, "QIC-2GB(C)" },
  533. { 0x23, 2666, 67733, "QIC-875M" },
  534. { 0x24, 2400, 61000, "DDS-2" },
  535. { 0x25, 3816, 97000, "DDS-3" },
  536. { 0x26, 3816, 97000, "DDS-4" },
  537. { 0x27, 3056, 77611, "Mammoth" },
  538. { 0x28, 1491, 37871, "X3.224" },
  539. { 0x40, 4880, 123952, "LTO-1" },
  540. { 0x41, 3868, 98250, "DLTapeIV(40GB)" },
  541. { 0x42, 7398, 187909, "LTO-2" },
  542. { 0x44, 9638, 244805, "LTO-3" },
  543. { 0x46, 12725, 323215, "LTO-4" },
  544. { 0x47, 6417, 163000, "DAT-72" },
  545. /*
  546. * XXX KDM note that 0x48 is also the density code for DAT-160.
  547. * For some reason they used overlapping density codes.
  548. */
  549. #if 0
  550. { 0x48, 6870, 174500, "DAT-160" },
  551. #endif
  552. { 0x48, 5236, 133000, "SDLTapeI(110)" },
  553. { 0x49, 7598, 193000, "SDLTapeI(160)" },
  554. { 0x4a, 0, 0, "T10000A" },
  555. { 0x4b, 0, 0, "T10000B" },
  556. { 0x4c, 0, 0, "T10000C" },
  557. { 0x4d, 0, 0, "T10000D" },
  558. { 0x51, 11800, 299720, "3592A1 (unencrypted)" },
  559. { 0x52, 11800, 299720, "3592A2 (unencrypted)" },
  560. { 0x53, 13452, 341681, "3592A3 (unencrypted)" },
  561. { 0x54, 19686, 500024, "3592A4 (unencrypted)" },
  562. { 0x55, 20670, 525018, "3592A5 (unencrypted)" },
  563. { 0x56, 20670, 525018, "3592B5 (unencrypted)" },
  564. { 0x57, 21850, 554990, "3592A6 (unencrypted)" },
  565. { 0x58, 15142, 384607, "LTO-5" },
  566. { 0x59, 21850, 554990, "3592A7 (unencrypted)" },
  567. { 0x5A, 15142, 384607, "LTO-6" },
  568. { 0x5C, 19107, 485318, "LTO-7" },
  569. { 0x5D, 19107, 485318, "LTO-M8" },
  570. { 0x5E, 20669, 524993, "LTO-8" },
  571. { 0x60, 23031, 584987, "LTO-9" },
  572. { 0x71, 11800, 299720, "3592A1 (encrypted)" },
  573. { 0x72, 11800, 299720, "3592A2 (encrypted)" },
  574. { 0x73, 13452, 341681, "3592A3 (encrypted)" },
  575. { 0x74, 19686, 500024, "3592A4 (encrypted)" },
  576. { 0x75, 20670, 525018, "3592A5 (encrypted)" },
  577. { 0x76, 20670, 525018, "3592B5 (encrypted)" },
  578. { 0x77, 21850, 554990, "3592A6 (encrypted)" },
  579. { 0x79, 21850, 554990, "3592A7 (encrypted)" },
  580. { 0x8c, 1789, 45434, "EXB-8500c" },
  581. { 0x90, 1703, 43245, "EXB-8200c" },
  582. { 0, 0, 0, NULL }
  583. };
  584. const char *
  585. mt_density_name(int density_num)
  586. {
  587. struct densities *sd;
  588. /* densities 0 and 0x7f are handled as special cases */
  589. if (density_num == 0)
  590. return ("default");
  591. if (density_num == 0x7f)
  592. return ("same");
  593. for (sd = dens; sd->dens != 0; sd++)
  594. if (sd->dens == density_num)
  595. break;
  596. if (sd->dens == 0)
  597. return ("UNKNOWN");
  598. return (sd->name);
  599. }
  600. /*
  601. * Given a specific density number, return either the bits per inch or bits
  602. * per millimeter for the given density.
  603. */
  604. int
  605. mt_density_bp(int density_num, int bpi)
  606. {
  607. struct densities *sd;
  608. for (sd = dens; sd->dens; sd++)
  609. if (sd->dens == density_num)
  610. break;
  611. if (sd->dens == 0)
  612. return (0);
  613. if (bpi)
  614. return (sd->bpi);
  615. else
  616. return (sd->bpmm);
  617. }
  618. int
  619. mt_density_num(const char *density_name)
  620. {
  621. struct densities *sd;
  622. size_t l = strlen(density_name);
  623. for (sd = dens; sd->dens; sd++)
  624. if (strncasecmp(sd->name, density_name, l) == 0)
  625. break;
  626. return (sd->dens);
  627. }
  628. /*
  629. * Get the current status XML string.
  630. * Returns 0 on success, -1 on failure (with errno set, and *xml_str == NULL).
  631. */
  632. int
  633. mt_get_xml_str(int mtfd, unsigned long cmd, char **xml_str)
  634. {
  635. size_t alloc_len = 32768;
  636. struct mtextget extget;
  637. int error;
  638. *xml_str = NULL;
  639. for (;;) {
  640. bzero(&extget, sizeof(extget));
  641. *xml_str = malloc(alloc_len);
  642. if (*xml_str == NULL)
  643. return (-1);
  644. extget.status_xml = *xml_str;
  645. extget.alloc_len = alloc_len;
  646. error = ioctl(mtfd, cmd, (caddr_t)&extget);
  647. if (error == 0 && extget.status == MT_EXT_GET_OK)
  648. break;
  649. free(*xml_str);
  650. *xml_str = NULL;
  651. if (error != 0 || extget.status != MT_EXT_GET_NEED_MORE_SPACE)
  652. return (-1);
  653. /* The driver needs more space, so double and try again. */
  654. alloc_len *= 2;
  655. }
  656. return (0);
  657. }
  658. /*
  659. * Populate a struct mt_status_data from the XML string via mt_get_xml_str().
  660. *
  661. * Returns XML_STATUS_OK on success.
  662. * If XML_STATUS_ERROR is returned, errno may be set to indicate the reason.
  663. * The caller must check status_data->error.
  664. */
  665. int
  666. mt_get_status(char *xml_str, struct mt_status_data *status_data)
  667. {
  668. XML_Parser parser;
  669. int retval;
  670. bzero(status_data, sizeof(*status_data));
  671. STAILQ_INIT(&status_data->entries);
  672. parser = XML_ParserCreate(NULL);
  673. if (parser == NULL) {
  674. errno = ENOMEM;
  675. return (XML_STATUS_ERROR);
  676. }
  677. XML_SetUserData(parser, status_data);
  678. XML_SetElementHandler(parser, mt_start_element, mt_end_element);
  679. XML_SetCharacterDataHandler(parser, mt_char_handler);
  680. retval = XML_Parse(parser, xml_str, strlen(xml_str), 1);
  681. XML_ParserFree(parser);
  682. return (retval);
  683. }