diff --git a/quickjs-libc.c b/quickjs-libc.c index 54a7a15..a64c4d6 100644 --- a/quickjs-libc.c +++ b/quickjs-libc.c @@ -385,12 +385,86 @@ fail: return JS_EXCEPTION; } +#define READALL_CHUNK (10*1024) + +static int readall(FILE *f, JSContext *ctx, uint8_t **dataptr, size_t *sizeptr) +{ + uint8_t *data = NULL, *temp; + size_t size = 0; + size_t used = 0; + size_t n; + + while (1) { + if (used + READALL_CHUNK + 1 > size) { + size = used + READALL_CHUNK + 1; + + /* Overflow check. Some ANSI C compilers + may optimize this away, though. */ + if (size <= used) { + if (ctx) + js_free(ctx, data); + else + free(data); + return -1; + } + + if (ctx) + temp = js_realloc(ctx, data, size); + else + temp = realloc(data, size); + + if (temp == NULL) { + if (ctx) + js_free(ctx, data); + else + free(data); + return -1; + } + data = temp; + } + + n = fread(data + used, 1, READALL_CHUNK, f); + if (n == 0) + break; + + used += n; + } + + if (ferror(f)) { + if (ctx) + js_free(ctx, data); + else + free(data); + return -1; + } + + if (ctx) + temp = js_realloc(ctx, data, used + 1); + else + temp = realloc(data, used + 1); + + if (temp == NULL) { + if (ctx) + js_free(ctx, data); + else + free(data); + return -1; + } + data = temp; + data[used] = '\0'; + + *dataptr = data; + *sizeptr = used; + + return 0; +} + uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, const char *filename) { FILE *f; uint8_t *buf; size_t buf_len; - long lret; + long lret = 0; f = fopen(filename, "rb"); if (!f) @@ -398,7 +472,7 @@ uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, const char *filename) if (fseek(f, 0, SEEK_END) < 0) goto fail; lret = ftell(f); - if (lret < 0) + if (lret <= 0) goto fail; /* XXX: on Linux, ftell() return LONG_MAX for directories */ if (lret == LONG_MAX) { @@ -414,13 +488,19 @@ uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, const char *filename) buf = malloc(buf_len + 1); if (!buf) goto fail; - if (fread(buf, 1, buf_len, f) != buf_len) { - errno = EIO; + buf_len = fread(buf, 1, buf_len, f); + if (ferror(f)) { if (ctx) js_free(ctx, buf); else free(buf); fail: + // Files in proc and sysfs may not be seekable or may falsely + // appear to be of zero size. Try to read them in another way. + if (lret == 0 && readall(f, ctx, &buf, pbuf_len) == 0) { + fclose(f); + return buf; + } fclose(f); return NULL; }