lwext4_server.c 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180
  1. /*
  2. * Copyright (c) 2014 Grzegorz Kostka (kostka.grzegorz@gmail.com)
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. *
  9. * - Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * - Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * - The name of the author may not be used to endorse or promote products
  15. * derived from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <unistd.h>
  31. #include <string.h>
  32. #include <stdint.h>
  33. #include <stdbool.h>
  34. #include <getopt.h>
  35. #include <time.h>
  36. #include <inttypes.h>
  37. #include <sys/time.h>
  38. #ifdef WIN32
  39. #include <winsock2.h>
  40. #include <ws2tcpip.h>
  41. #include <windows.h>
  42. #else
  43. #include <sys/socket.h>
  44. #include <netinet/in.h>
  45. #include <arpa/inet.h>
  46. #include <sys/types.h>
  47. #endif
  48. #include <ext4.h>
  49. #include "../blockdev/linux/file_dev.h"
  50. #include "../blockdev/windows/file_windows.h"
  51. static int winsock_init(void);
  52. static void winsock_fini(void);
  53. static char *entry_to_str(uint8_t type);
  54. #define MAX_FILES 64
  55. #define MAX_DIRS 64
  56. #define MAX_RW_BUFFER (1024 * 1024)
  57. #define RW_BUFFER_PATERN ('x')
  58. /**@brief Default connection port*/
  59. static int connection_port = 1234;
  60. /**@brief Default filesystem filename.*/
  61. static char *ext4_fname = "ext2";
  62. /**@brief Verbose mode*/
  63. static bool verbose = false;
  64. /**@brief Winpart mode*/
  65. static bool winpart = false;
  66. /**@brief Blockdev handle*/
  67. static struct ext4_blockdev *bd;
  68. static bool cache_wb = false;
  69. static char read_buffer[MAX_RW_BUFFER];
  70. static char write_buffer[MAX_RW_BUFFER];
  71. static const char *usage = " \n\
  72. Welcome in lwext4_server. \n\
  73. Copyright (c) 2013 Grzegorz Kostka (kostka.grzegorz@gmail.com) \n\
  74. Usage: \n\
  75. --image (-i) - ext2/3/4 image file \n\
  76. --port (-p) - server port \n\
  77. --verbose (-v) - verbose mode \n\
  78. --winpart (-w) - windows_partition mode \n\
  79. --cache_wb (-c) - cache writeback_mode \n\
  80. \n";
  81. /**@brief Open file instance descriptor.*/
  82. struct lwext4_files {
  83. char name[255];
  84. ext4_file fd;
  85. };
  86. /**@brief Open directory instance descriptor.*/
  87. struct lwext4_dirs {
  88. char name[255];
  89. ext4_dir fd;
  90. };
  91. /**@brief Library call opcode.*/
  92. struct lwext4_op_codes {
  93. char *func;
  94. };
  95. /**@brief Library call wraper.*/
  96. struct lwext4_call {
  97. int (*lwext4_call)(const char *p);
  98. };
  99. /**@brief */
  100. static struct lwext4_files file_tab[MAX_FILES];
  101. /**@brief */
  102. static struct lwext4_dirs dir_tab[MAX_DIRS];
  103. /**@brief */
  104. static struct lwext4_op_codes op_codes[] = {
  105. "device_register",
  106. "mount",
  107. "umount",
  108. "mount_point_stats",
  109. "cache_write_back",
  110. "fremove",
  111. "fopen",
  112. "fclose",
  113. "fread",
  114. "fwrite",
  115. "fseek",
  116. "ftell",
  117. "fsize",
  118. "dir_rm",
  119. "dir_mk",
  120. "dir_open",
  121. "dir_close",
  122. "dir_entry_get",
  123. "multi_fcreate",
  124. "multi_fwrite",
  125. "multi_fread",
  126. "multi_fremove",
  127. "multi_dcreate",
  128. "multi_dremove",
  129. "stats_save",
  130. "stats_check",
  131. };
  132. static int device_register(const char *p);
  133. static int mount(const char *p);
  134. static int umount(const char *p);
  135. static int mount_point_stats(const char *p);
  136. static int cache_write_back(const char *p);
  137. static int fremove(const char *p);
  138. static int file_open(const char *p);
  139. static int file_close(const char *p);
  140. static int file_read(const char *p);
  141. static int file_write(const char *p);
  142. static int file_seek(const char *p);
  143. static int file_tell(const char *p);
  144. static int file_size(const char *p);
  145. static int dir_rm(const char *p);
  146. static int dir_mk(const char *p);
  147. static int dir_open(const char *p);
  148. static int dir_close(const char *p);
  149. static int dir_close(const char *p);
  150. static int dir_entry_get(const char *p);
  151. static int multi_fcreate(const char *p);
  152. static int multi_fwrite(const char *p);
  153. static int multi_fread(const char *p);
  154. static int multi_fremove(const char *p);
  155. static int multi_dcreate(const char *p);
  156. static int multi_dremove(const char *p);
  157. static int stats_save(const char *p);
  158. static int stats_check(const char *p);
  159. /**@brief */
  160. static struct lwext4_call op_call[] = {
  161. device_register, /*PARAMS(3): 0 cache_mode dev_name */
  162. mount, /*PARAMS(2): dev_name mount_point */
  163. umount, /*PARAMS(1): mount_point */
  164. mount_point_stats, /*PARAMS(2): mount_point, 0 */
  165. cache_write_back, /*PARAMS(2): mount_point, en */
  166. fremove, /*PARAMS(1): path */
  167. file_open, /*PARAMS(2): fid path flags */
  168. file_close, /*PARAMS(1): fid */
  169. file_read, /*PARAMS(4): fid 0 len 0 */
  170. file_write, /*PARAMS(4): fid 0 len 0 */
  171. file_seek, /*PARAMS(2): fid off origin */
  172. file_tell, /*PARAMS(2): fid exp */
  173. file_size, /*PARAMS(2): fid exp */
  174. dir_rm, /*PARAMS(1): path */
  175. dir_mk, /*PARAMS(1): path */
  176. dir_open, /*PARAMS(2): did, path */
  177. dir_close, /*PARAMS(1): did */
  178. dir_entry_get, /*PARAMS(2): did, exp */
  179. multi_fcreate, /*PARAMS(3): path prefix cnt */
  180. multi_fwrite, /*PARAMS(4): path prefix cnt size */
  181. multi_fread, /*PARAMS(4): path prefix cnt size */
  182. multi_fremove, /*PARAMS(2): path prefix cnt */
  183. multi_dcreate, /*PARAMS(3): path prefix cnt */
  184. multi_dremove, /*PARAMS(2): path prefix */
  185. stats_save, /*PARAMS(1): path */
  186. stats_check, /*PARAMS(1): path */
  187. };
  188. static clock_t get_ms(void)
  189. {
  190. struct timeval t;
  191. gettimeofday(&t, NULL);
  192. return (t.tv_sec * 1000) + (t.tv_usec / 1000);
  193. }
  194. /**@brief */
  195. static int exec_op_code(const char *opcode)
  196. {
  197. int i;
  198. int r = -1;
  199. for (i = 0; i < sizeof(op_codes) / sizeof(op_codes[0]); ++i) {
  200. if (strncmp(op_codes[i].func, opcode, strlen(op_codes[i].func)))
  201. continue;
  202. if (opcode[strlen(op_codes[i].func)] != ' ')
  203. continue;
  204. printf("%s\n", opcode);
  205. opcode += strlen(op_codes[i].func);
  206. /*Call*/
  207. clock_t t = get_ms();
  208. r = op_call[i].lwext4_call(opcode);
  209. printf("rc: %d, time: %ums\n", r, (unsigned int)(get_ms() - t));
  210. break;
  211. }
  212. return r;
  213. }
  214. static int server_open(void)
  215. {
  216. int fd = 0;
  217. struct sockaddr_in serv_addr;
  218. memset(&serv_addr, 0, sizeof(serv_addr));
  219. if (winsock_init() < 0) {
  220. printf("winsock_init() error\n");
  221. exit(-1);
  222. }
  223. fd = socket(AF_INET, SOCK_STREAM, 0);
  224. if (fd < 0) {
  225. printf("socket() error: %s\n", strerror(errno));
  226. exit(-1);
  227. }
  228. int yes = 1;
  229. if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&yes,
  230. sizeof(int))) {
  231. printf("setsockopt() error: %s\n", strerror(errno));
  232. exit(-1);
  233. }
  234. serv_addr.sin_family = AF_INET;
  235. serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  236. serv_addr.sin_port = htons(connection_port);
  237. if (bind(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) {
  238. printf("bind() error: %s\n", strerror(errno));
  239. exit(-1);
  240. }
  241. if (listen(fd, 1)) {
  242. printf("listen() error: %s\n", strerror(errno));
  243. exit(-1);
  244. }
  245. return fd;
  246. }
  247. static bool parse_opt(int argc, char **argv)
  248. {
  249. int option_index = 0;
  250. int c;
  251. static struct option long_options[] = {
  252. {"image", required_argument, 0, 'i'},
  253. {"port", required_argument, 0, 'p'},
  254. {"verbose", no_argument, 0, 'v'},
  255. {"winpart", no_argument, 0, 'w'},
  256. {"cache_wb", no_argument, 0, 'c'},
  257. {"version", no_argument, 0, 'x'},
  258. {0, 0, 0, 0}};
  259. while (-1 != (c = getopt_long(argc, argv, "i:p:vcwx", long_options,
  260. &option_index))) {
  261. switch (c) {
  262. case 'i':
  263. ext4_fname = optarg;
  264. break;
  265. case 'p':
  266. connection_port = atoi(optarg);
  267. break;
  268. case 'v':
  269. verbose = true;
  270. break;
  271. case 'c':
  272. cache_wb = true;
  273. break;
  274. case 'w':
  275. winpart = true;
  276. break;
  277. case 'x':
  278. puts(VERSION);
  279. exit(0);
  280. break;
  281. default:
  282. printf("%s", usage);
  283. return false;
  284. }
  285. }
  286. return true;
  287. }
  288. int main(int argc, char *argv[])
  289. {
  290. int n;
  291. int listenfd;
  292. int connfd;
  293. char op_code[128];
  294. if (!parse_opt(argc, argv))
  295. return -1;
  296. listenfd = server_open();
  297. printf("lwext4_server: listening on port: %d\n", connection_port);
  298. memset(write_buffer, RW_BUFFER_PATERN, MAX_RW_BUFFER);
  299. while (1) {
  300. connfd = accept(listenfd, (struct sockaddr *)NULL, NULL);
  301. n = recv(connfd, op_code, sizeof(op_code), 0);
  302. if (n < 0) {
  303. printf("recv() error: %s fd = %d\n", strerror(errno),
  304. connfd);
  305. break;
  306. }
  307. op_code[n] = 0;
  308. int r = exec_op_code(op_code);
  309. n = send(connfd, (void *)&r, sizeof(r), 0);
  310. if (n < 0) {
  311. printf("send() error: %s fd = %d\n", strerror(errno),
  312. connfd);
  313. break;
  314. }
  315. close(connfd);
  316. }
  317. winsock_fini();
  318. return 0;
  319. }
  320. static int device_register(const char *p)
  321. {
  322. int dev;
  323. int cache_mode;
  324. char dev_name[32];
  325. if (sscanf(p, "%d %d %s", &dev, &cache_mode, dev_name) != 3) {
  326. printf("Param list error\n");
  327. return -1;
  328. }
  329. #ifdef WIN32
  330. if (winpart) {
  331. file_windows_name_set(ext4_fname);
  332. bd = file_windows_dev_get();
  333. } else
  334. #endif
  335. {
  336. file_dev_name_set(ext4_fname);
  337. bd = file_dev_get();
  338. }
  339. ext4_device_unregister_all();
  340. return ext4_device_register(bd, dev_name);
  341. }
  342. static int mount(const char *p)
  343. {
  344. char dev_name[32];
  345. char mount_point[32];
  346. int rc;
  347. if (sscanf(p, "%s %s", dev_name, mount_point) != 2) {
  348. printf("Param list error\n");
  349. return -1;
  350. }
  351. if (verbose)
  352. ext4_dmask_set(DEBUG_ALL);
  353. rc = ext4_mount(dev_name, mount_point, false);
  354. if (rc != EOK)
  355. return rc;
  356. rc = ext4_recover(mount_point);
  357. if (rc != EOK && rc != ENOTSUP)
  358. return rc;
  359. rc = ext4_journal_start(mount_point);
  360. if (rc != EOK)
  361. return rc;
  362. if (cache_wb)
  363. ext4_cache_write_back(mount_point, 1);
  364. return rc;
  365. }
  366. static int umount(const char *p)
  367. {
  368. char mount_point[32];
  369. int rc;
  370. if (sscanf(p, "%s", mount_point) != 1) {
  371. printf("Param list error\n");
  372. return -1;
  373. }
  374. if (cache_wb)
  375. ext4_cache_write_back(mount_point, 0);
  376. rc = ext4_journal_stop(mount_point);
  377. if (rc != EOK)
  378. return rc;
  379. rc = ext4_umount(mount_point);
  380. if (rc != EOK)
  381. return rc;
  382. return rc;
  383. }
  384. static int mount_point_stats(const char *p)
  385. {
  386. char mount_point[32];
  387. int d;
  388. int rc;
  389. struct ext4_mount_stats stats;
  390. if (sscanf(p, "%s %d", mount_point, &d) != 2) {
  391. printf("Param list error\n");
  392. return -1;
  393. }
  394. rc = ext4_mount_point_stats(mount_point, &stats);
  395. if (rc != EOK)
  396. return rc;
  397. if (verbose) {
  398. printf("\tinodes_count = %" PRIu32"\n", stats.inodes_count);
  399. printf("\tfree_inodes_count = %" PRIu32"\n",
  400. stats.free_inodes_count);
  401. printf("\tblocks_count = %" PRIu64"\n", stats.blocks_count);
  402. printf("\tfree_blocks_count = %" PRIu64"\n",
  403. stats.free_blocks_count);
  404. printf("\tblock_size = %" PRIu32"\n", stats.block_size);
  405. printf("\tblock_group_count = %" PRIu32"\n",
  406. stats.block_group_count);
  407. printf("\tblocks_per_group = %" PRIu32"\n",
  408. stats.blocks_per_group);
  409. printf("\tinodes_per_group = %" PRIu32"\n",
  410. stats.inodes_per_group);
  411. printf("\tvolume_name = %s\n", stats.volume_name);
  412. }
  413. return rc;
  414. }
  415. static int cache_write_back(const char *p)
  416. {
  417. char mount_point[32];
  418. int en;
  419. if (sscanf(p, "%s %d", mount_point, &en) != 2) {
  420. printf("Param list error\n");
  421. return -1;
  422. }
  423. return ext4_cache_write_back(mount_point, en);
  424. }
  425. static int fremove(const char *p)
  426. {
  427. char path[255];
  428. if (sscanf(p, "%s", path) != 1) {
  429. printf("Param list error\n");
  430. return -1;
  431. }
  432. return ext4_fremove(path);
  433. }
  434. static int file_open(const char *p)
  435. {
  436. int fid = MAX_FILES;
  437. char path[256];
  438. char flags[8];
  439. int rc;
  440. if (sscanf(p, "%d %s %s", &fid, path, flags) != 3) {
  441. printf("Param list error\n");
  442. return -1;
  443. }
  444. if (!(fid < MAX_FILES)) {
  445. printf("File id too big\n");
  446. return -1;
  447. }
  448. rc = ext4_fopen(&file_tab[fid].fd, path, flags);
  449. if (rc == EOK)
  450. strcpy(file_tab[fid].name, path);
  451. return rc;
  452. }
  453. static int file_close(const char *p)
  454. {
  455. int fid = MAX_FILES;
  456. int rc;
  457. if (sscanf(p, "%d", &fid) != 1) {
  458. printf("Param list error\n");
  459. return -1;
  460. }
  461. if (!(fid < MAX_FILES)) {
  462. printf("File id too big\n");
  463. return -1;
  464. }
  465. if (file_tab[fid].name[0] == 0) {
  466. printf("File id empty\n");
  467. return -1;
  468. }
  469. rc = ext4_fclose(&file_tab[fid].fd);
  470. if (rc == EOK)
  471. file_tab[fid].name[0] = 0;
  472. return rc;
  473. }
  474. static int file_read(const char *p)
  475. {
  476. int fid = MAX_FILES;
  477. int len;
  478. int d;
  479. int rc;
  480. size_t rb;
  481. if (sscanf(p, "%d %d %d %d", &fid, &d, &len, &d) != 4) {
  482. printf("Param list error\n");
  483. return -1;
  484. }
  485. if (!(fid < MAX_FILES)) {
  486. printf("File id too big\n");
  487. return -1;
  488. }
  489. if (file_tab[fid].name[0] == 0) {
  490. printf("File id empty\n");
  491. return -1;
  492. }
  493. while (len) {
  494. d = len > MAX_RW_BUFFER ? MAX_RW_BUFFER : len;
  495. memset(read_buffer, 0, MAX_RW_BUFFER);
  496. rc = ext4_fread(&file_tab[fid].fd, read_buffer, d, &rb);
  497. if (rc != EOK)
  498. break;
  499. if (rb != d) {
  500. printf("Read count error\n");
  501. return -1;
  502. }
  503. if (memcmp(read_buffer, write_buffer, d)) {
  504. printf("Read compare error\n");
  505. return -1;
  506. }
  507. len -= d;
  508. }
  509. return rc;
  510. }
  511. static int file_write(const char *p)
  512. {
  513. int fid = MAX_FILES;
  514. int d;
  515. int rc;
  516. int len;
  517. size_t wb;
  518. if (sscanf(p, "%d %d %d %d", &fid, &d, &len, &d) != 4) {
  519. printf("Param list error\n");
  520. return -1;
  521. }
  522. if (!(fid < MAX_FILES)) {
  523. printf("File id too big\n");
  524. return -1;
  525. }
  526. if (file_tab[fid].name[0] == 0) {
  527. printf("File id empty\n");
  528. return -1;
  529. }
  530. while (len) {
  531. d = len > MAX_RW_BUFFER ? MAX_RW_BUFFER : len;
  532. rc = ext4_fwrite(&file_tab[fid].fd, write_buffer, d, &wb);
  533. if (rc != EOK)
  534. break;
  535. if (wb != d) {
  536. printf("Write count error\n");
  537. return -1;
  538. }
  539. len -= d;
  540. }
  541. return rc;
  542. }
  543. static int file_seek(const char *p)
  544. {
  545. int fid = MAX_FILES;
  546. int off;
  547. int origin;
  548. if (sscanf(p, "%d %d %d", &fid, &off, &origin) != 3) {
  549. printf("Param list error\n");
  550. return -1;
  551. }
  552. if (!(fid < MAX_FILES)) {
  553. printf("File id too big\n");
  554. return -1;
  555. }
  556. if (file_tab[fid].name[0] == 0) {
  557. printf("File id empty\n");
  558. return -1;
  559. }
  560. return ext4_fseek(&file_tab[fid].fd, off, origin);
  561. }
  562. static int file_tell(const char *p)
  563. {
  564. int fid = MAX_FILES;
  565. uint32_t exp_pos;
  566. if (sscanf(p, "%d %u", &fid, &exp_pos) != 2) {
  567. printf("Param list error\n");
  568. return -1;
  569. }
  570. if (!(fid < MAX_FILES)) {
  571. printf("File id too big\n");
  572. return -1;
  573. }
  574. if (file_tab[fid].name[0] == 0) {
  575. printf("File id empty\n");
  576. return -1;
  577. }
  578. if (exp_pos != ext4_ftell(&file_tab[fid].fd)) {
  579. printf("Expected filepos error\n");
  580. return -1;
  581. }
  582. return EOK;
  583. }
  584. static int file_size(const char *p)
  585. {
  586. int fid = MAX_FILES;
  587. uint32_t exp_size;
  588. if (sscanf(p, "%d %u", &fid, &exp_size) != 2) {
  589. printf("Param list error\n");
  590. return -1;
  591. }
  592. if (!(fid < MAX_FILES)) {
  593. printf("File id too big\n");
  594. return -1;
  595. }
  596. if (file_tab[fid].name[0] == 0) {
  597. printf("File id empty\n");
  598. return -1;
  599. }
  600. if (exp_size != ext4_fsize(&file_tab[fid].fd)) {
  601. printf("Expected filesize error\n");
  602. return -1;
  603. }
  604. return EOK;
  605. }
  606. static int dir_rm(const char *p)
  607. {
  608. char path[255];
  609. if (sscanf(p, "%s", path) != 1) {
  610. printf("Param list error\n");
  611. return -1;
  612. }
  613. return ext4_dir_rm(path);
  614. }
  615. static int dir_mk(const char *p)
  616. {
  617. char path[255];
  618. if (sscanf(p, "%s", path) != 1) {
  619. printf("Param list error\n");
  620. return -1;
  621. }
  622. return ext4_dir_mk(path);
  623. }
  624. static int dir_open(const char *p)
  625. {
  626. int did = MAX_DIRS;
  627. char path[255];
  628. int rc;
  629. if (sscanf(p, "%d %s", &did, path) != 2) {
  630. printf("Param list error\n");
  631. return -1;
  632. }
  633. if (!(did < MAX_DIRS)) {
  634. printf("Dir id too big\n");
  635. return -1;
  636. }
  637. rc = ext4_dir_open(&dir_tab[did].fd, path);
  638. if (rc == EOK)
  639. strcpy(dir_tab[did].name, path);
  640. return rc;
  641. }
  642. static int dir_close(const char *p)
  643. {
  644. int did = MAX_DIRS;
  645. int rc;
  646. if (sscanf(p, "%d", &did) != 1) {
  647. printf("Param list error\n");
  648. return -1;
  649. }
  650. if (!(did < MAX_DIRS)) {
  651. printf("Dir id too big\n");
  652. return -1;
  653. }
  654. if (dir_tab[did].name[0] == 0) {
  655. printf("Dir id empty\n");
  656. return -1;
  657. }
  658. rc = ext4_dir_close(&dir_tab[did].fd);
  659. if (rc == EOK)
  660. dir_tab[did].name[0] = 0;
  661. return rc;
  662. }
  663. static int dir_entry_get(const char *p)
  664. {
  665. int did = MAX_DIRS;
  666. int exp;
  667. char name[256];
  668. if (sscanf(p, "%d %d", &did, &exp) != 2) {
  669. printf("Param list error\n");
  670. return -1;
  671. }
  672. if (!(did < MAX_DIRS)) {
  673. printf("Dir id too big\n");
  674. return -1;
  675. }
  676. if (dir_tab[did].name[0] == 0) {
  677. printf("Dir id empty\n");
  678. return -1;
  679. }
  680. int idx = 0;
  681. const ext4_direntry *d;
  682. while ((d = ext4_dir_entry_next(&dir_tab[did].fd)) != NULL) {
  683. idx++;
  684. memcpy(name, d->name, d->name_length);
  685. name[d->name_length] = 0;
  686. if (verbose) {
  687. printf("\t%s %s\n", entry_to_str(d->inode_type), name);
  688. }
  689. }
  690. if (idx < 2) {
  691. printf("Minumum dir entry error\n");
  692. return -1;
  693. }
  694. if ((idx - 2) != exp) {
  695. printf("Expected dir entry error\n");
  696. return -1;
  697. }
  698. return EOK;
  699. }
  700. static int multi_fcreate(const char *p)
  701. {
  702. char path[256];
  703. char path1[256];
  704. char prefix[32];
  705. int cnt;
  706. int rc;
  707. int i;
  708. ext4_file fd;
  709. if (sscanf(p, "%s %s %d", path, prefix, &cnt) != 3) {
  710. printf("Param list error\n");
  711. return -1;
  712. }
  713. for (i = 0; i < cnt; ++i) {
  714. sprintf(path1, "%s%s%d", path, prefix, i);
  715. rc = ext4_fopen(&fd, path1, "wb+");
  716. if (rc != EOK)
  717. break;
  718. }
  719. return rc;
  720. }
  721. static int multi_fwrite(const char *p)
  722. {
  723. char path[256];
  724. char path1[256];
  725. char prefix[32];
  726. int cnt, i;
  727. int len, ll;
  728. int rc;
  729. size_t d, wb;
  730. ext4_file fd;
  731. if (sscanf(p, "%s %s %d %d", path, prefix, &cnt, &ll) != 4) {
  732. printf("Param list error\n");
  733. return -1;
  734. }
  735. for (i = 0; i < cnt; ++i) {
  736. sprintf(path1, "%s%s%d", path, prefix, i);
  737. rc = ext4_fopen(&fd, path1, "rb+");
  738. if (rc != EOK)
  739. break;
  740. len = ll;
  741. while (len) {
  742. d = len > MAX_RW_BUFFER ? MAX_RW_BUFFER : len;
  743. rc = ext4_fwrite(&fd, write_buffer, d, &wb);
  744. if (rc != EOK)
  745. break;
  746. if (wb != d) {
  747. printf("Write count error\n");
  748. return -1;
  749. }
  750. len -= d;
  751. }
  752. }
  753. return rc;
  754. }
  755. static int multi_fread(const char *p)
  756. {
  757. char path[256];
  758. char path1[256];
  759. char prefix[32];
  760. int cnt;
  761. int len, ll;
  762. int rc ,i, d;
  763. size_t rb;
  764. ext4_file fd;
  765. if (sscanf(p, "%s %s %d %d", path, prefix, &cnt, &ll) != 4) {
  766. printf("Param list error\n");
  767. return -1;
  768. }
  769. for (i = 0; i < cnt; ++i) {
  770. sprintf(path1, "%s%s%d", path, prefix, i);
  771. rc = ext4_fopen(&fd, path1, "rb+");
  772. if (rc != EOK)
  773. break;
  774. len = ll;
  775. while (len) {
  776. d = len > MAX_RW_BUFFER ? MAX_RW_BUFFER : len;
  777. memset(read_buffer, 0, MAX_RW_BUFFER);
  778. rc = ext4_fread(&fd, read_buffer, d, &rb);
  779. if (rc != EOK)
  780. break;
  781. if (rb != d) {
  782. printf("Read count error\n");
  783. return -1;
  784. }
  785. if (memcmp(read_buffer, write_buffer, d)) {
  786. printf("Read compare error\n");
  787. return -1;
  788. }
  789. len -= d;
  790. }
  791. }
  792. return rc;
  793. }
  794. static int multi_fremove(const char *p)
  795. {
  796. char path[256];
  797. char path1[256];
  798. char prefix[32];
  799. int cnt, i, rc;
  800. if (sscanf(p, "%s %s %d", path, prefix, &cnt) != 3) {
  801. printf("Param list error\n");
  802. return -1;
  803. }
  804. for (i = 0; i < cnt; ++i) {
  805. sprintf(path1, "%s%s%d", path, prefix, i);
  806. rc = ext4_fremove(path1);
  807. if (rc != EOK)
  808. break;
  809. }
  810. return rc;
  811. }
  812. static int multi_dcreate(const char *p)
  813. {
  814. char path[256];
  815. char path1[256];
  816. char prefix[32];
  817. int cnt, i, rc;
  818. if (sscanf(p, "%s %s %d", path, prefix, &cnt) != 3) {
  819. printf("Param list error\n");
  820. return -1;
  821. }
  822. for (i = 0; i < cnt; ++i) {
  823. sprintf(path1, "%s%s%d", path, prefix, i);
  824. rc = ext4_dir_mk(path1);
  825. if (rc != EOK)
  826. break;
  827. }
  828. return rc;
  829. }
  830. static int multi_dremove(const char *p)
  831. {
  832. char path[256];
  833. char path1[256];
  834. char prefix[32];
  835. int cnt, i, rc;
  836. if (sscanf(p, "%s %s %d", path, prefix, &cnt) != 3) {
  837. printf("Param list error\n");
  838. return -1;
  839. }
  840. for (i = 0; i < cnt; ++i) {
  841. sprintf(path1, "%s%s%d", path, prefix, i);
  842. rc = ext4_dir_rm(path1);
  843. if (rc != EOK)
  844. break;
  845. }
  846. return rc;
  847. }
  848. struct ext4_mount_stats saved_stats;
  849. static int stats_save(const char *p)
  850. {
  851. char path[256];
  852. if (sscanf(p, "%s", path) != 1) {
  853. printf("Param list error\n");
  854. return -1;
  855. }
  856. return ext4_mount_point_stats(path, &saved_stats);
  857. }
  858. static int stats_check(const char *p)
  859. {
  860. char path[256];
  861. int rc;
  862. struct ext4_mount_stats actual_stats;
  863. if (sscanf(p, "%s", path) != 1) {
  864. printf("Param list error\n");
  865. return -1;
  866. }
  867. rc = ext4_mount_point_stats(path, &actual_stats);
  868. if (rc != EOK)
  869. return rc;
  870. if (memcmp(&saved_stats, &actual_stats,
  871. sizeof(struct ext4_mount_stats))) {
  872. if (verbose) {
  873. printf("\tMount point stats error:\n");
  874. printf("\tsaved_stats:\n");
  875. printf("\tinodes_count = %" PRIu32"\n",
  876. saved_stats.inodes_count);
  877. printf("\tfree_inodes_count = %" PRIu32"\n",
  878. saved_stats.free_inodes_count);
  879. printf("\tblocks_count = %" PRIu64"\n",
  880. saved_stats.blocks_count);
  881. printf("\tfree_blocks_count = %" PRIu64"\n",
  882. saved_stats.free_blocks_count);
  883. printf("\tblock_size = %" PRIu32"\n",
  884. saved_stats.block_size);
  885. printf("\tblock_group_count = %" PRIu32"\n",
  886. saved_stats.block_group_count);
  887. printf("\tblocks_per_group = %" PRIu32"\n",
  888. saved_stats.blocks_per_group);
  889. printf("\tinodes_per_group = %" PRIu32"\n",
  890. saved_stats.inodes_per_group);
  891. printf("\tvolume_name = %s\n", saved_stats.volume_name);
  892. printf("\tactual_stats:\n");
  893. printf("\tinodes_count = %" PRIu32"\n",
  894. actual_stats.inodes_count);
  895. printf("\tfree_inodes_count = %" PRIu32"\n",
  896. actual_stats.free_inodes_count);
  897. printf("\tblocks_count = %" PRIu64"\n",
  898. actual_stats.blocks_count);
  899. printf("\tfree_blocks_count = %" PRIu64"\n",
  900. actual_stats.free_blocks_count);
  901. printf("\tblock_size = %d\n", actual_stats.block_size);
  902. printf("\tblock_group_count = %" PRIu32"\n",
  903. actual_stats.block_group_count);
  904. printf("\tblocks_per_group = %" PRIu32"\n",
  905. actual_stats.blocks_per_group);
  906. printf("\tinodes_per_group = %" PRIu32"\n",
  907. actual_stats.inodes_per_group);
  908. printf("\tvolume_name = %s\n",
  909. actual_stats.volume_name);
  910. }
  911. return -1;
  912. }
  913. return rc;
  914. }
  915. static char *entry_to_str(uint8_t type)
  916. {
  917. switch (type) {
  918. case EXT4_DE_UNKNOWN:
  919. return "[unk] ";
  920. case EXT4_DE_REG_FILE:
  921. return "[fil] ";
  922. case EXT4_DE_DIR:
  923. return "[dir] ";
  924. case EXT4_DE_CHRDEV:
  925. return "[cha] ";
  926. case EXT4_DE_BLKDEV:
  927. return "[blk] ";
  928. case EXT4_DE_FIFO:
  929. return "[fif] ";
  930. case EXT4_DE_SOCK:
  931. return "[soc] ";
  932. case EXT4_DE_SYMLINK:
  933. return "[sym] ";
  934. default:
  935. break;
  936. }
  937. return "[???]";
  938. }
  939. static int winsock_init(void)
  940. {
  941. #if WIN32
  942. int rc;
  943. static WSADATA wsaData;
  944. rc = WSAStartup(MAKEWORD(2, 2), &wsaData);
  945. if (rc != 0) {
  946. return -1;
  947. }
  948. #endif
  949. return 0;
  950. }
  951. static void winsock_fini(void)
  952. {
  953. #if WIN32
  954. WSACleanup();
  955. #endif
  956. }