/sysutils/hal/files/hald-netbsd/probing/fsutils.c

https://github.com/mend0za/pkgsrc-2011Q3 · C · 217 lines · 170 code · 27 blank · 20 comment · 53 complexity · 86f38c79d7cb0bf153b50e59bf75c37c MD5 · raw file

  1. /***************************************************************************
  2. *
  3. * fsutils.c : filesystem utilities
  4. *
  5. * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
  6. * Use is subject to license terms.
  7. *
  8. * Licensed under the Academic Free License version 2.1
  9. *
  10. **************************************************************************/
  11. #ifdef HAVE_CONFIG_H
  12. # include <config.h>
  13. #endif
  14. #include <stdio.h>
  15. #include <sys/types.h>
  16. #include <sys/scsiio.h>
  17. #include <string.h>
  18. #include <strings.h>
  19. #include <ctype.h>
  20. #include <unistd.h>
  21. #include <stdlib.h>
  22. #include <errno.h>
  23. #include <fcntl.h>
  24. #include <sys/dkio.h>
  25. #include <libintl.h>
  26. #include <sys/disklabel.h>
  27. #include <sys/bootblock.h>
  28. #include <libhal.h>
  29. #include "fsutils.h"
  30. /*
  31. * Separates dos notation device spec into device and drive number
  32. */
  33. bool
  34. dos_to_dev(char *path, char **devpath, int *num)
  35. {
  36. char *p;
  37. if ((p = strrchr(path, ':')) == NULL) {
  38. return (false);
  39. }
  40. if ((*num = atoi(p + 1)) == 0) {
  41. return (false);
  42. }
  43. p[0] = '\0';
  44. *devpath = strdup(path);
  45. p[0] = ':';
  46. return (*devpath != NULL);
  47. }
  48. char *
  49. get_slice_name (char *devlink)
  50. {
  51. char *part, *slice, *disk;
  52. char *s = NULL;
  53. char *p;
  54. if ((p = strstr(devlink, "/lofi/")) != 0) {
  55. return (p + sizeof ("/lofi/") - 1);
  56. }
  57. part = strrchr(devlink, 'p');
  58. slice = strrchr(devlink, 's');
  59. disk = strrchr(devlink, 'd');
  60. if ((part != NULL) && (part > slice) && (part > disk)) {
  61. s = part;
  62. } else if ((slice != NULL) && (slice > disk)) {
  63. s = slice;
  64. } else {
  65. s = disk;
  66. }
  67. if ((s != NULL) && isdigit(s[1])) {
  68. return (s);
  69. } else {
  70. return ("");
  71. }
  72. }
  73. bool
  74. is_dos_drive(u_char type)
  75. {
  76. return ((type == 1) || (type == 4) || (type == 5) || (type == 6) ||
  77. ((type >= 8) && (type <= 0xf)));
  78. }
  79. bool
  80. is_dos_extended(u_char id)
  81. {
  82. return MBR_IS_EXTENDED(id);
  83. }
  84. struct part_find_s {
  85. int num;
  86. int count;
  87. int systid;
  88. int r_systid;
  89. int r_relsect;
  90. int r_numsect;
  91. };
  92. enum { WALK_CONTINUE, WALK_TERMINATE };
  93. /*
  94. * Walk partition tables and invoke a callback for each.
  95. */
  96. static void
  97. walk_partitions(int fd, int startsec, int (*f)(void *, int, int, int),
  98. void *arg)
  99. {
  100. uint32_t buf[1024/4];
  101. int bufsize = 1024;
  102. struct mbr_sector *msect = (struct mbr_sector *)&buf[0];
  103. struct mbr_partition mpart[MBR_PART_COUNT];
  104. int sec = startsec;
  105. int lastsec = sec + 1;
  106. int relsect;
  107. int ext = 0;
  108. int systid;
  109. bool valid;
  110. int i;
  111. while (sec != lastsec) {
  112. if (pread(fd, buf, bufsize, (off_t)sec * 512) != bufsize) {
  113. break;
  114. }
  115. lastsec = sec;
  116. if (le16toh(msect->mbr_magic) != MBR_MAGIC) {
  117. break;
  118. }
  119. memcpy(mpart, msect->mbr_parts, MBR_PART_COUNT * sizeof (struct mbr_partition));
  120. for (i = 0; i < MBR_PART_COUNT; i++) {
  121. systid = mpart[i].mbrp_type;
  122. relsect = sec + le32toh(mpart[i].mbrp_start);
  123. if (systid == 0) {
  124. continue;
  125. }
  126. valid = true;
  127. if (is_dos_extended(systid) && (sec == lastsec)) {
  128. sec = startsec + le32toh(mpart[i].mbrp_start);
  129. if (ext++ == 0) {
  130. relsect = startsec = sec;
  131. } else {
  132. valid = false;
  133. }
  134. }
  135. if (valid && f(arg, mpart[i].mbrp_type, relsect,
  136. le32toh(mpart[i].mbrp_size)) == WALK_TERMINATE) {
  137. return;
  138. }
  139. }
  140. }
  141. }
  142. static int
  143. find_dos_drive_cb(void *arg, int systid, int relsect, int numsect)
  144. {
  145. struct part_find_s *p = arg;
  146. if (is_dos_drive(systid)) {
  147. if (++p->count == p->num) {
  148. p->r_relsect = relsect;
  149. p->r_numsect = numsect;
  150. p->r_systid = systid;
  151. return (WALK_TERMINATE);
  152. }
  153. }
  154. return (WALK_CONTINUE);
  155. }
  156. /*
  157. * Given a dos drive number, return its relative sector number,
  158. * number of sectors in partition and the system id.
  159. */
  160. bool
  161. find_dos_drive(int fd, int num, int *relsect, int *numsect, int *systid)
  162. {
  163. struct part_find_s p = { 0, 0, 0, 0, 0, 0 };
  164. p.num = num;
  165. if (num > 0) {
  166. walk_partitions(fd, 0, find_dos_drive_cb, &p);
  167. if (p.count == num) {
  168. *relsect = p.r_relsect;
  169. *numsect = p.r_numsect;
  170. *systid = p.r_systid;
  171. return (true);
  172. }
  173. }
  174. return (false);
  175. }
  176. static int
  177. get_num_dos_drives_cb(void *arg, int systid, int relsect, int numsect)
  178. {
  179. if (is_dos_drive(systid)) {
  180. (*(int *)arg)++;
  181. }
  182. return (WALK_CONTINUE);
  183. }
  184. int
  185. get_num_dos_drives(int fd)
  186. {
  187. int count = 0;
  188. walk_partitions(fd, 0, get_num_dos_drives_cb, &count);
  189. return (count);
  190. }