Incorporate fix for NULL memory streams
[projects/chimara/chimara.git] / libchimara / stream.c
index a161a4b83437da93a84fc24d5489ec1f5ef1cfbd..96ab73fb08dcc97c8857541c0d91bafedbe7b33b 100644 (file)
@@ -284,6 +284,7 @@ glk_stream_open_memory(char *buf, glui32 buflen, glui32 fmode, glui32 rock)
        str->file_mode = fmode;
        str->type = STREAM_TYPE_MEMORY;
        str->mark = 0;
+       str->endmark = 0;
        str->unicode = FALSE;
 
        if(buf && buflen) 
@@ -322,6 +323,7 @@ glk_stream_open_memory_uni(glui32 *buf, glui32 buflen, glui32 fmode, glui32 rock
        str->file_mode = fmode;
        str->type = STREAM_TYPE_MEMORY;
        str->mark = 0;
+       str->endmark = 0;
        str->unicode = TRUE;
 
        if(buf && buflen) 
@@ -342,7 +344,7 @@ file_stream_new(frefid_t fileref, glui32 fmode, glui32 rock, gboolean unicode)
 {
        VALID_FILEREF(fileref, return NULL);
        
-       gchar *modestr;
+       const gchar *modestr;
        /* Binary mode is 0x000, text mode 0x100 */
        gboolean binary = !(fileref->usage & fileusage_TextMode);
        switch(fmode) 
@@ -352,20 +354,23 @@ file_stream_new(frefid_t fileref, glui32 fmode, glui32 rock, gboolean unicode)
                                ILLEGAL_PARAM("Tried to open a nonexistent file, '%s', in read mode", fileref->filename);
                                return NULL;
                        }
-                       modestr = g_strdup(binary? "rb" : "r");
+                       modestr = binary? "rb" : "r";
                        break;
                case filemode_Write:
-                       modestr = g_strdup(binary? "wb" : "w");
+                       modestr = binary? "wb" : "w";
                        break;
                case filemode_WriteAppend:
-                       modestr = g_strdup(binary? "ab" : "a");
-                       break;
                case filemode_ReadWrite:
-                       if( g_file_test(fileref->filename, G_FILE_TEST_EXISTS) ) {
-                               modestr = g_strdup(binary? "r+b" : "r+");
-                       } else {
-                               modestr = g_strdup(binary? "w+b" : "w+");
+               {
+                       /* We have to open the file first and then close it, in order to
+                        both make sure it exists and be able to seek in it later */
+                       FILE *fp = g_fopen(fileref->filename, binary? "ab" : "a");
+                       if(fclose(fp) != 0) {
+                               IO_WARNING( "Error opening file", fileref->filename, g_strerror(errno) );
+                               return NULL;
                        }
+                       modestr = binary? "r+b" : "r+";
+               }
                        break;
                default:
                        ILLEGAL_PARAM("Invalid file mode: %u", fmode);
@@ -373,12 +378,17 @@ file_stream_new(frefid_t fileref, glui32 fmode, glui32 rock, gboolean unicode)
        }
        
        FILE *fp = g_fopen(fileref->filename, modestr);
-       g_free(modestr);
        if(fp == NULL) {
                IO_WARNING( "Error opening file", fileref->filename, g_strerror(errno) );
                return NULL;
        }
        
+       /* Fast-forward to the end if we are appending */
+       if(fmode == filemode_WriteAppend && fseek(fp, 0, SEEK_END) != 0) {
+               IO_WARNING("Error fast-forwarding file to end", fileref->filename, g_strerror(errno));
+               return NULL;
+       }
+
        /* If they opened a file in write mode but didn't specifically get
        permission to do so, complain if the file already exists */
        if(fileref->orig_filemode == filemode_Read && fmode != filemode_Read) {