AU: Optionally limit the size of delta update operations.
Add a --chunk_size flag to delta_generator. If it's not -1, files will
be split into chunks of this size when generating delta payloads. This
effectively limits the size of each delta operation.
BUG=chromium:229797
TEST=unit tests; generated delta payloads and checked them through
paycheck.py.
Change-Id: I21502118088bfbac75aa8009eb144f6aaf23a83a
Reviewed-on: https://gerrit.chromium.org/gerrit/48357
Commit-Queue: Darin Petkov <[email protected]>
Reviewed-by: Darin Petkov <[email protected]>
Tested-by: Darin Petkov <[email protected]>
diff --git a/utils.cc b/utils.cc
index 6e14f22..3853b94 100644
--- a/utils.cc
+++ b/utils.cc
@@ -177,25 +177,56 @@
// Reads from an open file |fp|, appending the read content to the container
// pointer to by |out_p|. Returns true upon successful reading all of the
-// file's content, false otherwise.
+// file's content, false otherwise. If |size| is not -1, reads up to |size|
+// bytes.
template <class T>
-static bool Read(FILE* fp, T* out_p) {
+static bool Read(FILE* fp, off_t size, T* out_p) {
CHECK(fp);
+ CHECK(size == -1 || size >= 0);
char buf[1024];
- while (size_t nbytes = fread(buf, 1, sizeof(buf), fp))
+ while (size == -1 || size > 0) {
+ off_t bytes_to_read = sizeof(buf);
+ if (size > 0 && bytes_to_read > size) {
+ bytes_to_read = size;
+ }
+ size_t nbytes = fread(buf, 1, bytes_to_read, fp);
+ if (!nbytes) {
+ break;
+ }
AppendBytes(buf, nbytes, out_p);
- return feof(fp) && !ferror(fp);
+ if (size != -1) {
+ CHECK(size >= static_cast<off_t>(nbytes));
+ size -= nbytes;
+ }
+ }
+ if (ferror(fp)) {
+ return false;
+ }
+ return size == 0 || feof(fp);
}
-// Opens a file |path| for reading, then uses |append_func| to append its
-// content to a container |out_p|.
+// Opens a file |path| for reading and appends its the contents to a container
+// |out_p|. Starts reading the file from |offset|. If |offset| is beyond the end
+// of the file, returns success. If |size| is not -1, reads up to |size| bytes.
template <class T>
-static bool ReadFileAndAppend(const std::string& path, T* out_p) {
- FILE* fp = fopen(path.c_str(), "r");
- if (!fp)
+static bool ReadFileChunkAndAppend(const std::string& path,
+ off_t offset,
+ off_t size,
+ T* out_p) {
+ CHECK_GE(offset, 0);
+ CHECK(size == -1 || size >= 0);
+ file_util::ScopedFILE fp(fopen(path.c_str(), "r"));
+ if (!fp.get())
return false;
- bool success = Read(fp, out_p);
- return (success && !fclose(fp));
+ if (offset) {
+ // Return success without appending any data if a chunk beyond the end of
+ // the file is requested.
+ if (offset >= FileSize(path)) {
+ return true;
+ }
+ TEST_AND_RETURN_FALSE_ERRNO(fseek(fp.get(), offset, SEEK_SET) == 0);
+ }
+ return Read(fp.get(), size, out_p);
}
// Invokes a pipe |cmd|, then uses |append_func| to append its stdout to a
@@ -205,24 +236,29 @@
FILE* fp = popen(cmd.c_str(), "r");
if (!fp)
return false;
- bool success = Read(fp, out_p);
+ bool success = Read(fp, -1, out_p);
return (success && pclose(fp) >= 0);
}
-bool ReadFile(const std::string& path, std::vector<char>* out_p) {
- return ReadFileAndAppend(path, out_p);
+bool ReadFile(const string& path, vector<char>* out_p) {
+ return ReadFileChunkAndAppend(path, 0, -1, out_p);
}
-bool ReadFile(const std::string& path, std::string* out_p) {
- return ReadFileAndAppend(path, out_p);
+bool ReadFile(const string& path, string* out_p) {
+ return ReadFileChunkAndAppend(path, 0, -1, out_p);
}
-bool ReadPipe(const std::string& cmd, std::vector<char>* out_p) {
+bool ReadFileChunk(const string& path, off_t offset, off_t size,
+ vector<char>* out_p) {
+ return ReadFileChunkAndAppend(path, offset, size, out_p);
+}
+
+bool ReadPipe(const string& cmd, vector<char>* out_p) {
return ReadPipeAndAppend(cmd, out_p);
}
-bool ReadPipe(const std::string& cmd, std::string* out_p) {
+bool ReadPipe(const string& cmd, string* out_p) {
return ReadPipeAndAppend(cmd, out_p);
}