950
|
1 /*****************************************************************************/
|
|
2 /* parse-dir-listing.c - contains functions for parsing the different types */
|
|
3 /* of directory listings. */
|
|
4 /* Copyright (C) 1998-2008 Brian Masney <masneyb@gftp.org> */
|
|
5 /* */
|
|
6 /* This program is free software; you can redistribute it and/or modify */
|
|
7 /* it under the terms of the GNU General Public License as published by */
|
|
8 /* the Free Software Foundation; either version 2 of the License, or */
|
|
9 /* (at your option) any later version. */
|
|
10 /* */
|
|
11 /* This program is distributed in the hope that it will be useful, */
|
|
12 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
|
13 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
|
14 /* GNU General Public License for more details. */
|
|
15 /* */
|
|
16 /* You should have received a copy of the GNU General Public License */
|
|
17 /* along with this program; if not, write to the Free Software */
|
|
18 /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA */
|
|
19 /*****************************************************************************/
|
|
20
|
|
21 #include "gftp.h"
|
|
22 static const char cvsid[] = "$Id: protocols.c 952 2008-01-24 23:31:26Z masneyb $";
|
|
23
|
|
24 static char *
|
|
25 copy_token (/*@out@*/ char **dest, char *source)
|
|
26 {
|
|
27 char *endpos, savepos;
|
|
28
|
|
29 endpos = source;
|
|
30 while (*endpos != ' ' && *endpos != '\t' && *endpos != '\0')
|
|
31 endpos++;
|
|
32 if (*endpos == '\0')
|
|
33 {
|
|
34 *dest = NULL;
|
|
35 return (NULL);
|
|
36 }
|
|
37
|
|
38 savepos = *endpos;
|
|
39 *endpos = '\0';
|
|
40 *dest = g_malloc0 ((gulong) (endpos - source + 1));
|
|
41 strcpy (*dest, source);
|
|
42 *endpos = savepos;
|
|
43
|
|
44 /* Skip the blanks till we get to the next entry */
|
|
45 source = endpos + 1;
|
|
46 while ((*source == ' ' || *source == '\t') && *source != '\0')
|
|
47 source++;
|
|
48 return (source);
|
|
49 }
|
|
50
|
|
51
|
|
52 static char *
|
|
53 goto_next_token (char *pos)
|
|
54 {
|
|
55 while (*pos != ' ' && *pos != '\t' && *pos != '\0')
|
|
56 pos++;
|
|
57
|
|
58 while (*pos == ' ' || *pos == '\t')
|
|
59 pos++;
|
|
60
|
|
61 return (pos);
|
|
62 }
|
|
63
|
|
64
|
|
65 static time_t
|
|
66 parse_vms_time (char *str, char **endpos)
|
|
67 {
|
|
68 struct tm curtime;
|
|
69 time_t ret;
|
|
70
|
|
71 /* 8-JUN-2004 13:04:14 */
|
|
72 memset (&curtime, 0, sizeof (curtime));
|
|
73
|
|
74 *endpos = strptime (str, "%d-%b-%Y %H:%M:%S", &curtime);
|
|
75 if (*endpos == NULL)
|
|
76 *endpos = strptime (str, "%d-%b-%Y %H:%M", &curtime);
|
|
77
|
|
78 if (*endpos != NULL)
|
|
79 {
|
|
80 ret = mktime (&curtime);
|
|
81 for (; **endpos == ' ' || **endpos == '\t'; (*endpos)++);
|
|
82 }
|
|
83 else
|
|
84 {
|
|
85 ret = 0;
|
|
86 *endpos = goto_next_token (str);
|
|
87 if (*endpos != NULL)
|
|
88 *endpos = goto_next_token (*endpos);
|
|
89 }
|
|
90
|
|
91 return (ret);
|
|
92 }
|
|
93
|
|
94
|
|
95 time_t
|
|
96 parse_time (char *str, char **endpos)
|
|
97 {
|
|
98 struct tm curtime, *loctime;
|
|
99 time_t t, ret;
|
|
100 char *tmppos;
|
|
101 size_t slen;
|
|
102 int i, num;
|
|
103
|
|
104 slen = strlen (str);
|
|
105 memset (&curtime, 0, sizeof (curtime));
|
|
106 curtime.tm_isdst = -1;
|
|
107
|
|
108 if (slen > 4 && isdigit ((int) str[0]) && str[2] == '-' &&
|
|
109 isdigit ((int) str[3]))
|
|
110 {
|
|
111 /* This is how DOS will return the date/time */
|
|
112 /* 07-06-99 12:57PM */
|
|
113
|
|
114 tmppos = strptime (str, "%m-%d-%y %I:%M%p", &curtime);
|
|
115 }
|
|
116 else if (slen > 4 && isdigit ((int) str[0]) && str[2] == '-' &&
|
|
117 isalpha (str[3]))
|
|
118 {
|
|
119 /* 10-Jan-2003 09:14 */
|
|
120 tmppos = strptime (str, "%d-%h-%Y %H:%M", &curtime);
|
|
121 }
|
|
122 else if (slen > 4 && isdigit ((int) str[0]) && str[4] == '/')
|
|
123 {
|
|
124 /* 2003/12/25 */
|
|
125 tmppos = strptime (str, "%Y/%m/%d", &curtime);
|
|
126 }
|
|
127 else
|
|
128 {
|
|
129 /* This is how most UNIX, Novell, and MacOS ftp servers send their time */
|
|
130 /* Jul 06 12:57 or Jul 6 1999 */
|
|
131
|
|
132 if (strchr (str, ':') != NULL)
|
|
133 {
|
|
134 tmppos = strptime (str, "%h %d %H:%M", &curtime);
|
|
135 t = time (NULL);
|
|
136 loctime = localtime (&t);
|
|
137
|
|
138 if (curtime.tm_mon > loctime->tm_mon)
|
|
139 curtime.tm_year = loctime->tm_year - 1;
|
|
140 else
|
|
141 curtime.tm_year = loctime->tm_year;
|
|
142 }
|
|
143 else
|
|
144 tmppos = strptime (str, "%h %d %Y", &curtime);
|
|
145 }
|
|
146
|
|
147 if (tmppos != NULL)
|
|
148 ret = mktime (&curtime);
|
|
149 else
|
|
150 ret = 0;
|
|
151
|
|
152 if (endpos != NULL)
|
|
153 {
|
|
154 if (tmppos == NULL)
|
|
155 {
|
|
156 /* We cannot parse this date format. So, just skip this date field
|
|
157 and continue to the next token. This is mainly for the HTTP
|
|
158 support */
|
|
159
|
|
160 *endpos = str;
|
|
161 for (num = 0; num < 2 && **endpos != '\0'; num++)
|
|
162 {
|
|
163 for (i=0;
|
|
164 (*endpos)[i] != ' ' && (*endpos)[i] != '\t' &&
|
|
165 (*endpos)[i] != '\0';
|
|
166 i++);
|
|
167 *endpos += i;
|
|
168
|
|
169 for (i=0; (*endpos)[i] == ' ' || (*endpos)[i] == '\t'; i++);
|
|
170 *endpos += i;
|
|
171 }
|
|
172 }
|
|
173 else
|
|
174 *endpos = tmppos;
|
|
175 }
|
|
176
|
|
177 return (ret);
|
|
178 }
|
|
179
|
|
180
|
|
181 static mode_t
|
|
182 gftp_parse_vms_attribs (char **src, mode_t mask)
|
|
183 {
|
|
184 char *endpos;
|
|
185 mode_t ret;
|
|
186
|
|
187 if (*src == NULL)
|
|
188 return (0);
|
|
189
|
|
190 if ((endpos = strchr (*src, ',')) != NULL)
|
|
191 *endpos = '\0';
|
|
192
|
|
193 ret = 0;
|
|
194 if (strchr (*src, 'R') != NULL)
|
|
195 ret |= S_IRUSR | S_IRGRP | S_IROTH;
|
|
196 if (strchr (*src, 'W') != NULL)
|
|
197 ret |= S_IWUSR | S_IWGRP | S_IWOTH;
|
|
198 if (strchr (*src, 'E') != NULL)
|
|
199 ret |= S_IXUSR | S_IXGRP | S_IXOTH;
|
|
200
|
|
201 *src = endpos + 1;
|
|
202
|
|
203 return (ret & mask);
|
|
204 }
|
|
205
|
|
206
|
|
207 static int
|
|
208 gftp_parse_ls_vms (gftp_request * request, int fd, char *str, gftp_file * fle)
|
|
209 {
|
|
210 char *curpos, *endpos, tempstr[1024];
|
|
211 int multiline;
|
|
212 ssize_t len;
|
|
213
|
|
214 /* .PINE-DEBUG1;1 9 21-AUG-2002 20:06 [MYERSRG] (RWED,RWED,,) */
|
|
215 /* WWW.DIR;1 1 23-NOV-1999 05:47 [MYERSRG] (RWE,RWE,RE,E) */
|
|
216
|
|
217 /* Multiline VMS
|
|
218 $MAIN.TPU$JOURNAL;1
|
|
219 1/18 8-JUN-2004 13:04:14 [NUCLEAR,FISSION] (RWED,RWED,RE,)
|
|
220 TCPIP$FTP_SERVER.LOG;29
|
|
221 0/18 8-JUN-2004 14:42:04 [NUCLEAR,FISSION] (RWED,RWED,RE,)
|
|
222 TCPIP$FTP_SERVER.LOG;28
|
|
223 5/18 8-JUN-2004 13:05:11 [NUCLEAR,FISSION] (RWED,RWED,RE,)
|
|
224 TCPIP$FTP_SERVER.LOG;27
|
|
225 5/18 8-JUN-2004 13:03:51 [NUCLEAR,FISSION] (RWED,RWED,RE,) */
|
|
226
|
|
227 if ((curpos = strchr (str, ';')) == NULL)
|
|
228 return (GFTP_EFATAL);
|
|
229
|
|
230 multiline = strchr (str, ' ') == NULL;
|
|
231
|
|
232 *curpos = '\0';
|
|
233 if (strlen (str) > 4 && strcmp (curpos - 4, ".DIR") == 0)
|
|
234 {
|
|
235 fle->st_mode |= S_IFDIR;
|
|
236 *(curpos - 4) = '\0';
|
|
237 }
|
|
238
|
|
239 fle->file = g_strdup (str);
|
|
240
|
|
241 if (multiline)
|
|
242 {
|
|
243 if (request->get_next_dirlist_line == NULL)
|
|
244 return (GFTP_EFATAL);
|
|
245
|
|
246 len = request->get_next_dirlist_line (request, fd, tempstr,
|
|
247 sizeof (tempstr));
|
|
248 if (len <= 0)
|
|
249 return ((int) len);
|
|
250
|
|
251 for (curpos = tempstr; *curpos == ' ' || *curpos == '\t'; curpos++);
|
|
252 }
|
|
253 else
|
|
254 curpos = goto_next_token (curpos + 1);
|
|
255
|
|
256 fle->size = gftp_parse_file_size (curpos) * 512; /* Is this correct? */
|
|
257
|
|
258 curpos = goto_next_token (curpos);
|
|
259
|
|
260 fle->datetime = parse_vms_time (curpos, &curpos);
|
|
261
|
|
262 if (*curpos != '[')
|
|
263 return (GFTP_EFATAL);
|
|
264
|
|
265 if ((endpos = strchr (curpos, ']')) == NULL)
|
|
266 return (GFTP_EFATAL);
|
|
267
|
|
268 curpos = goto_next_token (endpos + 1);
|
|
269 if ((curpos = strchr (curpos, ',')) == NULL)
|
|
270 return (0);
|
|
271 curpos++;
|
|
272
|
|
273 fle->st_mode = gftp_parse_vms_attribs (&curpos, S_IRWXU);
|
|
274 fle->st_mode |= gftp_parse_vms_attribs (&curpos, S_IRWXG);
|
|
275 fle->st_mode |= gftp_parse_vms_attribs (&curpos, S_IRWXO);
|
|
276
|
|
277 fle->user = g_strdup ("");
|
|
278 fle->group = g_strdup ("");
|
|
279
|
|
280 return (0);
|
|
281 }
|
|
282
|
|
283
|
|
284 static int
|
|
285 gftp_parse_ls_mvs (char *str, gftp_file * fle)
|
|
286 {
|
|
287 char *curpos;
|
|
288
|
|
289 /* Volume Unit Referred Ext Used Recfm Lrecl BlkSz Dsorg Dsname */
|
|
290 /* SVI52A 3390 2003/12/10 8 216 FB 80 27920 PS CARDS.DELETES */
|
|
291 /* SVI528 3390 2003/12/12 1 5 FB 80 24000 PO CLIST */
|
|
292
|
|
293 curpos = goto_next_token (str + 1);
|
|
294 if (curpos == NULL)
|
|
295 return (GFTP_EFATAL);
|
|
296
|
|
297 curpos = goto_next_token (curpos + 1);
|
|
298 if (curpos == NULL)
|
|
299 return (GFTP_EFATAL);
|
|
300
|
|
301 fle->datetime = parse_time (curpos, &curpos);
|
|
302
|
|
303 curpos = goto_next_token (curpos);
|
|
304 if (curpos == NULL)
|
|
305 return (GFTP_EFATAL);
|
|
306
|
|
307 curpos = goto_next_token (curpos + 1);
|
|
308 if (curpos == NULL)
|
|
309 return (GFTP_EFATAL);
|
|
310
|
|
311 fle->size = gftp_parse_file_size (curpos) * 55996;
|
|
312 curpos = goto_next_token (curpos + 1);
|
|
313 if (curpos == NULL)
|
|
314 return (GFTP_EFATAL);
|
|
315
|
|
316 curpos = goto_next_token (curpos + 1);
|
|
317 if (curpos == NULL)
|
|
318 return (GFTP_EFATAL);
|
|
319
|
|
320 curpos = goto_next_token (curpos + 1);
|
|
321 if (curpos == NULL)
|
|
322 return (GFTP_EFATAL);
|
|
323
|
|
324 curpos = goto_next_token (curpos + 1);
|
|
325 if (curpos == NULL)
|
|
326 return (GFTP_EFATAL);
|
|
327
|
|
328 if (strncmp (curpos, "PS", 2) == 0)
|
|
329 fle->st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
|
|
330 else if (strncmp (curpos, "PO", 2) == 0)
|
|
331 fle->st_mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
|
|
332 else
|
|
333 return (GFTP_EFATAL);
|
|
334
|
|
335 curpos = goto_next_token (curpos + 1);
|
|
336
|
|
337 fle->user = g_strdup (_("unknown"));
|
|
338 fle->group = g_strdup (_("unknown"));
|
|
339 fle->file = g_strdup (curpos);
|
|
340
|
|
341 return (0);
|
|
342 }
|
|
343
|
|
344
|
|
345 static int
|
|
346 gftp_parse_ls_eplf (char *str, gftp_file * fle)
|
|
347 {
|
|
348 char *startpos;
|
|
349 int isdir = 0;
|
|
350
|
|
351 startpos = str;
|
|
352 while (startpos)
|
|
353 {
|
|
354 startpos++;
|
|
355 switch (*startpos)
|
|
356 {
|
|
357 case '/':
|
|
358 isdir = 1;
|
|
359 break;
|
|
360 case 's':
|
|
361 fle->size = gftp_parse_file_size (startpos + 1);
|
|
362 break;
|
|
363 case 'm':
|
|
364 fle->datetime = strtol (startpos + 1, NULL, 10);
|
|
365 break;
|
|
366 }
|
|
367 startpos = strchr (startpos, ',');
|
|
368 }
|
|
369
|
|
370 if ((startpos = strchr (str, 9)) == NULL)
|
|
371 return (GFTP_EFATAL);
|
|
372
|
|
373 if (isdir)
|
|
374 fle->st_mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
|
|
375 else
|
|
376 fle->st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
|
|
377
|
|
378 fle->file = g_strdup (startpos + 1);
|
|
379 fle->user = g_strdup (_("unknown"));
|
|
380 fle->group = g_strdup (_("unknown"));
|
|
381 return (0);
|
|
382 }
|
|
383
|
|
384
|
|
385 static int
|
|
386 gftp_parse_ls_unix (gftp_request * request, char *str, size_t slen,
|
|
387 gftp_file * fle)
|
|
388 {
|
|
389 char *endpos, *startpos, *pos, *attribs;
|
|
390 int cols;
|
|
391
|
|
392 /* If there is no space between the attribs and links field, just make one */
|
|
393 if (slen > 10)
|
|
394 str[10] = ' ';
|
|
395
|
|
396 /* Determine the number of columns */
|
|
397 cols = 0;
|
|
398 pos = str;
|
|
399 while (*pos != '\0')
|
|
400 {
|
|
401 while (*pos != '\0' && *pos != ' ' && *pos != '\t')
|
|
402 {
|
|
403 if (*pos == ':')
|
|
404 break;
|
|
405 pos++;
|
|
406 }
|
|
407
|
|
408 cols++;
|
|
409
|
|
410 if (*pos == ':')
|
|
411 {
|
|
412 cols++;
|
|
413 break;
|
|
414 }
|
|
415
|
|
416 while (*pos == ' ' || *pos == '\t')
|
|
417 pos++;
|
|
418 }
|
|
419
|
|
420 startpos = str;
|
|
421 /* Copy file attributes */
|
|
422 if ((startpos = copy_token (&attribs, startpos)) == NULL)
|
|
423 return (GFTP_EFATAL);
|
|
424
|
|
425 if (strlen (attribs) < 10)
|
|
426 return (GFTP_EFATAL);
|
|
427
|
|
428 fle->st_mode = gftp_convert_attributes_to_mode_t (attribs);
|
|
429 g_free (attribs);
|
|
430
|
|
431 if (cols >= 9)
|
|
432 {
|
|
433 /* Skip the number of links */
|
|
434 startpos = goto_next_token (startpos);
|
|
435
|
|
436 /* Copy the user that owns this file */
|
|
437 if ((startpos = copy_token (&fle->user, startpos)) == NULL)
|
|
438 return (GFTP_EFATAL);
|
|
439
|
|
440 /* Copy the group that owns this file */
|
|
441 if ((startpos = copy_token (&fle->group, startpos)) == NULL)
|
|
442 return (GFTP_EFATAL);
|
|
443 }
|
|
444 else
|
|
445 {
|
|
446 fle->group = g_strdup (_("unknown"));
|
|
447 if (cols == 8)
|
|
448 {
|
|
449 if ((startpos = copy_token (&fle->user, startpos)) == NULL)
|
|
450 return (GFTP_EFATAL);
|
|
451 }
|
|
452 else
|
|
453 fle->user = g_strdup (_("unknown"));
|
|
454 startpos = goto_next_token (startpos);
|
|
455 }
|
|
456
|
|
457 if (request->server_type == GFTP_DIRTYPE_CRAY)
|
|
458 {
|
|
459 /* See if this is a Cray directory listing. It has the following format:
|
|
460 drwx------ 2 feiliu g913 DK common 4096 Sep 24 2001 wv */
|
|
461 if (cols == 11 && strstr (str, "->") == NULL)
|
|
462 {
|
|
463 startpos = goto_next_token (startpos);
|
|
464 startpos = goto_next_token (startpos);
|
|
465 }
|
|
466 }
|
|
467
|
|
468 /* See if this is a block or character device. We will store the major number
|
|
469 in the high word and the minor number in the low word. */
|
|
470 if (GFTP_IS_SPECIAL_DEVICE (fle->st_mode) &&
|
|
471 (endpos = strchr (startpos, ',')) != NULL)
|
|
472 {
|
|
473 fle->size = (unsigned long) strtol (startpos, NULL, 10) << 16;
|
|
474
|
|
475 startpos = endpos + 1;
|
|
476 while (*startpos == ' ')
|
|
477 startpos++;
|
|
478
|
|
479 /* Get the minor number */
|
|
480 if ((endpos = strchr (startpos, ' ')) == NULL)
|
|
481 return (GFTP_EFATAL);
|
|
482 fle->size |= strtol (startpos, NULL, 10) & 0xFF;
|
|
483 }
|
|
484 else
|
|
485 {
|
|
486 /* This is a regular file */
|
|
487 if ((endpos = strchr (startpos, ' ')) == NULL)
|
|
488 return (GFTP_EFATAL);
|
|
489 fle->size = gftp_parse_file_size (startpos);
|
|
490 }
|
|
491
|
|
492 /* Skip the blanks till we get to the next entry */
|
|
493 startpos = endpos + 1;
|
|
494 while (*startpos == ' ')
|
|
495 startpos++;
|
|
496
|
|
497 fle->datetime = parse_time (startpos, &startpos);
|
|
498
|
|
499 /* Skip the blanks till we get to the next entry */
|
|
500 startpos = goto_next_token (startpos);
|
|
501
|
|
502 /* Parse the filename. If this file is a symbolic link, remove the -> part */
|
|
503 if (S_ISLNK (fle->st_mode) && ((endpos = strstr (startpos, "->")) != NULL))
|
|
504 *(endpos - 1) = '\0';
|
|
505
|
|
506 fle->file = g_strdup (startpos);
|
|
507
|
|
508 /* Uncomment this if you want to strip the spaces off of the end of the file.
|
|
509 I don't want to do this by default since there are valid filenames with
|
|
510 spaces at the end of them. Some broken FTP servers like the Paradyne IPC
|
|
511 DSLAMS append a bunch of spaces at the end of the file.
|
|
512 for (endpos = fle->file + strlen (fle->file) - 1;
|
|
513 *endpos == ' ';
|
|
514 *endpos-- = '\0');
|
|
515 */
|
|
516
|
|
517 return (0);
|
|
518 }
|
|
519
|
|
520
|
|
521 static int
|
|
522 gftp_parse_ls_nt (char *str, gftp_file * fle)
|
|
523 {
|
|
524 char *startpos;
|
|
525
|
|
526 startpos = str;
|
|
527 fle->datetime = parse_time (startpos, &startpos);
|
|
528
|
|
529 fle->user = g_strdup (_("unknown"));
|
|
530 fle->group = g_strdup (_("unknown"));
|
|
531
|
|
532 startpos = goto_next_token (startpos);
|
|
533
|
|
534 if (startpos[0] == '<')
|
|
535 fle->st_mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
|
|
536 else
|
|
537 {
|
|
538 fle->st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
|
|
539 fle->size = gftp_parse_file_size (startpos);
|
|
540 }
|
|
541
|
|
542 startpos = goto_next_token (startpos);
|
|
543 fle->file = g_strdup (startpos);
|
|
544 return (0);
|
|
545 }
|
|
546
|
|
547
|
|
548 static int
|
|
549 gftp_parse_ls_novell (char *str, gftp_file * fle)
|
|
550 {
|
|
551 char *startpos;
|
|
552
|
|
553 if (str[12] != ' ')
|
|
554 return (GFTP_EFATAL);
|
|
555
|
|
556 str[12] = '\0';
|
|
557 fle->st_mode = gftp_convert_attributes_to_mode_t (str);
|
|
558 startpos = str + 13;
|
|
559
|
|
560 while ((*startpos == ' ' || *startpos == '\t') && *startpos != '\0')
|
|
561 startpos++;
|
|
562
|
|
563 if ((startpos = copy_token (&fle->user, startpos)) == NULL)
|
|
564 return (GFTP_EFATAL);
|
|
565
|
|
566 fle->group = g_strdup (_("unknown"));
|
|
567
|
|
568 while (*startpos != '\0' && !isdigit (*startpos))
|
|
569 startpos++;
|
|
570
|
|
571 fle->size = gftp_parse_file_size (startpos);
|
|
572
|
|
573 startpos = goto_next_token (startpos);
|
|
574 fle->datetime = parse_time (startpos, &startpos);
|
|
575
|
|
576 startpos = goto_next_token (startpos);
|
|
577 fle->file = g_strdup (startpos);
|
|
578 return (0);
|
|
579 }
|
|
580
|
|
581
|
|
582 int
|
|
583 gftp_parse_ls (gftp_request * request, const char *lsoutput, gftp_file * fle,
|
|
584 int fd)
|
|
585 {
|
|
586 char *str, *endpos, tmpchar;
|
|
587 int result, is_vms;
|
|
588 size_t len;
|
|
589
|
|
590 g_return_val_if_fail (lsoutput != NULL, GFTP_EFATAL);
|
|
591 g_return_val_if_fail (fle != NULL, GFTP_EFATAL);
|
|
592
|
|
593 str = g_strdup (lsoutput);
|
|
594 memset (fle, 0, sizeof (*fle));
|
|
595
|
|
596 len = strlen (str);
|
|
597 if (len > 0 && str[len - 1] == '\n')
|
|
598 str[--len] = '\0';
|
|
599 if (len > 0 && str[len - 1] == '\r')
|
|
600 str[--len] = '\0';
|
|
601
|
|
602 switch (request->server_type)
|
|
603 {
|
|
604 case GFTP_DIRTYPE_CRAY:
|
|
605 case GFTP_DIRTYPE_UNIX:
|
|
606 result = gftp_parse_ls_unix (request, str, len, fle);
|
|
607 break;
|
|
608 case GFTP_DIRTYPE_EPLF:
|
|
609 result = gftp_parse_ls_eplf (str, fle);
|
|
610 break;
|
|
611 case GFTP_DIRTYPE_NOVELL:
|
|
612 result = gftp_parse_ls_novell (str, fle);
|
|
613 break;
|
|
614 case GFTP_DIRTYPE_DOS:
|
|
615 result = gftp_parse_ls_nt (str, fle);
|
|
616 break;
|
|
617 case GFTP_DIRTYPE_VMS:
|
|
618 result = gftp_parse_ls_vms (request, fd, str, fle);
|
|
619 break;
|
|
620 case GFTP_DIRTYPE_MVS:
|
|
621 result = gftp_parse_ls_mvs (str, fle);
|
|
622 break;
|
|
623 default: /* autodetect */
|
|
624 if (*lsoutput == '+')
|
|
625 result = gftp_parse_ls_eplf (str, fle);
|
|
626 else if (isdigit ((int) str[0]) && str[2] == '-')
|
|
627 result = gftp_parse_ls_nt (str, fle);
|
|
628 else if (str[1] == ' ' && str[2] == '[')
|
|
629 result = gftp_parse_ls_novell (str, fle);
|
|
630 else
|
|
631 {
|
|
632 if ((endpos = strchr (str, ' ')) != NULL)
|
|
633 {
|
|
634 /* If the first token in the string has a ; in it, then */
|
|
635 /* we'll assume that this is a VMS directory listing */
|
|
636 tmpchar = *endpos;
|
|
637 *endpos = '\0';
|
|
638 is_vms = strchr (str, ';') != NULL;
|
|
639 *endpos = tmpchar;
|
|
640 }
|
|
641 else
|
|
642 is_vms = 0;
|
|
643
|
|
644 if (is_vms)
|
|
645 result = gftp_parse_ls_vms (request, fd, str, fle);
|
|
646 else
|
|
647 result = gftp_parse_ls_unix (request, str, len, fle);
|
|
648 }
|
|
649 break;
|
|
650 }
|
|
651 g_free (str);
|
|
652
|
|
653 return (result);
|
|
654 }
|
|
655
|