/ source / tools / src / kgroup.cpp
kgroup.cpp
  1  // "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
  2  // Ken Silverman's official web site: "http://www.advsys.net/ken"
  3  // See the included license file "BUILDLIC.TXT" for license info.
  4  //
  5  // This file has been modified from Ken Silverman's original release
  6  // by Jonathon Fowler (jf@jonof.id.au)
  7  
  8  #include "compat.h"
  9  #include "kplib.h"
 10  
 11  // Glibc doesn't provide this function, so for the sake of less ugliess
 12  // for all platforms, here's a replacement just for this program.
 13  static void jstrupr(char *s) { while (*s) { *s = Btoupper(*s); s++; } }
 14  
 15  #define MAXFILES 4096
 16  
 17  static char buf[65536];        // These limits should be abolished one day
 18  
 19  static int numfiles;
 20  static char filespec[MAXFILES][128], filelist[MAXFILES][16];
 21  static int fileleng[MAXFILES];
 22  
 23  
 24  static char const * matchstr = "*.*";
 25  int checkmatch(const struct Bdirent *a)
 26  {
 27      if (a->mode & BS_IFDIR) return 0;    // is a directory
 28      if (a->namlen > 12) return 0;    // name too long
 29      return Bwildmatch(a->name, matchstr);
 30  }
 31  
 32  int filesize(const char *path, const char *name)
 33  {
 34      char p[BMAX_PATH];
 35      struct stat st;
 36  
 37      strcpy(p, path);
 38      strcat(p, "/");
 39      strcat(p, name);
 40  
 41      if (!stat(p, &st)) return st.st_size;
 42      return 0;
 43  }
 44  
 45  void findfiles(const char *dafilespec)
 46  {
 47      struct Bdirent *name;
 48      int daspeclen;
 49      char daspec[128];
 50      char const * dir;
 51      BDIR *di;
 52  
 53      strcpy(daspec,dafilespec);
 54      daspeclen=strlen(daspec);
 55      while ((daspec[daspeclen] != '\\') && (daspec[daspeclen] != '/') && (daspeclen > 0)) daspeclen--;
 56      if (daspeclen > 0) {
 57          daspec[daspeclen]=0;
 58          dir = daspec;
 59          matchstr = &daspec[daspeclen+1];
 60      } else {
 61          dir = ".";
 62          matchstr = daspec;
 63      }
 64  
 65      di = Bopendir(dir);
 66      if (!di) return;
 67  
 68      while ((name = Breaddir(di))) {
 69          if (!checkmatch(name)) continue;
 70  
 71          strcpy(&filelist[numfiles][0],name->name);
 72          jstrupr(&filelist[numfiles][0]);
 73          fileleng[numfiles] = name->size;
 74          filelist[numfiles][12] = (char)(fileleng[numfiles]&255);
 75          filelist[numfiles][13] = (char)((fileleng[numfiles]>>8)&255);
 76          filelist[numfiles][14] = (char)((fileleng[numfiles]>>16)&255);
 77          filelist[numfiles][15] = (char)((fileleng[numfiles]>>24)&255);
 78  
 79          strcpy(filespec[numfiles],dir);
 80          strcat(filespec[numfiles], "/");
 81          strcat(filespec[numfiles],name->name);
 82  
 83          numfiles++;
 84          if (numfiles > MAXFILES)
 85          {
 86              Bprintf("FATAL ERROR: TOO MANY FILES SELECTED! (MAX is 4096)\n");
 87              exit(0);
 88          }
 89      }
 90  
 91      Bclosedir(di);
 92  }
 93  
 94  int main(int argc, char **argv)
 95  {
 96      int i, j, k, l, fil, fil2;
 97  
 98      if (argc < 3)
 99      {
100          Bprintf("KGROUP <grouped file><@file or filespec...>               by Kenneth Silverman\n");
101          Bprintf("   This program collects many files into 1 big uncompressed file called a\n");
102          Bprintf("   group file\n");
103          Bprintf("   Ex: kgroup stuff.dat *.art *.map *.k?? palette.dat tables.dat\n");
104          Bprintf("      (stuff.dat is the group file, the rest are the files to add)\n");
105          exit(0);
106      }
107  
108      engineCreateAllocator();
109  
110      numfiles = 0;
111      for(i=argc-1;i>1;i--)
112      {
113          if (argv[i][0] == '@')
114          {
115              if ((fil = Bopen(&argv[i][1],BO_BINARY|BO_RDONLY,BS_IREAD)) != -1)
116              {
117                  l = Bread(fil,buf,65536);
118                  j = 0;
119                  while ((j < l) && (buf[j] <= 32)) j++;
120                  while (j < l)
121                  {
122                      k = j;
123                      while ((k < l) && (buf[k] > 32)) k++;
124  
125                      buf[k] = 0;
126                      findfiles(&buf[j]);
127                      j = k+1;
128  
129                      while ((j < l) && (buf[j] <= 32)) j++;
130                  }
131                  Bclose(fil);
132              }
133          }
134          else
135              findfiles(argv[i]);
136      }
137  
138      if ((fil = Bopen(argv[1],BO_BINARY|BO_TRUNC|BO_CREAT|BO_WRONLY,BS_IREAD|BS_IWRITE)) == -1)
139      {
140          Bprintf("Error: %s could not be opened\n",argv[1]);
141          exit(0);
142      }
143      Bwrite(fil,"KenSilverman",12);
144      Bwrite(fil,&numfiles,4);
145      Bwrite(fil,filelist,numfiles<<4);
146  
147      for(i=0;i<numfiles;i++)
148      {
149          Bprintf("Adding %s...\n",filespec[i]);
150          if ((fil2 = Bopen(filespec[i],BO_BINARY|BO_RDONLY,BS_IREAD)) == -1)
151          {
152              Bprintf("Error: %s not found\n",filespec[i]);
153              Bclose(fil);
154              return(0);
155          }
156          for(j=0;j<fileleng[i];j+=65536)
157          {
158              k = min(fileleng[i]-j,65536);
159              Bread(fil2,buf,k);
160              if (Bwrite(fil,buf,k) < k)
161              {
162                  Bclose(fil2);
163                  Bclose(fil);
164                  Bprintf("OUT OF HD SPACE!\n");
165                  return(0);
166              }
167          }
168          Bclose(fil2);
169      }
170      Bclose(fil);
171      Bprintf("Saved to %s.\n",argv[1]);
172  
173      return 0;
174  }
175