daliservix.cpp 48 KB

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