#include "dp.h"
#include "linux.h"
#include "list.h"
+#include "util.h"
static int
__attribute__((__nonnull__ (1,2,3)))
static int
open_disk(struct disk_info *info, int flags)
{
- char diskname[PATH_MAX+1] = "";
- char diskpath[PATH_MAX+1] = "";
+ char *diskpath = NULL;
int rc;
- rc = get_disk_name(info->major, info->minor, diskname, PATH_MAX);
+ rc = asprintfa(&diskpath, "/dev/%s", info->disk_name);
if (rc < 0)
return -1;
- strcpy(diskpath, "/dev/");
- strncat(diskpath, diskname, PATH_MAX - 5);
return open(diskpath, flags);
}
}
if (!(options & EFIBOOT_ABBREV_FILE)) {
- int disk_fd = open_disk(info,
- (options& EFIBOOT_OPTIONS_WRITE_SIGNATURE)?O_RDWR:O_RDONLY);
+ int disk_fd;
int saved_errno;
+ int rc;
+
+ rc = set_disk_and_part_name(info);
+ if (rc < 0)
+ goto err;
+
+ disk_fd = open_disk(info,
+ (options& EFIBOOT_OPTIONS_WRITE_SIGNATURE)?O_RDWR:O_RDONLY);
if (disk_fd < 0)
goto err;
}
ssize_t
-__attribute__((__nonnull__ (3)))
-__attribute__((__visibility__ ("default")))
-efi_generate_file_device_path(uint8_t *buf, ssize_t size,
- const char const *filepath,
- uint32_t options, ...)
+efi_va_generate_file_device_path_from_esp(uint8_t *buf, ssize_t size,
+ const char *devpath, int partition,
+ const char *relpath,
+ uint32_t options, va_list ap)
{
int rc;
ssize_t ret = -1;
- char *devpath = NULL;
- char *relpath = NULL;
struct disk_info info = { 0, };
int fd = -1;
int saved_errno;
- rc = find_file(filepath, &devpath, &relpath);
- if (rc < 0)
- return -1;
-
fd = open(devpath, O_RDONLY);
if (fd < 0)
goto err;
if (rc < 0)
goto err;
+ if (partition > 0)
+ info.part = partition;
+
if (options & EFIBOOT_ABBREV_EDD10) {
- va_list ap;
- va_start(ap, options);
+ va_list aq;
+ va_copy(aq, ap);
- info.edd10_devicenum = va_arg(ap, uint32_t);
+ info.edd10_devicenum = va_arg(aq, uint32_t);
- va_end(ap);
+ va_end(aq);
}
- ret = make_the_whole_path(buf, size, fd, &info, devpath,
- relpath, options);
+ char *dp = strdupa(devpath);
+ char *rp = strdupa(relpath);
+ ret = make_the_whole_path(buf, size, fd, &info, dp, rp, options);
err:
saved_errno = errno;
if (info.disk_name) {
if (fd >= 0)
close(fd);
+ errno = saved_errno;
+ return ret;
+}
+
+ssize_t
+__attribute__((__nonnull__ (3, 5)))
+__attribute__((__visibility__ ("default")))
+efi_generate_file_device_path_from_esp(uint8_t *buf, ssize_t size,
+ const char *devpath, int partition,
+ const char *relpath,
+ uint32_t options, ...)
+{
+ ssize_t ret;
+ int saved_errno;
+ va_list ap;
+
+ va_start(ap, options);
+ ret = efi_va_generate_file_device_path_from_esp(buf, size, devpath,
+ partition, relpath,
+ options, ap);
+ saved_errno = errno;
+ va_end(ap);
+ errno = saved_errno;
+ return ret;
+}
+
+
+ssize_t
+__attribute__((__nonnull__ (3)))
+__attribute__((__visibility__ ("default")))
+efi_generate_file_device_path(uint8_t *buf, ssize_t size,
+ const char const *filepath,
+ uint32_t options, ...)
+{
+ int rc;
+ ssize_t ret;
+ char *devpath = NULL;
+ char *relpath = NULL;
+ va_list ap;
+ int saved_errno;
+
+ rc = find_file(filepath, &devpath, &relpath);
+ if (rc < 0)
+ return -1;
+
+ va_start(ap, options);
+
+ ret = efi_va_generate_file_device_path_from_esp(buf, size, devpath,
+ 0, relpath, options, ap);
+ saved_errno = errno;
+ va_end(ap);
if (devpath)
free(devpath);
if (relpath)
int
__attribute__((__visibility__ ("hidden")))
-get_disk_name(uint64_t major, unsigned char minor,
- char *pathname, size_t max)
+set_disk_and_part_name(struct disk_info *info)
{
char *linkbuf;
ssize_t rc;
rc = sysfs_readlink(&linkbuf, "/sys/dev/block/%"PRIu64":%hhd",
- major, minor);
+ info->major, info->minor);
if (rc < 0)
return -1;
- char *dev;
- dev = strrchr(linkbuf, '/');
- if (!dev) {
+ char *ultimate;
+ ultimate = strrchr(linkbuf, '/');
+ if (!ultimate) {
errno = EINVAL;
return -1;
}
- *dev = '\0';
+ *ultimate = '\0';
+ ultimate++;
- dev = strrchr(linkbuf, '/');
- if (!dev) {
+ char *penultimate;
+ penultimate = strrchr(linkbuf, '/');
+ if (!penultimate) {
errno = EINVAL;
return -1;
}
+ penultimate++;
+
+ if (!strcmp(penultimate, "block")) {
+ if (!info->disk_name) {
+ info->disk_name = strdup(ultimate);
+ if (!info->disk_name)
+ return -1;
+ }
+ if (!info->part_name) {
+ rc = asprintf(&info->part_name, "%s%d", info->disk_name,
+ info->part);
+ if (rc < 0)
+ return -1;
+ }
+ } else {
+ if (!info->disk_name) {
+ info->disk_name = strdup(penultimate);
+ if (!info->disk_name)
+ return -1;
+ }
+ if (!info->part_name) {
+ info->part_name = strdup(ultimate);
+ if (!info->part_name)
+ return -1;
+ }
+ }
- strncpy(pathname, dev+1, max);
return 0;
}
*/
char *disk_name = NULL;
char *part_name = NULL;
- rc = sscanf(pbuf+*poff, "block/%m[^/]/%m[^/]%n", &disk_name, &part_name,
- &psz);
- if (rc != 2)
+ int psz1 = 0;
+ rc = sscanf(pbuf+*poff, "block/%m[^/]%n/%m[^/]%n", &disk_name, &psz,
+ &part_name, &psz1);
+ if (rc == 1) {
+ rc = asprintf(&part_name, "%s%d", disk_name, info->part);
+ if (rc < 0) {
+ free(disk_name);
+ errno = EINVAL;
+ return -1;
+ }
+ *poff += psz;
+ } else if (rc != 2) {
+ errno = EINVAL;
return -1;
- *poff += psz;
+ } else {
+ *poff += psz1;
+ }
info->sata_info.scsi_bus = scsi_bus;
info->sata_info.scsi_device = scsi_device;