Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 24d99d2d authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge changes from topic "sparse-file-read-enum" am: f401dcdf

Original change: https://android-review.googlesource.com/c/platform/system/core/+/1935419

Change-Id: Icbdc98f397254dc323e2ea298c209e032c122cb4
parents f6b10663 f401dcdf
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -93,7 +93,7 @@ int main(int argc, char* argv[]) {
  }

  sparse_file_verbose(s);
  ret = sparse_file_read(s, in, false, false);
  ret = sparse_file_read(s, in, SPARSE_READ_MODE_NORMAL, false);
  if (ret) {
    fprintf(stderr, "Failed to read file\n");
    exit(-1);
+26 −7
Original line number Diff line number Diff line
@@ -225,23 +225,42 @@ int sparse_file_foreach_chunk(struct sparse_file *s, bool sparse, bool crc,
	int (*write)(void *priv, const void *data, size_t len, unsigned int block,
		     unsigned int nr_blocks),
	void *priv);

/**
 * enum sparse_read_mode - The method to use when reading in files
 * @SPARSE_READ_MODE_NORMAL: The input is a regular file. Constant chunks of
 *                           data (including holes) will be be converted to
 *                           fill chunks.
 * @SPARSE_READ_MODE_SPARSE: The input is an Android sparse file.
 * @SPARSE_READ_MODE_HOLE: The input is a regular file. Holes will be converted
 *                         to "don't care" chunks. Other constant chunks will
 *                         be converted to fill chunks.
 */
enum sparse_read_mode {
	SPARSE_READ_MODE_NORMAL = false,
	SPARSE_READ_MODE_SPARSE = true,
	SPARSE_READ_MODE_HOLE,
};

/**
 * sparse_file_read - read a file into a sparse file cookie
 *
 * @s - sparse file cookie
 * @fd - file descriptor to read from
 * @sparse - read a file in the Android sparse file format
 * @mode - mode to use when reading the input file
 * @crc - verify the crc of a file in the Android sparse file format
 *
 * Reads a file into a sparse file cookie.  If sparse is true, the file is
 * assumed to be in the Android sparse file format.  If sparse is false, the
 * file will be sparsed by looking for block aligned chunks of all zeros or
 * another 32 bit value.  If crc is true, the crc of the sparse file will be
 * verified.
 * Reads a file into a sparse file cookie. If @mode is
 * %SPARSE_READ_MODE_SPARSE, the file is assumed to be in the Android sparse
 * file format. If @mode is %SPARSE_READ_MODE_NORMAL, the file will be sparsed
 * by looking for block aligned chunks of all zeros or another 32 bit value. If
 * @mode is %SPARSE_READ_MODE_HOLE, the file will be sparsed like
 * %SPARSE_READ_MODE_NORMAL, but holes in the file will be converted to "don't
 * care" chunks. If crc is true, the crc of the sparse file will be verified.
 *
 * Returns 0 on success, negative errno on error.
 */
int sparse_file_read(struct sparse_file *s, int fd, bool sparse, bool crc);
int sparse_file_read(struct sparse_file *s, int fd, enum sparse_read_mode mode, bool crc);

/**
 * sparse_file_import - import an existing sparse file
+83 −13
Original line number Diff line number Diff line
@@ -457,12 +457,10 @@ static int sparse_file_read_sparse(struct sparse_file* s, SparseFileSource* sour
  return 0;
}

static int sparse_file_read_normal(struct sparse_file* s, int fd) {
static int do_sparse_file_read_normal(struct sparse_file* s, int fd, uint32_t* buf, int64_t offset,
                                      int64_t remain) {
  int ret;
  uint32_t* buf = (uint32_t*)malloc(s->block_size);
  unsigned int block = 0;
  int64_t remain = s->len;
  int64_t offset = 0;
  unsigned int block = offset / s->block_size;
  unsigned int to_read;
  unsigned int i;
  bool sparse_block;
@@ -476,7 +474,6 @@ static int sparse_file_read_normal(struct sparse_file* s, int fd) {
    ret = read_all(fd, buf, to_read);
    if (ret < 0) {
      error("failed to read sparse file");
      free(buf);
      return ret;
    }

@@ -504,20 +501,93 @@ static int sparse_file_read_normal(struct sparse_file* s, int fd) {
    block++;
  }

  return 0;
}

static int sparse_file_read_normal(struct sparse_file* s, int fd) {
  int ret;
  uint32_t* buf = (uint32_t*)malloc(s->block_size);

  if (!buf)
    return -ENOMEM;

  ret = do_sparse_file_read_normal(s, fd, buf, 0, s->len);
  free(buf);
  return ret;
}

#ifdef __linux__
static int sparse_file_read_hole(struct sparse_file* s, int fd) {
  int ret;
  uint32_t* buf = (uint32_t*)malloc(s->block_size);
  int64_t end = 0;
  int64_t start = 0;

  if (!buf) {
    return -ENOMEM;
  }

  do {
    start = lseek(fd, end, SEEK_DATA);
    if (start < 0) {
      if (errno == ENXIO)
        /* The rest of the file is a hole */
        break;

      error("could not seek to data");
      free(buf);
      return -errno;
    } else if (start > s->len) {
      break;
    }

    end = lseek(fd, start, SEEK_HOLE);
    if (end < 0) {
      error("could not seek to end");
      free(buf);
      return -errno;
    }
    end = std::min(end, s->len);

    start = ALIGN_DOWN(start, s->block_size);
    end = ALIGN(end, s->block_size);
    if (lseek(fd, start, SEEK_SET) < 0) {
      free(buf);
      return -errno;
    }

    ret = do_sparse_file_read_normal(s, fd, buf, start, end - start);
    if (ret) {
      free(buf);
      return ret;
    }
  } while (end < s->len);

  free(buf);
  return 0;
}
#else
static int sparse_file_read_hole(struct sparse_file* s __unused, int fd __unused) {
  return -ENOTSUP;
}
#endif

int sparse_file_read(struct sparse_file* s, int fd, bool sparse, bool crc) {
  if (crc && !sparse) {
int sparse_file_read(struct sparse_file* s, int fd, enum sparse_read_mode mode, bool crc) {
  if (crc && mode != SPARSE_READ_MODE_SPARSE) {
    return -EINVAL;
  }

  if (sparse) {
  switch (mode) {
    case SPARSE_READ_MODE_SPARSE: {
      SparseFileFdSource source(fd);
      return sparse_file_read_sparse(s, &source, crc);
  } else {
    }
    case SPARSE_READ_MODE_NORMAL:
      return sparse_file_read_normal(s, fd);
    case SPARSE_READ_MODE_HOLE:
      return sparse_file_read_hole(s, fd);
    default:
      return -EINVAL;
  }
}