aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2021-03-03 02:24:32 +0000
committerMichael Brown <mcb30@ipxe.org>2021-03-03 02:26:42 +0000
commit65bd5c05db2a050a4c0f26ccc0b1e9828b00abbf (patch)
tree8b304e947b9960418ea95007de99ff157931f22b
parent1c4917b6a739c887acbf6f7631b1f74084430ee7 (diff)
downloadipxe-65bd5c05db2a050a4c0f26ccc0b1e9828b00abbf.zip
ipxe-65bd5c05db2a050a4c0f26ccc0b1e9828b00abbf.tar.gz
ipxe-65bd5c05db2a050a4c0f26ccc0b1e9828b00abbf.tar.bz2
[linux] Do not assume that stat() works on sysfs files
Linux kernel 3.12 and earlier report a zero size via stat() for all ACPI table files in sysfs. There is no way to determine the file size other than by reading the file until EOF. Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r--src/interface/linux/linux_sysfs.c49
1 files changed, 20 insertions, 29 deletions
diff --git a/src/interface/linux/linux_sysfs.c b/src/interface/linux/linux_sysfs.c
index 463bc2a..4f0027c 100644
--- a/src/interface/linux/linux_sysfs.c
+++ b/src/interface/linux/linux_sysfs.c
@@ -32,6 +32,9 @@ FILE_LICENCE ( GPL2_OR_LATER );
*
*/
+/** Read blocksize */
+#define LINUX_SYSFS_BLKSIZE 4096
+
/**
* Read file from sysfs
*
@@ -40,9 +43,9 @@ FILE_LICENCE ( GPL2_OR_LATER );
* @ret len Length read, or negative error
*/
int linux_sysfs_read ( const char *filename, userptr_t *data ) {
- size_t offset;
- size_t len;
+ userptr_t tmp;
ssize_t read;
+ size_t len;
int fd;
int rc;
@@ -55,37 +58,27 @@ int linux_sysfs_read ( const char *filename, userptr_t *data ) {
goto err_open;
}
- /* Get file length */
- if ( linux_fstat_size ( fd, &len ) == -1 ) {
- rc = -ELINUX ( linux_errno );
- DBGC ( filename, "LINUX could not stat %s: %s\n",
- filename, linux_strerror ( linux_errno ) );
- goto err_stat;
- }
+ /* Read file */
+ for ( *data = UNULL, len = 0 ; ; len += read ) {
- /* Allocate buffer */
- *data = umalloc ( len );
- if ( ! *data ) {
- rc = -ENOMEM;
- DBGC ( filename, "LINUX could not allocate %zd bytes for %s\n",
- len, filename );
- goto err_alloc;
- }
+ /* (Re)allocate space */
+ tmp = urealloc ( *data, ( len + LINUX_SYSFS_BLKSIZE ) );
+ if ( ! tmp ) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+ *data = tmp;
- /* Read file */
- for ( offset = 0 ; offset < len ; offset += read ) {
- read = linux_read ( fd, user_to_virt ( *data, offset ), len );
+ /* Read from file */
+ read = linux_read ( fd, user_to_virt ( *data, len ),
+ LINUX_SYSFS_BLKSIZE );
+ if ( read == 0 )
+ break;
if ( read < 0 ) {
DBGC ( filename, "LINUX could not read %s: %s\n",
filename, linux_strerror ( linux_errno ) );
goto err_read;
}
- if ( read == 0 ) {
- rc = -EIO;
- DBGC ( filename, "LINUX read underlength %s\n",
- filename );
- goto err_eof;
- }
}
/* Close file */
@@ -94,11 +87,9 @@ int linux_sysfs_read ( const char *filename, userptr_t *data ) {
DBGC ( filename, "LINUX read %s\n", filename );
return len;
- err_eof:
err_read:
- ufree ( *data );
err_alloc:
- err_stat:
+ ufree ( *data );
linux_close ( fd );
err_open:
return rc;