1*7563SPrasad.Singamsetty@Sun.COM /*
22912Sartem *
32912Sartem * fsutils.c : filesystem utilities
42912Sartem *
56395Sartem * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
62912Sartem * Use is subject to license terms.
72912Sartem *
82912Sartem * Licensed under the Academic Free License version 2.1
92912Sartem *
10*7563SPrasad.Singamsetty@Sun.COM */
112912Sartem
122912Sartem #ifdef HAVE_CONFIG_H
13*7563SPrasad.Singamsetty@Sun.COM #include <config.h>
142912Sartem #endif
152912Sartem
162912Sartem #include <stdio.h>
172912Sartem #include <sys/types.h>
182912Sartem #include <sys/scsi/impl/uscsi.h>
192912Sartem #include <string.h>
202912Sartem #include <strings.h>
212912Sartem #include <ctype.h>
222912Sartem #include <unistd.h>
232912Sartem #include <stdlib.h>
242912Sartem #include <errno.h>
252912Sartem #include <fcntl.h>
262912Sartem #include <sys/dkio.h>
272912Sartem #include <libintl.h>
282912Sartem #include <sys/dktp/fdisk.h>
292912Sartem #include <sys/fs/pc_label.h>
302912Sartem
312912Sartem #include <libhal.h>
322912Sartem #include "fsutils.h"
332912Sartem
342912Sartem /*
352912Sartem * Separates dos notation device spec into device and drive number
362912Sartem */
372912Sartem boolean_t
dos_to_dev(char * path,char ** devpath,int * num)382912Sartem dos_to_dev(char *path, char **devpath, int *num)
392912Sartem {
402912Sartem char *p;
412912Sartem
422912Sartem if ((p = strrchr(path, ':')) == NULL) {
432912Sartem return (B_FALSE);
442912Sartem }
452912Sartem if ((*num = atoi(p + 1)) == 0) {
462912Sartem return (B_FALSE);
472912Sartem }
482912Sartem p[0] = '\0';
492912Sartem *devpath = strdup(path);
502912Sartem p[0] = ':';
512912Sartem return (*devpath != NULL);
522912Sartem }
532912Sartem
542912Sartem char *
get_slice_name(char * devlink)55*7563SPrasad.Singamsetty@Sun.COM get_slice_name(char *devlink)
562912Sartem {
572912Sartem char *part, *slice, *disk;
582912Sartem char *s = NULL;
592912Sartem char *p;
602912Sartem
612912Sartem if ((p = strstr(devlink, "/lofi/")) != 0) {
622912Sartem return (p + sizeof ("/lofi/") - 1);
632912Sartem }
642912Sartem
652912Sartem part = strrchr(devlink, 'p');
662912Sartem slice = strrchr(devlink, 's');
672912Sartem disk = strrchr(devlink, 'd');
682912Sartem
692912Sartem if ((part != NULL) && (part > slice) && (part > disk)) {
702912Sartem s = part;
712912Sartem } else if ((slice != NULL) && (slice > disk)) {
722912Sartem s = slice;
732912Sartem } else {
742912Sartem s = disk;
752912Sartem }
762912Sartem if ((s != NULL) && isdigit(s[1])) {
772912Sartem return (s);
782912Sartem } else {
792912Sartem return ("");
802912Sartem }
812912Sartem }
822912Sartem
832912Sartem boolean_t
is_dos_drive(uchar_t type)842912Sartem is_dos_drive(uchar_t type)
852912Sartem {
863602Sartem return ((type == DOSOS12) || (type == DOSOS16) ||
873602Sartem (type == DOSHUGE) || (type == FDISK_WINDOWS) ||
883602Sartem (type == FDISK_EXT_WIN) || (type == FDISK_FAT95) ||
893602Sartem (type == DIAGPART));
902912Sartem }
912912Sartem
922912Sartem boolean_t
is_dos_extended(uchar_t id)932912Sartem is_dos_extended(uchar_t id)
942912Sartem {
952912Sartem return ((id == EXTDOS) || (id == FDISK_EXTLBA));
962912Sartem }
972912Sartem
982912Sartem struct part_find_s {
992912Sartem int num;
1002912Sartem int count;
1012912Sartem int systid;
1022912Sartem int r_systid;
103*7563SPrasad.Singamsetty@Sun.COM uint_t r_relsect;
104*7563SPrasad.Singamsetty@Sun.COM uint_t r_numsect;
1052912Sartem };
1062912Sartem
1072912Sartem enum { WALK_CONTINUE, WALK_TERMINATE };
1082912Sartem
1092912Sartem /*
1102912Sartem * Walk partition tables and invoke a callback for each.
1112912Sartem */
1122912Sartem static void
walk_partitions(int fd,int startsec,uint_t secsz,int (* f)(void *,int,uint_t,uint_t),void * arg)1136395Sartem walk_partitions(int fd, int startsec, uint_t secsz,
114*7563SPrasad.Singamsetty@Sun.COM int (*f)(void *, int, uint_t, uint_t), void *arg)
1152912Sartem {
1162912Sartem uint32_t buf[1024/4];
1172912Sartem int bufsize = 1024;
1182912Sartem struct mboot *mboot = (struct mboot *)&buf[0];
1192912Sartem struct ipart ipart[FD_NUMPART];
120*7563SPrasad.Singamsetty@Sun.COM uint_t sec = startsec;
121*7563SPrasad.Singamsetty@Sun.COM uint_t lastsec = sec + 1;
122*7563SPrasad.Singamsetty@Sun.COM uint_t relsect;
1232912Sartem int ext = 0;
1242912Sartem int systid;
1252912Sartem boolean_t valid;
1262912Sartem int i;
1272912Sartem
1282912Sartem while (sec != lastsec) {
1296395Sartem if (pread(fd, buf, bufsize, (off_t)sec * secsz) != bufsize) {
1302912Sartem break;
1312912Sartem }
1322912Sartem lastsec = sec;
1332912Sartem if (ltohs(mboot->signature) != MBB_MAGIC) {
1342912Sartem break;
1352912Sartem }
1362912Sartem bcopy(mboot->parts, ipart, FD_NUMPART * sizeof (struct ipart));
1372912Sartem
1382912Sartem for (i = 0; i < FD_NUMPART; i++) {
1392912Sartem systid = ipart[i].systid;
1402912Sartem relsect = sec + ltohi(ipart[i].relsect);
1412912Sartem if (systid == 0) {
1422912Sartem continue;
1432912Sartem }
1442912Sartem valid = B_TRUE;
1452912Sartem if (is_dos_extended(systid) && (sec == lastsec)) {
1462912Sartem sec = startsec + ltohi(ipart[i].relsect);
1472912Sartem if (ext++ == 0) {
1482912Sartem relsect = startsec = sec;
1492912Sartem } else {
1502912Sartem valid = B_FALSE;
1512912Sartem }
1522912Sartem }
1532912Sartem if (valid && f(arg, ipart[i].systid, relsect,
1542912Sartem ltohi(ipart[i].numsect)) == WALK_TERMINATE) {
1552912Sartem return;
1562912Sartem }
1572912Sartem }
1582912Sartem }
1592912Sartem }
1602912Sartem
1612912Sartem static int
find_dos_drive_cb(void * arg,int systid,uint_t relsect,uint_t numsect)162*7563SPrasad.Singamsetty@Sun.COM find_dos_drive_cb(void *arg, int systid, uint_t relsect, uint_t numsect)
1632912Sartem {
1642912Sartem struct part_find_s *p = arg;
1652912Sartem
1662912Sartem if (is_dos_drive(systid)) {
1672912Sartem if (++p->count == p->num) {
1682912Sartem p->r_relsect = relsect;
1692912Sartem p->r_numsect = numsect;
1702912Sartem p->r_systid = systid;
1712912Sartem return (WALK_TERMINATE);
1722912Sartem }
1732912Sartem }
1742912Sartem
1752912Sartem return (WALK_CONTINUE);
1762912Sartem }
1772912Sartem
1782912Sartem /*
1792912Sartem * Given a dos drive number, return its relative sector number,
1802912Sartem * number of sectors in partition and the system id.
1812912Sartem */
1822912Sartem boolean_t
find_dos_drive(int fd,int num,uint_t secsz,off_t * offset)1836395Sartem find_dos_drive(int fd, int num, uint_t secsz, off_t *offset)
1842912Sartem {
1852912Sartem struct part_find_s p = { 0, 0, 0, 0, 0, 0 };
1862912Sartem
1872912Sartem p.num = num;
1882912Sartem
1892912Sartem if (num > 0) {
1906395Sartem walk_partitions(fd, 0, secsz, find_dos_drive_cb, &p);
1912912Sartem if (p.count == num) {
1926395Sartem *offset = (off_t)p.r_relsect * secsz;
1932912Sartem return (B_TRUE);
1942912Sartem }
1952912Sartem }
1962912Sartem
1972912Sartem return (B_FALSE);
1982912Sartem }
1992912Sartem
2002912Sartem static int
get_num_dos_drives_cb(void * arg,int systid,uint_t relsect,uint_t numsect)201*7563SPrasad.Singamsetty@Sun.COM get_num_dos_drives_cb(void *arg, int systid, uint_t relsect, uint_t numsect)
2022912Sartem {
2032912Sartem if (is_dos_drive(systid)) {
2042912Sartem (*(int *)arg)++;
2052912Sartem }
2062912Sartem return (WALK_CONTINUE);
2072912Sartem }
2082912Sartem
2092912Sartem int
get_num_dos_drives(int fd,uint_t secsz)2106395Sartem get_num_dos_drives(int fd, uint_t secsz)
2112912Sartem {
2122912Sartem int count = 0;
2132912Sartem
2146395Sartem walk_partitions(fd, 0, secsz, get_num_dos_drives_cb, &count);
2152912Sartem
2162912Sartem return (count);
2172912Sartem }
2182912Sartem
2192912Sartem /*
2202912Sartem * Return true if all non-empty slices in vtoc have identical start/size and
2212912Sartem * are tagged backup/entire disk.
2222912Sartem */
2232912Sartem boolean_t
vtoc_one_slice_entire_disk(struct extvtoc * vtoc)224*7563SPrasad.Singamsetty@Sun.COM vtoc_one_slice_entire_disk(struct extvtoc *vtoc)
2252912Sartem {
2262912Sartem int i;
227*7563SPrasad.Singamsetty@Sun.COM struct extpartition *p;
228*7563SPrasad.Singamsetty@Sun.COM diskaddr_t prev_start;
229*7563SPrasad.Singamsetty@Sun.COM diskaddr_t prev_size;
2302912Sartem
2312912Sartem for (i = 0; i < vtoc->v_nparts; i++) {
2322912Sartem p = &vtoc->v_part[i];
2332912Sartem if (p->p_size == 0) {
2342912Sartem continue;
2352912Sartem }
2362912Sartem if ((p->p_tag != V_BACKUP) && ((p->p_tag != V_UNASSIGNED))) {
2372912Sartem return (B_FALSE);
2382912Sartem }
2392912Sartem if ((i > 0) &&
2402912Sartem ((p->p_start != prev_start) || (p->p_size != prev_size))) {
2412912Sartem return (B_FALSE);
2422912Sartem }
2432912Sartem prev_start = p->p_start;
2442912Sartem prev_size = p->p_size;
2452912Sartem }
2462912Sartem
2472912Sartem return (B_TRUE);
2482912Sartem }
249