combine.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #ifdef _WIN32
  14. #define _WIN32_WINNT 0x0400
  15. #include <windows.h>
  16. #endif
  17. #include "platform.h"
  18. #include "jlib.hpp"
  19. #include "jio.hpp"
  20. #include "jfile.hpp"
  21. #include "jexcept.hpp"
  22. #include "jhtree.hpp"
  23. #include "jsocket.hpp"
  24. #include "jlog.hpp"
  25. void usage()
  26. {
  27. printf("\nCOMBINE <srcpaths> <targetpath> [<options>]\n");
  28. printf("Options:\n");
  29. printf(" -header:<text> header text\n");
  30. printf(" -glue:<text> file separator text\n");
  31. printf(" -footer:<text> footer text\n");
  32. printf(" -prefix:<cmdlist> file prefix\n");
  33. printf(" -r process sub directories\n");
  34. exit(2);
  35. }
  36. bool isWild(const char *path)
  37. {
  38. if (strchr(path,'?')||strchr(path,'*'))
  39. return true;
  40. return false;
  41. }
  42. #define BUFFER_SIZE 0x100000
  43. void appendFile(IFileIO *srcio,IFileIOStream *out,bool sub)
  44. {
  45. static byte buf[BUFFER_SIZE];
  46. Owned<IFileIOStream> srcstrm = createIOStream(srcio);
  47. for (;;) {
  48. size32_t rd = srcstrm->read(BUFFER_SIZE,buf);
  49. if (!rd)
  50. break;
  51. out->write(rd,buf);
  52. }
  53. }
  54. bool addFilename(StringAttrArray &names,const char *name,bool sub)
  55. {
  56. if (isWild(name)) {
  57. StringBuffer dir;
  58. const char *tail = splitDirTail(name,dir);
  59. if (isWild(dir.str())) {
  60. printf("Directory %s - cannot be wild!\n",dir.str());
  61. return false;
  62. }
  63. Owned<IFile> dirf = createIFile(dir.str());
  64. Owned<IDirectoryIterator> iter = dirf->directoryFiles(tail,sub,false);
  65. StringBuffer subname;
  66. ForEach(*iter) {
  67. subname.clear().append(iter->query().queryFilename());
  68. names.append(*new StringAttrItem(subname.str()));
  69. }
  70. }
  71. else
  72. names.append(*new StringAttrItem(name));
  73. return true;
  74. }
  75. static void genPrefix(MemoryBuffer &out,const char *prefix,const char *filename,unsigned __int64 length)
  76. {
  77. out.setEndian(__LITTLE_ENDIAN);
  78. const char * s = prefix;
  79. while (s&&*s) {
  80. StringAttr command;
  81. const char * comma = strchr(s, ',');
  82. if (comma) {
  83. command.set(s, comma-s);
  84. s = comma+1;
  85. }
  86. else {
  87. command.set(s);
  88. s = NULL;
  89. }
  90. command.toUpperCase();
  91. if (memcmp(command, "FILENAME", 8) == 0) {
  92. StringBuffer tmp;
  93. const char *tail = splitDirTail(filename,tmp);
  94. tmp.clear().append(tail);
  95. if (command[8] == ':') {
  96. unsigned maxLen = atoi(command+9);
  97. tmp.padTo(maxLen);
  98. out.append(maxLen, tmp.str());
  99. }
  100. else {
  101. out.append((unsigned)tmp.length());
  102. out.append(tmp.length(), tmp.str());
  103. }
  104. }
  105. else if ((memcmp(command, "FILESIZE", 8) == 0) || (command.length() == 2))
  106. {
  107. const char * format = command;
  108. if (memcmp(format, "FILESIZE", 8) == 0) {
  109. if (format[8] == ':')
  110. format = format+9;
  111. else
  112. format = "L4";
  113. }
  114. bool bigEndian;
  115. char c = format[0];
  116. if (c == 'B')
  117. bigEndian = true;
  118. else if (c == 'L')
  119. bigEndian = false;
  120. else
  121. throw MakeStringException(-1,"Invalid prefix format %s", format);
  122. c = format[1];
  123. if ((c <= '0') || (c > '8'))
  124. throw MakeStringException(-1,"Invalid prefix format %s", format);
  125. unsigned l = (c - '0');
  126. unsigned __int64 value = length;
  127. byte temp[8];
  128. for (unsigned i=0; i<l; i++) {
  129. temp[i] = (byte)value;
  130. value >>= 8;
  131. }
  132. if (value)
  133. throw MakeStringException(-1,"Prefix too small");
  134. if (bigEndian)
  135. {
  136. byte temp2[8];
  137. _cpyrevn(&temp2, &temp, l);
  138. out.append(l, &temp2);
  139. }
  140. else
  141. out.append(l, &temp);
  142. }
  143. else
  144. throw MakeStringException(-1,"Invalid prefix format %s", command.get());
  145. }
  146. }
  147. int main(int argc, const char *argv[])
  148. {
  149. InitModuleObjects();
  150. UnsignedArray srcargs;
  151. unsigned dstarg = 0;
  152. StringBuffer header;
  153. StringBuffer footer;
  154. StringBuffer glue;
  155. StringBuffer prefix;
  156. bool sub = false;
  157. for (unsigned ai=1;ai<argc;ai++) {
  158. const char *arg = argv[ai];
  159. if (arg[0]=='-')
  160. {
  161. if (memicmp(arg+1,"header:",7)==0)
  162. header.clear().append(arg+8);
  163. else if (memicmp(arg+1,"footer:",7)==0)
  164. footer.clear().append(arg+8);
  165. else if (memicmp(arg+1,"glue:",5)==0)
  166. glue.clear().append(arg+6);
  167. else if (memicmp(arg+1,"prefix:",7)==0)
  168. prefix.clear().append(arg+8);
  169. else if (stricmp(arg+1,"r")==0)
  170. sub = true;
  171. }
  172. else {
  173. if (dstarg)
  174. srcargs.append(dstarg);
  175. dstarg = ai;
  176. }
  177. }
  178. if (!dstarg||!srcargs.ordinality())
  179. usage();
  180. try {
  181. if (isWild(argv[dstarg])) {
  182. printf("ERROR Target %s cannot be wild!\n",argv[dstarg]);
  183. return 1;
  184. }
  185. Owned<IFile> dst = createIFile(argv[dstarg]);
  186. if (!dst||dst->exists()) {
  187. printf("ERROR Target %s already exists\n",argv[dstarg]);
  188. return 1;
  189. }
  190. Owned<IFileIO> dstio = dst->open(IFOcreate);
  191. if (!dstio) {
  192. printf("ERROR Could not open Target %s\n",argv[dstarg]);
  193. return 1;
  194. }
  195. Owned<IFileIOStream> dststrm = createIOStream(dstio);
  196. if (header.length())
  197. dststrm->write(header.length(),header.str());
  198. StringAttrArray srcnames;
  199. ForEachItemIn(i,srcargs)
  200. if (!addFilename(srcnames,argv[srcargs.item(i)],sub))
  201. return 1;
  202. MemoryBuffer pref;
  203. ForEachItemIn(j,srcnames) {
  204. Owned<IFile> src = createIFile(srcnames.item(j).text.get());
  205. Owned<IFileIO> srcio = src?src->open(IFOread):NULL;
  206. if (!srcio) {
  207. printf("ERROR Could not open Source %s\n",srcnames.item(j).text.get());
  208. return 1;
  209. }
  210. if (j&&glue.length())
  211. dststrm->write(glue.length(),glue.str());
  212. if (prefix.length()) {
  213. genPrefix(pref.clear(),prefix.str(),srcnames.item(j).text.get(),srcio->size());
  214. if (pref.length())
  215. dststrm->write(pref.length(),pref.toByteArray());
  216. }
  217. appendFile(srcio,dststrm,sub);
  218. }
  219. if (footer.length())
  220. dststrm->write(footer.length(),footer.str());
  221. }
  222. catch (IException * e) {
  223. pexception("COMBINE: ",e);
  224. e->Release();
  225. }
  226. releaseAtoms();
  227. return 0;
  228. }