[Add] Support for non POSIX systems with open/read/write in packfile system

This commit is contained in:
Allanis 2013-02-23 19:21:13 +00:00
parent 5841d23f54
commit a296bd7aa0
4 changed files with 174 additions and 38 deletions

View File

@ -99,7 +99,7 @@ int main(int argc, char** argv) {
// See if the data file is valid.
if(pack_check(data)) {
ERR("Data file '%s' not found", data);
ERR("Data file '%s' not found", DATA);
WARN("You can specify what data file you want to use with '-d'");
WARN("See -h or -- help for more infoamtion.");
SDL_Quit();

View File

@ -8,8 +8,9 @@
#include "pack.h"
#include "music.h"
#define MUSIC_PLAYING (2<<0)
#define MUSIC_KILL (9<<0)
#define MUSIC_STOPPED (1<<1)
#define MUSIC_PLAYING (1<<2)
#define MUSIC_KILL (1<<9)
#define music_is(f) (music_state & f)
#define music_set(f) (music_state |= f)
#define music_rm(f) (music_state ^= f)
@ -71,6 +72,7 @@ int music_thread(void* unused) {
// Main loop.
while(!music_is(MUSIC_KILL)) {
if(music_is(MUSIC_PLAYING)) {
music_rm(MUSIC_STOPPED);
SDL_mutexP(music_vorbis_lock); // Lock the mutex.
SDL_mutexP(sound_lock);
@ -113,6 +115,7 @@ int music_thread(void* unused) {
SDL_mutexV(sound_lock);
SDL_mutexV(music_vorbis_lock);
}
music_set(MUSIC_STOPPED);
SDL_Delay(0); // We must not kill resources.
}
return 0;
@ -135,6 +138,10 @@ static int stream_loadBuffer(ALuint buffer) {
&section); // Current bitstream.
if(result == 0) return 1;
else if(result == OV_HOLE)
WARN("OGG: Vorbis hole detected in music!");
else if(result == OV_EBADLINK)
WARN("OGG: Invalid stream section or corrupt link in music!");
size += result;
if(size == BUFFER_SIZE) break; // Buffer is full.
@ -148,7 +155,7 @@ static int stream_loadBuffer(ALuint buffer) {
int music_init(void) {
music_vorbis_lock = SDL_CreateMutex();
music_find();
music_vorbis.file.fd = 0; // Indication that it's not loaded..
music_vorbis.file.end = 0; // Indication that it's not loaded..
SDL_mutexP(sound_lock);
@ -235,7 +242,7 @@ static int music_find(void) {
static void music_free(void) {
SDL_mutexP(music_vorbis_lock);
if(music_vorbis.file.fd != 0) {
if(music_vorbis.file.end != 0) {
ov_clear(&music_vorbis.stream);
pack_close(&music_vorbis.file);
}
@ -257,6 +264,7 @@ void music_load(const char* name) {
char tmp[64];
music_stop();
while(!music_is(MUSIC_STOPPED)) SDL_Delay(0);
for(i = 0; i < nmusic_selection; i++)
if(strcmp(music_selection[i], name)==0) {

View File

@ -43,6 +43,7 @@ const uint64_t magic = 0x25524573; // sER%
// Grab the filesize.
static off_t getfilesize(const char* filename) {
#ifdef _POSIX_SOURCE
struct stat file;
if(!stat(filename, &file))
@ -50,46 +51,94 @@ static off_t getfilesize(const char* filename) {
ERR("Unable to get filesize of %s", filename);
return 0;
#else
long size;
FILE* fp = fopen(filename, "rb");
if(fp == NULL) return 0;
fseek(fp, 0, SEEK_END);
size = ftell(fp);
fclose(fp);
return size;
#endif
}
// Return true if filename is a Packfile.
int pack_check(const char* filename) {
int ret;
char* buf;
buf = malloc(sizeof(magic));
#ifdef _POSIX_SOURCE
int fd = open(filename, O_RDONLY);
if(fd == -1) {
ERR("Error opening %s: %s", filename, strerror(errno));
return -1;
}
char* buf = malloc(sizeof(magic));
if(read(fd, buf, sizeof(magic)) != sizeof(magic)) {
ERR("Error reading magic number: %s", strerror(errno));
free(buf);
return -1;
}
ret = (memcmp(buf, &magic, sizeof(magic))==0) ? 0 : 1;
close(fd);
#else
FILE* file = fopen(filename, "rb");
if(file == NULL) {
ERR("Error opening '%s': %s", filename, strerror(errno));
return -1;
}
buf = malloc(sizeof(magic));
if(fread(buf, 1, sizeof(magic), file) != sizeof(magic)) {
ERR("Error reading magic number: %s", strerror(errno));
free(buf);
return -1;
}
ret = (memcmp(buf, &magic, sizeof(magic))==0) ? 0 : 1;
fclose(file);
#endif
int ret = (memcmp(buf, &magic, sizeof(magic))==0) ? 0 : 1;
free(buf);
return ret;
}
// Pack nfiles, infiles into outfile.
#define WRITE(f,b,n) if(write(f,b,n)==-1) { \
#ifdef _POSIX_SOURCE
#define WRITE(b,n) if(write(outfd, b, n)==-1) { \
ERR("Error writing to file: %s", strerror(errno)); \
free(buf); return -1; }
#else
#define WRITE(b,n) if(fwrite(b, 1, n, outf)==0) { \
ERR("Error writing to file: %s", strerror(errno)); \
free(buf); return -1; }
#endif
int pack_files(const char* outfile, const char** infiles, const uint32_t nfiles) {
void* buf;
#ifdef _POSIX_SOURCE
struct stat file;
int outfd, infd;
#else
FILE* outf, *inf;
#endif
uint32_t i;
int namesize;
int outfd, infd;
uint32_t indexsize, pointer;
int bytes;
const uint8_t b = '\0';
for(namesize = 0, i = 0; i < nfiles; i++) {
// Make sure file exists before writing.
#ifdef _POSIX_SOURCE
if(stat(infiles[i], &file)) {
#else
if(getfilesize(infiles[i]) == 0) {
#endif
ERR("File %s does not exist", infiles[i]);
return -1;
}
@ -106,8 +155,13 @@ int pack_files(const char* outfile, const char** infiles, const uint32_t nfiles)
DEBUG("Index size is %d", indexsize);
// Create the output file.
#ifdef _POSIX_SOURCE
outfd = creat(outfile, PERMS);
if(outfd == -1) {
#else
outf = fopen(outfile, "wb");
if(outf == NULL) {
#endif
ERR("Unable to open %s for writing", outfile);
return -1;
}
@ -116,18 +170,18 @@ int pack_files(const char* outfile, const char** infiles, const uint32_t nfiles)
buf = malloc(BLOCKSIZE);
// Magic number.
WRITE(outfd, &magic, sizeof(magic));
WRITE(&magic, sizeof(magic));
DEBUG("Wrote magic number");
// Number of files.
WRITE(outfd, &nfiles, sizeof(nfiles));
WRITE(&nfiles, sizeof(nfiles));
DEBUG("Wrote number of files: %d", nfiles);
// Create file dependent index part.
pointer = indexsize;
for(i = 0; i < nfiles; i++) {
WRITE(outfd, infiles[i], strlen(infiles[i]));
WRITE(infiles[i], strlen(infiles[i]));
DEBUG("File: '%s' at %d", infiles[i], pointer);
WRITE(outfd, &b, 1);
WRITE(outfd, &pointer, 4);
WRITE(&b, 1);
WRITE(&pointer, 4);
pointer += 4 + getfilesize(infiles[i]) + 16; // Set pointer to be next file pos.
}
@ -136,22 +190,35 @@ int pack_files(const char* outfile, const char** infiles, const uint32_t nfiles)
md5_byte_t* md5val = malloc(16);
for(i = 0; i < nfiles; i++) {
bytes = (uint32_t)getfilesize(infiles[i]);
WRITE(outfd, &bytes, 4); // filesize.
WRITE(&bytes, 4); // filesize.
DEBUG("About to write '%s' of %d bytes", infiles[i], bytes);
infd = open(infiles[i], O_RDONLY);
md5_init(&md5);
#ifdef _POSIX_SOURCE
infd = open(infiles[i], O_RDONLY);
while((bytes = read(infd, buf, BLOCKSIZE))) {
WRITE(outfd, buf, bytes); // Data.
#else
nf = fopen(infiles[i], "rb");
while((bytes = fread(buf, 1, BLOCKSIZE, inf))) {
#endif
WRITE(buf, bytes); // Data.
md5_append(&md5, buf, bytes);
}
md5_finish(&md5, md5val);
WRITE(outfd, md5val, 16);
WRITE(md5val, 16);
#ifdef _POSIX_SOURCE
close(infd);
#else
fclose(inf);
#endif
DEBUG("Wrote file '%s'", infiles[i]);
}
free(md5val);
#ifdef _POSIX_SOURCE
close(outfd);
#else
fclose(outf);
#endif
free(buf);
DEBUG("Packfile success\n\t%d files\n\t%d bytes", nfiles, (int)getfilesize(outfile));
@ -160,9 +227,15 @@ int pack_files(const char* outfile, const char** infiles, const uint32_t nfiles)
#undef WRITE
// Opens the filename in packfile for reading.
#define READ(f,b,n) if(read(f,b,n) != n) { \
#ifdef _POSIX_SOURCE
#define READ(b,n) if(read(file->fd, (b), (n))!=(n)) { \
ERR("Too few bytes read. Expected more."); \
free(buf); return -1; }
#else
#define READ(b,n) if(fread((b), 1, (n), file->fp)!=(n)) { \
ERR("Fewer bytes read then expected"); \
free(buf); return -1; }
#endif
int pack_open(Packfile* file, const char* packfile, const char* filename) {
int j;
uint32_t nfiles, i;
@ -170,46 +243,57 @@ int pack_open(Packfile* file, const char* packfile, const char* filename) {
file->start = file->end = 0;
#ifdef _POSIX_SOURCE
file->fd = open(packfile, O_RDONLY);
if(file->fd == -1) {
#else
file->fp = fopen(packfile, "rb");
if(file->fp == NULL) {
#endif
ERR("Error opening %s: %s", filename, strerror(errno));
return -1;
}
READ(file->fd, buf, sizeof(magic)); // Make sure it's a packfile.
READ(buf, sizeof(magic)); // Make sure it's a packfile.
if(memcmp(buf, &magic, sizeof(magic))) {
ERR("File %s is not a valid packfile", filename);
return -1;
}
READ(file->fd, &nfiles, 4);
READ(&nfiles, 4);
for(i = 0; i < nfiles; i++) {
// Start to search files.
j = 0;
READ(file->fd, &buf[j], 1); // Get the name.
READ(&buf[j], 1); // Get the name.
while(buf[j++] != '\0')
READ(file->fd, &buf[j], 1);
READ(&buf[j], 1);
if(strcmp(filename, buf) == 0) {
// We found the file.
READ(file->fd, &file->start, 4);
READ(&file->start, 4);
DEBUG("'%s' found at %d", filename, file->start);
break;
}
#ifdef _POSIX_SOURCE
lseek(file->fd, 4, SEEK_CUR); // Ignore the file location.
#else
fseek(file->fp, 4, SEEK_CUR);
#endif
}
free(buf);
if(file->start) {
// Go to the beginning of the file.
#ifdef _POSIX_SOURCE
if((uint32_t)lseek(file->fd, file->start, SEEK_SET) != file->start) {
#else
fseek(file->fp, file->start, SEEK_SET);
if(errno) {
#endif
ERR("Failure to seek to file start: %s", strerror(errno));
return -1;
}
if(read(file->fd, &file->end, 4) != 4) {
ERR("Too few bytes read. Expected more.");
return -1;
}
READ(&file->end, 4);
DEBUG("\t%d bytes", file->end);
file->pos = file->start;
file->end += file->start;
@ -228,7 +312,11 @@ ssize_t pack_read(Packfile* file, void* buf, size_t count) {
int bytes;
#ifdef _POSIX_SOURCE
if((bytes = read(file->fd, buf, count)) == -1) {
#else
if((byts = freed(buf, 1, count, file->fp)) == -1) {
#endif
ERR("Error while reading file: %s", strerror(errno));
return -1;
}
@ -270,8 +358,12 @@ void* pack_readfile(const char* packfile, const char* filename, uint32_t* filesi
md5_byte_t* md5fd = malloc(16);
md5_init(&md5);
md5_append(&md5, buf, bytes);
md5_finish(&md5, md5val);;
md5_finish(&md5, md5val);
#ifdef _POSIX_SOURCE
if((bytes = read(file->fd, md5fd, 16)) == -1)
#else
if((bytes = fread(md5fd, 1, 16, file->fp)) == -1)
#endif
WARN("Failure to read MD5, continuing anyway..");
else if(memcmp(md5val, md5fd, 16))
WARN("MD5 gives different value, possible memory corruption, continuing..");
@ -295,46 +387,75 @@ void* pack_readfile(const char* packfile, const char* filename, uint32_t* filesi
// Load the filenames int the packfile to filenames.
// filenames should be freed after use
// On error if filenames is (char**)-1.
#define READ(f,b,n) if(read(f,b,n)!=n) { ERR("Too few bytes read. Expected more."); return NULL; }
#ifdef _POSIX_SOURCE
#define READ(b,n) if(read(fd, (b), (n))!=(n)) { \
ERR("Too few bytes read"); \
return NULL; }
#else
#define READ(b,n) if(fread((b), 1, (n), fp) != (n)) { \
ERR("Too few bytes read"); \
return NULL; }
#endif
char** pack_listfiles(const char* packfile, uint32_t* nfiles) {
int fd, j;
#ifdef _POSIX_SOURCE
int fd;
#else
FILE* fp;
#endif
int j;
uint32_t i;
char** filenames;
char* buf = malloc(sizeof(magic));
*nfiles = 0;
#ifdef _POSIX_SOURCE
fd = open(packfile, O_RDONLY);
if(fd == -1) {
#else
fp = fopen(packfile, "rb");
if(fp == NULL) {
#endif
ERR("opening %s: %s", packfile, strerror(errno));
return NULL;
}
READ(fd, buf, sizeof(magic)); // Make sure it is a packfile.
READ(buf, sizeof(magic)); // Make sure it is a packfile.
if(memcmp(buf, &magic, sizeof(magic))) {
ERR("File %s is not a valid packfile", packfile);
return NULL;
}
READ(fd, nfiles, 4);
READ(nfiles, 4);
filenames = malloc(((*nfiles)+1)*sizeof(char*));
for(i = 0; i < *nfiles; i++) {
// Start searching files.
j = 0;
filenames[i] = malloc(MAX_FILENAME * sizeof(char));
READ(fd, &filenames[i][j], 1); // Get the name.
READ(&filenames[i][j], 1); // Get the name.
while(filenames[i][j++] != '\0')
READ(fd, &filenames[i][j], 1);
READ(fd, buf, 4); // skip the location.
READ(&filenames[i][j], 1);
READ(buf, 4); // skip the location.
}
free(buf);
#ifdef _POSIX_SOURCE
close(fd);
#else
fclose(fp);
#endif
return filenames;
}
#undef READ
// Close the packfile.
int pack_close(Packfile* file) {
int i = close(file->fd);
int i;
#ifdef _POSIX_SOURCE
i = close(file->fd);
#else
i = fclose(file->fp);
#endif
return (i) ? -1 : 0;
}

View File

@ -1,9 +1,16 @@
#pragma once
#include <fcntl.h>
#ifndef _POSIX_SOURCE // No posix.
#include <stdio.h>
#endif
#include <stdint.h>
typedef struct {
#ifdef _POSIX_SOURCE
int fd; // File descriptor.
#else
FILE* fp;
#endif
uint32_t pos; // position.
uint32_t start, end; // file limits.
} Packfile;