OSDN Git Service

linux.h: add some more sysfs helpers, and improve their error handling.
authorPeter Jones <pjones@redhat.com>
Tue, 22 May 2018 13:55:05 +0000 (09:55 -0400)
committerPeter Jones <pmjones@gmail.com>
Fri, 8 Jun 2018 19:11:37 +0000 (15:11 -0400)
... this also moves them from util.h

Signed-off-by: Peter Jones <pjones@redhat.com>
src/linux.c
src/linux.h
src/util.h

index abb841f..8bc59e3 100644 (file)
@@ -48,7 +48,7 @@ set_disk_and_part_name(struct disk_info *info)
        char *linkbuf;
        ssize_t rc;
 
-       rc = sysfs_readlink(&linkbuf, "/sys/dev/block/%"PRIu64":%"PRIu32,
+       rc = sysfs_readlink(&linkbuf, "dev/block/%"PRIu64":%"PRIu32,
                      info->major, info->minor);
        if (rc < 0 || !linkbuf)
                return -1;
@@ -145,13 +145,13 @@ get_partition_number(const char *devpath)
        maj = major(statbuf.st_rdev);
        min = minor(statbuf.st_rdev);
 
-       rc = sysfs_readlink(&linkbuf, "/sys/dev/block/%u:%u", maj, min);
+       rc = sysfs_readlink(&linkbuf, "dev/block/%u:%u", maj, min);
        if (rc < 0 || !linkbuf) {
                efi_error("couldn't get partition number for %u:%u", maj, min);
                return -1;
        }
 
-       rc = read_sysfs_file(&partbuf, "/sys/dev/block/%s/partition", linkbuf);
+       rc = read_sysfs_file(&partbuf, "dev/block/%s/partition", linkbuf);
        if (rc < 0) {
                efi_error("couldn't get partition number for %s", linkbuf);
                /* This isn't strictly an error for e.g. nvdimm pmem devices */
@@ -180,7 +180,7 @@ find_parent_devpath(const char * const child, char **parent)
        node++;
 
        /* look up full path symlink */
-       ret = sysfs_readlink(&linkbuf, "/sys/class/block/%s", node);
+       ret = sysfs_readlink(&linkbuf, "class/block/%s", node);
        if (ret < 0 || !linkbuf)
                return ret;
 
@@ -213,7 +213,7 @@ sysfs_test_pmem(const char *buf)
        int rc;
 
        rc = sysfs_readlink(&driverbuf,
-                           "/sys/dev/block/%s/device/driver", buf);
+                           "dev/block/%s/device/driver", buf);
        if (rc < 0 || !driverbuf)
                return 0;
 
@@ -327,7 +327,7 @@ sysfs_sata_get_port_info(uint32_t print_id, struct disk_info *info)
        }
        closedir(d);
 
-       rc = read_sysfs_file(&buf, "/sys/class/ata_port/ata%d/port_no",
+       rc = read_sysfs_file(&buf, "class/ata_port/ata%d/port_no",
                             print_id);
        if (rc <= 0 || buf == NULL)
                return -1;
@@ -377,7 +377,7 @@ sysfs_parse_pmem(uint8_t *buf,  ssize_t size, ssize_t *off,
        int rc;
 
        rc = read_sysfs_file(&filebuf,
-                            "/sys/class/block/%s/device/uuid", pbuf);
+                            "class/block/%s/device/uuid", pbuf);
        if ((rc < 0 && errno == ENOENT) || filebuf == NULL)
                return -1;
 
@@ -435,11 +435,11 @@ sysfs_parse_nvme(uint8_t *buf, ssize_t size, ssize_t *off,
         * now fish the eui out of sysfs is there is one...
         */
        rc = read_sysfs_file(&filebuf,
-                            "/sys/class/block/nvme%dn%d/eui",
+                            "class/block/nvme%dn%d/eui",
                             ctrl_id, ns_id);
        if ((rc < 0 && errno == ENOENT) || filebuf == NULL) {
                rc = read_sysfs_file(&filebuf,
-                            "/sys/class/block/nvme%dn%d/device/eui",
+                            "class/block/nvme%dn%d/device/eui",
                             ctrl_id, ns_id);
        }
        if (rc >= 0 && filebuf != NULL) {
@@ -680,7 +680,7 @@ sysfs_parse_sas(uint8_t *buf, ssize_t size, ssize_t *off,
         * we also need to get the actual sas_address from someplace...
         */
        rc = read_sysfs_file(&filebuf,
-                            "/sys/class/block/%s/device/sas_address",
+                            "class/block/%s/device/sas_address",
                             disk_name);
        if (rc < 0 || filebuf == NULL)
                return -1;
@@ -730,7 +730,7 @@ make_pci_path(uint8_t *buf, ssize_t size, char *pathstr, ssize_t *pathoff)
 
        uint8_t *fbuf = NULL;
        rc = read_sysfs_file(&fbuf,
-                            "/sys/devices/pci%04hx:%02hhx/firmware_node/hid",
+                            "devices/pci%04hx:%02hhx/firmware_node/hid",
                             root_domain, root_bus);
        if (rc < 0 || fbuf == NULL)
                return -1;
@@ -753,7 +753,7 @@ make_pci_path(uint8_t *buf, ssize_t size, char *pathstr, ssize_t *pathoff)
        fbuf = NULL;
        int use_uid_str = 0;
        rc = read_sysfs_file(&fbuf,
-                            "/sys/devices/pci%04hx:%02hhx/firmware_node/uid",
+                            "devices/pci%04hx:%02hhx/firmware_node/uid",
                             root_domain, root_bus);
        if ((rc <= 0 && errno != ENOENT) || fbuf == NULL)
                return -1;
@@ -820,7 +820,7 @@ make_blockdev_path(uint8_t *buf, ssize_t size, struct disk_info *info)
        int rc;
        int found = 0;
 
-       rc = sysfs_readlink(&linkbuf, "/sys/dev/block/%"PRIu64":%u",
+       rc = sysfs_readlink(&linkbuf, "dev/block/%"PRIu64":%u",
                            info->major, info->minor);
        if (rc < 0 || !linkbuf) {
                efi_error("couldn't read link for /sys/dev/block/%"PRIu64":%u",
@@ -871,7 +871,7 @@ make_blockdev_path(uint8_t *buf, ssize_t size, struct disk_info *info)
                if (!tmppath)
                        return -1;
                tmppath[loff] = '\0';
-               rc = sysfs_readlink(&driverbuf, "/sys/dev/block/%s/driver",
+               rc = sysfs_readlink(&driverbuf, "dev/block/%s/driver",
                                    tmppath);
                if (rc < 0 || !driverbuf)
                        return -1;
@@ -975,7 +975,7 @@ make_blockdev_path(uint8_t *buf, ssize_t size, struct disk_info *info)
        if (!found && info->interface_type == scsi) {
                char *linkbuf;
 
-               rc = sysfs_readlink(&linkbuf, "/sys/class/block/%s/device",
+               rc = sysfs_readlink(&linkbuf, "class/block/%s/device",
                              info->disk_name);
                if (rc < 0 || !linkbuf)
                        return 0;
@@ -1098,7 +1098,7 @@ eb_disk_info_from_fd(int fd, struct disk_info *info)
                return 0;
        }
 
-       rc = sysfs_readlink(&driver, "/sys/dev/block/%"PRIu64":%"PRIu32"/device/driver",
+       rc = sysfs_readlink(&driver, "dev/block/%"PRIu64":%"PRIu32"/device/driver",
                            info->major, info->minor);
        if (rc > 0) {
                char *last = strrchr(driver, '/');
@@ -1127,7 +1127,7 @@ make_net_pci_path(uint8_t *buf, ssize_t size, const char * const ifname)
        int lsz = 0;
        int rc;
 
-       rc = sysfs_readlink(&linkbuf, "/sys/class/net/%s", ifname);
+       rc = sysfs_readlink(&linkbuf, "class/net/%s", ifname);
        if (rc < 0 || !linkbuf)
                return -1;
 
index 3e89854..dfe8aee 100644 (file)
@@ -114,4 +114,78 @@ extern int HIDDEN find_parent_devpath(const char * const child,
 extern ssize_t HIDDEN make_mac_path(uint8_t *buf, ssize_t size,
                                     const char * const ifname);
 
+#define read_sysfs_file(buf, fmt, args...)                              \
+        ({                                                              \
+                uint8_t *buf_ = NULL;                                   \
+                ssize_t bufsize_ = -1;                                  \
+                int error_;                                             \
+                                                                        \
+                bufsize_ = get_file(&buf_, "/sys/" fmt, ## args);       \
+                if (bufsize_ > 0) {                                     \
+                        uint8_t *buf2_ = alloca(bufsize_);              \
+                        error_ = errno;                                 \
+                        if (buf2_)                                      \
+                                memcpy(buf2_, buf_, bufsize_);          \
+                        free(buf_);                                     \
+                        *(buf) = (__typeof__(*(buf)))buf2_;             \
+                        errno = error_;                                 \
+                }                                                       \
+                bufsize_;                                               \
+        })
+
+#define sysfs_readlink(linkbuf, fmt, args...)                           \
+        ({                                                              \
+                char *_lb = alloca(PATH_MAX+1);                         \
+                char *_pn;                                              \
+                int _rc;                                                \
+                                                                        \
+                *(linkbuf) = NULL;                                      \
+                _rc = asprintfa(&_pn, "/sys/" fmt, ## args);            \
+                if (_rc >= 0) {                                         \
+                        ssize_t _linksz;                                \
+                        _rc = _linksz = readlink(_pn, _lb, PATH_MAX);   \
+                        if (_linksz >= 0)                               \
+                                _lb[_linksz] = '\0';                    \
+                        else                                            \
+                                efi_error("readlink of %s failed", _pn);\
+                        *(linkbuf) = _lb;                               \
+                } else {                                                \
+                        efi_error("could not allocate memory");         \
+                }                                                       \
+                _rc;                                                    \
+        })
+
+#define sysfs_stat(statbuf, fmt, args...)                               \
+        ({                                                              \
+                int rc_;                                                \
+                char *pn_;                                              \
+                                                                        \
+                rc_ = asprintfa(&pn_, "/sys/" fmt, ## args);            \
+                if (rc_ >= 0) {                                         \
+                        rc_ = stat(pn_, statbuf);                       \
+                        if (rc_ < 0)                                    \
+                                efi_error("could not stat %s", pn_);    \
+                } else {                                                \
+                        efi_error("could not allocate memory");         \
+                }                                                       \
+                rc_;                                                    \
+        })
+
+#define sysfs_opendir(fmt, args...)                                     \
+        ({                                                              \
+                int rc_;                                                \
+                char *pn_;                                              \
+                DIR *dir_ = NULL;                                       \
+                                                                        \
+                rc_ = asprintfa(&pn_, "/sys/" fmt, ## args);            \
+                if (rc_ >= 0) {                                         \
+                        dir_ = opendir(pn_);                            \
+                        if (dir_ == NULL)                               \
+                                efi_error("could not open %s", pn_);    \
+                } else {                                                \
+                        efi_error("could not allocate memory");         \
+                }                                                       \
+                dir_;                                                   \
+        })
+
 #endif /* _EFIBOOT_LINUX_H */
index 01e311a..59e54de 100644 (file)
@@ -292,60 +292,70 @@ get_sector_size(int filedes)
                 _rc;                                                    \
         })
 
-#define read_sysfs_file(buf, fmt, args...)                              \
+#define vasprintfa(str, fmt, ap)                                        \
         ({                                                              \
-                int _rc=-1;                                             \
-                char *_pathname;                                        \
-                uint8_t *_buf=NULL;                                     \
-                size_t _bufsize=-1;                                     \
-                int _saved_errno;                                       \
-                                                                        \
-                *(buf) = NULL;                                          \
-                _rc = asprintfa(&_pathname, (fmt), ## args);            \
-                if (_rc >= 0) {                                         \
-                        int _fd;                                        \
-                        _fd = open(_pathname, O_RDONLY);                \
-                        _saved_errno = errno;                           \
-                        _rc = -1;                                       \
-                        if (_fd >= 0) {                                 \
-                                _rc = read_file(_fd, &_buf, &_bufsize); \
-                                _saved_errno = errno;                   \
-                                close(_fd);                             \
-                                errno = _saved_errno;                   \
-                        }                                               \
-                }                                                       \
-                if (_rc >= 0) {                                         \
-                        uint8_t *_buf2 = alloca(_bufsize);              \
-                        _saved_errno = errno;                           \
-                        if (_buf2) {                                    \
-                                memcpy(_buf2, _buf, _bufsize);          \
-                                _rc = _bufsize;                         \
+                char *_tmp = NULL;                                      \
+                int _rc;                                                \
+                *(str) = NULL;                                          \
+                _rc = vasprintf((str), (fmt), (ap));                    \
+                if (_rc > 0) {                                          \
+                        _tmp = strdupa(*(str));                         \
+                        if (!_tmp) {                                    \
+                                _rc = -1;                               \
+                        } else {                                        \
+                                free(*(str));                           \
+                                *(str) = _tmp;                          \
                         }                                               \
-                        free(_buf);                                     \
-                        *((uint8_t **)buf) = _buf2;                     \
-                        errno = _saved_errno;                           \
+                } else {                                                \
+                        _rc = -1;                                       \
                 }                                                       \
                 _rc;                                                    \
         })
 
-#define sysfs_readlink(linkbuf, fmt, args...)                           \
-        ({                                                              \
-                char *_lb = alloca(PATH_MAX+1);                         \
-                char *_pn;                                              \
-                int _rc;                                                \
-                                                                        \
-                *(linkbuf) = NULL;                                      \
-                _rc = asprintfa(&_pn, fmt, ## args);                    \
-                if (_rc >= 0) {                                         \
-                        ssize_t _linksz;                                \
-                        _linksz = readlink(_pn, _lb, PATH_MAX);         \
-                        _rc = _linksz;                                  \
-                        if (_linksz >= 0)                               \
-                                _lb[_linksz] = '\0';                    \
-                        *(linkbuf) = _lb;                               \
-                }                                                       \
-                _rc;                                                    \
-        })
+static inline ssize_t
+get_file(uint8_t **result, const char * const fmt, ...)
+{
+        char *path;
+        uint8_t *buf = NULL;
+        size_t bufsize = 0;
+        ssize_t rc;
+        va_list ap;
+        int error;
+        int fd;
+
+        if (result == NULL) {
+                efi_error("invalid parameter 'result'");
+                return -1;
+        }
+
+        va_start(ap, fmt);
+        rc = vasprintfa(&path, fmt, ap);
+        va_end(ap);
+        if (rc < 0) {
+                efi_error("could not allocate memory");
+                return -1;
+        }
+
+        fd = open(path, O_RDONLY);
+        if (fd < 0) {
+                efi_error("could not open file \"%s\" for reading",
+                          path);
+                return -1;
+        }
+
+        rc = read_file(fd, &buf, &bufsize);
+        error = errno;
+        close(fd);
+        errno = error;
+
+        if (rc < 0) {
+                efi_error("could not read file \"%s\"", path);
+                return -1;
+        }
+
+        *result = buf;
+        return bufsize;
+}
 
 static inline void UNUSED
 swizzle_guid_to_uuid(efi_guid_t *guid)