10f66f451Sopenharmony_ci/* blkid.c - Prints type, label and UUID of filesystem(s). 20f66f451Sopenharmony_ci * 30f66f451Sopenharmony_ci * Copyright 2013 Brad Conroy <bconroy@uis.edu> 40f66f451Sopenharmony_ci * 50f66f451Sopenharmony_ci * See ftp://ftp.kernel.org/pub/linux/utils/util-linux/v2.24/libblkid-docs/api-index-full.html 60f66f451Sopenharmony_ci * TODO: -U and -L should require arguments 70f66f451Sopenharmony_ci 80f66f451Sopenharmony_ciUSE_BLKID(NEWTOY(blkid, "ULs*[!LU]", TOYFLAG_BIN)) 90f66f451Sopenharmony_ciUSE_FSTYPE(NEWTOY(fstype, "<1", TOYFLAG_BIN)) 100f66f451Sopenharmony_ci 110f66f451Sopenharmony_ciconfig BLKID 120f66f451Sopenharmony_ci bool "blkid" 130f66f451Sopenharmony_ci default y 140f66f451Sopenharmony_ci help 150f66f451Sopenharmony_ci usage: blkid [-s TAG] [-UL] DEV... 160f66f451Sopenharmony_ci 170f66f451Sopenharmony_ci Print type, label and UUID of filesystem on a block device or image. 180f66f451Sopenharmony_ci 190f66f451Sopenharmony_ci -U Show UUID only (or device with that UUID) 200f66f451Sopenharmony_ci -L Show LABEL only (or device with that LABEL) 210f66f451Sopenharmony_ci -s TAG Only show matching tags (default all) 220f66f451Sopenharmony_ci 230f66f451Sopenharmony_ciconfig FSTYPE 240f66f451Sopenharmony_ci bool "fstype" 250f66f451Sopenharmony_ci default y 260f66f451Sopenharmony_ci help 270f66f451Sopenharmony_ci usage: fstype DEV... 280f66f451Sopenharmony_ci 290f66f451Sopenharmony_ci Print type of filesystem on a block device or image. 300f66f451Sopenharmony_ci*/ 310f66f451Sopenharmony_ci 320f66f451Sopenharmony_ci#define FOR_blkid 330f66f451Sopenharmony_ci#include "toys.h" 340f66f451Sopenharmony_ci 350f66f451Sopenharmony_ciGLOBALS( 360f66f451Sopenharmony_ci struct arg_list *s; 370f66f451Sopenharmony_ci) 380f66f451Sopenharmony_ci 390f66f451Sopenharmony_cistruct fstype { 400f66f451Sopenharmony_ci char *name; 410f66f451Sopenharmony_ci uint64_t magic; 420f66f451Sopenharmony_ci int magic_len, magic_offset, uuid_off, label_len, label_off; 430f66f451Sopenharmony_ci} static const fstypes[] = { 440f66f451Sopenharmony_ci {"ext2", 0xEF53, 2, 1080, 1128, 16, 1144}, // keep this first for ext3/4 check 450f66f451Sopenharmony_ci {"swap", 0x4341505350415753LL, 8, 4086, 1036, 15, 1052}, 460f66f451Sopenharmony_ci // NTFS label actually 8/16 0x4d80 but horrible: 16 bit wide characters via 470f66f451Sopenharmony_ci // codepage, something called a uuid that's only 8 bytes long... 480f66f451Sopenharmony_ci {"ntfs", 0x5346544e, 4, 3, 0x48, 0, 0}, 490f66f451Sopenharmony_ci 500f66f451Sopenharmony_ci {"adfs", 0xadf5, 2, 0xc00, 0,0,0}, 510f66f451Sopenharmony_ci {"bfs", 0x1badface, 4, 0, 0,0,0}, 520f66f451Sopenharmony_ci {"btrfs", 0x4D5F53665248425FULL, 8, 65600, 65803, 256, 65819}, 530f66f451Sopenharmony_ci {"cramfs", 0x28cd3d45, 4, 0, 0, 16, 48}, 540f66f451Sopenharmony_ci {"f2fs", 0xF2F52010, 4, 1024, 1132, 512, 0x47c}, 550f66f451Sopenharmony_ci {"jfs", 0x3153464a, 4, 32768, 32920, 16, 32904}, 560f66f451Sopenharmony_ci {"nilfs", 0x3434, 2, 1030, 1176, 80, 1192}, 570f66f451Sopenharmony_ci {"reiserfs", 0x724573496552ULL, 6, 8244, 8276, 16, 8292}, 580f66f451Sopenharmony_ci {"reiserfs", 0x724573496552ULL, 6, 65588, 65620, 16, 65636}, 590f66f451Sopenharmony_ci {"romfs", 0x2d6d6f72, 4, 0, 0,0,0}, 600f66f451Sopenharmony_ci {"squashfs", 0x73717368, 4, 0, 0,0,0}, 610f66f451Sopenharmony_ci {"xiafs", 0x012fd16d, 4, 572, 0,0,0}, 620f66f451Sopenharmony_ci {"xfs", 0x42534658, 4, 0, 32, 12, 108}, 630f66f451Sopenharmony_ci {"vfat", 0x3233544146ULL, 5, 82, 67, 11, 71}, // fat32 640f66f451Sopenharmony_ci {"vfat", 0x31544146, 4, 54, 39, 11, 43} // fat1 650f66f451Sopenharmony_ci}; 660f66f451Sopenharmony_ci 670f66f451Sopenharmony_cistatic void show_tag(char *key, char *value) 680f66f451Sopenharmony_ci{ 690f66f451Sopenharmony_ci int show = 0; 700f66f451Sopenharmony_ci struct arg_list *al; 710f66f451Sopenharmony_ci 720f66f451Sopenharmony_ci if (TT.s) { 730f66f451Sopenharmony_ci for (al = TT.s; al; al = al->next) if (!strcmp(key, al->arg)) show = 1; 740f66f451Sopenharmony_ci } else show = 1; 750f66f451Sopenharmony_ci 760f66f451Sopenharmony_ci if (show && *value) printf(" %s=\"%s\"", key, value); 770f66f451Sopenharmony_ci} 780f66f451Sopenharmony_ci 790f66f451Sopenharmony_cistatic void flagshow(char *s, char *name) 800f66f451Sopenharmony_ci{ 810f66f451Sopenharmony_ci if (*toys.optargs && strcmp(s, *toys.optargs)) return; 820f66f451Sopenharmony_ci printf("%s\n", *toys.optargs ? name : s); 830f66f451Sopenharmony_ci if (*toys.optargs) xexit(); 840f66f451Sopenharmony_ci} 850f66f451Sopenharmony_ci 860f66f451Sopenharmony_cistatic void do_blkid(int fd, char *name) 870f66f451Sopenharmony_ci{ 880f66f451Sopenharmony_ci int off, i, j, len; 890f66f451Sopenharmony_ci char buf[128], *type, *s; 900f66f451Sopenharmony_ci 910f66f451Sopenharmony_ci off = i = 0; 920f66f451Sopenharmony_ci 930f66f451Sopenharmony_ci for (;;) { 940f66f451Sopenharmony_ci int pass = 0; 950f66f451Sopenharmony_ci 960f66f451Sopenharmony_ci // Read next block of data 970f66f451Sopenharmony_ci len = readall(fd, toybuf, sizeof(toybuf)); 980f66f451Sopenharmony_ci if (len != sizeof(toybuf)) return; 990f66f451Sopenharmony_ci 1000f66f451Sopenharmony_ci // Iterate through types in range 1010f66f451Sopenharmony_ci for (i=0; i<ARRAY_LEN(fstypes); i++) { 1020f66f451Sopenharmony_ci uint64_t test; 1030f66f451Sopenharmony_ci 1040f66f451Sopenharmony_ci // Skip tests not in this 4k block 1050f66f451Sopenharmony_ci if (fstypes[i].magic_offset > off+sizeof(toybuf)) { 1060f66f451Sopenharmony_ci pass++; 1070f66f451Sopenharmony_ci continue; 1080f66f451Sopenharmony_ci } 1090f66f451Sopenharmony_ci if (fstypes[i].magic_offset < off) continue; 1100f66f451Sopenharmony_ci 1110f66f451Sopenharmony_ci // Populate 64 bit little endian magic value 1120f66f451Sopenharmony_ci test = 0; 1130f66f451Sopenharmony_ci for (j = 0; j < fstypes[i].magic_len; j++) 1140f66f451Sopenharmony_ci test += ((uint64_t)toybuf[j+fstypes[i].magic_offset-off])<<(8*j); 1150f66f451Sopenharmony_ci if (test == fstypes[i].magic) break; 1160f66f451Sopenharmony_ci } 1170f66f451Sopenharmony_ci 1180f66f451Sopenharmony_ci if (i == ARRAY_LEN(fstypes)) { 1190f66f451Sopenharmony_ci off += len; 1200f66f451Sopenharmony_ci if (pass) continue; 1210f66f451Sopenharmony_ci return; 1220f66f451Sopenharmony_ci } 1230f66f451Sopenharmony_ci break; 1240f66f451Sopenharmony_ci } 1250f66f451Sopenharmony_ci 1260f66f451Sopenharmony_ci // distinguish ext2/3/4 1270f66f451Sopenharmony_ci type = fstypes[i].name; 1280f66f451Sopenharmony_ci if (!i) { 1290f66f451Sopenharmony_ci if (toybuf[1116]&4) type = "ext3"; 1300f66f451Sopenharmony_ci if (toybuf[1120]&64) type = "ext4"; 1310f66f451Sopenharmony_ci } 1320f66f451Sopenharmony_ci 1330f66f451Sopenharmony_ci // Output for fstype 1340f66f451Sopenharmony_ci if (*toys.which->name == 'f') { 1350f66f451Sopenharmony_ci puts(type); 1360f66f451Sopenharmony_ci return; 1370f66f451Sopenharmony_ci } 1380f66f451Sopenharmony_ci 1390f66f451Sopenharmony_ci // output for blkid 1400f66f451Sopenharmony_ci if (!FLAG(L) && !FLAG(U)) printf("%s:",name); 1410f66f451Sopenharmony_ci 1420f66f451Sopenharmony_ci len = fstypes[i].label_len; 1430f66f451Sopenharmony_ci if (!FLAG(U) && len) { 1440f66f451Sopenharmony_ci s = toybuf+fstypes[i].label_off-off; 1450f66f451Sopenharmony_ci if (!strcmp(type, "vfat")) { 1460f66f451Sopenharmony_ci show_tag("SEC_TYPE", "msdos"); 1470f66f451Sopenharmony_ci while (len && s[len-1]==' ') len--; 1480f66f451Sopenharmony_ci if (strstart(&s, "NO NAME")) len=0; 1490f66f451Sopenharmony_ci } 1500f66f451Sopenharmony_ci // TODO: special case NTFS $VOLUME_NAME here... 1510f66f451Sopenharmony_ci if (len) { 1520f66f451Sopenharmony_ci if (!strcmp(type, "f2fs")) { 1530f66f451Sopenharmony_ci // Convert UTF16LE to ASCII by replacing non-ASCII with '?'. 1540f66f451Sopenharmony_ci // TODO: support non-ASCII. 1550f66f451Sopenharmony_ci for (j=0; j<len; j++) { 1560f66f451Sopenharmony_ci buf[j] = s[2*j]; 1570f66f451Sopenharmony_ci if (s[2*j+1]) buf[j]='?'; 1580f66f451Sopenharmony_ci if (!buf[j]) break; 1590f66f451Sopenharmony_ci } 1600f66f451Sopenharmony_ci } else sprintf(buf, "%.*s", len, s); 1610f66f451Sopenharmony_ci if (FLAG(L)) return flagshow(buf, name); 1620f66f451Sopenharmony_ci show_tag("LABEL", buf); 1630f66f451Sopenharmony_ci } 1640f66f451Sopenharmony_ci } 1650f66f451Sopenharmony_ci 1660f66f451Sopenharmony_ci len = fstypes[i].uuid_off; 1670f66f451Sopenharmony_ci if (!FLAG(L) && len) { 1680f66f451Sopenharmony_ci int uoff = len-off; 1690f66f451Sopenharmony_ci 1700f66f451Sopenharmony_ci // Assemble UUID with whatever size and set of dashes this filesystem uses 1710f66f451Sopenharmony_ci s = buf; 1720f66f451Sopenharmony_ci if (!strcmp(type, "ntfs")) { 1730f66f451Sopenharmony_ci for (j = 7; j >= 0; --j) s += sprintf(s, "%02X", toybuf[uoff+j]); 1740f66f451Sopenharmony_ci } else if (!strcmp(type, "vfat")) { 1750f66f451Sopenharmony_ci s += sprintf(s, "%02X%02X-%02X%02X", toybuf[uoff+3], toybuf[uoff+2], 1760f66f451Sopenharmony_ci toybuf[uoff+1], toybuf[uoff]); 1770f66f451Sopenharmony_ci } else { 1780f66f451Sopenharmony_ci for (j = 0; j < 16; j++) 1790f66f451Sopenharmony_ci s += sprintf(s, "-%02x"+!(0x550 & (1<<j)), toybuf[uoff+j]); 1800f66f451Sopenharmony_ci } 1810f66f451Sopenharmony_ci 1820f66f451Sopenharmony_ci if (FLAG(U)) return flagshow(buf, name); 1830f66f451Sopenharmony_ci show_tag("UUID", buf); 1840f66f451Sopenharmony_ci } 1850f66f451Sopenharmony_ci 1860f66f451Sopenharmony_ci if ((!strcmp(type, "ext3")||!strcmp(type,"ext4")) && !(toybuf[1120]&~0x12)) 1870f66f451Sopenharmony_ci show_tag("SEC_TYPE", "ext2"); 1880f66f451Sopenharmony_ci 1890f66f451Sopenharmony_ci if (FLAG(U) || FLAG(L)) return; 1900f66f451Sopenharmony_ci 1910f66f451Sopenharmony_ci show_tag("TYPE", type); 1920f66f451Sopenharmony_ci xputc('\n'); 1930f66f451Sopenharmony_ci} 1940f66f451Sopenharmony_ci 1950f66f451Sopenharmony_civoid blkid_main(void) 1960f66f451Sopenharmony_ci{ 1970f66f451Sopenharmony_ci if (*toys.optargs && !FLAG(L) && !FLAG(U)) loopfiles(toys.optargs, do_blkid); 1980f66f451Sopenharmony_ci else { 1990f66f451Sopenharmony_ci unsigned int ma, mi, sz, fd; 2000f66f451Sopenharmony_ci char name[32], device[5+32]; 2010f66f451Sopenharmony_ci FILE *fp = xfopen("/proc/partitions", "r"); 2020f66f451Sopenharmony_ci 2030f66f451Sopenharmony_ci while (fgets(toybuf, sizeof(toybuf), fp)) { 2040f66f451Sopenharmony_ci if (sscanf(toybuf, " %u %u %u %31s", &ma, &mi, &sz, name) != 4) 2050f66f451Sopenharmony_ci continue; 2060f66f451Sopenharmony_ci 2070f66f451Sopenharmony_ci sprintf(device, "/dev/%.20s", name); 2080f66f451Sopenharmony_ci if (-1 == (fd = open(device, O_RDONLY))) { 2090f66f451Sopenharmony_ci if (errno != ENOMEDIUM) perror_msg_raw(device); 2100f66f451Sopenharmony_ci } else { 2110f66f451Sopenharmony_ci do_blkid(fd, device); 2120f66f451Sopenharmony_ci close(fd); 2130f66f451Sopenharmony_ci } 2140f66f451Sopenharmony_ci } 2150f66f451Sopenharmony_ci if (CFG_TOYBOX_FREE) fclose(fp); 2160f66f451Sopenharmony_ci } 2170f66f451Sopenharmony_ci 2180f66f451Sopenharmony_ci if (FLAG(L) || FLAG(U)) toys.exitval = 2; 2190f66f451Sopenharmony_ci} 2200f66f451Sopenharmony_ci 2210f66f451Sopenharmony_civoid fstype_main(void) 2220f66f451Sopenharmony_ci{ 2230f66f451Sopenharmony_ci loopfiles(toys.optargs, do_blkid); 2240f66f451Sopenharmony_ci} 225