]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - libblkid/src/devno.c
2 * devno.c - find a particular device by its device number (major/minor)
4 * Copyright (C) 2000, 2001, 2003 Theodore Ts'o
5 * Copyright (C) 2001 Andreas Dilger
8 * This file may be redistributed under the terms of the
9 * GNU Lesser General Public License.
19 #ifdef HAVE_SYS_TYPES_H
20 #include <sys/types.h>
22 #ifdef HAVE_SYS_STAT_H
29 #ifdef HAVE_SYS_MKDEV_H
30 #include <sys/mkdev.h>
36 #include "pathnames.h"
40 char *blkid_strconcat(const char *a
, const char *b
, const char *c
)
43 size_t len
, al
, bl
, cl
;
45 al
= a
? strlen(a
) : 0;
46 bl
= b
? strlen(b
) : 0;
47 cl
= c
? strlen(c
) : 0;
52 p
= res
= malloc(len
+ 1);
72 * This function adds an entry to the directory list
74 static void add_to_dirlist(const char *dir
, const char *subdir
,
75 struct dir_list
**list
)
79 dp
= malloc(sizeof(struct dir_list
));
82 dp
->name
= subdir
? blkid_strconcat(dir
, "/", subdir
) :
83 dir
? strdup(dir
) : NULL
;
94 * This function frees a directory list
96 static void free_dirlist(struct dir_list
**list
)
98 struct dir_list
*dp
, *next
;
100 for (dp
= *list
; dp
; dp
= next
) {
108 void blkid__scan_dir(char *dirname
, dev_t devno
, struct dir_list
**list
,
115 if ((dir
= opendir(dirname
)) == NULL
)
118 while ((dp
= readdir(dir
)) != 0) {
119 #ifdef _DIRENT_HAVE_D_TYPE
120 if (dp
->d_type
!= DT_UNKNOWN
&& dp
->d_type
!= DT_BLK
&&
121 dp
->d_type
!= DT_LNK
&& dp
->d_type
!= DT_DIR
)
124 if (dp
->d_name
[0] == '.' &&
125 ((dp
->d_name
[1] == 0) ||
126 ((dp
->d_name
[1] == '.') && (dp
->d_name
[2] == 0))))
129 if (fstat_at(dirfd(dir
), dirname
, dp
->d_name
, &st
, 0))
132 if (S_ISBLK(st
.st_mode
) && st
.st_rdev
== devno
) {
133 *devname
= blkid_strconcat(dirname
, "/", dp
->d_name
);
135 printf("found 0x%llx at %s\n", (long long)devno
,
140 if (!list
|| !S_ISDIR(st
.st_mode
))
143 /* add subdirectory (but not symlink) to the list */
144 #ifdef _DIRENT_HAVE_D_TYPE
145 if (dp
->d_type
== DT_LNK
)
147 if (dp
->d_type
== DT_UNKNOWN
)
150 if (fstat_at(dirfd(dir
), dirname
, dp
->d_name
, &st
, 1) ||
151 !S_ISDIR(st
.st_mode
))
152 continue; /* symlink or lstat() failed */
155 if (*dp
->d_name
== '.' || (
156 #ifdef _DIRENT_HAVE_D_TYPE
157 dp
->d_type
== DT_DIR
&&
159 strcmp(dp
->d_name
, "shm") == 0))
160 /* ignore /dev/.{udev,mount,mdadm} and /dev/shm */
163 add_to_dirlist(dirname
, dp
->d_name
, list
);
169 /* Directories where we will try to search for device numbers */
170 static const char *devdirs
[] = { "/devices", "/devfs", "/dev", NULL
};
174 * @title: Miscellaneous utils
175 * @short_description: mix of various utils for low-level and high-level API
180 static char *scandev_devno_to_devpath(dev_t devno
)
182 struct dir_list
*list
= NULL
, *new_list
= NULL
;
183 char *devname
= NULL
;
187 * Add the starting directories to search in reverse order of
188 * importance, since we are using a stack...
190 for (dir
= devdirs
; *dir
; dir
++)
191 add_to_dirlist(*dir
, NULL
, &list
);
194 struct dir_list
*current
= list
;
197 DBG(DEBUG_DEVNO
, printf("directory %s\n", current
->name
));
198 blkid__scan_dir(current
->name
, devno
, &new_list
, &devname
);
204 * If we're done checking at this level, descend to
205 * the next level of subdirectories. (breadth-first)
213 free_dirlist(&new_list
);
219 * blkid_devno_to_devname:
220 * @devno: device number
222 * This function finds the pathname to a block device with a given
225 * Returns: a pointer to allocated memory to the pathname on success,
226 * and NULL on failure.
228 char *blkid_devno_to_devname(dev_t devno
)
233 path
= sysfs_devno_to_devpath(devno
, buf
, sizeof(buf
));
237 path
= scandev_devno_to_devpath(devno
);
241 printf("blkid: couldn't find devno 0x%04lx\n",
242 (unsigned long) devno
));
245 printf("found devno 0x%04llx as %s\n", (long long)devno
, path
));
253 * blkid_devno_to_wholedisk:
254 * @dev: device number
255 * @diskname: buffer to return diskname (or NULL)
256 * @len: diskname buffer size (or 0)
257 * @diskdevno: pointer to returns devno of entire disk (or NULL)
259 * This function uses sysfs to convert the @devno device number to the *name*
260 * of the whole disk. The function DOES NOT return full device name. The @dev
261 * argument could be partition or whole disk -- both is converted.
263 * For example: sda1, 0x0801 --> sda, 0x0800
265 * For conversion to the full disk *path* use blkid_devno_to_devname(), for
271 * dev_t dev = 0x0801, disk; // sda1 = 8:1
272 * char *diskpath, diskname[32];
274 * blkid_devno_to_wholedisk(dev, diskname, sizeof(diskname), &disk);
275 * diskpath = blkid_devno_to_devname(disk);
277 * // print "0x0801: sda, /dev/sda, 8:0
278 * printf("0x%x: %s, %s, %d:%d\n",
279 * dev, diskname, diskpath, major(disk), minor(disk));
286 * Returns: 0 on success or -1 in case of error.
288 int blkid_devno_to_wholedisk(dev_t dev
, char *diskname
,
289 size_t len
, dev_t
*diskdevno
)
291 return sysfs_devno_to_wholedisk( dev
, diskname
, len
, diskdevno
);
295 * Returns 1 if the @major number is associated with @drvname.
297 int blkid_driver_has_major(const char *drvname
, int major
)
303 f
= fopen(_PATH_PROC_DEVICES
, "r");
307 while (fgets(buf
, sizeof(buf
), f
)) { /* skip to block dev section */
308 if (strncmp("Block devices:\n", buf
, sizeof(buf
)) == 0)
312 while (fgets(buf
, sizeof(buf
), f
)) {
316 if (sscanf(buf
, "%d %64[^\n ]", &maj
, name
) != 2)
319 if (maj
== major
&& strcmp(name
, drvname
) == 0) {
327 DBG(DEBUG_DEVNO
, printf("major %d %s associated with '%s' driver\n",
328 major
, match
? "is" : "is NOT", drvname
));
334 int main(int argc
, char** argv
)
337 char diskname
[PATH_MAX
];
339 dev_t devno
, disk_devno
;
340 const char *errmsg
= "Couldn't parse %s: %s\n";
342 blkid_init_debug(DEBUG_ALL
);
343 if ((argc
!= 2) && (argc
!= 3)) {
344 fprintf(stderr
, "Usage:\t%s device_number\n\t%s major minor\n"
345 "Resolve a device number to a device name\n",
350 devno
= strtoul(argv
[1], &tmp
, 0);
352 fprintf(stderr
, errmsg
, "device number", argv
[1]);
356 major
= strtoul(argv
[1], &tmp
, 0);
358 fprintf(stderr
, errmsg
, "major number", argv
[1]);
361 minor
= strtoul(argv
[2], &tmp
, 0);
363 fprintf(stderr
, errmsg
, "minor number", argv
[2]);
366 devno
= makedev(major
, minor
);
368 printf("Looking for device 0x%04llx\n", (long long)devno
);
369 devname
= blkid_devno_to_devname(devno
);
372 printf("Looking for whole-device for 0x%04llx\n", (long long)devno
);
373 blkid_devno_to_wholedisk(devno
, diskname
, sizeof(diskname
), &disk_devno
);