daliservix.cpp 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722
  1. /*##############################################################################
  2. Copyright (C) 2011 HPCC Systems.
  3. All rights reserved. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Affero General Public License as
  5. published by the Free Software Foundation, either version 3 of the
  6. License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Affero General Public License for more details.
  11. You should have received a copy of the GNU Affero General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ############################################################################## */
  14. // Dali Unix Server
  15. //----------------
  16. // to compile:
  17. // Solaris: gcc daliservix.cpp -o daliservix -lsocket -lnsl
  18. // or for x86: /usr/sfw/bin/gcc daliservix.cpp -o daliservix -lposix4 -lsocket -lstdc++ -lnsl
  19. // Linux: gcc daliservix.cpp -o daliservix
  20. #define _LARGEFILE64_SOURCE 1
  21. #define _FILE_OFFSET_BITS 64
  22. #include <unistd.h>
  23. #include <stdlib.h>
  24. #include <stdio.h>
  25. #include <stdarg.h>
  26. #include <string.h>
  27. #include <sys/types.h>
  28. #include <sys/socket.h>
  29. #include <sys/wait.h>
  30. #include <netinet/in.h>
  31. #include <arpa/inet.h>
  32. #include <netdb.h>
  33. #include <sys/ioctl.h>
  34. #include <fcntl.h>
  35. #include <sys/time.h>
  36. #include <sys/stat.h>
  37. #include <assert.h>
  38. #include <sys/socket.h>
  39. #include <semaphore.h>
  40. #include <errno.h>
  41. #include <utime.h>
  42. #include <dirent.h>
  43. #include <ctype.h>
  44. #include <signal.h>
  45. static const char *VERSTRINGBE= "DS V1.6 - Solaris";
  46. static const char *VERSTRINGLE= "DS V1.6 - Solaris X86";
  47. #define VERNUM 16
  48. #define WATCHDOG_ALARM_TIME (24*60*60)
  49. //#define _TRACE
  50. //#define _TRACE_RW
  51. //-------------------------------------------------------------------------------------
  52. #ifndef size32_t // solaris hasn't defined
  53. #define size32_t unsigned
  54. #endif
  55. //------------------------------------------------------------------------------------
  56. #define BUFFER_READS
  57. #define BUFFER_WRITES
  58. typedef unsigned char byte;
  59. typedef long long __int64;
  60. enum fileBool { foundNo = false, foundYes = true, notFound = 2 };
  61. const int endiancheck = 1;
  62. #define is_bigendian() ((*(const char*)&endiancheck) == 0)
  63. #define VERSTRING (is_bigendian()?VERSTRINGBE:VERSTRINGLE)
  64. #define READ_BUFFER_SIZE (10*1048576) // 10MB
  65. #define WRITE_BUFFER_SIZE (10*1048576) // 10MB
  66. #define MAX_BLOCK_HEADER (READ_BUFFER_SIZE+64)
  67. void usage()
  68. {
  69. printf("usage: daliservix [ <port> <send-buffer-size-kb> <recv-buffer-size-kb> ]\n\n");
  70. printf("Default port is 7100\n");
  71. printf("Version %d: %s\n\n",VERNUM,VERSTRING);
  72. }
  73. static sem_t *logsem;
  74. void Log(const char *s)
  75. {
  76. char timeStamp[32];
  77. time_t tNow;
  78. time(&tNow);
  79. unsigned tpid = getpid();
  80. struct tm ltNow;
  81. localtime_r(&tNow, &ltNow);
  82. strftime(timeStamp, 32, "%m/%d/%y %H:%M:%S ", &ltNow);
  83. sem_wait(logsem);
  84. fprintf(stderr,"%s PID=%04x - %s\n",timeStamp,getpid(),s);
  85. sem_post(logsem);
  86. }
  87. void LogF(const char *fmt, ...) __attribute__((format(printf, 1, 2)))
  88. {
  89. static char logbuf[1024*16];
  90. va_list args;
  91. va_start( args, fmt);
  92. if (vsnprintf(logbuf,sizeof(logbuf)-2,fmt,args)<0)
  93. logbuf[sizeof(logbuf)-3] = 0;
  94. Log(logbuf);
  95. va_end( args );
  96. }
  97. const char *findTail(const char *path)
  98. {
  99. if (!path)
  100. return NULL;
  101. const char *tail=path;
  102. const char *s = path;
  103. while (*s)
  104. if (*(s++)=='/')
  105. tail = s;
  106. return tail;
  107. }
  108. char * makePath(char *path,const char *dir,const char *tail)
  109. {
  110. path[0] = 0;
  111. unsigned l = 0;
  112. if (dir&&(tail[0]!='/')) {
  113. strcpy(path,dir);
  114. l = strlen(path);
  115. if (l && (path[l-1]!='/'))
  116. path[l++] = '/';
  117. }
  118. strcpy(path+l,tail);
  119. return path;
  120. }
  121. static bool WildMatchN ( const char *src, int srclen, int srcidx,
  122. const char *pat, int patlen, int patidx,int nocase)
  123. {
  124. char next_char;
  125. for (;;) {
  126. if (patidx == patlen)
  127. return (srcidx == srclen);
  128. next_char = pat[patidx++];
  129. if (next_char == '?') {
  130. if (srcidx == srclen)
  131. return false;
  132. srcidx++;
  133. }
  134. else if (next_char != '*') {
  135. if (nocase) {
  136. if ((srcidx == srclen) ||
  137. (toupper(src[srcidx])!=toupper(next_char)))
  138. return false;
  139. }
  140. else
  141. if ((srcidx == srclen) || (src[srcidx]!=next_char))
  142. return false;
  143. srcidx++;
  144. }
  145. else {
  146. if (patidx == patlen)
  147. return true;
  148. while (srcidx < srclen) {
  149. if (WildMatchN(src,srclen,srcidx,
  150. pat, patlen, patidx,nocase))
  151. return true;
  152. srcidx++;
  153. }
  154. return false;
  155. }
  156. }
  157. }
  158. bool WildMatch(const char *src, int srclen, const char *pat, int patlen,bool nocase)
  159. {
  160. if (pat[0]=='*') {
  161. // common case optimization
  162. int i = patlen;
  163. int j = srclen;
  164. while (--i>0) {
  165. if (pat[i]=='*') goto Normal;
  166. if (j--==0) return false;
  167. if (nocase) {
  168. if ((toupper(pat[i])!=toupper(src[j]))&&(pat[i]!='?'))
  169. return false;
  170. }
  171. else
  172. if ((pat[i]!=src[j])&&(pat[i]!='?'))
  173. return false;
  174. }
  175. return true;
  176. }
  177. Normal:
  178. return WildMatchN(src,srclen,0,pat,patlen,0,nocase);
  179. }
  180. bool WildMatch(const char *src, const char *pat, bool nocase)
  181. {
  182. return WildMatch(src,strlen(src),pat,strlen(pat),nocase);
  183. }
  184. static unsigned long crc_32_tab[] = { /* CRC polynomial 0xedb88320 */
  185. 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL,
  186. 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L,
  187. 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L,
  188. 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L,
  189. 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
  190. 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L,
  191. 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, 0x35b5a8faL, 0x42b2986cL,
  192. 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L,
  193. 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L,
  194. 0xcfba9599L, 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
  195. 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, 0x01db7106L,
  196. 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L,
  197. 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL,
  198. 0x91646c97L, 0xe6635c01L, 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL,
  199. 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
  200. 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L,
  201. 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L,
  202. 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L,
  203. 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL,
  204. 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
  205. 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L,
  206. 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL,
  207. 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L, 0xe3630b12L, 0x94643b84L,
  208. 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L,
  209. 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
  210. 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL,
  211. 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, 0xd6d6a3e8L, 0xa1d1937eL,
  212. 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL,
  213. 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L,
  214. 0x316e8eefL, 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
  215. 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, 0xb2bd0b28L,
  216. 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL,
  217. 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL,
  218. 0x72076785L, 0x05005713L, 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L,
  219. 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
  220. 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L,
  221. 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L,
  222. 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L,
  223. 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL,
  224. 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
  225. 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L,
  226. 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L,
  227. 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL
  228. };
  229. #define UPDC32(octet, crc) (crc_32_tab[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8))
  230. unsigned long crc32(const char *buf, unsigned len, unsigned long crc)
  231. {
  232. unsigned char c;
  233. while(len >= 12)
  234. {
  235. c = *buf++; crc = UPDC32(c,crc);
  236. c = *buf++; crc = UPDC32(c,crc);
  237. c = *buf++; crc = UPDC32(c,crc);
  238. c = *buf++; crc = UPDC32(c,crc);
  239. len -= 4;
  240. }
  241. switch (len)
  242. {
  243. case 11: c = *buf++; crc = UPDC32(c,crc);
  244. case 10: c = *buf++; crc = UPDC32(c,crc);
  245. case 9: c = *buf++; crc = UPDC32(c,crc);
  246. case 8: c = *buf++; crc = UPDC32(c,crc);
  247. case 7: c = *buf++; crc = UPDC32(c,crc);
  248. case 6: c = *buf++; crc = UPDC32(c,crc);
  249. case 5: c = *buf++; crc = UPDC32(c,crc);
  250. case 4: c = *buf++; crc = UPDC32(c,crc);
  251. case 3: c = *buf++; crc = UPDC32(c,crc);
  252. case 2: c = *buf++; crc = UPDC32(c,crc);
  253. case 1: c = *buf++; crc = UPDC32(c,crc);
  254. }
  255. return(crc);
  256. }
  257. void processCommand(int socket);
  258. extern "C" void sighup_callback(int signo)
  259. {
  260. LogF("SIGHUP(%d) received, stopping",signo);
  261. exit(0);
  262. }
  263. static int activity;
  264. extern "C" void sigalarm_callback(int signo)
  265. {
  266. if (signo!=0) {
  267. LogF("SIGALRM(%d) received",signo);
  268. if (activity==0) {
  269. LogF("No activity since last alarm, aborting process");
  270. exit(0);
  271. }
  272. }
  273. activity = 0;
  274. signal(SIGALRM, sigalarm_callback);
  275. alarm(WATCHDOG_ALARM_TIME);
  276. }
  277. static size32_t do_pread(int fd, void *buf, size32_t count, off_t offset, int &err)
  278. {
  279. if (++activity==0)
  280. activity++;
  281. do {
  282. int sz = (int)pread(fd,buf,count,offset);
  283. if (sz>=0) {
  284. err = 0;
  285. return (size32_t)sz;
  286. }
  287. err = errno;
  288. } while (err==EINTR);
  289. return (size32_t)-1;
  290. }
  291. static size32_t do_pwrite(int fd, const void *buf, size32_t len, off_t offset)
  292. {
  293. if (++activity==0)
  294. activity++;
  295. int err;
  296. do {
  297. int sz = (int)pwrite(fd,buf,len,offset);
  298. if (sz>=0) {
  299. if (sz!=len) {
  300. LogF("pwrite out of space");
  301. }
  302. return (size32_t)sz;
  303. }
  304. err = errno;
  305. } while (err==EINTR);
  306. LogF("pwrite errno = %d",errno);
  307. return (size32_t)-1;
  308. }
  309. static size32_t do_recv(int sock, void *buf, size_t len, int flags, int &err)
  310. {
  311. if (++activity==0)
  312. activity++;
  313. do {
  314. int sz = (int)recv(sock,buf,len,flags);
  315. if (sz>=0) {
  316. err = 0;
  317. return (size32_t)sz;
  318. }
  319. err = errno;
  320. } while (err==EINTR);
  321. return (size32_t)-1;
  322. }
  323. int server(int port,unsigned sendbufsize,unsigned recvbufsize)
  324. {
  325. fprintf(stderr, "%s\n", VERSTRING);
  326. fprintf(stderr, "Opening Dali server on port %d\n", port);
  327. struct protoent *proto;
  328. if ( ( proto = getprotobyname("tcp")) == NULL) {
  329. perror("Could not get protocol number for TCP");
  330. return -1;
  331. }
  332. int sockfd;
  333. if ( (sockfd = socket(AF_INET, SOCK_STREAM, proto->p_proto)) < 0) {
  334. perror("Could not obtain a socket");
  335. return -1;
  336. }
  337. struct sockaddr_in servsock;
  338. memset( (char *)&servsock, 0, sizeof(servsock));
  339. servsock.sin_family = AF_INET;
  340. servsock.sin_addr.s_addr = htonl(INADDR_ANY);
  341. servsock.sin_port = htons(port);
  342. if (bind(sockfd, (struct sockaddr *)&servsock, sizeof(servsock)) < 0) {
  343. perror("Could not bind local socket\n");
  344. return -1;
  345. }
  346. sem_unlink("/DALISERVIX_LOGSEM");
  347. logsem = sem_open("/DALISERVIX_LOGSEM", O_CREAT, S_IRWXG , 1); // |S_IRWXO|S_IRWXU
  348. if (logsem == SEM_FAILED)
  349. perror("sem_open logsem");
  350. LogF("Opening Dali server on port %d", (int)port);
  351. listen(sockfd, 5);
  352. while (1) {
  353. struct sockaddr_in clientsock;
  354. socklen_t clilen = sizeof(clientsock);
  355. int newsockfd = accept(sockfd, (struct sockaddr *) &clientsock, &clilen); // blocks here
  356. #ifdef _TRACE
  357. LogF("accept returned sockfd %d", (int)newsockfd);
  358. #endif
  359. if (newsockfd < 0) {
  360. perror("accept error");
  361. return -1;
  362. }
  363. int childpid;
  364. if ( (childpid = fork()) < 0) {
  365. perror("fork failed");
  366. return -1;
  367. }
  368. if (childpid == 0) { // the child
  369. close(sockfd);
  370. if ((childpid = fork()) < 0) { // forking twice to avoid zombies:
  371. perror("fork 2 failed\n");
  372. return -1;
  373. }
  374. else if (childpid > 0)
  375. exit(0);
  376. //sleep(1);
  377. if (sendbufsize)
  378. setsockopt(newsockfd, SOL_SOCKET, SO_SNDBUF, (char *) &sendbufsize, sizeof(sendbufsize));
  379. if (recvbufsize)
  380. setsockopt(newsockfd, SOL_SOCKET, SO_RCVBUF, (char *) &recvbufsize, sizeof(recvbufsize));
  381. signal(SIGHUP, sighup_callback);
  382. sigalarm_callback(0); // initialize
  383. processCommand(newsockfd);
  384. close(newsockfd);
  385. #ifdef _TRACE
  386. LogF("child with sockfd %d closing", (int)newsockfd);
  387. #endif
  388. exit(0);
  389. }
  390. close(newsockfd);
  391. int testpid;
  392. if ((testpid = waitpid(childpid, NULL, 0)) != childpid) {
  393. perror("waitpid error");
  394. return -1;
  395. }
  396. }
  397. }
  398. int main(int argc, char **argv)
  399. {
  400. assert(sizeof(bool)==sizeof(byte));
  401. int port;
  402. unsigned sendbufsize = 0;
  403. unsigned recvbufsize = 0;
  404. if (argc == 1)
  405. port = 7100;
  406. else {
  407. port = atoi(argv[1]);
  408. if (port==0) {
  409. usage();
  410. exit(-1);
  411. }
  412. sendbufsize = (argc>2)?(atoi(argv[2])*1024):0;
  413. recvbufsize = (argc>3)?(atoi(argv[3])*1024):0;
  414. }
  415. server(port,sendbufsize,recvbufsize);
  416. exit(0);
  417. }
  418. //================================================================================================================
  419. #define MAXHANDLES 100
  420. inline void _cpyrevn(void * _tgt, const void * _src, unsigned len)
  421. {
  422. char * tgt = (char *)_tgt; const char * src = (const char *)_src+len;
  423. for (;len;len--) {
  424. *tgt++ = *--src;
  425. }
  426. }
  427. inline void _rev4(char *b) { char t=b[0]; b[0]=b[3]; b[3]=t; t=b[1]; b[1]=b[2]; b[2]=t; }
  428. inline void BECONV(unsigned &v)
  429. {
  430. if (!is_bigendian())
  431. _rev4((char *)&v);
  432. }
  433. inline void be_memcpy(void * _tgt, const void * _src, unsigned len)
  434. {
  435. if (is_bigendian())
  436. memcpy(_tgt, _src, len);
  437. else
  438. _cpyrevn(_tgt, _src, len);
  439. }
  440. class CMemoryBuffer
  441. {
  442. byte * buffer;
  443. size32_t curLen;
  444. size32_t readPos;
  445. size32_t maxLen;
  446. public:
  447. CMemoryBuffer()
  448. {
  449. curLen = 0;
  450. readPos = 0;
  451. maxLen = 1024;
  452. buffer = (byte *)malloc(maxLen);
  453. }
  454. ~CMemoryBuffer()
  455. {
  456. free(buffer);
  457. }
  458. size32_t length() { return curLen; }
  459. size32_t curPos() { return readPos; }
  460. void setLength(size32_t len)
  461. {
  462. assert (len<=maxLen);
  463. curLen = len;
  464. }
  465. inline CMemoryBuffer & appendBigEndian(size_t len, const void * value)
  466. {
  467. be_memcpy(reserve(len), value, len);
  468. return *this;
  469. }
  470. inline void readBigEndian(size_t len, void * value)
  471. {
  472. be_memcpy(value, readBlock(len), len);
  473. }
  474. void *reserve(size32_t sz)
  475. {
  476. if (sz>maxLen-curLen) {
  477. do {
  478. maxLen += maxLen;
  479. } while (sz>maxLen-curLen);
  480. buffer = (byte *)realloc(buffer,maxLen);
  481. }
  482. byte *ret = buffer+curLen;
  483. curLen+=sz;
  484. return ret;
  485. }
  486. CMemoryBuffer & append(fpos_t value)
  487. {
  488. return appendBigEndian(sizeof(value),&value);
  489. }
  490. CMemoryBuffer & append(unsigned value)
  491. {
  492. return appendBigEndian(sizeof(value),&value);
  493. }
  494. CMemoryBuffer & append(int value)
  495. {
  496. return appendBigEndian(sizeof(value),&value);
  497. }
  498. CMemoryBuffer & append(short value)
  499. {
  500. return appendBigEndian(sizeof(value),&value);
  501. }
  502. CMemoryBuffer & append(byte value)
  503. {
  504. memcpy(reserve(sizeof(value)),&value,sizeof(value));
  505. return *this;
  506. }
  507. CMemoryBuffer & append(bool value)
  508. {
  509. memcpy(reserve(sizeof(value)),&value,1);
  510. return *this;
  511. }
  512. CMemoryBuffer & append(const char *s)
  513. {
  514. if (!s)
  515. append("");
  516. else {
  517. size32_t l=strlen(s)+1;
  518. memcpy(reserve(l),s,l);
  519. }
  520. return *this;
  521. }
  522. void read(byte &b)
  523. {
  524. memcpy(&b,buffer+readPos++,1);
  525. }
  526. void read(fpos_t &i)
  527. {
  528. readBigEndian(sizeof(i),&i);
  529. }
  530. void read(unsigned &i)
  531. {
  532. readBigEndian(sizeof(i),&i);
  533. }
  534. void read(int &i)
  535. {
  536. readBigEndian(sizeof(i),&i);
  537. }
  538. void read(short &i)
  539. {
  540. readBigEndian(sizeof(i),&i);
  541. }
  542. void read(bool &_b)
  543. {
  544. byte b;
  545. memcpy(&b,buffer+readPos,sizeof(b));
  546. readPos+=sizeof(b);
  547. _b = (bool)b;
  548. }
  549. char *readStr()
  550. {
  551. size32_t l = strlen((char *)buffer+readPos)+1;
  552. char *ret = (char *)malloc(l);
  553. memcpy(ret,buffer+readPos,l);
  554. readPos+=l;
  555. return ret;
  556. }
  557. const byte *readBlock(size32_t sz)
  558. {
  559. assert (sz<=maxLen-readPos);
  560. byte *ret = buffer+readPos;
  561. readPos+=sz;
  562. return ret;
  563. }
  564. CMemoryBuffer & reset(size32_t pos=0) { readPos = pos; return *this; }
  565. CMemoryBuffer & clear() { curLen = 0; readPos = 0; return *this; }
  566. byte *toByteArray()
  567. {
  568. return buffer;
  569. }
  570. byte *detach()
  571. {
  572. byte *ret = buffer;
  573. curLen = 0;
  574. readPos = 0;
  575. maxLen = 1024;
  576. buffer = (byte *)malloc(maxLen);
  577. return ret;
  578. }
  579. };
  580. struct CDateTime
  581. {
  582. CDateTime()
  583. {
  584. year = 0;
  585. month = 0;
  586. day = 0;
  587. hour = 0;
  588. min = 0;
  589. sec = 0;
  590. nanosec = 0;
  591. }
  592. void deserialize(CMemoryBuffer &src)
  593. {
  594. src.read(year);
  595. src.read(month);
  596. src.read(day);
  597. src.read(hour);
  598. src.read(min);
  599. src.read(sec);
  600. src.read(nanosec);
  601. }
  602. void serialize(CMemoryBuffer &dst) const
  603. {
  604. dst.append(year).append(month).append(day).append(hour).append(min).append(sec).append(nanosec);
  605. }
  606. void setDate(unsigned _year, unsigned _month, unsigned _day)
  607. {
  608. year = _year;
  609. month = _month;
  610. day = _day;
  611. }
  612. void setTime(unsigned _hour, unsigned _min, unsigned _sec, unsigned _nanosec)
  613. {
  614. hour = _hour;
  615. min = _min;
  616. sec = _sec;
  617. nanosec = _nanosec;
  618. }
  619. void getDate(int & _year, int & _month, int & _day) const
  620. {
  621. _year = year;
  622. _month = month;
  623. _day = day;
  624. }
  625. void getTime(int & _hour, int & _min, int & _sec, int & _nanosec) const
  626. {
  627. _hour = hour;
  628. _min = min;
  629. _sec = sec;
  630. _nanosec = nanosec;
  631. }
  632. protected:
  633. short year;
  634. byte month;
  635. byte day;
  636. byte hour;
  637. byte min;
  638. byte sec;
  639. unsigned nanosec;
  640. };
  641. void timetToIDateTime(CDateTime * target, time_t time)
  642. {
  643. if (target)
  644. {
  645. struct tm tm_r;
  646. struct tm * gmt = localtime_r(&time,&tm_r);
  647. //struct tm * gmt = gmtime(&time);
  648. target->setDate(gmt->tm_year + 1900, gmt->tm_mon + 1, gmt->tm_mday);
  649. target->setTime(gmt->tm_hour, gmt->tm_min, gmt->tm_sec, 0);
  650. }
  651. }
  652. time_t timetFromIDateTime(const CDateTime * source)
  653. {
  654. if (source == NULL)
  655. return (time_t) 0;
  656. int bluff;
  657. struct tm ttm;
  658. source->getDate(ttm.tm_year, ttm.tm_mon, ttm.tm_mday);
  659. source->getTime(ttm.tm_hour, ttm.tm_min, ttm.tm_sec, bluff);
  660. ttm.tm_isdst = -1;
  661. if(ttm.tm_year >= 1900)
  662. ttm.tm_year -= 1900;
  663. ttm.tm_mon -= 1;
  664. time_t time = mktime(&ttm);
  665. if (time == (time_t)-1)
  666. time = 0;
  667. return time;
  668. }
  669. bool checkDirExists(const char * filename)
  670. {
  671. struct stat info;
  672. if (stat(filename, &info) != 0)
  673. return false;
  674. return ((info.st_mode&S_IFMT)==S_IFDIR);
  675. }
  676. static bool recursiveCreateDirectory(const char * path)
  677. {
  678. if (!path || !path[0])
  679. return false;
  680. if (checkDirExists(path))
  681. return false;
  682. if (mkdir(path,S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH)==0)
  683. return true; // mode compatible with linux setting
  684. const char * cur = path;
  685. if (*cur=='/')
  686. cur++;
  687. const char * last = NULL;
  688. while (*cur) {
  689. if ((*cur=='/') && cur[1])
  690. last = cur;
  691. cur++;
  692. }
  693. if (!last)
  694. return false;
  695. unsigned len = last-path;
  696. char *parent = (char *)malloc(len+1);
  697. memcpy(parent,path,len);
  698. parent[len] = 0;
  699. if (mkdir(path,0)!=0) {
  700. free(parent);
  701. return false;
  702. }
  703. free(parent);
  704. return true;
  705. }
  706. #define throwError3(e,v,s) { LogF("ERROR: %s(%d) '%s'",#e,v,s?s:""); \
  707. char msg[512]; \
  708. sprintf(msg,"ERROR: %s(%d) '%s'",#e,v,s?s:""); \
  709. reply.append(e); reply.append(msg); }
  710. #define throwError(e) { LogF("ERROR: %s",#e); reply.append(e).append(#e); }
  711. #define throwError2(e,v) { LogF("ERROR: %s(%d)",#e,v); \
  712. char msg[512]; \
  713. sprintf(msg,"ERROR: %s(%d)",#e,v); \
  714. reply.append(e); reply.append(msg); }
  715. void sendMemoryBuffer(int socket, CMemoryBuffer & src)
  716. {
  717. unsigned length = src.length() - sizeof(unsigned);
  718. char * buffer = (char *)src.toByteArray();
  719. be_memcpy(buffer, &length, sizeof(unsigned));
  720. int remaining = (int)src.length();
  721. while(1) {
  722. int ret = send(socket, buffer, remaining,0);
  723. #ifdef _TRACE_RW
  724. LogF("SEND(%d)",remaining);
  725. #endif
  726. if (ret<0) {
  727. perror("send failed");
  728. exit(0);
  729. }
  730. remaining -= ret;
  731. if (remaining==0)
  732. break;
  733. buffer += ret;
  734. }
  735. }
  736. bool receiveMemoryBuffer(int socket, CMemoryBuffer & tgt)
  737. {
  738. unsigned oldTgtPos = tgt.length();
  739. unsigned gotLength;
  740. int err;
  741. size32_t ret = do_recv(socket, (char *)&gotLength, sizeof(gotLength),MSG_WAITALL, err);
  742. BECONV(gotLength);
  743. if (ret!=sizeof(gotLength)) {
  744. if (err&&(err!=ECONNRESET)) {
  745. LogF("recv(2) failed %d",err);
  746. exit(0);
  747. }
  748. close(socket);
  749. return false;
  750. }
  751. if (gotLength>MAX_BLOCK_HEADER) {
  752. LogF("invalid block length %d",gotLength);
  753. return false;
  754. }
  755. byte * replyBuff = (byte *)tgt.reserve(gotLength);
  756. ret = do_recv(socket, (char *)replyBuff, gotLength,MSG_WAITALL, err);
  757. #ifdef _TRACE_RW
  758. LogF("RECV(%d)",gotLength+sizeof(unsigned));
  759. #endif
  760. if (err!=0) {
  761. LogF("recv(3) failed, gotLength= %d, replyBuff = %d, err = %d",gotLength,(int)replyBuff, err);
  762. exit(0);
  763. }
  764. if (ret==0)
  765. return false;
  766. tgt.reset(oldTgtPos);
  767. return true;
  768. }
  769. //---------------------------------------------------------------------------
  770. typedef enum { IFOcreate, IFOread, IFOwrite, IFOreadwrite, IFOcreaterw } IFOmode; // modes for open
  771. typedef enum { IFSHnone, IFSHread, IFSHwrite } IFSHmode; // sharing options.
  772. enum {
  773. RFCopenIO,
  774. RFCcloseIO,
  775. RFCread,
  776. RFCwrite,
  777. RFCsize,
  778. RFCexists,
  779. RFCremove,
  780. RFCrename,
  781. RFCgetver,
  782. RFCisfile,
  783. RFCisdirectory,
  784. RFCisreadonly,
  785. RFCsetreadonly,
  786. RFCgettime,
  787. RFCsettime,
  788. RFCcreatedir,
  789. RFCgetdir,
  790. RFCstop, // not supported
  791. RFCexec, // not supported
  792. RFCkill, // not supported
  793. RFCredeploy, // not supported
  794. RFCgetcrc,
  795. //
  796. RFCmove,
  797. RFCmax
  798. };
  799. #define RFCunlock 31 // not supported but supressed
  800. typedef unsigned char RemoteFileCommandType;
  801. #define ERR_REMOTE_FIRST 8200
  802. #define ERR_REMOTE_LAST 8249
  803. #define RFSERR_InvalidCommand 8200
  804. #define RFSERR_NullFileIOHandle 8201
  805. #define RFSERR_InvalidFileIOHandle 8202
  806. #define RFSERR_TimeoutFileIOHandle 8203
  807. #define RFSERR_OpenFailed 8204
  808. #define RFSERR_ReadFailed 8205
  809. #define RFSERR_WriteFailed 8206
  810. #define RFSERR_RenameFailed 8207
  811. #define RFSERR_SetReadOnlyFailed 8208
  812. #define RFSERR_GetDirFailed 8209
  813. #define RFSERR_MoveFailed 8210
  814. #define RFEnoerror 0U
  815. class CRemoteFileServer
  816. {
  817. unsigned numhandles;
  818. protected:
  819. typedef bool (CRemoteFileServer :: * commandFunc)(CMemoryBuffer & msg, CMemoryBuffer & reply);
  820. public:
  821. void registerCommand(RemoteFileCommandType cmd, commandFunc handler) { table[cmd] = handler; }
  822. CRemoteFileServer()
  823. {
  824. numhandles = 0;
  825. rbuffer = NULL;
  826. rbufhandle = 0;
  827. rbufbase = 0;
  828. rbufsize = 0;
  829. wbuffer = NULL;
  830. wbufhandle = 0;
  831. wbufbase = 0;
  832. wbufsize = 0;
  833. RemoteFileCommandType idx;
  834. for (idx = (RemoteFileCommandType)0; idx < RFCmax; idx++)
  835. table[idx] = &CRemoteFileServer::cmdUnknown;
  836. registerCommand(RFCcloseIO, &CRemoteFileServer::cmdCloseFileIO);
  837. registerCommand(RFCopenIO, &CRemoteFileServer::cmdOpenFileIO);
  838. registerCommand(RFCread, &CRemoteFileServer::cmdRead);
  839. registerCommand(RFCsize, &CRemoteFileServer::cmdSize);
  840. registerCommand(RFCwrite, &CRemoteFileServer::cmdWrite);
  841. registerCommand(RFCexists, &CRemoteFileServer::cmdExists);
  842. registerCommand(RFCremove, &CRemoteFileServer::cmdRemove);
  843. registerCommand(RFCrename, &CRemoteFileServer::cmdRename);
  844. registerCommand(RFCgetver, &CRemoteFileServer::cmdGetVer);
  845. registerCommand(RFCisfile, &CRemoteFileServer::cmdIsFile);
  846. registerCommand(RFCisdirectory, &CRemoteFileServer::cmdIsDir);
  847. registerCommand(RFCisreadonly, &CRemoteFileServer::cmdIsReadOnly);
  848. registerCommand(RFCsetreadonly, &CRemoteFileServer::cmdSetReadOnly);
  849. registerCommand(RFCgettime, &CRemoteFileServer::cmdGetTime);
  850. registerCommand(RFCsettime, &CRemoteFileServer::cmdSetTime);
  851. registerCommand(RFCcreatedir, &CRemoteFileServer::cmdCreateDir);
  852. registerCommand(RFCgetdir, &CRemoteFileServer::cmdGetDir);
  853. registerCommand(RFCgetcrc, &CRemoteFileServer::cmdGetCrc);
  854. registerCommand(RFCmove, &CRemoteFileServer::cmdMove);
  855. }
  856. ~CRemoteFileServer()
  857. {
  858. free(rbuffer);
  859. free(wbuffer);
  860. while (numhandles)
  861. close(handles[--numhandles]);
  862. }
  863. //MORE: The file handles should timeout after a while, and accessing an old (invalid handle)
  864. // should throw a different exception
  865. bool checkFileIOHandle(CMemoryBuffer &reply, int handle)
  866. {
  867. if (handle<=0) {
  868. throwError(RFSERR_NullFileIOHandle);
  869. return false;
  870. }
  871. unsigned i;
  872. for (i=0;i<MAXHANDLES;i++)
  873. if (handles[i]==handle)
  874. return true;
  875. throwError(RFSERR_InvalidFileIOHandle);
  876. return false;
  877. }
  878. bool cmdOpenFileIO(CMemoryBuffer & msg, CMemoryBuffer & reply)
  879. {
  880. char *name = msg.readStr();
  881. byte mode;
  882. msg.read(mode);
  883. byte share;
  884. msg.read(share); // not used (yet)
  885. int handle;
  886. switch (mode)
  887. {
  888. case IFOcreate:
  889. handle = open(name, O_WRONLY|O_TRUNC|O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH );
  890. break;
  891. case IFOread:
  892. handle = open(name, O_RDONLY);
  893. break;
  894. case IFOwrite:
  895. handle = open(name, O_WRONLY);
  896. break;
  897. case IFOcreaterw:
  898. handle = open(name, O_RDWR|O_TRUNC|O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH );
  899. break;
  900. case IFOreadwrite:
  901. handle = open(name, O_RDWR);
  902. break;
  903. }
  904. #ifdef _TRACE
  905. LogF("open file %s, mode %d, handle = %d",name,(int)mode,handle);
  906. #endif
  907. if ((handle<0)&&(errno==2)) {
  908. LogF("Could not find file '%s'",name);
  909. handle = 0;
  910. }
  911. if (handle>=0) {
  912. reply.append(RFEnoerror);
  913. reply.append(handle);
  914. if (handle) {
  915. assert(numhandles<MAXHANDLES); // TBD
  916. handles[numhandles++] = handle;
  917. }
  918. free(name);
  919. return true;
  920. }
  921. throwError3(RFSERR_OpenFailed,errno,name);
  922. free(name);
  923. return false;
  924. }
  925. bool cmdCloseFileIO(CMemoryBuffer & msg, CMemoryBuffer & reply)
  926. {
  927. int handle = readFileIOHandle(msg,reply);
  928. if (handle<0)
  929. return false;
  930. #ifdef _TRACE
  931. LogF("close file, handle = %d",handle);
  932. #endif
  933. if (wbufhandle==handle) {
  934. if (!flushwrite()) {
  935. throwError(RFSERR_WriteFailed);
  936. return false;
  937. }
  938. wbufhandle = NULL;
  939. }
  940. if (rbufhandle==handle)
  941. rbufhandle = NULL;
  942. close(handle);
  943. unsigned i;
  944. for (i=0;i<numhandles;i++)
  945. if (handles[i]==handle) {
  946. numhandles--;
  947. while (i<numhandles)
  948. handles[i] = handles[i+1];
  949. }
  950. reply.append(RFEnoerror);
  951. return true;
  952. }
  953. size32_t do_buf_read(int handle, void *data, size32_t len, fpos_t pos, int &err)
  954. {
  955. size32_t done=0;
  956. size32_t rd;
  957. err = 0;
  958. while (1) {
  959. if (handle!=rbufhandle) {
  960. if (rbufhandle!=0)
  961. break;
  962. rbufhandle = handle;
  963. if (!rbuffer)
  964. rbuffer = (char *)malloc(READ_BUFFER_SIZE);
  965. rd = do_pread(rbufhandle,rbuffer,READ_BUFFER_SIZE,pos,err);
  966. if (err!=0) {
  967. rbufsize = 0;
  968. return rd;
  969. }
  970. if (rd==0)
  971. return done;
  972. rbufbase = pos;
  973. rbufsize = rd;
  974. }
  975. if (pos<rbufbase)
  976. break;
  977. if (pos>=rbufbase+rbufsize)
  978. rbufhandle = 0;
  979. else {
  980. size32_t ofs = (size32_t)(pos-rbufbase);
  981. size32_t cpy = rbufsize-ofs;
  982. if (cpy>len)
  983. cpy = len;
  984. memcpy(data,rbuffer+ofs,cpy);
  985. len -= cpy;
  986. done += cpy;
  987. if (len==0)
  988. return done;
  989. data = (char *)data+cpy;
  990. pos += cpy;
  991. }
  992. }
  993. rd = do_pread(handle,data,len,pos,err);
  994. if (err!=0)
  995. return rd;
  996. return done+rd;
  997. }
  998. bool flushwrite()
  999. {
  1000. if (wbufhandle&&(wbufsize!=0)) {
  1001. clock_t t;
  1002. size32_t numWritten = do_pwrite(wbufhandle, wbuffer, wbufsize, wbufbase);
  1003. wbufbase += wbufsize;
  1004. if (numWritten!=wbufsize) {
  1005. wbufsize = 0;
  1006. return false;
  1007. }
  1008. wbufsize = 0;
  1009. }
  1010. return true;
  1011. }
  1012. size32_t dowrite(int handle, const byte *data, size32_t len, fpos_t pos)
  1013. {
  1014. size32_t done=0;
  1015. while (len) {
  1016. if (handle!=wbufhandle) {
  1017. if (wbufhandle!=0) // only one handle used per process but in case not
  1018. return do_pwrite(handle, data, len, pos);
  1019. wbufhandle = handle;
  1020. if (!wbuffer)
  1021. wbuffer = (char *)malloc(WRITE_BUFFER_SIZE);
  1022. wbufbase = pos;
  1023. wbufsize = 0;
  1024. }
  1025. if ((pos!=wbufbase+wbufsize)||(len+wbufsize>WRITE_BUFFER_SIZE)) {
  1026. if (!flushwrite())
  1027. return (size32_t)-1;
  1028. wbufbase = pos;
  1029. }
  1030. size32_t tocopy = len;
  1031. if (tocopy>WRITE_BUFFER_SIZE)
  1032. tocopy = WRITE_BUFFER_SIZE;
  1033. len -= tocopy;
  1034. memcpy(wbuffer+wbufsize,data,tocopy);
  1035. data = ((byte *)data)+tocopy;
  1036. wbufsize += tocopy;
  1037. pos += tocopy;
  1038. done += tocopy;
  1039. }
  1040. return done;
  1041. }
  1042. bool cmdRead(CMemoryBuffer & msg, CMemoryBuffer & reply)
  1043. {
  1044. fpos_t pos;
  1045. size32_t len;
  1046. int handle = readFileIOHandle(msg,reply);
  1047. if (handle<0)
  1048. return false;
  1049. msg.read(pos);
  1050. msg.read(len);
  1051. //arrange it so we read directly into the reply buffer...
  1052. unsigned posOfErr = reply.length();
  1053. reply.append((unsigned)RFEnoerror);
  1054. size32_t numRead;
  1055. unsigned posOfLength = reply.length();
  1056. reply.reserve(sizeof(numRead));
  1057. void * data = reply.reserve(len);
  1058. int err;
  1059. #ifdef BUFFER_READS
  1060. numRead = do_buf_read(handle, data, len, pos, err);
  1061. #else
  1062. numRead = do_pread(handle, data, len, pos, err);
  1063. #endif
  1064. #ifdef _TRACE
  1065. LogF("read file, handle = %d, pos = %lld, toread = %d, read = %d",handle,pos,len,numRead);
  1066. #endif
  1067. if (numRead==(size32_t)-1) {
  1068. reply.setLength(posOfErr);
  1069. throwError2(RFSERR_ReadFailed,err);
  1070. return false;
  1071. }
  1072. be_memcpy((char *)reply.toByteArray()+posOfLength,&numRead,sizeof(numRead));
  1073. reply.setLength(posOfLength+sizeof(numRead)+numRead);
  1074. return true;
  1075. }
  1076. bool cmdSize(CMemoryBuffer & msg, CMemoryBuffer & reply)
  1077. {
  1078. int handle = readFileIOHandle(msg,reply);
  1079. if (handle<0)
  1080. return false;
  1081. #ifdef BUFFER_WRITES
  1082. if (wbufhandle==handle) {
  1083. if (!flushwrite()) {
  1084. throwError(RFSERR_WriteFailed);
  1085. return false;
  1086. }
  1087. wbufhandle = NULL;
  1088. }
  1089. #endif
  1090. fpos_t size = lseek(handle,0,SEEK_END); // we don't use seek pos so no need to restore
  1091. reply.append((unsigned)RFEnoerror).append(size);
  1092. #ifdef _TRACE
  1093. LogF("size file, handle = %d, size = %lld",handle,size);
  1094. #endif
  1095. return true;
  1096. }
  1097. bool cmdWrite(CMemoryBuffer & msg, CMemoryBuffer & reply)
  1098. {
  1099. fpos_t pos;
  1100. size32_t len;
  1101. const byte * data;
  1102. int handle = readFileIOHandle(msg,reply);
  1103. if (handle<0)
  1104. return false;
  1105. msg.read(pos);
  1106. msg.read(len);
  1107. data = msg.readBlock(len);
  1108. #ifdef BUFFER_WRITES
  1109. size32_t numWritten = dowrite(handle, data, len, pos);
  1110. #else
  1111. size32_t numWritten = do_pwrite(handle, data, len, pos);
  1112. #endif
  1113. #ifdef _TRACE
  1114. LogF("write file, handle = %d, towrite = %d, written = %d",handle,len,numWritten);
  1115. #endif
  1116. if (numWritten==(size32_t)-1) {
  1117. throwError(RFSERR_WriteFailed);
  1118. return false;
  1119. }
  1120. reply.append((unsigned)RFEnoerror).append(numWritten);
  1121. return true;
  1122. }
  1123. bool cmdExists(CMemoryBuffer & msg, CMemoryBuffer & reply)
  1124. {
  1125. char *filename = msg.readStr();
  1126. #ifdef _TRACE
  1127. LogF("exists, '%s'",filename);
  1128. #endif
  1129. struct stat s;
  1130. reply.append((unsigned)RFEnoerror).append((bool)(stat(filename,&s)==0));
  1131. free(filename);
  1132. return true;
  1133. }
  1134. bool cmdRemove(CMemoryBuffer & msg, CMemoryBuffer & reply)
  1135. {
  1136. char *filename = msg.readStr();
  1137. #ifdef _TRACE
  1138. LogF("remove, '%s'",filename);
  1139. #endif
  1140. reply.append((unsigned)RFEnoerror).append((bool)(unlink(filename)==0));
  1141. free(filename);
  1142. return true;
  1143. }
  1144. bool cmdRename(CMemoryBuffer & msg, CMemoryBuffer & reply)
  1145. {
  1146. char *from = msg.readStr();
  1147. char *to = msg.readStr();
  1148. const char *totail = findTail(to);
  1149. if (totail==to) { // kludge
  1150. const char *fromtail = findTail(from);
  1151. if (fromtail!=from) {
  1152. unsigned l = fromtail-from;
  1153. char * s = (char *)malloc(strlen(to)+l+1);
  1154. memcpy(s,from,l);
  1155. strcpy(s+l,to);
  1156. free(to);
  1157. to = s;
  1158. }
  1159. }
  1160. #ifdef _TRACE
  1161. LogF("rename, '%s' to '%s'",from,to);
  1162. #endif
  1163. if (rename(from,to)!=0) {
  1164. throwError(RFSERR_RenameFailed);
  1165. free(from);
  1166. free(to);
  1167. return false;
  1168. }
  1169. reply.append((unsigned)RFEnoerror);
  1170. free(from);
  1171. free(to);
  1172. return true;
  1173. }
  1174. bool cmdUnknown(CMemoryBuffer & msg, CMemoryBuffer & reply)
  1175. {
  1176. RemoteFileCommandType cmd;
  1177. msg.reset();
  1178. msg.read(cmd);
  1179. if (cmd!=RFCunlock) {
  1180. throwError2(RFSERR_InvalidCommand, cmd);
  1181. }
  1182. else { // kludge - don't log if unlock
  1183. char msg[512];
  1184. sprintf(msg,"ERROR: RFSERR_InvalidCommand (%d)",cmd);
  1185. reply.append(RFSERR_InvalidCommand); reply.append(msg);
  1186. }
  1187. return false;
  1188. }
  1189. bool cmdGetVer(CMemoryBuffer & msg, CMemoryBuffer & reply)
  1190. {
  1191. if (msg.length()-msg.curPos()>sizeof(unsigned))
  1192. reply.append((unsigned)RFEnoerror).append(VERSTRING);
  1193. else
  1194. reply.append((unsigned)0x10000+VERNUM).append(VERSTRING);
  1195. return true;
  1196. }
  1197. bool cmdIsFile(CMemoryBuffer &msg, CMemoryBuffer &reply)
  1198. {
  1199. char *filename = msg.readStr();
  1200. #ifdef _TRACE
  1201. LogF("isFile, '%s'",filename);
  1202. #endif
  1203. struct stat s;
  1204. unsigned ret;
  1205. if (stat(filename, &s) != 0)
  1206. ret = (unsigned)notFound;
  1207. else
  1208. ret = (unsigned)(((s.st_mode&S_IFMT)==S_IFREG) ? foundYes : foundNo);
  1209. reply.append((unsigned)RFEnoerror).append(ret);
  1210. free(filename);
  1211. return true;
  1212. }
  1213. bool cmdIsDir(CMemoryBuffer &msg, CMemoryBuffer &reply)
  1214. {
  1215. char *filename = msg.readStr();
  1216. #ifdef _TRACE
  1217. LogF("isDir, '%s'",filename);
  1218. #endif
  1219. struct stat s;
  1220. unsigned ret;
  1221. if (stat(filename, &s) != 0)
  1222. ret = (unsigned)notFound;
  1223. else
  1224. ret = (unsigned)(((s.st_mode&S_IFMT)==S_IFDIR) ? foundYes : foundNo);
  1225. reply.append((unsigned)RFEnoerror).append(ret);
  1226. free(filename);
  1227. return true;
  1228. }
  1229. bool cmdIsReadOnly(CMemoryBuffer &msg, CMemoryBuffer &reply)
  1230. {
  1231. char *filename = msg.readStr();
  1232. #ifdef _TRACE
  1233. LogF("isReadOnly, '%s'",filename);
  1234. #endif
  1235. struct stat s;
  1236. unsigned ret;
  1237. if (stat(filename, &s) != 0)
  1238. ret = (unsigned)notFound;
  1239. else
  1240. ret = (s.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)) ? foundNo : foundYes;
  1241. // I don't think this is necessarily correct but consistant with linux implementation
  1242. reply.append((unsigned)RFEnoerror).append(ret);
  1243. free(filename);
  1244. return true;
  1245. }
  1246. bool cmdSetReadOnly(CMemoryBuffer &msg, CMemoryBuffer &reply)
  1247. {
  1248. char *filename = msg.readStr();
  1249. bool set;
  1250. msg.read(set);
  1251. #ifdef _TRACE
  1252. LogF("setReadOnly, '%s'",filename);
  1253. #endif
  1254. struct stat s;
  1255. unsigned ret;
  1256. if (stat(filename, &s) != 0) {
  1257. throwError(RFSERR_SetReadOnlyFailed);
  1258. free(filename);
  1259. return false;
  1260. }
  1261. // not sure correct but consistant with isReadOnly
  1262. if (set)
  1263. s.st_mode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
  1264. else
  1265. s.st_mode |= (S_IWUSR|S_IWGRP|S_IWOTH);
  1266. chmod(filename, s.st_mode);
  1267. reply.append((unsigned)RFEnoerror);
  1268. free(filename);
  1269. return true;
  1270. }
  1271. bool cmdGetTime(CMemoryBuffer &msg, CMemoryBuffer &reply)
  1272. {
  1273. char *filename = msg.readStr();
  1274. #ifdef _TRACE
  1275. LogF("getTime, '%s'",filename);
  1276. #endif
  1277. CDateTime createTime;
  1278. CDateTime modifiedTime;
  1279. CDateTime accessedTime;
  1280. struct stat info;
  1281. if (stat(filename, &info) != 0) {
  1282. reply.append((unsigned)RFEnoerror).append((bool)false);
  1283. free(filename);
  1284. return true;
  1285. }
  1286. timetToIDateTime(&accessedTime, info.st_atime);
  1287. timetToIDateTime(&createTime, info.st_ctime);
  1288. timetToIDateTime(&modifiedTime, info.st_mtime);
  1289. reply.append((unsigned)RFEnoerror).append((bool)true);
  1290. createTime.serialize(reply);
  1291. modifiedTime.serialize(reply);
  1292. accessedTime.serialize(reply);
  1293. free(filename);
  1294. return true;
  1295. }
  1296. bool cmdSetTime(CMemoryBuffer &msg, CMemoryBuffer &reply)
  1297. {
  1298. char *filename = msg.readStr();
  1299. bool creategot;
  1300. CDateTime createTime;
  1301. bool modifiedgot;
  1302. CDateTime modifiedTime;
  1303. bool accessedgot;
  1304. CDateTime accessedTime;
  1305. msg.read(creategot);
  1306. if (creategot)
  1307. createTime.deserialize(msg);
  1308. msg.read(modifiedgot);
  1309. if (modifiedgot)
  1310. modifiedTime.deserialize(msg);
  1311. msg.read(accessedgot);
  1312. if (accessedgot)
  1313. accessedTime.deserialize(msg);
  1314. #ifdef _TRACE
  1315. LogF("setTime, '%s' %d",filename);
  1316. #endif
  1317. struct utimbuf am;
  1318. if (!accessedgot||!modifiedgot) {
  1319. struct stat info;
  1320. if (stat(filename, &info) != 0) {
  1321. reply.append((unsigned)RFEnoerror).append((bool)false);
  1322. free(filename);
  1323. return true;
  1324. }
  1325. am.actime = info.st_atime;
  1326. am.modtime = info.st_mtime;
  1327. }
  1328. if (accessedgot)
  1329. am.actime = timetFromIDateTime (&accessedTime);
  1330. if (modifiedgot)
  1331. am.modtime = timetFromIDateTime (&modifiedTime);
  1332. if(utime(filename, &am)!=0)
  1333. reply.append((unsigned)RFEnoerror).append((bool)false);
  1334. else
  1335. reply.append((unsigned)RFEnoerror).append((bool)true);
  1336. free(filename);
  1337. return true;
  1338. }
  1339. bool cmdCreateDir(CMemoryBuffer &msg, CMemoryBuffer &reply)
  1340. {
  1341. char *path = msg.readStr();
  1342. #ifdef _TRACE
  1343. LogF("createDir, '%s'",path);
  1344. #endif
  1345. if (*path&&recursiveCreateDirectory(path))
  1346. reply.append((unsigned)RFEnoerror).append((bool)true);
  1347. else
  1348. reply.append((unsigned)RFEnoerror).append((bool)false);
  1349. free(path);
  1350. return true;
  1351. }
  1352. bool cmdGetDir(CMemoryBuffer &msg, CMemoryBuffer &reply)
  1353. {
  1354. char *path = msg.readStr();
  1355. char *wildcard = msg.readStr();
  1356. bool includedir;
  1357. bool sub;
  1358. msg.read(includedir);
  1359. msg.read(sub);
  1360. #ifdef _TRACE
  1361. LogF("getDir, '%s' '%s'",path,wildcard);
  1362. #endif
  1363. DIR * handle = opendir(path);
  1364. if (!handle) {
  1365. throwError(RFSERR_GetDirFailed);
  1366. free(path);
  1367. free(wildcard);
  1368. return false;
  1369. }
  1370. reply.append((unsigned)RFEnoerror);
  1371. byte b=1;
  1372. struct dirent *entry;
  1373. while(1) {
  1374. entry = readdir(handle);
  1375. // need better checking here?
  1376. if (!entry)
  1377. break;
  1378. if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
  1379. continue;
  1380. struct stat st;
  1381. char fullname[512];
  1382. if (stat(makePath(fullname,path,entry->d_name), &st) != 0)
  1383. continue;
  1384. bool curisdir = false;
  1385. if ((st.st_mode&S_IFMT)==S_IFDIR) {
  1386. // sub TBD
  1387. if (!includedir)
  1388. continue;
  1389. curisdir = true;
  1390. }
  1391. if (!*wildcard || WildMatch(entry->d_name, wildcard, false)) {
  1392. reply.append(b);
  1393. reply.append(curisdir);
  1394. fpos_t sz = curisdir?0:st.st_size;
  1395. CDateTime dt;
  1396. memset(&dt,0,sizeof(dt));
  1397. char fullname[512];
  1398. timetToIDateTime(&dt,st.st_mtime);
  1399. reply.append(sz);
  1400. dt.serialize(reply);
  1401. reply.append(entry->d_name);
  1402. }
  1403. }
  1404. closedir(handle);
  1405. b = 0;
  1406. reply.append(b);
  1407. free(path);
  1408. free(wildcard);
  1409. }
  1410. bool cmdGetCrc(CMemoryBuffer &msg, CMemoryBuffer &reply)
  1411. {
  1412. char *filename = msg.readStr();
  1413. fpos_t pos=0;
  1414. fpos_t len=0x7fffffffffffffffLL;
  1415. //msg.read(pos); // pos/len not supported yet
  1416. //msg.read(len);
  1417. #ifdef _TRACE
  1418. LogF("getCrc, '%s' %d %d",filename,from,len);
  1419. #endif
  1420. int handle = open(filename, O_RDONLY);
  1421. if (handle<0) {
  1422. throwError3(RFSERR_OpenFailed,errno,filename);
  1423. free(filename);
  1424. return false;
  1425. }
  1426. void *buf = malloc(READ_BUFFER_SIZE);
  1427. unsigned long crc=~0;
  1428. while (len!=0) {
  1429. size32_t sz = (len>READ_BUFFER_SIZE)?READ_BUFFER_SIZE:((size32_t)len);
  1430. int err;
  1431. sz = do_pread(handle,buf,sz,pos,err);
  1432. if (err!=0) {
  1433. throwError3(RFSERR_ReadFailed,err,filename);
  1434. free(filename);
  1435. return false;
  1436. }
  1437. if (sz==0)
  1438. len = 0;
  1439. else
  1440. crc = crc32((const char *)buf,sz,crc);
  1441. len -= sz;
  1442. pos += sz;
  1443. }
  1444. close(handle);
  1445. free(buf);
  1446. reply.append((unsigned)RFEnoerror).append((unsigned)(~crc));
  1447. free(filename);
  1448. return true;
  1449. }
  1450. bool cmdMove(CMemoryBuffer &msg, CMemoryBuffer &reply)
  1451. {
  1452. char *from = msg.readStr();
  1453. char *to = msg.readStr();
  1454. #ifdef _TRACE
  1455. LogF("move, '%s' %s",from,to);
  1456. #endif
  1457. int err = rename(from,to);
  1458. if (err<0) {
  1459. throwError3(RFSERR_MoveFailed,errno,from);
  1460. free(from);
  1461. free(to);
  1462. return false;
  1463. }
  1464. reply.append((unsigned)RFEnoerror);
  1465. free(from);
  1466. free(to);
  1467. return true;
  1468. }
  1469. bool dispatchCommand(CMemoryBuffer & msg, CMemoryBuffer & reply)
  1470. {
  1471. RemoteFileCommandType cmd;
  1472. msg.read(cmd);
  1473. if (cmd < RFCmax)
  1474. return (this->*(table[cmd]))(msg, reply);
  1475. return cmdUnknown(msg,reply);
  1476. }
  1477. void processCommand(int socket)
  1478. {
  1479. char retname[256];
  1480. struct sockaddr_in *nameptr;
  1481. struct sockaddr_in name;
  1482. socklen_t namelen = sizeof(name);
  1483. nameptr = &name;
  1484. if(getpeername(socket,(struct sockaddr*)&name, &namelen)<0) {
  1485. LogF("getpeername failed %d",errno);
  1486. }
  1487. else {
  1488. strncpy(retname,inet_ntoa(nameptr->sin_addr),sizeof(retname));
  1489. LogF("Connected to %s",retname);
  1490. }
  1491. CMemoryBuffer replyBuffer;
  1492. CMemoryBuffer commandBuffer;
  1493. while (receiveMemoryBuffer(socket, commandBuffer.clear())) {
  1494. dispatchCommand(commandBuffer, replyBuffer.clear().append((unsigned)0)); // reserve space for length prefix
  1495. sendMemoryBuffer(socket, replyBuffer);
  1496. }
  1497. }
  1498. int readFileIOHandle(CMemoryBuffer & msg, CMemoryBuffer & reply)
  1499. {
  1500. int handle;
  1501. msg.read(handle);
  1502. if (!checkFileIOHandle(reply,handle))
  1503. return -1;
  1504. return handle;
  1505. }
  1506. protected:
  1507. commandFunc table[RFCmax];
  1508. int handles[MAXHANDLES];
  1509. char * rbuffer;
  1510. int rbufhandle;
  1511. fpos_t rbufbase;
  1512. size32_t rbufsize;
  1513. char * wbuffer;
  1514. int wbufhandle;
  1515. fpos_t wbufbase;
  1516. size32_t wbufsize;
  1517. };
  1518. void processCommand(int socket)
  1519. {
  1520. CRemoteFileServer server;
  1521. server.processCommand(socket);
  1522. }