Tar handler
This commit is contained in:
parent
828d55e708
commit
6bd3ff85a5
16
.vscode/settings.json
vendored
Normal file
16
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"array": "cpp",
|
||||||
|
"deque": "cpp",
|
||||||
|
"string": "cpp",
|
||||||
|
"unordered_map": "cpp",
|
||||||
|
"vector": "cpp",
|
||||||
|
"iterator": "cpp",
|
||||||
|
"memory_resource": "cpp",
|
||||||
|
"optional": "cpp",
|
||||||
|
"string_view": "cpp",
|
||||||
|
"initializer_list": "cpp",
|
||||||
|
"type_traits": "cpp",
|
||||||
|
"utility": "cpp"
|
||||||
|
}
|
||||||
|
}
|
2
Makefile
2
Makefile
@ -9,7 +9,7 @@ CXXFLAGS += -pedantic
|
|||||||
CXXFLAGS += -pedantic-errors
|
CXXFLAGS += -pedantic-errors
|
||||||
CXXFLAGS += -ffunction-sections -fdata-sections
|
CXXFLAGS += -ffunction-sections -fdata-sections
|
||||||
CXXFLAGS += -fno-implicit-inline-templates
|
CXXFLAGS += -fno-implicit-inline-templates
|
||||||
CXXFLAGS += -Iinc
|
CXXFLAGS += -Isrc
|
||||||
|
|
||||||
|
|
||||||
LD_LIBS := -lc -lgcc -lpthread
|
LD_LIBS := -lc -lgcc -lpthread
|
||||||
|
43
inc/Buffer.h
Normal file
43
inc/Buffer.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#ifndef __INC_BUFFER_H__
|
||||||
|
#define __INC_BUFFER_H__
|
||||||
|
|
||||||
|
template<typename T, std::size_t S>
|
||||||
|
class Buffer
|
||||||
|
: std::array<T, S>
|
||||||
|
{
|
||||||
|
typedef std::array<T,S> ArrayT;
|
||||||
|
typedef typename ArrayT::reference reference;
|
||||||
|
typedef typename ArrayT::const_reference const_reference;
|
||||||
|
typedef typename ArrayT::size_type size_type;
|
||||||
|
typedef typename ArrayT::value_type value_type;
|
||||||
|
typedef typename ArrayT::iterator iterator;
|
||||||
|
typedef typename ArrayT::const_iterator const_iterator;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Buffer() : length(0) {}
|
||||||
|
|
||||||
|
constexpr reference front() noexcept { return ArrayT::front(); }
|
||||||
|
constexpr reference back() noexcept { return *(ArrayT::begin() + length); }
|
||||||
|
constexpr T * data() noexcept { return ArrayT::data(); }
|
||||||
|
|
||||||
|
constexpr iterator begin() noexcept { return ArrayT::begin();}
|
||||||
|
constexpr const_iterator cbegin() const noexcept { return ArrayT::cbegin(); }
|
||||||
|
constexpr iterator end() noexcept { return (ArrayT::begin() + length); }
|
||||||
|
constexpr const_iterator cend() const noexcept { return (ArrayT::cbegin() + length); }
|
||||||
|
|
||||||
|
constexpr size_type size() const noexcept {return length;}
|
||||||
|
constexpr size_type max_size() const noexcept {return ArrayT::max_size();}
|
||||||
|
|
||||||
|
constexpr void push_back(const_reference v) noexcept { *(this->begin() + length++) = v; };
|
||||||
|
constexpr void push_back(value_type&&v) noexcept { *(this->begin() + length++) = std::move(v); }
|
||||||
|
|
||||||
|
inline void fill(const_reference &v){ ArrayT::fill(v); length = ArrayT::max_size(); }
|
||||||
|
inline void fill(const_iterator b, const_iterator e) { std::copy(b, e, ArrayT::begin()); length = e - b; }
|
||||||
|
inline void fill_n(const_iterator b, size_type s) { std::copy(b, b + s, ArrayT::begin()); length = s; }
|
||||||
|
constexpr void clear() noexcept { this->length = 0; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_type length;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -1,24 +0,0 @@
|
|||||||
#ifndef __INC_RINGBUFFER_H__
|
|
||||||
#define __INC_RINGBUFFER_H__
|
|
||||||
|
|
||||||
#include <array>
|
|
||||||
|
|
||||||
class ringbuffer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ringbuffer();
|
|
||||||
|
|
||||||
int write(char);
|
|
||||||
int read(char&);
|
|
||||||
|
|
||||||
private:
|
|
||||||
enum {
|
|
||||||
MAX_BUFFER_SIZE = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
std::array<char, MAX_BUFFER_SIZE> buffer;
|
|
||||||
std::array<char, MAX_BUFFER_SIZE>::iterator head;
|
|
||||||
std::array<char, MAX_BUFFER_SIZE>::iterator tail;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
111
src/TarHandler.cc
Normal file
111
src/TarHandler.cc
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
#include "TarHandler.h"
|
||||||
|
|
||||||
|
#define ASCII_TO_NUMBER(num) ((num) - 48) //Converts an ascii digit to the corresponding number
|
||||||
|
|
||||||
|
TarHandler::TarHandler()
|
||||||
|
: idle(true)
|
||||||
|
, tar_index(0)
|
||||||
|
, next_tar_header(0)
|
||||||
|
, file_size(0)
|
||||||
|
, read_byte_count(0)
|
||||||
|
, processed_tar_blocks(0)
|
||||||
|
, file_processed_bytes(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void TarHandler::tcp_in_handler(char* data, std::size_t size)
|
||||||
|
{
|
||||||
|
if(this->idle) {
|
||||||
|
this->idle = false;
|
||||||
|
this->tar_index = 0;
|
||||||
|
this->file_size = 0;
|
||||||
|
this->next_tar_header;
|
||||||
|
this->read_byte_count = 0;
|
||||||
|
this->file_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// process incoming buffer
|
||||||
|
for(std::size_t i = 0; i < size; i++) {
|
||||||
|
this->tar_block[this->tar_index] = data[i];
|
||||||
|
this->read_byte_count++;
|
||||||
|
if(this->tar_index++ == TAR_BLOCK_SIZE - 1) {
|
||||||
|
this->tar_block_handler();
|
||||||
|
this->tar_index = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TarHandler::tar_block_handler()
|
||||||
|
{
|
||||||
|
this->processed_tar_blocks++;
|
||||||
|
if(this->next_tar_header == (this->read_byte_count) - TAR_BLOCK_SIZE) {
|
||||||
|
// Tar header detected
|
||||||
|
struct tar_file_header tar_header;
|
||||||
|
memcpy(&tar_header, this->tar_block, TAR_BLOCK_SIZE);
|
||||||
|
if(!check_checksum(&tar_header)) {
|
||||||
|
fprintf(stderr, "checksum missmatch\r\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this->file_size = decode_tar_octal(tar_header.file_size, sizeof(tar_header.file_size));
|
||||||
|
this->file_processed_bytes = 0;
|
||||||
|
printf("%s - size: %lu\r\n", tar_header.filename, file_size);
|
||||||
|
this->next_tar_header = (file_size / TAR_BLOCK_SIZE + 1) * TAR_BLOCK_SIZE + this->processed_tar_blocks * TAR_BLOCK_SIZE;
|
||||||
|
} else {
|
||||||
|
std::size_t i = 0;
|
||||||
|
if((this->file_size - this->file_processed_bytes) >= TAR_BLOCK_SIZE) {
|
||||||
|
for(i = 0; i < TAR_BLOCK_SIZE; i++) {
|
||||||
|
printf("%c", this->tar_block[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for(i = 0; i < (this->file_size - this->file_processed_bytes); i++) {
|
||||||
|
printf("%c", this->tar_block[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->file_processed_bytes += i;
|
||||||
|
printf("processed bytes: %lu\r\n", this->file_processed_bytes);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t TarHandler::decode_tar_octal(char* data, std::size_t size)
|
||||||
|
{
|
||||||
|
unsigned char *current_ptr = (unsigned char *) data + size;
|
||||||
|
uint64_t sum = 0;
|
||||||
|
uint64_t current_multiplier = 1;
|
||||||
|
|
||||||
|
unsigned char* check_ptr = current_ptr; //This is used to check where the last NUL/space char is
|
||||||
|
for(; check_ptr >= (unsigned char *) data; --check_ptr) {
|
||||||
|
if((*check_ptr) == 0 || (*check_ptr) == ' ') {
|
||||||
|
current_ptr = check_ptr - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(; current_ptr >= (unsigned char *) data; --current_ptr) {
|
||||||
|
sum += ASCII_TO_NUMBER(*current_ptr) * current_multiplier;
|
||||||
|
current_multiplier *= 8;
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TarHandler::check_checksum(struct tar_file_header *tar_header)
|
||||||
|
{
|
||||||
|
char original_checksum[8];
|
||||||
|
memcpy(original_checksum, tar_header->checksum, 8);
|
||||||
|
memset(tar_header->checksum, ' ', 8);
|
||||||
|
|
||||||
|
int64_t unsigned_sum = 0;
|
||||||
|
int64_t signed_sum = 0;
|
||||||
|
unsigned char *uc_tar = (unsigned char *)tar_header;
|
||||||
|
signed char *sc_tar = (signed char *)tar_header;
|
||||||
|
for(int i = 0; i < TAR_BLOCK_SIZE; i++) {
|
||||||
|
unsigned_sum += uc_tar[i];
|
||||||
|
signed_sum += sc_tar[i];
|
||||||
|
}
|
||||||
|
//Copy back the checksum
|
||||||
|
memcpy(tar_header->checksum, original_checksum, 8);
|
||||||
|
//Decode the original checksum
|
||||||
|
uint64_t reference_checksum = decode_tar_octal(original_checksum, sizeof(original_checksum));
|
||||||
|
return (reference_checksum == unsigned_sum || reference_checksum == signed_sum);
|
||||||
|
}
|
53
src/TarHandler.h
Normal file
53
src/TarHandler.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
class TarHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct tar_file_header {
|
||||||
|
char filename[100];
|
||||||
|
char mode[8];
|
||||||
|
char uid[8];
|
||||||
|
char gid[8];
|
||||||
|
char file_size[12];
|
||||||
|
char last_modification[12];
|
||||||
|
char checksum[8];
|
||||||
|
char type_flag;
|
||||||
|
char linked_file_name[100];
|
||||||
|
char ustar_indicator[6];
|
||||||
|
char ustar_version[2];
|
||||||
|
char owner_user_name[32];
|
||||||
|
char owner_group_name[32];
|
||||||
|
char device_major_number[8];
|
||||||
|
char device_minor_number[8];
|
||||||
|
char filename_prefix[155];
|
||||||
|
char padding[12];
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
TarHandler();
|
||||||
|
|
||||||
|
void tcp_in_handler(char* data, std::size_t size);
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint64_t decode_tar_octal(char* data, std::size_t size);
|
||||||
|
|
||||||
|
bool check_checksum(struct tar_file_header *tar_header);
|
||||||
|
|
||||||
|
bool tar_block_handler();
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TAR_BLOCK_SIZE = 512
|
||||||
|
};
|
||||||
|
|
||||||
|
char tar_block[TAR_BLOCK_SIZE];
|
||||||
|
std::size_t tar_index;
|
||||||
|
std::size_t next_tar_header;
|
||||||
|
std::size_t file_size;
|
||||||
|
std::size_t read_byte_count;
|
||||||
|
std::size_t processed_tar_blocks;
|
||||||
|
std::size_t file_processed_bytes;
|
||||||
|
|
||||||
|
bool idle;
|
||||||
|
};
|
47
src/main.cc
47
src/main.cc
@ -1,23 +1,38 @@
|
|||||||
#include <iostream>
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "TarHandler.h"
|
||||||
|
|
||||||
#include "ringbuffer.h"
|
|
||||||
|
|
||||||
ringbuffer buf;
|
#define TAR_FILE "test.tar"
|
||||||
|
|
||||||
int main(void) {
|
#define BLOCK_SIZE 1522
|
||||||
buf.write('a');
|
|
||||||
buf.write('b');
|
|
||||||
buf.write('c');
|
|
||||||
|
|
||||||
char c;
|
|
||||||
if(buf.read(c)) {
|
int main(void)
|
||||||
std::cout << c;
|
{
|
||||||
}
|
int fd = open(TAR_FILE, O_RDONLY);
|
||||||
if(buf.read(c)) {
|
if(fd < 0) {
|
||||||
std::cout << c;
|
fprintf(stderr, "Unable to open %s\r\n", TAR_FILE);
|
||||||
}
|
return fd;
|
||||||
if(buf.read(c)) {
|
|
||||||
std::cout << c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int res;
|
||||||
|
char block[BLOCK_SIZE];
|
||||||
|
size_t processed_blocks = 0;
|
||||||
|
TarHandler tar_handler;
|
||||||
|
do {
|
||||||
|
res = read(fd, block, sizeof(block));
|
||||||
|
tar_handler.tcp_in_handler(block, res);
|
||||||
|
processed_blocks++;
|
||||||
|
} while(res > 0);
|
||||||
|
printf("processed blocks: %lu\r\n", processed_blocks);
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
#include "ringbuffer.h"
|
|
||||||
|
|
||||||
ringbuffer::ringbuffer()
|
|
||||||
{
|
|
||||||
head = buffer.begin();
|
|
||||||
tail = buffer.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
int ringbuffer::write(char c)
|
|
||||||
{
|
|
||||||
if(head - tail == MAX_BUFFER_SIZE) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(head == buffer.end()) {
|
|
||||||
head = buffer.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
*head = c;
|
|
||||||
head++;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ringbuffer::read(char& c)
|
|
||||||
{
|
|
||||||
if(head - tail == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(tail == buffer.end()) {
|
|
||||||
tail = buffer.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
c = *tail;
|
|
||||||
tail++;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user