commit d4e4f3d2ba15cf8c2f225aefb9cc165d406e0b3e
parent 7a88f218494b5a414030c408dcfc30225c2a395e
Author: Nihal Jere <nihal@nihaljere.xyz>
Date: Fri, 19 Feb 2021 17:00:40 -0600
tar.c: replace fd parameter with gzFile
tar_remove requires ftruncate, but I think don't think we need to use
it. A solution should be found to truncate with libz regardless.
read_size and write_size are replaced with gzread_size and gzwrite_size.
read_size is still needed in one case, so it is kept
Diffstat:
M | tar.c | | | 111 | ++++++++++++++++++++++++++++++++++++++++++------------------------------------- |
M | tar.h | | | 16 | ++++++++-------- |
2 files changed, 67 insertions(+), 60 deletions(-)
diff --git a/tar.c b/tar.c
@@ -23,6 +23,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE
*/
+#include "zlib.h"
#include "tar.h"
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
@@ -36,11 +37,14 @@ THE SOFTWARE
#define WRITE_ERROR(fmt, ...) { ERROR(fmt, ##__VA_ARGS__); tar_free(*archive); *archive = NULL; return -1; }
#define EXIST_ERROR(fmt, ...) const int rc = errno; if (rc != EEXIST) { ERROR(fmt, ##__VA_ARGS__); return -1; }
+// force gzread() to complete
+static int gzread_size(gzFile gzf, char *buf, int size);
+
// force read() to complete
static int read_size(int fd, char *buf, int size);
-// force write() to complete
-static int write_size(int fd, char *buf, int size);
+// force gzwrite() to complete
+static int gzwrite_size(gzFile gzf, char *buf, int size);
// convert octal string to unsigned integer
static unsigned int oct2uint(char *oct, unsigned int size);
@@ -51,8 +55,8 @@ static int iszeroed(char *buf, size_t size);
// make directory recursively
static int recursive_mkdir(const char *dir, const unsigned int mode, const char verbosity);
-int tar_read(const int fd, struct tar_t **archive, const char verbosity) {
- if (fd < 0) {
+int tar_read(const gzFile gzf, struct tar_t **archive, const char verbosity) {
+ if (gzf == NULL) {
ERROR("Bad file descriptor");
}
@@ -68,7 +72,7 @@ int tar_read(const int fd, struct tar_t **archive, const char verbosity) {
for(count = 0; ; count++) {
*tar = malloc(sizeof(struct tar_t));
- if (update && (read_size(fd, (*tar)->block, 512) != 512)) {
+ if (update && (gzread_size(gzf, (*tar)->block, 512) != 512)) {
V_PRINT(stderr, "Error: Bad read. Stopping");
tar_free(*tar);
*tar = NULL;
@@ -78,7 +82,7 @@ int tar_read(const int fd, struct tar_t **archive, const char verbosity) {
update = 1;
// if current block is all zeros
if (iszeroed((*tar)->block, 512)) {
- if (read_size(fd, (*tar)->block, 512) != 512) {
+ if (gzread_size(gzf, (*tar)->block, 512) != 512) {
V_PRINT(stderr, "Error: Bad read. Stopping");
tar_free(*tar);
*tar = NULL;
@@ -91,7 +95,7 @@ int tar_read(const int fd, struct tar_t **archive, const char verbosity) {
*tar = NULL;
// skip to end of record
- if (lseek(fd, RECORDSIZE - (offset % RECORDSIZE), SEEK_CUR) == (off_t) (-1)) {
+ if (gzseek(gzf, RECORDSIZE - (offset % RECORDSIZE), SEEK_CUR) == (off_t) (-1)) {
RC_ERROR("Unable to seek file: %s", strerror(rc));
}
@@ -112,7 +116,7 @@ int tar_read(const int fd, struct tar_t **archive, const char verbosity) {
// move file descriptor
offset += 512 + jump;
- if (lseek(fd, jump, SEEK_CUR) == (off_t) (-1)) {
+ if (gzseek(gzf, jump, SEEK_CUR) == (off_t) (-1)) {
RC_ERROR("Unable to seek file: %s", strerror(rc));
}
@@ -123,8 +127,8 @@ int tar_read(const int fd, struct tar_t **archive, const char verbosity) {
return count;
}
-int tar_write(const int fd, struct tar_t **archive, const size_t filecount, const char *files[], const char verbosity) {
- if (fd < 0) {
+int tar_write(const gzFile gzf, struct tar_t **archive, const size_t filecount, const char *files[], const char verbosity) {
+ if (gzf == NULL) {
ERROR("Bad file descriptor");
}
@@ -151,19 +155,19 @@ int tar_write(const int fd, struct tar_t **archive, const size_t filecount, cons
// move file descriptor
offset = (*tar)->begin + jump;
- if (lseek(fd, offset, SEEK_SET) == (off_t) (-1)) {
+ if (gzseek(gzf, offset, SEEK_SET) == (off_t) (-1)) {
RC_ERROR("Unable to seek file: %s", strerror(rc));
}
tar = &((*tar)->next);
}
// write entries first
- if (write_entries(fd, tar, archive, filecount, files, &offset, verbosity) < 0) {
+ if (write_entries(gzf, tar, archive, filecount, files, &offset, verbosity) < 0) {
WRITE_ERROR("Failed to write entries");
}
// write ending data
- if (write_end_data(fd, offset, verbosity) < 0) {
+ if (write_end_data(gzf, offset, verbosity) < 0) {
ERROR("Failed to write end data");
}
@@ -203,7 +207,7 @@ int tar_ls(FILE *f, struct tar_t *archive, const size_t filecount, const char *f
return 0;
}
-int tar_extract(const int fd, struct tar_t *archive, const size_t filecount, const char *files[], const char verbosity) {
+int tar_extract(const gzFile gzf, struct tar_t *archive, const size_t filecount, const char *files[], const char verbosity) {
int ret = 0;
// extract entries with given names
@@ -215,11 +219,11 @@ int tar_extract(const int fd, struct tar_t *archive, const size_t filecount, con
while (archive) {
for(size_t i = 0; i < filecount; i++) {
if (!strncmp(archive->name, files[i], MAX(strlen(archive->name), strlen(files[i])))) {
- if (lseek(fd, archive->begin, SEEK_SET) == (off_t) (-1)) {
+ if (gzseek(gzf, archive->begin, SEEK_SET) == (off_t) (-1)) {
RC_ERROR("Unable to seek file: %s", strerror(rc));
}
- if (extract_entry(fd, archive, verbosity) < 0) {
+ if (extract_entry(gzf, archive, verbosity) < 0) {
ret = -1;
}
break;
@@ -231,13 +235,13 @@ int tar_extract(const int fd, struct tar_t *archive, const size_t filecount, con
// extract all
else{
// move offset to beginning
- if (lseek(fd, 0, SEEK_SET) == (off_t) (-1)) {
+ if (gzseek(gzf, 0, SEEK_SET) == (off_t) (-1)) {
RC_ERROR("Unable to seek file: %s", strerror(rc));
}
// extract each entry
while (archive) {
- if (extract_entry(fd, archive, verbosity) < 0) {
+ if (extract_entry(gzf, archive, verbosity) < 0) {
ret = -1;
}
archive = archive->next;
@@ -247,7 +251,7 @@ int tar_extract(const int fd, struct tar_t *archive, const size_t filecount, con
return ret;
}
-int tar_update(const int fd, struct tar_t **archive, const size_t filecount, const char *files[], const char verbosity) {
+int tar_update(const gzFile gzf, struct tar_t **archive, const size_t filecount, const char *files[], const char verbosity) {
if (!filecount) {
return 0;
}
@@ -291,7 +295,7 @@ int tar_update(const int fd, struct tar_t **archive, const size_t filecount, con
}
// update listed files only
- if (tar_write(fd, archive, count, (const char **) newer, verbosity) < 0) {
+ if (tar_write(gzf, archive, count, (const char **) newer, verbosity) < 0) {
ERROR("Unable to update archive");
}
@@ -304,8 +308,8 @@ int tar_update(const int fd, struct tar_t **archive, const size_t filecount, con
return all ? 0 : -1;
}
-int tar_remove(const int fd, struct tar_t **archive, const size_t filecount, const char *files[], const char verbosity) {
- if (fd < 0) {
+int tar_remove(const gzFile gzf, struct tar_t **archive, const size_t filecount, const char *files[], const char verbosity) {
+ if (gzf == NULL) {
return -1;
}
@@ -323,14 +327,8 @@ int tar_remove(const int fd, struct tar_t **archive, const size_t filecount, con
return 0;
}
- // get file permissions
- struct stat st;
- if (fstat(fd, &st)) {
- RC_ERROR("Unable to stat archive: %s", strerror(rc));
- }
-
// reset offset of original file
- if (lseek(fd, 0, SEEK_SET) == (off_t) (-1)) {
+ if (gzseek(gzf, 0, SEEK_SET) == (off_t) (-1)) {
RC_ERROR("Unable to seek file: %s", strerror(rc));
}
@@ -368,24 +366,24 @@ int tar_remove(const int fd, struct tar_t **archive, const size_t filecount, con
int got = 0;
while (got < total) {
// go to old data
- if (lseek(fd, read_offset, SEEK_SET) == (off_t) (-1)) {
+ if (gzseek(gzf, read_offset, SEEK_SET) == (off_t) (-1)) {
RC_ERROR("Cannot seek: %s", strerror(rc));
}
char buf[512];
// copy chunk out
- if (read_size(fd, buf, 512) != 512) {// guarenteed 512 octets
+ if (gzread_size(gzf, buf, 512) != 512) {// guarenteed 512 octets
ERROR("Read error");
}
// go to new position
- if (lseek(fd, write_offset, SEEK_SET) == (off_t) (-1)) {
+ if (gzseek(gzf, write_offset, SEEK_SET) == (off_t) (-1)) {
RC_ERROR("Cannot seek: %s", strerror(rc));
}
// write data in
- if (write_size(fd, buf, 512) != 512) {
+ if (gzwrite_size(gzf, buf, 512) != 512) {
RC_ERROR("Write error: %s", strerror(rc));
}
@@ -400,7 +398,7 @@ int tar_remove(const int fd, struct tar_t **archive, const size_t filecount, con
write_offset += total;
// skip past data
- if (lseek(fd, read_offset, SEEK_SET) == (off_t) (-1)) {
+ if (gzseek(gzf, read_offset, SEEK_SET) == (off_t) (-1)) {
RC_ERROR("Cannot seek: %s", strerror(rc));
}
}
@@ -430,13 +428,14 @@ int tar_remove(const int fd, struct tar_t **archive, const size_t filecount, con
}
}
+ /* TODO we don't use tar_remove, but a solution should be found for this
// resize file
if (ftruncate(fd, write_offset) < 0) {
RC_ERROR("Could not truncate file: %s", strerror(rc));
}
-
+ */
// add end data
- if (write_end_data(fd, write_offset, verbosity) < 0) {
+ if (write_end_data(gzf, write_offset, verbosity) < 0) {
V_PRINT(stderr, "Error: Could not close file");
}
@@ -753,7 +752,7 @@ int ls_entry(FILE *f, struct tar_t *entry, const size_t filecount, const char *f
return 0;
}
-int extract_entry(const int fd, struct tar_t *entry, const char verbosity) {
+int extract_entry(const gzFile gzf, struct tar_t *entry, const char verbosity) {
V_PRINT(stdout, "%s", entry->name);
if ((entry->type == REGULAR) || (entry->type == NORMAL) || (entry->type == CONTIGUOUS)) {
@@ -787,7 +786,7 @@ int extract_entry(const int fd, struct tar_t *entry, const char verbosity) {
}
// move archive pointer to data location
- if (lseek(fd, 512 + entry->begin, SEEK_SET) == (off_t) (-1)) {
+ if (gzseek(gzf, 512 + entry->begin, SEEK_SET) == (off_t) (-1)) {
RC_ERROR("Bad index: %s", strerror(rc));
}
@@ -796,7 +795,7 @@ int extract_entry(const int fd, struct tar_t *entry, const char verbosity) {
int got = 0;
while (got < size) {
int r;
- if ((r = read_size(fd, buf, MIN(size - got, 512))) < 0) {
+ if ((r = gzread_size(gzf, buf, MIN(size - got, 512))) < 0) {
EXIST_ERROR("Unable to read from archive: %s", strerror(rc));
}
@@ -848,8 +847,8 @@ int extract_entry(const int fd, struct tar_t *entry, const char verbosity) {
return 0;
}
-int write_entries(const int fd, struct tar_t **archive, struct tar_t **head, const size_t filecount, const char *files[], int *offset, const char verbosity) {
- if (fd < 0) {
+int write_entries(const gzFile gzf, struct tar_t **archive, struct tar_t **head, const size_t filecount, const char *files[], int *offset, const char verbosity) {
+ if (gzf == NULL) {
ERROR("Bad file descriptor");
}
@@ -890,7 +889,7 @@ int write_entries(const int fd, struct tar_t **archive, struct tar_t **head, con
V_PRINT(stdout, "Writing %s", (*tar)->name);
// write metadata to (*tar) file
- if (write_size(fd, (*tar)->block, 512) != 512) {
+ if (gzwrite_size(gzf, (*tar)->block, 512) != 512) {
WRITE_ERROR("Failed to write metadata to archive");
}
@@ -909,7 +908,7 @@ int write_entries(const int fd, struct tar_t **archive, struct tar_t **head, con
sprintf(path, "%s/%s", parent, dir->d_name);
// recursively write each subdirectory
- if (write_entries(fd, &((*tar)->next), head, 1, (const char **) &path, offset, verbosity) < 0) {
+ if (write_entries(gzf, &((*tar)->next), head, 1, (const char **) &path, offset, verbosity) < 0) {
WRITE_ERROR("Recurse error");
}
@@ -952,7 +951,7 @@ int write_entries(const int fd, struct tar_t **archive, struct tar_t **head, con
}
// write metadata to (*tar) file
- if (write_size(fd, (*tar)->block, 512) != 512) {
+ if (gzwrite_size(gzf, (*tar)->block, 512) != 512) {
WRITE_ERROR("Failed to write metadata to archive");
}
@@ -967,7 +966,7 @@ int write_entries(const int fd, struct tar_t **archive, struct tar_t **head, con
int r = 0;
char buf[512];
while ((r = read_size(f, buf, 512)) > 0) {
- if (write_size(fd, buf, r) != r) {
+ if (gzwrite_size(gzf, buf, r) != r) {
RC_ERROR("Could not write to archive: %s", strerror(rc));
}
}
@@ -981,7 +980,7 @@ int write_entries(const int fd, struct tar_t **archive, struct tar_t **head, con
const unsigned int pad = 512 - size % 512;
if (pad != 512) {
for(unsigned int j = 0; j < pad; j++) {
- if (write_size(fd, "\0", 1) != 1) {
+ if (gzwrite_size(gzf, "\0", 1) != 1) {
WRITE_ERROR("Could not write padding data");
}
}
@@ -998,15 +997,15 @@ int write_entries(const int fd, struct tar_t **archive, struct tar_t **head, con
return 0;
}
-int write_end_data(const int fd, int size, const char verbosity) {
- if (fd < 0) {
+int write_end_data(const gzFile gzf, int size, const char verbosity) {
+ if (gzf == NULL) {
return -1;
}
// complete current record
const int pad = RECORDSIZE - (size % RECORDSIZE);
for(int i = 0; i < pad; i++) {
- if (write(fd, "\0", 1) != 1) {
+ if (gzwrite(gzf, "\0", 1) != 1) {
V_PRINT(stderr, "Error: Unable to close tar file");
return -1;
}
@@ -1015,7 +1014,7 @@ int write_end_data(const int fd, int size, const char verbosity) {
// if the current record does not have 2 blocks of zeros, add a whole other record
if (pad < (2 *BLOCKSIZE)) {
for(int i = 0; i < RECORDSIZE; i++) {
- if (write(fd, "\0", 1) != 1) {
+ if (gzwrite(gzf, "\0", 1) != 1) {
V_PRINT(stderr, "Error: Unable to close tar file");
return -1;
}
@@ -1056,9 +1055,17 @@ int read_size(int fd, char *buf, int size) {
return got;
}
-int write_size(int fd, char *buf, int size) {
+int gzread_size(gzFile gzf, char *buf, int size) {
+ int got = 0, rc;
+ while ((got < size) && ((rc = gzread(gzf, buf + got, size - got)) > 0)) {
+ got += rc;
+ }
+ return got;
+}
+
+int gzwrite_size(gzFile gzf, char *buf, int size) {
int wrote = 0, rc;
- while ((wrote < size) && ((rc = write(fd, buf + wrote, size - wrote)) > 0)) {
+ while ((wrote < size) && ((rc = gzwrite(gzf, buf + wrote, size - wrote)) > 0)) {
wrote += rc;
}
return wrote;
diff --git a/tar.h b/tar.h
@@ -109,11 +109,11 @@ struct tar_t {
// core functions //////////////////////////////////////////////////////////////
// read a tar file
// archive should be address to null pointer
-int tar_read(const int fd, struct tar_t ** archive, const char verbosity);
+int tar_read(const gzFile gzf, struct tar_t ** archive, const char verbosity);
// write to a tar file
// if archive contains data, the new data will be appended to the back of the file (terminating blocks will be rewritten)
-int tar_write(const int fd, struct tar_t ** archive, const size_t filecount, const char * files[], const char verbosity);
+int tar_write(const gzFile gzf, struct tar_t ** archive, const size_t filecount, const char * files[], const char verbosity);
// recursive freeing of entries
void tar_free(struct tar_t * archive);
@@ -125,13 +125,13 @@ void tar_free(struct tar_t * archive);
int tar_ls(FILE * f, struct tar_t * archive, const size_t filecount, const char * files[], const char verbosity);
// extracts files from an archive
-int tar_extract(const int fd, struct tar_t * archive, const size_t filecount, const char * files[], const char verbosity);
+int tar_extract(const gzFile gzf, struct tar_t * archive, const size_t filecount, const char * files[], const char verbosity);
// update files in tar with provided list
-int tar_update(const int fd, struct tar_t ** archive, const size_t filecount, const char * files[], const char verbosity);
+int tar_update(const gzFile gzf, struct tar_t ** archive, const size_t filecount, const char * files[], const char verbosity);
// remove entries from tar
-int tar_remove(const int fd, struct tar_t ** archive, const size_t filecount, const char * files[], const char verbosity);
+int tar_remove(const gzFile gzf, struct tar_t ** archive, const size_t filecount, const char * files[], const char verbosity);
// show files that are missing from the current directory
int tar_diff(FILE * f, struct tar_t * archive, const char verbosity);
@@ -159,13 +159,13 @@ int ls_entry(FILE * f, struct tar_t * archive, const size_t filecount, const cha
// extracts a single entry
// expects file descriptor offset to already be set to correct location
-int extract_entry(const int fd, struct tar_t * entry, const char verbosity);
+int extract_entry(const gzFile gzf, struct tar_t * entry, const char verbosity);
// write entries to a tar file
-int write_entries(const int fd, struct tar_t ** archive, struct tar_t ** head, const size_t filecount, const char * files[], int * offset, const char verbosity);
+int write_entries(const gzFile gzf, struct tar_t ** archive, struct tar_t ** head, const size_t filecount, const char * files[], int * offset, const char verbosity);
// add ending data
-int write_end_data(const int fd, int size, const char verbosity);
+int write_end_data(const gzFile gzf, int size, const char verbosity);
// check if entry is a match for any of the given file names
// returns index + 1 if match is found