Author Topic: Simple command-line VP utility  (Read 1216 times)

0 Members and 1 Guest are viewing this topic.

Offline delt

  • 23
  • Dressed to kill
Simple command-line VP utility
Hello everyone, it's been a while, years even, since i posted on this site... Freespace 1 and 2 have always been my all-time favourite games ever since they came out!

I've recently been playing Freespace 2 (and the excellent "fsport" of freespace 1) and i was reminded of how much the music in these games is just awesome. So, to extract it from the game data, i wrote a small command-line utility for manipulating .VP files - it should compile and run on any POSIX compliant operating system, i've tested it on a few linux systems (slackware, ubuntu) and on freebsd. Please keep in mind i haven't programmed in C for several years before writing this small project :D

Here it is: http://www.deimos.ca/vpfile-0.01a.tar.gz

It doesn't depend on anything else than a C compiler, the standard C libs, and basic knowledge of how to use a command line shell. To compile and install, just type:

make && sudo make install

If anyone gets this working on other systems, please let me know.
You can have the world at your feet by tomorrow, just sign on this line ____________

 

Offline delt

  • 23
  • Dressed to kill
Re: Simple command-line VP utility
New version, 0.02alpha: fixed bug with timestamp on extracted files. Also tested on OpenBSD and NetBSD.

http://www.deimos.ca/vpfile-0.02a.tar.gz
You can have the world at your feet by tomorrow, just sign on this line ____________

 

Offline headdie

  • i don't use punctuation lol
  • 212
  • Lawful Neutral with a Chaotic outook
    • Minecraft
    • Skype
    • Twitter
    • Headdie on Deviant Art
Re: Simple command-line VP utility
whats wrong with vp viewer for extracting files?
Minister of Interstellar Affairs Sol Union - Retired
quote General Battuta - "FRED is canon!"
Contact me at [email protected]
My Release Thread, Old Release Thread, Celestial Objects Thread, My rubbish attempts at art

 

Offline The E

  • He's Ebeneezer Goode
  • Global Moderator
  • 213
  • Nothing personal, just tech support.
    • Steam
    • Twitter
Re: Simple command-line VP utility
Nothing. But it doesn't exactly work on non Windows PCs, and for some tasks, commandline utilities are simply faster; both the mediavps and blue planet have build scripts that we can just run and which use commandline tools to build vps.
Let there be light
Let there be moon
Let there be stars and let there be you
Let there be monsters and let there be pain
Let us begin to feel again
--Devin Townsend, Genesis

 

Offline headdie

  • i don't use punctuation lol
  • 212
  • Lawful Neutral with a Chaotic outook
    • Minecraft
    • Skype
    • Twitter
    • Headdie on Deviant Art
Re: Simple command-line VP utility
Fair enough then
Minister of Interstellar Affairs Sol Union - Retired
quote General Battuta - "FRED is canon!"
Contact me at [email protected]
My Release Thread, Old Release Thread, Celestial Objects Thread, My rubbish attempts at art

 

Offline Echelon9

  • 210
Re: Simple command-line VP utility
Hi delt,
Looks like a neat little tool.
Suggest considering the below patch, which I've written to address a few memory management issues within the commandline tool (buffer overruns, unfree'd heap blocks, resource leaks etc).

Confirmation was received from running your tool through the below cycle with Valgrind and cppcheck, and then confirming the hash of the README file was preserved:
Code: [Select]
$ valgrind --leak-check=full ./vpfile c test.vp README
$ valgrind --leak-check=full ./vpfile l test.vp
$ valgrind --leak-check=full ./vpfile x test.vp
$ cppcheck . 2> err.txt

Patch:
Code: [Select]
diff -u vpfile/vpfile.c vpfile-patch/vpfile.c
--- vpfile/vpfile.c 2014-11-25 18:51:10.000000000 +1100
+++ vpfile-patch/vpfile.c 2015-03-06 23:01:35.112886167 +1100
@@ -129,7 +129,7 @@
   char buffer [32];
   
   if (message) printf ("%s", message);
-  scanf ("%35s", buffer);
+  scanf ("%31s", buffer);
   if (buffer [0] == 'y' || buffer [0] == 'Y')
     return 1;
   else
@@ -370,24 +370,30 @@
           buffer = safe_malloc (vp -> direntries [i].size);
           if (fseek (vp -> f, vp -> direntries [i].offset, SEEK_SET)) {
             sprintf (vp -> errormsg, "Couldn't seek into inputfile");
+            free (buffer);
             return 0;
           }
           s = fread (buffer, 1, vp -> direntries [i].size, vp -> f);
           if (s != vp -> direntries [i].size) {
             sprintf (vp -> errormsg, "Error reading into buffer for file %s: expected %d, got %d",
                      vp -> fullpaths [i], (int) vp -> direntries [i].size, (int) s);
+            free (buffer);
             return 0;
           }
           s = (fwrite (buffer, 1, vp -> direntries [i].size, outputfile));
           if (s != vp -> direntries [i].size) {
             sprintf (vp -> errormsg, "Error writing to file %s: expected %d, got %d",
                      vp -> fullpaths [i], (int) vp -> direntries [i].size, (int) s);
+            free (buffer);
             return 0;
           }
           if (fclose (outputfile)) {
-             sprintf (vp -> errormsg, "Error closing file %s", vp -> fullpaths [i]);
+            sprintf (vp -> errormsg, "Error closing file %s", vp -> fullpaths [i]);
+            free (buffer);
             return 0;
           }
+
+   free (buffer);
         }
       }
     }
@@ -590,7 +596,6 @@
 }
 
 int dispose_of_vp_outputfile (t_vp_outputfile *vp, t_opts *opts) {
-  int i = 0;
   t_direntry_list *direntry_list = NULL, *last_direntry_list = NULL;
   
   // let's take care of the filename list_vp_contents
@@ -676,6 +681,7 @@
   // we can count and write all the data segments in the same pass
   if (!vp -> direntry_list) {
     printf ("write_vp_outputfile () -- vp contains no entries!!!\n");
+    fclose (f);
     return 0;
   }
   
@@ -697,16 +703,20 @@
       if (!inputfile) {
         printf ("\nError: Can't read from input file %s\n\n", direntry_list -> fullpath);
         //printf ("direntry_list -> fullpath: %s\n", direntry_list -> fullpath);
+        fclose (f);
         return 0;
       }
       if (fstat (fileno (inputfile), &statinfo)) {
         printf ("Error stat'ing file %s\n", direntry_list -> fullpath);
+        fclose (f);
         return 0;
       }
       opts -> v > 2 && printf ("Allocating memory for file buffer\n");
       buffer = safe_malloc (statinfo.st_size);
       if ((s = fread (buffer, 1, statinfo.st_size, inputfile) != statinfo.st_size)) {
         printf ("Error reading %d bytes from %s (got %d bytes)\n", (int) statinfo.st_size, direntry_list -> fullpath, (int) s);
+        free (buffer);
+        fclose (f);
         return 0;
       }
       opts -> v > 1 && printf ("Read %d bytes from file %s\n", (int) statinfo.st_size, direntry_list -> fullpath);
@@ -714,6 +724,8 @@
       totalsize += statinfo.st_size;
       if ((s = fwrite (buffer, 1, statinfo.st_size, f) != statinfo.st_size)) {
         printf ("Error writing %d bytes to output file (%d bytes made it)\n", (int) statinfo.st_size, (int) s);
+ free (buffer);
+        fclose (f);
         return 0;
       }
       if (inputfile)
@@ -749,6 +761,7 @@
   }
   fclose (f);
   if (opts -> v > 2) inspect_vp_outputfile (vp, opts);
+  free (buffer);
   return 1;
 }
 
@@ -916,7 +929,7 @@
    if (opts -> equal_sign) bitfield |= 2;
    if (bitfield != 1) { // ...in which case we're at the compound to the last argument, so don't add
             //printf ("Allocating memory for opts -> extra_args [%d]\n", opts -> extra_arg_count);
-     opts -> extra_args [opts -> extra_arg_count] = safe_malloc (strlen (argv [i]));
+     opts -> extra_args [opts -> extra_arg_count] = safe_malloc (strlen (argv [i]) + 1);
      strcpy (opts -> extra_args [opts -> extra_arg_count], argv [i]);
      opts -> extra_arg_count++;
    }
@@ -989,6 +1002,11 @@
     print_usage (&opts);
   }
 
+  for (i = 0; i < opts.extra_arg_count; ++i)
+    if (opts.extra_args [i] != NULL)
+      free (opts.extra_args [i]);
+  free (opts.extra_args);
+
   // exit cleanly
   return 0;
 }