d3699d57 |
/* an mspack_system implementation which reads one or more files, and
* only writes to one file; the file is not actually written to, but
* an MD5 sum is computed and is available once the written-to file is
* closed. You can use anything for the written-to filename, NULL is
* probably the most obvious. The code is not multithreadable.
*/
#include <md5.h>
#include <stdio.h>
#include <stdarg.h>
struct md5_ctx md5_context;
char md5_string[33];
struct mspack_file_p {
FILE *fh;
};
static struct mspack_file *m_open(struct mspack_system *self, const char *filename, int mode) {
struct mspack_file_p *fh;
if (mode != MSPACK_SYS_OPEN_WRITE && |
cafa0bf3 |
mode != MSPACK_SYS_OPEN_READ) return NULL; |
d3699d57 |
if ((fh = (struct mspack_file_p *) malloc(sizeof(struct mspack_file_p)))) { |
cafa0bf3 |
if (mode == MSPACK_SYS_OPEN_WRITE) {
fh->fh = NULL;
md5_init_ctx(&md5_context);
return (struct mspack_file *) fh;
}
else {
if ((fh->fh = fopen(filename, "rb")))
return (struct mspack_file *) fh;
}
/* error - free file handle and return NULL */
free(fh); |
d3699d57 |
}
return NULL;
}
static void m_close(struct mspack_file *file) {
struct mspack_file_p *self = (struct mspack_file_p *) file;
if (self) {
if (self->fh) fclose(self->fh);
else { |
cafa0bf3 |
unsigned char md5[16];
md5_finish_ctx(&md5_context, (void *) &md5);
snprintf(md5_string, sizeof(md5_string),
"%02x%02x%02x%02x%02x%02x%02x%02x"
"%02x%02x%02x%02x%02x%02x%02x%02x",
md5[0], md5[1], md5[2], md5[3],
md5[4], md5[5], md5[6], md5[7],
md5[8], md5[9], md5[10], md5[11],
md5[12], md5[13], md5[14], md5[15]); |
d3699d57 |
}
free(self);
}
}
static int m_read(struct mspack_file *file, void *buffer, int bytes) {
struct mspack_file_p *self = (struct mspack_file_p *) file;
if (self && self->fh && buffer && bytes >= 0) {
size_t count = fread(buffer, 1, bytes, self->fh);
if (!ferror(self->fh)) return (int) count;
}
return -1;
}
static int m_write(struct mspack_file *file, void *buffer, int bytes) {
struct mspack_file_p *self = (struct mspack_file_p *) file;
if (!self || self->fh || !buffer || bytes < 0) return -1;
md5_process_bytes(buffer, bytes, &md5_context);
return bytes;
}
static int m_seek(struct mspack_file *file, off_t offset, int mode) {
struct mspack_file_p *self = (struct mspack_file_p *) file;
if (self && self->fh) { |
cafa0bf3 |
switch (mode) {
case MSPACK_SYS_SEEK_START: mode = SEEK_SET; break;
case MSPACK_SYS_SEEK_CUR: mode = SEEK_CUR; break;
case MSPACK_SYS_SEEK_END: mode = SEEK_END; break;
default: return -1;
} |
d3699d57 |
#if HAVE_FSEEKO |
cafa0bf3 |
return fseeko(self->fh, offset, mode); |
d3699d57 |
#else |
cafa0bf3 |
return fseek(self->fh, offset, mode); |
d3699d57 |
#endif
}
return -1;
}
static off_t m_tell(struct mspack_file *file) {
struct mspack_file_p *self = (struct mspack_file_p *) file;
#if HAVE_FSEEKO
return (self && self->fh) ? (off_t) ftello(self->fh) : 0;
#else
return (self && self->fh) ? (off_t) ftell(self->fh) : 0;
#endif
}
static void m_msg(struct mspack_file *file, const char *format, ...) {
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
fputc((int) '\n', stderr);
fflush(stderr);
}
static void *m_alloc(struct mspack_system *self, size_t bytes) {
return malloc(bytes);
}
static void m_free(void *buffer) {
free(buffer);
}
static void m_copy(void *src, void *dest, size_t bytes) {
memcpy(dest, src, bytes);
}
static struct mspack_system read_files_write_md5 = {
&m_open, &m_close, &m_read, &m_write, &m_seek,
&m_tell, &m_msg, &m_alloc, &m_free, &m_copy, NULL
}; |