source: FTPfs/curlftpfs-0.9.1/ftpfs-ls.c @ 104

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