diff --git a/libexfat/io.c b/libexfat/io.c index 066180db..644590f9 100644 --- a/libexfat/io.c +++ b/libexfat/io.c @@ -386,112 +386,3 @@ ssize_t exfat_pwrite(struct exfat_dev* dev, const void* buffer, size_t size, return pwrite(dev->fd, buffer, size, offset); #endif } - -ssize_t exfat_generic_pread(const struct exfat* ef, struct exfat_node* node, - void* buffer, size_t size, off_t offset) -{ - uint64_t newsize = offset; - cluster_t cluster; - char* bufp = buffer; - off_t lsize, loffset, remainder; - - if (offset < 0) - return -EINVAL; - if (newsize >= node->size) - return 0; - if (size == 0) - return 0; - - cluster = exfat_advance_cluster(ef, node, newsize / CLUSTER_SIZE(*ef->sb)); - if (CLUSTER_INVALID(*ef->sb, cluster)) - { - exfat_error("invalid cluster 0x%x while reading", cluster); - return -EIO; - } - - loffset = newsize % CLUSTER_SIZE(*ef->sb); - remainder = MIN(size, node->size - newsize); - while (remainder > 0) - { - if (CLUSTER_INVALID(*ef->sb, cluster)) - { - exfat_error("invalid cluster 0x%x while reading", cluster); - return -EIO; - } - lsize = MIN(CLUSTER_SIZE(*ef->sb) - loffset, remainder); - if (exfat_pread(ef->dev, bufp, lsize, - exfat_c2o(ef, cluster) + loffset) < 0) - { - exfat_error("failed to read cluster %#x", cluster); - return -EIO; - } - bufp += lsize; - loffset = 0; - remainder -= lsize; - cluster = exfat_next_cluster(ef, node, cluster); - } - if (!(node->attrib & EXFAT_ATTRIB_DIR) && !ef->ro && !ef->noatime) - exfat_update_atime(node); - return MIN(size, node->size - newsize) - remainder; -} - -ssize_t exfat_generic_pwrite(struct exfat* ef, struct exfat_node* node, - const void* buffer, size_t size, off_t offset) -{ - uint64_t newsize = offset; - int rc; - cluster_t cluster; - const char* bufp = buffer; - off_t lsize, loffset, remainder; - - if (offset < 0) - return -EINVAL; - if (newsize > node->size) - { - rc = exfat_truncate(ef, node, newsize, true); - if (rc != 0) - return rc; - } - if (newsize + size > node->size) - { - rc = exfat_truncate(ef, node, newsize + size, false); - if (rc != 0) - return rc; - } - if (size == 0) - return 0; - - cluster = exfat_advance_cluster(ef, node, newsize / CLUSTER_SIZE(*ef->sb)); - if (CLUSTER_INVALID(*ef->sb, cluster)) - { - exfat_error("invalid cluster 0x%x while writing", cluster); - return -EIO; - } - - loffset = newsize % CLUSTER_SIZE(*ef->sb); - remainder = size; - while (remainder > 0) - { - if (CLUSTER_INVALID(*ef->sb, cluster)) - { - exfat_error("invalid cluster 0x%x while writing", cluster); - return -EIO; - } - lsize = MIN(CLUSTER_SIZE(*ef->sb) - loffset, remainder); - if (exfat_pwrite(ef->dev, bufp, lsize, - exfat_c2o(ef, cluster) + loffset) < 0) - { - exfat_error("failed to write cluster %#x", cluster); - return -EIO; - } - bufp += lsize; - loffset = 0; - remainder -= lsize; - cluster = exfat_next_cluster(ef, node, cluster); - } - if (!(node->attrib & EXFAT_ATTRIB_DIR)) - /* directory's mtime should be updated by the caller only when it - creates or removes something in this directory */ - exfat_update_mtime(node); - return size - remainder; -} diff --git a/libexfat/node.c b/libexfat/node.c index a500524a..f71aa5b0 100644 --- a/libexfat/node.c +++ b/libexfat/node.c @@ -1238,3 +1238,112 @@ int exfat_set_label(struct exfat* ef, const char* label) strcpy(ef->label, label); return 0; } + +ssize_t exfat_generic_pread(const struct exfat* ef, struct exfat_node* node, + void* buffer, size_t size, off_t offset) +{ + uint64_t newsize = offset; + cluster_t cluster; + char* bufp = buffer; + off_t lsize, loffset, remainder; + + if (offset < 0) + return -EINVAL; + if (newsize >= node->size) + return 0; + if (size == 0) + return 0; + + cluster = exfat_advance_cluster(ef, node, newsize / CLUSTER_SIZE(*ef->sb)); + if (CLUSTER_INVALID(*ef->sb, cluster)) + { + exfat_error("invalid cluster 0x%x while reading", cluster); + return -EIO; + } + + loffset = newsize % CLUSTER_SIZE(*ef->sb); + remainder = MIN(size, node->size - newsize); + while (remainder > 0) + { + if (CLUSTER_INVALID(*ef->sb, cluster)) + { + exfat_error("invalid cluster 0x%x while reading", cluster); + return -EIO; + } + lsize = MIN(CLUSTER_SIZE(*ef->sb) - loffset, remainder); + if (exfat_pread(ef->dev, bufp, lsize, + exfat_c2o(ef, cluster) + loffset) < 0) + { + exfat_error("failed to read cluster %#x", cluster); + return -EIO; + } + bufp += lsize; + loffset = 0; + remainder -= lsize; + cluster = exfat_next_cluster(ef, node, cluster); + } + if (!(node->attrib & EXFAT_ATTRIB_DIR) && !ef->ro && !ef->noatime) + exfat_update_atime(node); + return MIN(size, node->size - newsize) - remainder; +} + +ssize_t exfat_generic_pwrite(struct exfat* ef, struct exfat_node* node, + const void* buffer, size_t size, off_t offset) +{ + uint64_t newsize = offset; + int rc; + cluster_t cluster; + const char* bufp = buffer; + off_t lsize, loffset, remainder; + + if (offset < 0) + return -EINVAL; + if (newsize > node->size) + { + rc = exfat_truncate(ef, node, newsize, true); + if (rc != 0) + return rc; + } + if (newsize + size > node->size) + { + rc = exfat_truncate(ef, node, newsize + size, false); + if (rc != 0) + return rc; + } + if (size == 0) + return 0; + + cluster = exfat_advance_cluster(ef, node, newsize / CLUSTER_SIZE(*ef->sb)); + if (CLUSTER_INVALID(*ef->sb, cluster)) + { + exfat_error("invalid cluster 0x%x while writing", cluster); + return -EIO; + } + + loffset = newsize % CLUSTER_SIZE(*ef->sb); + remainder = size; + while (remainder > 0) + { + if (CLUSTER_INVALID(*ef->sb, cluster)) + { + exfat_error("invalid cluster 0x%x while writing", cluster); + return -EIO; + } + lsize = MIN(CLUSTER_SIZE(*ef->sb) - loffset, remainder); + if (exfat_pwrite(ef->dev, bufp, lsize, + exfat_c2o(ef, cluster) + loffset) < 0) + { + exfat_error("failed to write cluster %#x", cluster); + return -EIO; + } + bufp += lsize; + loffset = 0; + remainder -= lsize; + cluster = exfat_next_cluster(ef, node, cluster); + } + if (!(node->attrib & EXFAT_ATTRIB_DIR)) + /* directory's mtime should be updated by the caller only when it + creates or removes something in this directory */ + exfat_update_mtime(node); + return size - remainder; +}