return 1;
}
+
+int partition_node_of(const char *node, unsigned nr, char **ret) {
+ int r;
+
+ assert(node);
+ assert(nr > 0);
+ assert(ret);
+
+ /* Given a device node path to a block device returns the device node path to the partition block
+ * device of the specified partition */
+
+ _cleanup_free_ char *fn = NULL;
+ r = path_extract_filename(node, &fn);
+ if (r < 0)
+ return r;
+ if (r == O_DIRECTORY)
+ return -EISDIR;
+
+ _cleanup_free_ char *dn = NULL;
+ r = path_extract_directory(node, &dn);
+ if (r < 0 && r != -EDESTADDRREQ) /* allow if only filename is specified */
+ return r;
+
+ size_t l = strlen(fn);
+ assert(l > 0); /* underflow check for the subtraction below */
+
+ bool need_p = ascii_isdigit(fn[l-1]); /* Last char a digit? */
+
+ _cleanup_free_ char *subnode = NULL;
+ if (asprintf(&subnode, "%s%s%u", fn, need_p ? "p" : "", nr) < 0)
+ return -ENOMEM;
+
+ if (dn) {
+ _cleanup_free_ char *j = path_join(dn, subnode);
+ if (!j)
+ return -ENOMEM;
+
+ *ret = TAKE_PTR(j);
+ } else
+ *ret = TAKE_PTR(subnode);
+
+ return 0;
+}
if (!s)
return -ENOMEM;
} else {
- size_t l = strlen(whole_devname);
- if (l < 1) /* underflow check for the subtraction below */
- return -EINVAL;
-
- bool need_p = ascii_isdigit(whole_devname[l-1]); /* Last char a digit? */
-
- if (asprintf(&s, "%s%s%i", whole_devname, need_p ? "p" : "", nr) < 0)
- return -ENOMEM;
+ r = partition_node_of(whole_devname, nr, &s);
+ if (r < 0)
+ return r;
}
} else {
if (nr < 0) /* whole disk? */
}
}
+static void test_partition_node_of_one(const char *main, unsigned partition, const char *result, int retval) {
+ _cleanup_free_ char *s = NULL;
+ int r;
+
+ r = partition_node_of(main, partition, &s);
+ ASSERT_EQ(r, retval);
+ if (r < 0)
+ return;
+ ASSERT_STREQ(s, result);
+
+ log_info("%s with %u → %s", main, partition, result);
+}
+
+TEST(partition_node_of) {
+ test_partition_node_of_one("/dev/sda", 2, "/dev/sda2", 0);
+ test_partition_node_of_one("sda", 3, "sda3", 0);
+ test_partition_node_of_one("/dev/nvme0n1", 7, "/dev/nvme0n1p7", 0);
+ test_partition_node_of_one("nvme0n1", 8, "nvme0n1p8", 0);
+ test_partition_node_of_one("/dev/loop1", 3, "/dev/loop1p3", 0);
+ test_partition_node_of_one("", 1, NULL, -EINVAL);
+ test_partition_node_of_one("/", 1, NULL, -EADDRNOTAVAIL);
+ test_partition_node_of_one("/dev/", 1, NULL, -EISDIR);
+ test_partition_node_of_one("/sda", 1, "/sda1", 0);
+ test_partition_node_of_one(".", 1, NULL, -EADDRNOTAVAIL);
+}
+
DEFINE_TEST_MAIN(LOG_INFO);