xmalloc_open_read_close: use fstat to get file size (instead of lseek).
authorDenis Vlasenko <vda.linux@googlemail.com>
Sun, 20 Apr 2008 14:45:43 +0000 (14:45 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Sun, 20 Apr 2008 14:45:43 +0000 (14:45 -0000)
by Joakim Tjernlund <Joakim.Tjernlund AT transmode.se>

function                                             old     new   delta
xmalloc_open_read_close                              190     181      -9

libbb/read.c

index e5f140f3b8e036fa4cc3ef4e16a10a142a4b6838..288358d79bfbc9a9bc54692e85d5be0e52188bf0 100644 (file)
@@ -203,6 +203,48 @@ ssize_t open_read_close(const char *filename, void *buf, size_t size)
        return read_close(fd, buf, size);
 }
 
+// Read (potentially big) files in one go. File size is estimated by
+// lseek to end.
+void *xmalloc_open_read_close(const char *filename, size_t *sizep)
+{
+       char *buf;
+       size_t size;
+       int fd;
+       off_t len;
+       struct stat st;
+
+       fd = open(filename, O_RDONLY);
+       if (fd < 0)
+               return NULL;
+
+       st.st_size = 0; /* in case fstat fail, define to 0 */
+       fstat(fd, &st);
+       /* /proc/N/stat files report len 0 here */
+       /* In order to make such files readable, we add small const */
+       len = st.st_size | 0x3ff; /* read only 1k on unseekable files */
+       size = sizep ? *sizep : INT_MAX;
+       if (len < size)
+               size = len;
+       buf = xmalloc(size + 1);
+       size = read_close(fd, buf, size);
+       if ((ssize_t)size < 0) {
+               free(buf);
+               return NULL;
+       }
+       xrealloc(buf, size + 1);
+       buf[size] = '\0';
+
+       if (sizep)
+               *sizep = size;
+       return buf;
+}
+
+#ifdef USING_LSEEK_TO_GET_SIZE
+/* Alternatively, file size can be obtained by lseek to the end.
+ * The code is slightly bigger. Retained in case fstat approach
+ * will not work for some weird cases (/proc, block devices, etc).
+ * (NB: lseek also can fail to work for some weird files) */
+
 // Read (potentially big) files in one go. File size is estimated by
 // lseek to end.
 void *xmalloc_open_read_close(const char *filename, size_t *sizep)
@@ -240,6 +282,7 @@ void *xmalloc_open_read_close(const char *filename, size_t *sizep)
                *sizep = size;
        return buf;
 }
+#endif
 
 void *xmalloc_xopen_read_close(const char *filename, size_t *sizep)
 {