1/* See LICENSE file for copyright and license details. */
2#include "diskutil.h"
3#include "util.h"
4
5#include <fcntl.h>
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9#include <unistd.h>
10
11static char *oflag = "full";
12static char *sflag = NULL;
13static int Uflag = 0;
14static int Lflag = 0;
15
16static void
17usage(void)
18{
19 eprintf("usage: %s [-o format] [-s tag] [-U] [-L] [device ...]\n", argv0);
20}
21
22static void
23print_tag(const char *devname, const char *tag, const char *value)
24{
25 (void)devname;
26 if (sflag && strcasecmp(sflag, tag) != 0)
27 return;
28
29 if (strcmp(oflag, "value") == 0) {
30 printf("%s\n", value);
31 } else if (strcmp(oflag, "export") == 0) {
32 printf("%s=%s\n", tag, value);
33 } else {
34 printf(" %s=\"%s\"", tag, value);
35 }
36}
37
38static int
39do_blkid(const char *path)
40{
41 struct BlockDev dev;
42 char type[64] = {0};
43 char label[256] = {0};
44 char uuid[256] = {0};
45 int res;
46
47 if (blockdev_open(&dev, path, 0) < 0)
48 return -1;
49
50 res = blockdev_detect_fs(&dev, type, sizeof(type), label, sizeof(label), uuid, sizeof(uuid));
51 if (res == 0) {
52 if (Uflag || Lflag) {
53 if (Uflag) {
54 printf("%s\n", uuid);
55 } else {
56 printf("%s\n", label);
57 }
58 } else {
59 if (strcmp(oflag, "export") == 0) {
60 printf("DEVNAME=%s\n", path);
61 } else if (strcmp(oflag, "value") != 0) {
62 printf("%s:", path);
63 }
64
65 if (label[0])
66 print_tag(path, "LABEL", label);
67 if (uuid[0])
68 print_tag(path, "UUID", uuid);
69 print_tag(path, "TYPE", type);
70
71 if (strcmp(oflag, "full") == 0)
72 printf("\n");
73 }
74 }
75
76 blockdev_close(&dev);
77 return res == 0 ? 0 : -2;
78}
79
80// ?man blkid: print block device attributes
81// ?man arguments: [device ...]
82// ?man blkid locates and prints attributes (such as uuid, volume label, and
83// filesystem type) ?man of block devices or partition images
84int
85main(int argc, char *argv[])
86{
87 int ret = 0;
88
89 ARGBEGIN
90 {
91 // ?man -o:specify output format (full, value, export)
92 case 'o':
93 oflag = EARGF(usage());
94 break;
95 // ?man -s:only show specified tag (e.g. UUID, LABEL, TYPE)
96 case 's':
97 sflag = EARGF(usage());
98 break;
99 // ?man -U:print UUID only
100 case 'U':
101 Uflag = 1;
102 break;
103 // ?man -L:print volume label only
104 case 'L':
105 Lflag = 1;
106 break;
107 default:
108 usage();
109 }
110 ARGEND
111
112 if (argc > 0) {
113 for (; *argv; argv++) {
114 if (do_blkid(*argv) < 0)
115 ret = 1;
116 }
117 } else {
118 struct BlockDevInfo *list = blockdev_get_list();
119 struct BlockDevInfo *curr;
120 if (!list) {
121 return 1;
122 }
123 for (curr = list; curr; curr = curr->next) {
124 do_blkid(curr->path);
125 struct BlockDevInfo *part;
126 for (part = curr->parts; part; part = part->next) {
127 do_blkid(part->path);
128 }
129 }
130 blockdev_free_list(list);
131 }
132
133 if (fshut(stdin, "<stdin>") | fshut(stdout, "<stdout>"))
134 ret = 2;
135
136 return ret;
137}