/* ** Copyright 2000-2004 University of Illinois Board of Trustees ** Copyright 2000-2004 Mark D. Roth ** All rights reserved. ** ** list_parse_eplf.c - EPLF-style FTP directory parsing code ** ** Mark D. Roth */ #include #include #include #include #include #include #ifdef STDC_HEADERS # include #endif /* ** parse EPLF directories ** ** EPLF format documented here: ** http://cr.yp.to/ftp/list/eplf.html */ int _ftp_list_parse_eplf(FTP *ftp, char *buf, file_info_t *fip) { char *fieldp, *nextp; unsigned long ul; unsigned int ui; #ifdef DEBUG printf("==> _ftp_list_parse_eplf(ftp=0x%lx (%s), buf=0x%lx, " "fip=0x%lx)\n", ftp, ftp->ftp_host, buf, fip); #endif /* skip leading '+' */ if (buf[0] != '+') { errno = EINVAL; return FLP_ERROR; } nextp = buf + 1; /* extract filename */ fieldp = strchr(nextp, '\t'); if (fieldp == NULL) { errno = EINVAL; return FLP_ERROR; } *fieldp++ = '\0'; strlcpy(fip->fi_filename, fieldp, sizeof(fip->fi_filename)); /* parse facts */ while ((fieldp = strsep(&nextp, ",")) != NULL) { if (*fieldp == '\0') continue; switch (*fieldp) { case 'r': /* RETR may succeed */ fip->fi_stat.fs_mode |= S_IFREG; continue; case '/': /* CWD may succeed */ fip->fi_stat.fs_mode |= S_IFDIR; continue; case 's': /* file size */ sscanf(fieldp + 1, "%lu", &ul); fip->fi_stat.fs_size = (off_t)ul; continue; case 'm': /* mtime */ sscanf(fieldp + 1, "%lu", &ul); fip->fi_stat.fs_mtime = (time_t)ul; continue; case 'u': /* "up" - file mode */ /* if it's not "up", treat as an unknown fact */ if (fieldp[1] != 'p') continue; sscanf(fieldp + 2, "%lo", &ui); fip->fi_stat.fs_mode |= (mode_t)ui; continue; default: /* unknown fact */ break; } /* otherwise, unknown fact, so just ignore it */ } /* EPLF doesn't encode these fields at all, so set defaults */ strlcpy(fip->fi_stat.fs_username, "-1", sizeof(fip->fi_stat.fs_username)); strlcpy(fip->fi_stat.fs_groupname, "-1", sizeof(fip->fi_stat.fs_groupname)); fip->fi_stat.fs_nlink = 1; #ifdef DEBUG printf("<== _ftp_list_parse_eplf(): success\n"); #endif return 0; }