From a296bd7aa03b4258f0ec374207758f5b20df6686 Mon Sep 17 00:00:00 2001
From: Allanis <allanis@saracraft.net>
Date: Sat, 23 Feb 2013 19:21:13 +0000
Subject: [PATCH] [Add] Support for non POSIX systems with open/read/write in
 packfile system

---
 src/main.c  |   2 +-
 src/music.c |  16 +++--
 src/pack.c  | 187 ++++++++++++++++++++++++++++++++++++++++++----------
 src/pack.h  |   7 ++
 4 files changed, 174 insertions(+), 38 deletions(-)

diff --git a/src/main.c b/src/main.c
index 8fcd20f..0a419b9 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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();
diff --git a/src/music.c b/src/music.c
index 73e128a..afc9e79 100644
--- a/src/music.c
+++ b/src/music.c
@@ -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) {
diff --git a/src/pack.c b/src/pack.c
index 4899bd8..2d422ef 100644
--- a/src/pack.c
+++ b/src/pack.c
@@ -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;
 }
 
diff --git a/src/pack.h b/src/pack.h
index 72ddb0b..111b815 100644
--- a/src/pack.h
+++ b/src/pack.h
@@ -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;