Basic file listing :)
This commit is contained in:
parent
e233ca00eb
commit
0952af15b4
3
Makefile
3
Makefile
@ -9,7 +9,8 @@ CFLAGS ?= -O2 -Wall -Wextra
|
|||||||
CFLAGS := ${CFLAGS} -I.
|
CFLAGS := ${CFLAGS} -I.
|
||||||
DESTDIR ?= /usr/local
|
DESTDIR ?= /usr/local
|
||||||
|
|
||||||
OBJS := $(OBJ)/tar.o
|
OBJS := $(OBJ)/tar.o \
|
||||||
|
$(OBJ)/util.o
|
||||||
|
|
||||||
build: $(OBJS)
|
build: $(OBJS)
|
||||||
@echo -- Creating $(LIBNAME).a
|
@echo -- Creating $(LIBNAME).a
|
||||||
|
35
README.md
35
README.md
@ -1,3 +1,36 @@
|
|||||||
# minitar
|
# minitar
|
||||||
|
|
||||||
Tiny C library to interact with tar archives
|
Tiny C library to interact with tar archives
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <minitar.h>
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
if(argc == 1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Usage: %s [file]\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
struct minitar* mp = minitar_open(argv[1]);
|
||||||
|
if(!mp)
|
||||||
|
{
|
||||||
|
perror(argv[1]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
struct minitar_entry* entry;
|
||||||
|
do {
|
||||||
|
entry = minitar_read_entry(mp);
|
||||||
|
if(entry) {
|
||||||
|
printf("Found file %s\n", entry->metadata.name);
|
||||||
|
minitar_free_entry(entry);
|
||||||
|
}
|
||||||
|
} while(entry);
|
||||||
|
minitar_close(mp);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This program will list out the files in a tar archive :)
|
30
minitar.h
30
minitar.h
@ -1,13 +1,43 @@
|
|||||||
#ifndef MINITAR_H
|
#ifndef MINITAR_H
|
||||||
#define MINITAR_H
|
#define MINITAR_H
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
struct minitar
|
struct minitar
|
||||||
{
|
{
|
||||||
FILE* stream;
|
FILE* stream;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum minitar_file_type
|
||||||
|
{
|
||||||
|
MTAR_REGULAR,
|
||||||
|
MTAR_CHRDEV,
|
||||||
|
MTAR_BLKDEV,
|
||||||
|
MTAR_DIRECTORY
|
||||||
|
};
|
||||||
|
|
||||||
|
struct minitar_entry_metadata
|
||||||
|
{
|
||||||
|
char name[257];
|
||||||
|
mode_t mode;
|
||||||
|
uid_t uid;
|
||||||
|
gid_t gid;
|
||||||
|
size_t size;
|
||||||
|
time_t mtime;
|
||||||
|
enum minitar_file_type type;
|
||||||
|
char uname[32];
|
||||||
|
char gname[32];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct minitar_entry
|
||||||
|
{
|
||||||
|
struct minitar_entry_metadata metadata;
|
||||||
|
char* ptr;
|
||||||
|
};
|
||||||
|
|
||||||
struct minitar* minitar_open(const char* pathname);
|
struct minitar* minitar_open(const char* pathname);
|
||||||
|
struct minitar_entry* minitar_read_entry(struct minitar* mp);
|
||||||
|
void minitar_free_entry(struct minitar_entry* entry);
|
||||||
int minitar_close(struct minitar* mp);
|
int minitar_close(struct minitar* mp);
|
||||||
|
|
||||||
#endif
|
#endif
|
41
src/tar.c
41
src/tar.c
@ -1,5 +1,11 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "minitar.h"
|
#include "minitar.h"
|
||||||
|
#include "tar.h"
|
||||||
|
|
||||||
|
int minitar_read_header(struct minitar* mp, struct tar_header* hdr);
|
||||||
|
int minitar_validate_header(struct tar_header* hdr);
|
||||||
|
void minitar_parse_tar_header(struct tar_header* hdr, struct minitar_entry_metadata* metadata);
|
||||||
|
struct minitar_entry* minitar_dup_entry(struct minitar_entry* original);
|
||||||
|
|
||||||
struct minitar* minitar_open(const char* path)
|
struct minitar* minitar_open(const char* path)
|
||||||
{
|
{
|
||||||
@ -17,4 +23,39 @@ int minitar_close(struct minitar* mp)
|
|||||||
free(mp);
|
free(mp);
|
||||||
if(rc) return rc;
|
if(rc) return rc;
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct minitar_entry* minitar_attempt_read_entry(struct minitar* mp, int* valid)
|
||||||
|
{
|
||||||
|
struct minitar_entry entry;
|
||||||
|
struct tar_header hdr;
|
||||||
|
if(!minitar_read_header(mp, &hdr))
|
||||||
|
{
|
||||||
|
*valid = 1; // we are at end-of-file
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if(!minitar_validate_header(&hdr))
|
||||||
|
{
|
||||||
|
*valid = 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
*valid = 1;
|
||||||
|
minitar_parse_tar_header(&hdr, &entry.metadata);
|
||||||
|
// FIXME: Actually read the file and place it in buf.
|
||||||
|
return minitar_dup_entry(&entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct minitar_entry* minitar_read_entry(struct minitar* mp)
|
||||||
|
{
|
||||||
|
int valid;
|
||||||
|
struct minitar_entry* result;
|
||||||
|
do {
|
||||||
|
result = minitar_attempt_read_entry(mp, &valid);
|
||||||
|
} while(!valid);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void minitar_free_entry(struct minitar_entry* entry)
|
||||||
|
{
|
||||||
|
free(entry); // FIXME: Also free the file's content, when it's placed in buf.
|
||||||
}
|
}
|
24
src/tar.h
Normal file
24
src/tar.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#ifndef MINITAR_TAR_H
|
||||||
|
#define MINITAR_TAR_H
|
||||||
|
|
||||||
|
struct tar_header {
|
||||||
|
char name[100];
|
||||||
|
char mode[8];
|
||||||
|
char uid[8];
|
||||||
|
char gid[8];
|
||||||
|
char size[12];
|
||||||
|
char mtime[12];
|
||||||
|
char chksum[8];
|
||||||
|
char typeflag;
|
||||||
|
char linkname[100];
|
||||||
|
char magic[6];
|
||||||
|
char version[2];
|
||||||
|
char uname[32];
|
||||||
|
char gname[32];
|
||||||
|
char devmajor[8];
|
||||||
|
char devminor[8];
|
||||||
|
char prefix[155];
|
||||||
|
char padding[12];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
#endif
|
90
src/util.c
Normal file
90
src/util.c
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
#define _POSIX_C_SOURCE 200809L
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdnoreturn.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "minitar.h"
|
||||||
|
#include "tar.h"
|
||||||
|
|
||||||
|
noreturn void minitar_panic(const char* message)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "minitar: %s\n", message);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
void minitar_parse_tar_header(struct tar_header* hdr, struct minitar_entry_metadata* metadata)
|
||||||
|
{
|
||||||
|
if(!strlen(hdr->prefix))
|
||||||
|
{
|
||||||
|
strncpy(metadata->name, hdr->name, 100);
|
||||||
|
metadata->name[100] = '\0';
|
||||||
|
} else {
|
||||||
|
strcpy(metadata->name, hdr->prefix);
|
||||||
|
strcat(metadata->name, "/");
|
||||||
|
strncat(metadata->name, hdr->name, 100);
|
||||||
|
metadata->name[256] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
metadata->mode = (mode_t)strtol(hdr->mode, NULL, 8);
|
||||||
|
metadata->uid = (uid_t)strtoul(hdr->uid, NULL, 8);
|
||||||
|
metadata->gid = (gid_t)strtoul(hdr->gid, NULL, 8);
|
||||||
|
|
||||||
|
char* sizeptr = strndup(hdr->size, 12);
|
||||||
|
if(!sizeptr) minitar_panic("Failed to allocate memory to duplicate a tar header's size field");
|
||||||
|
metadata->size = (size_t)strtoull(sizeptr, NULL, 8);
|
||||||
|
free(sizeptr);
|
||||||
|
|
||||||
|
char* timeptr = strndup(hdr->mtime, 12);
|
||||||
|
if(!timeptr) minitar_panic("Failed to allocate memory to duplicate a tar header's mtime field");
|
||||||
|
metadata->mtime = (time_t)strtol(timeptr, NULL, 8);
|
||||||
|
free(timeptr);
|
||||||
|
|
||||||
|
switch(hdr->typeflag)
|
||||||
|
{
|
||||||
|
case '\0':
|
||||||
|
case '0':
|
||||||
|
metadata->type = MTAR_REGULAR;
|
||||||
|
break;
|
||||||
|
case '1':
|
||||||
|
minitar_panic("Links to other files within a tar archive are unsupported");
|
||||||
|
case '2':
|
||||||
|
minitar_panic("Symbolic links are unsupported");
|
||||||
|
case '3':
|
||||||
|
metadata->type = MTAR_CHRDEV;
|
||||||
|
break;
|
||||||
|
case '4':
|
||||||
|
metadata->type = MTAR_BLKDEV;
|
||||||
|
break;
|
||||||
|
case '5':
|
||||||
|
metadata->type = MTAR_DIRECTORY;
|
||||||
|
break;
|
||||||
|
case '6':
|
||||||
|
minitar_panic("FIFOs are unsupported");
|
||||||
|
default:
|
||||||
|
minitar_panic("Unknown entry type in tar header");
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(metadata->uname, hdr->uname);
|
||||||
|
strcpy(metadata->gname, hdr->gname);
|
||||||
|
}
|
||||||
|
|
||||||
|
int minitar_validate_header(struct tar_header* hdr)
|
||||||
|
{
|
||||||
|
return !strncmp(hdr->magic, "ustar", 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
int minitar_read_header(struct minitar* mp, struct tar_header* hdr)
|
||||||
|
{
|
||||||
|
size_t rc = fread(hdr, sizeof *hdr, 1, mp->stream);
|
||||||
|
if(rc == 0 && feof(mp->stream)) return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct minitar_entry* minitar_dup_entry(struct minitar_entry* original)
|
||||||
|
{
|
||||||
|
struct minitar_entry* new = malloc(sizeof *original);
|
||||||
|
if(!new) return NULL;
|
||||||
|
memcpy(new, original, sizeof *new);
|
||||||
|
return new;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user