+
+inline size_t scanFileData(UnixPlusPlus::FileDesc fd, size_t limit, void (^handle)(const void *buffer, size_t size))
+{
+ UnixPlusPlus::FileDesc::UnixStat st;
+ size_t total = 0;
+ unsigned char *buffer = NULL;
+
+ try {
+ fd.fstat(st);
+ size_t bufSize = MAX(64 * 1024, st.st_blksize);
+ buffer = (unsigned char *)valloc(bufSize);
+ if (!buffer)
+ return 0;
+
+ for (;;) {
+ size_t size = bufSize;
+ if (limit && limit < size)
+ size = limit;
+ size_t got = fd.read(buffer, size);
+ total += got;
+ if (fd.atEnd())
+ break;
+ handle(buffer, got);
+ if (limit && (limit -= got) == 0)
+ break;
+ }
+ }
+ catch(...) {
+ /* don't leak this on error */
+ if (buffer)
+ free(buffer);
+ throw;
+ }
+
+ free(buffer);
+ return total;
+}
+