Mirror of CollapseOS
25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

151 satır
3.7KB

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <dirent.h>
  5. #include <string.h>
  6. #include <fnmatch.h>
  7. #include <libgen.h>
  8. #include <sys/stat.h>
  9. #include "cfs.h"
  10. #define PUTC(c) putc(c, spitstream)
  11. static FILE *spitstream = stdout;
  12. void set_spit_stream(FILE *stream)
  13. {
  14. spitstream = stream;
  15. }
  16. int is_regular_file(char *path)
  17. {
  18. struct stat path_stat;
  19. stat(path, &path_stat);
  20. return S_ISREG(path_stat.st_mode);
  21. }
  22. void spitempty()
  23. {
  24. PUTC('C');
  25. PUTC('F');
  26. PUTC('S');
  27. for (int i=0; i<0x20-3; i++) {
  28. PUTC(0);
  29. }
  30. }
  31. int spitblock(char *fullpath, char *fn)
  32. {
  33. FILE *fp = fopen(fullpath, "r");
  34. fseek(fp, 0, SEEK_END);
  35. long fsize = ftell(fp);
  36. if (fsize > MAX_FILE_SIZE) {
  37. fclose(fp);
  38. fprintf(stderr, "File too big: %s %ld\n", fullpath, fsize);
  39. return 1;
  40. }
  41. /* Compute block count.
  42. * We always have at least one, which contains 0x100 bytes - 0x20, which is
  43. * metadata. The rest of the blocks have a steady 0x100.
  44. */
  45. unsigned char blockcount = 1;
  46. int fsize2 = fsize - (BLKSIZE - HEADERSIZE);
  47. if (fsize2 > 0) {
  48. blockcount += (fsize2 / BLKSIZE);
  49. }
  50. if (blockcount * BLKSIZE < fsize + HEADERSIZE) {
  51. blockcount++;
  52. }
  53. PUTC('C');
  54. PUTC('F');
  55. PUTC('S');
  56. PUTC(blockcount);
  57. // file size is little endian
  58. PUTC(fsize & 0xff);
  59. PUTC((fsize >> 8) & 0xff);
  60. int fnlen = strlen(fn);
  61. for (int i=0; i<MAX_FN_LEN; i++) {
  62. if (i < fnlen) {
  63. PUTC(fn[i]);
  64. } else {
  65. PUTC(0);
  66. }
  67. }
  68. // And the last FN char which is always null
  69. PUTC(0);
  70. char buf[MAX_FILE_SIZE] = {0};
  71. rewind(fp);
  72. fread(buf, fsize, 1, fp);
  73. fclose(fp);
  74. fwrite(buf, (blockcount * BLKSIZE) - HEADERSIZE, 1, spitstream);
  75. fflush(spitstream);
  76. return 0;
  77. }
  78. int spitdir(char *path, char *prefix, char **patterns)
  79. {
  80. DIR *dp;
  81. struct dirent *ep;
  82. int prefixlen = strlen(prefix);
  83. dp = opendir(path);
  84. if (dp == NULL) {
  85. fprintf(stderr, "Couldn't open directory.\n");
  86. return 1;
  87. }
  88. while ((ep = readdir(dp))) {
  89. if ((strcmp(ep->d_name, ".") == 0) || strcmp(ep->d_name, "..") == 0) {
  90. continue;
  91. }
  92. if (ep->d_type != DT_DIR && ep->d_type != DT_REG) {
  93. fprintf(stderr, "Only regular file or directories are supported\n");
  94. return 1;
  95. }
  96. int slen = strlen(ep->d_name);
  97. if (prefixlen + slen> MAX_FN_LEN) {
  98. fprintf(stderr, "Filename too long: %s/%s\n", prefix, ep->d_name);
  99. return 1;
  100. }
  101. char fullpath[0x1000];
  102. strcpy(fullpath, path);
  103. strcat(fullpath, "/");
  104. strcat(fullpath, ep->d_name);
  105. char newprefix[MAX_FN_LEN];
  106. strcpy(newprefix, prefix);
  107. if (prefixlen > 0) {
  108. strcat(newprefix, "/");
  109. }
  110. strcat(newprefix, ep->d_name);
  111. if (ep->d_type == DT_DIR) {
  112. int r = spitdir(fullpath, newprefix, patterns);
  113. if (r != 0) {
  114. return r;
  115. }
  116. } else {
  117. char **p = patterns;
  118. // if we have no pattern, we match all
  119. if (p && *p) {
  120. int matches = 0;
  121. while (*p) {
  122. if (fnmatch(*p, ep->d_name, 0) == 0) {
  123. matches = 1;
  124. break;
  125. }
  126. p++;
  127. }
  128. if (!matches) {
  129. continue;
  130. }
  131. }
  132. int r = spitblock(fullpath, newprefix);
  133. if (r != 0) {
  134. return r;
  135. }
  136. }
  137. }
  138. closedir(dp);
  139. return 0;
  140. }