ftpfs-ls.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. /*
  2. FTP file system
  3. Copyright (C) 2006 Robson Braga Araujo <robsonbraga@gmail.com>
  4. This program can be distributed under the terms of the GNU GPL.
  5. See the file COPYING.
  6. */
  7. #ifndef __FreeBSD__
  8. #define _XOPEN_SOURCE 600
  9. #else
  10. #define _XOPEN_SOURCE
  11. #endif
  12. #include <time.h>
  13. #include <string.h>
  14. #include <sys/types.h>
  15. #include <sys/stat.h>
  16. #include <unistd.h>
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <glib.h>
  20. #include "ftpfs.h"
  21. #include "charset_utils.h"
  22. #include "ftpfs-ls.h"
  23. static int parse_dir_unix(const char *line,
  24. struct stat *sbuf,
  25. char *file,
  26. char *link) {
  27. char mode[12];
  28. long nlink = 1;
  29. char user[33];
  30. char group[33];
  31. unsigned long long size;
  32. char month[4];
  33. char day[3];
  34. char year[6];
  35. char date[20];
  36. struct tm tm;
  37. time_t tt;
  38. int res;
  39. memset(file, 0, sizeof(char)*1024);
  40. memset(&tm, 0, sizeof(tm));
  41. memset(&tt, 0, sizeof(tt));
  42. #define SPACES "%*[ \t]"
  43. res = sscanf(line,
  44. "%11s"
  45. "%lu" SPACES
  46. "%32s" SPACES
  47. "%32s" SPACES
  48. "%llu" SPACES
  49. "%3s" SPACES
  50. "%2s" SPACES
  51. "%5s" "%*c"
  52. "%1023c",
  53. mode, &nlink, user, group, &size, month, day, year, file);
  54. if (res < 9) {
  55. res = sscanf(line,
  56. "%11s"
  57. "%32s" SPACES
  58. "%32s" SPACES
  59. "%llu" SPACES
  60. "%3s" SPACES
  61. "%2s" SPACES
  62. "%5s" "%*c"
  63. "%1023c",
  64. mode, user, group, &size, month, day, year, file);
  65. if (res < 8) {
  66. return 0;
  67. }
  68. }
  69. #undef SPACES
  70. char *link_marker = strstr(file, " -> ");
  71. if (link_marker) {
  72. strcpy(link, link_marker + 4);
  73. *link_marker = '\0';
  74. }
  75. int i = 0;
  76. if (mode[i] == 'd') {
  77. sbuf->st_mode |= S_IFDIR;
  78. } else if (mode[i] == 'l') {
  79. sbuf->st_mode |= S_IFLNK;
  80. } else {
  81. sbuf->st_mode |= S_IFREG;
  82. }
  83. for (i = 1; i < 10; ++i) {
  84. if (mode[i] != '-') {
  85. sbuf->st_mode |= 1 << (9 - i);
  86. }
  87. }
  88. sbuf->st_nlink = nlink;
  89. sbuf->st_size = size;
  90. if (ftpfs.blksize) {
  91. sbuf->st_blksize = ftpfs.blksize;
  92. sbuf->st_blocks =
  93. ((size + ftpfs.blksize - 1) & ~((unsigned long long) ftpfs.blksize - 1)) >> 9;
  94. }
  95. sprintf(date,"%s,%s,%s", year, month, day);
  96. tt = time(NULL);
  97. gmtime_r(&tt, &tm);
  98. tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
  99. if(strchr(year, ':')) {
  100. int cur_mon = tm.tm_mon; // save current month
  101. strptime(date, "%H:%M,%b,%d", &tm);
  102. // Unix systems omit the year for the last six months
  103. if (cur_mon + 5 < tm.tm_mon) { // month from last year
  104. DEBUG(2, "correct year: cur_mon: %d, file_mon: %d\n", cur_mon, tm.tm_mon);
  105. tm.tm_year--; // correct the year
  106. }
  107. } else {
  108. strptime(date, "%Y,%b,%d", &tm);
  109. }
  110. sbuf->st_atime = sbuf->st_ctime = sbuf->st_mtime = mktime(&tm);
  111. return 1;
  112. }
  113. static int parse_dir_win(const char *line,
  114. struct stat *sbuf,
  115. char *file,
  116. char *link) {
  117. char date[9];
  118. char hour[8];
  119. char size[33];
  120. struct tm tm;
  121. time_t tt;
  122. int res;
  123. (void)link;
  124. memset(file, 0, sizeof(char)*1024);
  125. memset(&tm, 0, sizeof(tm));
  126. memset(&tt, 0, sizeof(tt));
  127. res = sscanf(line, "%8s%*[ \t]%7s%*[ \t]%32s%*[ \t]%1023c",
  128. date, hour, size, file);
  129. if (res < 4) {
  130. return 0;
  131. }
  132. DEBUG(2, "date: %s hour: %s size: %s file: %s\n", date, hour, size, file);
  133. tt = time(NULL);
  134. gmtime_r(&tt, &tm);
  135. tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
  136. strptime(date, "%m-%d-%y", &tm);
  137. strptime(hour, "%I:%M%p", &tm);
  138. sbuf->st_atime = sbuf->st_ctime = sbuf->st_mtime = mktime(&tm);
  139. sbuf->st_nlink = 1;
  140. if (!strcmp(size, "<DIR>")) {
  141. sbuf->st_mode |= S_IFDIR;
  142. } else {
  143. unsigned long long nsize = strtoull(size, NULL, 0);
  144. sbuf->st_mode |= S_IFREG;
  145. sbuf->st_size = nsize;
  146. if (ftpfs.blksize) {
  147. sbuf->st_blksize = ftpfs.blksize;
  148. sbuf->st_blocks =
  149. ((nsize + ftpfs.blksize - 1) & ~((unsigned long long) ftpfs.blksize - 1)) >> 9;
  150. }
  151. }
  152. return 1;
  153. }
  154. static int parse_dir_netware(const char *line,
  155. struct stat *sbuf,
  156. char *file,
  157. char *link) {
  158. (void) line;
  159. (void) sbuf;
  160. (void) file;
  161. (void) link;
  162. return 0;
  163. }
  164. int parse_dir(const char* list, const char* dir,
  165. const char* name, struct stat* sbuf,
  166. char* linkbuf, int linklen,
  167. off_t h, fuse_fill_dir_t filler, void *fuse_buf) {
  168. (void) h;
  169. char *file;
  170. char *link;
  171. const char *start = list;
  172. const char *end = list;
  173. char found = 0;
  174. struct stat stat_buf;
  175. if (sbuf) memset(sbuf, 0, sizeof(struct stat));
  176. if (name && sbuf && name[0] == '\0') {
  177. sbuf->st_mode |= S_IFDIR;
  178. sbuf->st_mode |= 0755;
  179. sbuf->st_size = 1024;
  180. sbuf->st_nlink = 1;
  181. return 0;
  182. }
  183. file = (char *)malloc(1024*sizeof(char));
  184. link = (char *)malloc(1024*sizeof(char));
  185. while ((end = strchr(start, '\n')) != NULL) {
  186. char* line;
  187. memset(&stat_buf, 0, sizeof(stat_buf));
  188. if (end > start && *(end-1) == '\r') end--;
  189. line = (char*)malloc(end - start + 1);
  190. strncpy(line, start, end - start);
  191. line[end - start] = '\0';
  192. start = *end == '\r' ? end + 2 : end + 1;
  193. stat_buf.st_uid = getuid();
  194. stat_buf.st_gid = getgid();
  195. if (ftpfs.codepage) {
  196. convert_charsets(ftpfs.codepage, ftpfs.iocharset, &line);
  197. }
  198. file[0] = link[0] = '\0';
  199. int res = parse_dir_unix(line, &stat_buf, file, link) ||
  200. parse_dir_win(line, &stat_buf, file, link) ||
  201. parse_dir_netware(line, &stat_buf, file, link);
  202. if (res) {
  203. char *full_path = g_strdup_printf("%s%s", dir, file);
  204. if (link[0]) {
  205. char *reallink;
  206. if (link[0] == '/' && ftpfs.symlink_prefix_len) {
  207. reallink = g_strdup_printf("%s%s", ftpfs.symlink_prefix, link);
  208. } else {
  209. reallink = g_strdup(link);
  210. }
  211. int linksize = strlen(reallink);
  212. cache_add_link(full_path, reallink, linksize+1);
  213. DEBUG(1, "cache_add_link: %s %s\n", full_path, reallink);
  214. if (linkbuf && linklen) {
  215. if (linksize > linklen) linksize = linklen - 1;
  216. strncpy(linkbuf, reallink, linksize);
  217. linkbuf[linksize] = '\0';
  218. }
  219. free(reallink);
  220. }
  221. if (filler) {
  222. filler(fuse_buf, file, &stat_buf, 0, 0);
  223. }
  224. if (name && !strcmp(name, file)) {
  225. if (sbuf) *sbuf = stat_buf;
  226. found = 1;
  227. }
  228. free(full_path);
  229. }
  230. free(line);
  231. }
  232. free(file);
  233. free(link);
  234. return !found;
  235. }