]>
Commit | Line | Data |
---|---|---|
6ada3523 MY |
1 | /* |
2 | * lsfd-bdev.c - handle associations opening block devices | |
3 | * | |
4 | * Copyright (C) 2021 Red Hat, Inc. All rights reserved. | |
5 | * Written by Masatake YAMATO <yamato@redhat.com> | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License as published by | |
9 | * the Free Software Foundation; either version 2 of the License, or | |
10 | * (at your option) any later version. | |
11 | * | |
12 | * This program is distributed in the hope that it would be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with this program; if not, write to the Free Software Foundation, | |
19 | * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
20 | */ | |
21 | ||
6ada3523 MY |
22 | #include "lsfd.h" |
23 | ||
353151b0 MY |
24 | static struct list_head partitions; |
25 | ||
26 | struct partition { | |
27 | struct list_head partitions; | |
28 | dev_t dev; | |
29 | char *name; | |
30 | }; | |
31 | ||
26508d63 MY |
32 | static bool bdev_fill_column(struct proc *proc __attribute__((__unused__)), |
33 | struct file *file __attribute__((__unused__)), | |
34 | struct libscols_line *ln, | |
35 | int column_id, | |
36 | size_t column_index) | |
6ada3523 MY |
37 | { |
38 | char *str = NULL; | |
57d5ee16 | 39 | const char *partition, *devdrv; |
b3a23f4d | 40 | |
6ada3523 MY |
41 | switch(column_id) { |
42 | case COL_TYPE: | |
43 | if (scols_line_set_data(ln, column_index, "BLK")) | |
44 | err(EXIT_FAILURE, _("failed to add output data")); | |
45 | return true; | |
57d5ee16 MY |
46 | case COL_BLKDRV: |
47 | devdrv = get_blkdrv(major(file->stat.st_rdev)); | |
48 | if (devdrv) | |
e0dc84da | 49 | str = xstrdup(devdrv); |
57d5ee16 MY |
50 | else |
51 | xasprintf(&str, "%u", | |
52 | major(file->stat.st_rdev)); | |
53 | break; | |
7591516d MY |
54 | case COL_DEVTYPE: |
55 | if (scols_line_set_data(ln, column_index, | |
56 | "blk")) | |
57 | err(EXIT_FAILURE, _("failed to add output data")); | |
58 | return true; | |
618db964 | 59 | case COL_SOURCE: |
b3a23f4d MY |
60 | case COL_PARTITION: |
61 | partition = get_partition(file->stat.st_rdev); | |
62 | if (partition) { | |
e0dc84da | 63 | str = xstrdup(partition); |
b3a23f4d MY |
64 | break; |
65 | } | |
57d5ee16 MY |
66 | devdrv = get_blkdrv(major(file->stat.st_rdev)); |
67 | if (devdrv) { | |
68 | xasprintf(&str, "%s:%u", devdrv, | |
69 | minor(file->stat.st_rdev)); | |
70 | break; | |
71 | } | |
b3a23f4d | 72 | /* FALL THROUGH */ |
6cdc9906 | 73 | case COL_MAJMIN: |
6ada3523 MY |
74 | xasprintf(&str, "%u:%u", |
75 | major(file->stat.st_rdev), | |
76 | minor(file->stat.st_rdev)); | |
77 | break; | |
78 | default: | |
79 | return false; | |
80 | } | |
81 | ||
82 | if (!str) | |
83 | err(EXIT_FAILURE, _("failed to add output data")); | |
84 | if (scols_line_refer_data(ln, column_index, str)) | |
85 | err(EXIT_FAILURE, _("failed to add output data")); | |
86 | return true; | |
87 | } | |
88 | ||
2d95dc09 | 89 | static struct partition *new_partition(dev_t dev, const char *name) |
353151b0 MY |
90 | { |
91 | struct partition *partition = xcalloc(1, sizeof(*partition)); | |
92 | ||
93 | INIT_LIST_HEAD(&partition->partitions); | |
94 | ||
95 | partition->dev = dev; | |
96 | partition->name = xstrdup(name); | |
97 | ||
98 | return partition; | |
99 | } | |
100 | ||
101 | static void free_partition(struct partition *partition) | |
102 | { | |
103 | free(partition->name); | |
104 | free(partition); | |
105 | } | |
106 | ||
107 | static void read_partitions(struct list_head *partitions_list, FILE *part_fp) | |
108 | { | |
109 | unsigned int major, minor; | |
110 | char line[256]; | |
111 | char name[sizeof(line)]; | |
112 | ||
113 | while (fgets(line, sizeof(line), part_fp)) { | |
114 | struct partition *partition; | |
115 | ||
116 | if (sscanf(line, "%u %u %*u %s", &major, &minor, name) != 3) | |
117 | continue; | |
2d95dc09 | 118 | partition = new_partition(makedev(major, minor), name); |
353151b0 MY |
119 | list_add_tail(&partition->partitions, partitions_list); |
120 | } | |
121 | } | |
122 | ||
123 | static void bdev_class_initialize(void) | |
124 | { | |
3401af7c MY |
125 | FILE *part_fp; |
126 | ||
353151b0 MY |
127 | INIT_LIST_HEAD(&partitions); |
128 | ||
3401af7c | 129 | part_fp = fopen("/proc/partitions", "r"); |
353151b0 MY |
130 | if (part_fp) { |
131 | read_partitions(&partitions, part_fp); | |
132 | fclose(part_fp); | |
133 | } | |
134 | } | |
135 | ||
136 | static void bdev_class_finalize(void) | |
137 | { | |
138 | list_free(&partitions, struct partition, partitions, free_partition); | |
139 | } | |
140 | ||
141 | const char *get_partition(dev_t dev) | |
142 | { | |
143 | struct list_head *p; | |
144 | list_for_each(p, &partitions) { | |
145 | struct partition *partition = list_entry(p, struct partition, partitions); | |
146 | if (partition->dev == dev) | |
147 | return partition->name; | |
148 | } | |
149 | return NULL; | |
150 | } | |
151 | ||
14e16696 MY |
152 | const struct file_class bdev_class = { |
153 | .super = &file_class, | |
154 | .size = sizeof(struct file), | |
353151b0 MY |
155 | .initialize_class = bdev_class_initialize, |
156 | .finalize_class = bdev_class_finalize, | |
14e16696 MY |
157 | .fill_column = bdev_fill_column, |
158 | .free_content = NULL, | |
159 | }; |