/
githubmirror
/
efivar
Обзор
Документация
Войти
/
githubmirror
/
efivar
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
23
src/util.h
210 строк
5 KB
Peter Jones
Add some more utility functions for reading sysfs crap.
01 май 2015, 18:05
01 май 2015, 18:05
f9524f1
Код
Авторство
О чём код?
/* * Copyright 2011-2014 Red Hat, Inc. * All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library. If not, see <http://www.gnu.org/licenses/>. * * Author(s): Peter Jones <pjones@redhat.com> */ #ifndef EFIVAR_UTIL_H #define EFIVAR_UTIL_H 1 #include <errno.h> #include <stdio.h> #include <stdarg.h> #include <stdlib.h> #include <string.h> #include <sys/ioctl.h> #include <sys/mount.h> #include <unistd.h> static inline int __attribute__((unused)) read_file(int fd, uint8_t **buf, size_t *bufsize) { uint8_t *p; size_t size = 4096; size_t filesize = 0; ssize_t s = 0; uint8_t *newbuf; if (!(newbuf = calloc(size, sizeof (uint8_t)))) return -1; *buf = newbuf; do { p = *buf + filesize; /* size - filesize shouldn't exceed SSIZE_MAX because we're * only allocating 4096 bytes at a time and we're checking that * before doing so. */ s = read(fd, p, size - filesize); if (s < 0 && errno == EAGAIN) { continue; } else if (s < 0) { int saved_errno = errno; free(*buf); *buf = NULL; *bufsize = 0; errno = saved_errno; return -1; } filesize += s; /* only exit for empty reads */ if (s == 0) break; if (filesize >= size) { /* See if we're going to overrun and return an error * instead. */ if (size > (size_t)-1 - 4096) { free(*buf); *buf = NULL; *bufsize = 0; errno = ENOMEM; return -1; } newbuf = realloc(*buf, size + 4096); if (newbuf == NULL) { int saved_errno = errno; free(*buf); *buf = NULL; *bufsize = 0; errno = saved_errno; return -1; } *buf = newbuf; memset(*buf + size, '\0', 4096); size += 4096; } } while (1); newbuf = realloc(*buf, filesize+1); if (!newbuf) { free(*buf); *buf = NULL; return -1; } newbuf[filesize] = '\0'; *buf = newbuf; *bufsize = filesize+1; return 0; } static inline uint64_t __attribute__((unused)) lcm(uint64_t x, uint64_t y) { uint64_t m = x, n = y, o; while ((o = m % n)) { m = n; n = o; } return (x / n) * y; } /************************************************************ * get_sector_size * Requires: * - filedes is an open file descriptor, suitable for reading * Modifies: nothing * Returns: * sector size, or 512. ************************************************************/ static inline int __attribute__((unused)) get_sector_size(int filedes) { int rc, sector_size = 512; rc = ioctl(filedes, BLKSSZGET, §or_size); if (rc) sector_size = 512; return sector_size; } #define asprintfa(str, fmt, args...) \ ({ \ char *_tmp = NULL; \ int _rc; \ *(str) = NULL; \ _rc = asprintf((str), (fmt), ## args); \ if (_rc > 0) { \ _tmp = strdupa(*(str)); \ if (!_tmp) { \ _rc = -1; \ } else { \ free(*(str)); \ *(str) = _tmp; \ } \ } else { \ _rc = -1; \ } \ _rc; \ }) #define read_sysfs_file(buf, fmt, args...) \ ({ \ 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; \ } \ free(_buf); \ *((uint8_t **)buf) = _buf2; \ errno = _saved_errno; \ } \ _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; \ }) #endif /* EFIVAR_UTIL_H */