summaryrefslogtreecommitdiffabout
path: root/src/eyetil.cc
blob: 2fbd687958ce132b62af6c25f0b44400a5e1ab39 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include <stdlib.h>
#include <sys/stat.h>
#include <syslog.h>
#include <iostream>
#include <cassert>
#include <stdexcept>
#include <openssl/md5.h>
#include "eyetil.h"

binary_t& binary_t::from_hex(const std::string& h) {
    /* TODO: algorithmize */
    std::string::size_type hs = h.length();
    if(hs&1)
	throw std::runtime_error("odd number of characters in hexadecimal number");
    int rvs = hs>>1;
    resize(rvs);
    const unsigned char *hp = (const unsigned char*)h.data();
    iterator oi=begin();
    char t[3] = { 0,0,0 };
    for(int i=0;i<rvs;++i) {
	t[0]=*(hp++); t[1]=*(hp++);
	*(oi++) = strtol(t,0,16);
    }
    return *this;
}

binary_t& binary_t::from_data(const void *d,size_t s) {
    resize(s);
    std::copy((const unsigned char*)d,(const unsigned char *)d+s,
	    begin() );
    return *this;
}

std::string binary_t::hex() const {
    std::string rv;
    rv.reserve((size()<<1)+1);
    char t[3] = {0,0,0};
    for(const_iterator i=begin(),ie=end();i!=ie;++i) {
	int rc = snprintf(t,sizeof(t),"%02x",*i);
	assert(rc<sizeof(t));
	rv += t;
    }
    return rv;
}

binary_t binary_t::md5() const {
    binary_t rv(MD5_DIGEST_LENGTH);
    if(!MD5(
		(const unsigned char*)&(front()),size(),
		(unsigned char*)&(rv.front()) ))
	throw std::runtime_error("failed to md5()");
    return rv;
}

static void make_path_for_template(const std::string& p,mode_t m) {
    struct stat st;
    std::string pp;
    for(std::string::size_type sl=p.find('/',1);
	    sl!=std::string::npos;
	    sl=p.find('/',sl+1)) {
	if(stat( (pp=p.substr(0,sl)).c_str() ,&st)
		|| !S_ISDIR(st.st_mode)) {
	    if(mkdir(pp.c_str(),m))
		throw std::runtime_error("failed to mkdir()");
	}
    }
}

tmpdir_t::tmpdir_t(const std::string& dt) : dir(dt) {
    make_path_for_template(dt,0777);
    if(!mkdtemp((char*)dir.data()))
	throw std::runtime_error("failed to mkdtmp()");
}
tmpdir_t::~tmpdir_t() {
    assert(!dir.empty());
    if(rmdir(dir.c_str())) {
	syslog(LOG_WARNING,"Failed to remove '%s' directory",dir.c_str());
    }
}

std::string tmpdir_t::get_file(const std::string& f) {
    std::string::size_type ls = f.rfind('/');
    return dir+'/'+(
	    (ls==std::string::npos)
	    ? f
	    : f.substr(ls+1)
	);
}

tarchive_t::tarchive_t(void *p,size_t s) : a(archive_read_new()), e(0) {
    if(!a) throw std::runtime_error("failed to archive_read_new()");
    if(archive_read_support_format_tar(a)) {
	archive_read_finish(a);
	throw std::runtime_error("failed to archive_read_support_format_tar()");
    }
    if(archive_read_open_memory(a,p,s)) {
	archive_read_finish(a);
	throw std::runtime_error("failed to archive_read_open_memory()");
    }
}
tarchive_t::~tarchive_t() {
    assert(a);
    archive_read_finish(a);
}

bool tarchive_t::read_next_header() {
    assert(a);
    return archive_read_next_header(a,&e)==ARCHIVE_OK;
}

std::string tarchive_t::entry_pathname() {
    assert(a); assert(e);
    return archive_entry_pathname(e);
}

bool tarchive_t::read_data_into_fd(int fd) {
    assert(a);
    return archive_read_data_into_fd(a,fd)==ARCHIVE_OK;
}