I know that you didn't ask for code but here you go (I really had fun writing it).
#include <stdio.h>
#include <dirent.h>
#include <limits.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/stat.h>
static int
walkdir(const char *const path, int (*visit)(const char *const, const char *const), void *data)
{
struct dirent *entry;
DIR *dir;
dir = opendir(path);
if (dir == NULL)
return -1;
while ((entry = readdir(dir)) != NULL) {
int code;
code = visit(path, entry->d_name);
if (code != 0) {
closedir(dir);
return code;
}
}
closedir(dir);
return 0;
}
static char *
file_get_content(const char *const path)
{
int file;
struct stat st;
char *text;
size_t size;
text = NULL;
file = -1;
if (stat(path, &st) == -1)
goto error;
size = st.st_size;
text = malloc(size + 1);
if (text == NULL)
goto error; // file too large, cannot read like this
file = open(path, O_RDONLY);
if (file == -1)
goto error;
if ((size = read(file, text, size)) <= 0)
goto error;
text[size] = '\0';
if (file != -1)
close(file);
return text;
error:
if (file != -1)
close(file);
free(text);
return NULL;
}
static size_t
get_size(const char *const dirpath, const char *const name)
{
char path[PATH_MAX];
char *text;
int length;
size_t size;
length = snprintf(path, sizeof(path), "%s/%s/size", dirpath, name);
if (((size_t) length) > sizeof(path))
return 0;
size = 0;
text = file_get_content(path);
if (text != NULL) {
size = strtoll(text, NULL, 10);
free(text);
}
return size;
}
static int
display_block(const char *const dirpath, const char *const name)
{
const char *block;
block = strrchr(dirpath, '/');
if (block == NULL)
return -1;
block += 1;
if (strstr(name, block) == name) {
size_t size;
// get_ the parition size
//
// Note, I had to divice the size by 2 because it didn't
// match the sizes reported by `df'.
//
// Also, it appears that it's in megabytes
// (i.e. twice the size in MB)
size = get_size(dirpath, name) / (1 << 21);
// Display the result
fprintf(stdout, "\tpartition: %s (%zu GB)\n", name, size);
}
return 0;
}
static char *
get_vendor(const char *const name)
{
char path[PATH_MAX];
int length;
char *value;
// get_ partitions
length = snprintf(path, sizeof(path), "/sys/block/%s/device/vendor", name);
if (((size_t) length) > sizeof(path))
return NULL;
value = file_get_content(path);
if (value == NULL)
return NULL;
// Make the trailing `\n' a '\0' instead
strtok(value, "\n");
return value;
}
static char *
get_model(const char *const name)
{
char path[PATH_MAX];
int length;
char *value;
// get_ partitions
length = snprintf(path, sizeof(path), "/sys/block/%s/device/model", name);
if (((size_t) length) > sizeof(path))
return NULL;
value = file_get_content(path);
if (value == NULL)
return NULL;
// Make the trailing `\n' a '\0' instead
strtok(value, "\n");
return value;
}
static int
parse_block(const char *const name)
{
char path[PATH_MAX];
int length;
char *vendor;
char *model;
// get_ partitions
length = snprintf(path, sizeof(path), "/sys/block/%s", name);
if (((size_t) length) > sizeof(path))
return -1;
vendor = get_vendor(name);
model = get_model(name);
if ((model != NULL) && (vendor != NULL)) {
fprintf(stdout, "block device: %s (%s %s)\n", name, vendor, model);
walkdir(path, display_block, NULL);
}
free(vendor);
free(model);
return 0;
}
static int
list_devices(const char *const dirpath, const char *const name)
{
if (*name == '.')
return 0;
parse_block(name);
return 0;
}
int
main(void)
{
return walkdir("/sys/block", list_devices, NULL);
}
This will show you the devices and some information about them, also the size that you are very interested in.
Note, that there is no need for them to be mounted.
You can of course, find more information in other places. Just check the appropriate directories and you will be able to get everything. For instance, there is a file removable that tells you whether the device is removable, which I think will be very useful in your case.