static int rfile_parse_eplf(rfile *f, char *str, const char *dirpath) { char *e; if(!str || str[0] != '+') return -1; str++; f->perm = xstrdup("-rw-r--r--"); f->size = 0L; f->mtime = 0; f->link = 0; f->nhl = 0; f->owner = xstrdup("owner"); f->group = xstrdup("group"); f->date = xstrdup("Jan 0 1900"); f->path = 0; while((e = strqsep(&str, ',')) != 0) { switch(*e) { case '/': f->perm[0] = 'd'; break; case 'm': f->mtime = strtoul(e+1, 0, 10); free(f->date); f->date = time_to_string(f->mtime); break; case 's': f->size = strtoull(e+1, 0, 10); break; case '\t': if (asprintf(&f->path, "%s/%s", strcmp(dirpath, "/") ? dirpath : "", e+1) == -1) f->path = NULL; break; } } if (!f->path) return -1; rfile_parse_colors(f); return 0; }
void rfile_fake(rfile *f, const char *path) { ftp_trace("faking file '%s'\n", path); free(f->perm); f->perm = xstrdup("-rw-r-r-"); free(f->owner); f->owner = xstrdup("owner"); free(f->group); f->group = xstrdup("group"); free(f->link); f->link = 0; free(f->path); f->path = xstrdup(path); free(f->date); f->date = xstrdup("Jan 0 1900"); f->mtime = 0; f->nhl = 0; f->size = (unsigned long long)-1; rfile_parse_colors(f); }
rdirectory *ssh_read_directory(const char *path) { char *p = ftp_path_absolute(path); stripslash(p); sftp_dir dir = sftp_opendir(ftp->sftp_session, p); if (!dir) { free(p); return 0; } ftp_trace("*** start parsing directory listing ***\n"); rdirectory* rdir = rdir_create(); sftp_attributes attrib = NULL; while ((attrib = sftp_readdir(ftp->sftp_session, dir)) != NULL) { ftp_trace("%s\n", attrib->longname); rfile* rf = rfile_create(); rf->perm = perm2string(attrib->permissions); rf->nhl = 0; // atoi(e); if (attrib->owner) rf->owner = xstrdup(attrib->owner); if (attrib->group) rf->group = xstrdup(attrib->group); if (asprintf(&rf->path, "%s/%s", p, attrib->name) == -1) { ftp_err(_("Failed to allocate memory.\n")); sftp_closedir(dir); free(p); rdir_destroy(rdir); rfile_destroy(rf); } rf->mtime = attrib->mtime; rf->date = time_to_string(rf->mtime); rf->size = attrib->size; rfile_parse_colors(rf); rf->link = NULL; if (rislink(rf) && ftp->ssh_version > 2) rf->link = sftp_readlink(ftp->sftp_session, rf->path); list_additem(rdir->files, (void *)rf); sftp_attributes_free(attrib); } ftp_trace("*** end parsing directory listing ***\n"); if (!sftp_dir_eof(dir)) { ftp_err(_("Couldn't list directory: %s\n"), ssh_get_error(ftp->session)); sftp_closedir(dir); free(p); rdir_destroy(rdir); return NULL; } sftp_closedir(dir); rdir->path = p; ftp_trace("added directory '%s' to cache\n", p); list_additem(ftp->cache, rdir); return rdir; }
rdirectory *ssh_read_directory(const char *path) { rdirectory *rdir; int i; SFTP_DIRENT **dir; char *p = ftp_path_absolute(path); stripslash(p); if(ssh_readdir(p, &dir) != 0) { free(p); return 0; } rdir = rdir_create(); ftp_trace("*** start parsing directory listing ***\n"); for(i = 0; dir[i]; i++) { rfile *rf; char *e, *cf = dir[i]->longname; ftp_trace("%s\n", dir[i]->longname); rf = rfile_create(); rf->perm = perm2string(dir[i]->a.perm); e = strqsep(&cf, ' '); /* skip permissions */ e = strqsep(&cf, ' '); /* nhl? */ /* if(ftp->ssh_version > 2) {*/ rf->nhl = atoi(e); /* } else*/ /* rf->nhl = 0;*/ #if 1 e = strqsep(&cf, ' '); rf->owner = xstrdup(e); e = strqsep(&cf, ' '); rf->group = xstrdup(e); #else asprintf(&rf->owner, "%d", dir[i]->a.uid); asprintf(&rf->group, "%d", dir[i]->a.gid); #endif asprintf(&rf->path, "%s/%s", p, dir[i]->filename); rf->mtime = dir[i]->a.mtime; if(rf->mtime == 0) { char *m, *d, *y; while(e && month_number(e) == -1) e = strqsep(&cf, ' '); if(e) { m = e; d = strqsep(&cf, ' '); y = strqsep(&cf, ' '); ftp_trace("parsing time: m:%s d:%s y:%s\n", m, d, y); rfile_parse_time(rf, m, d, y); } } rf->date = time_to_string(rf->mtime); rf->size = dir[i]->a.size; rfile_parse_colors(rf); rf->link = 0; if(rislink(rf) && ftp->ssh_version > 2) rf->link = ssh_readlink(rf->path); list_additem(rdir->files, (void *)rf); } ftp_trace("*** end parsing directory listing ***\n"); ssh_free_dirents(dir); rdir->path = p; ftp_trace("added directory '%s' to cache\n", p); list_additem(ftp->cache, rdir); return rdir; }
static int rfile_parse_mlsd(rfile *f, char *str, const char *dirpath) { char *e; bool isdir = false; if(!str) return -1; e = strchr(str, ' '); if(e) { if (asprintf(&f->path, "%s/%s", strcmp(dirpath, "/") ? dirpath : "", base_name_ptr(e+1)) == -1) { f->path = NULL; return -1; } *e = 0; } else return -1; f->perm = 0; f->size = 0L; f->mtime = 0; f->link = 0; f->nhl = 0; f->owner = xstrdup("owner"); f->group = xstrdup("group"); f->date = xstrdup("Jan 0 1900"); while((e = strqsep(&str, ';')) != 0) { char *factname, *value; factname = strqsep(&e, '='); value = e; if(!factname || !value) { return -1; } if(strcasecmp(factname, "size") == 0 || strcasecmp(factname, "sizd") == 0) /* the "sizd" fact is not standardized in "Extension to * FTP" Internet draft, but PureFTPd uses it for some * reason for size of directories */ f->size = strtoull(value,NULL,10); else if(strcasecmp(factname, "type") == 0) { if(strcasecmp(value, "file") == 0) isdir = false; else if(strcasecmp(value, "dir") == 0 || strcasecmp(value, "cdir") == 0 || strcasecmp(value, "pdir") == 0) isdir = true; } else if(strcasecmp(factname, "modify") == 0) { struct tm ts; sscanf(value, "%04d%02d%02d%02d%02d%02d", &ts.tm_year, &ts.tm_mon, &ts.tm_mday, &ts.tm_hour, &ts.tm_min, &ts.tm_sec); ts.tm_year -= 1900; ts.tm_mon--; f->mtime = gmt_mktime(&ts); free(f->date); f->date = time_to_string(f->mtime); } else if(strcasecmp(factname, "UNIX.mode") == 0) { free(f->perm); f->perm = perm2string(strtoul(value, 0, 8)); } else if(strcasecmp(factname, "UNIX.gid") == 0) { free(f->group); f->group = xstrdup(value); } else if(strcasecmp(factname, "UNIX.uid") == 0) { free(f->owner); f->owner = xstrdup(value); } } if(!f->perm) f->perm = xstrdup("-rw-r--r--"); if(isdir) f->perm[0] = 'd'; rfile_parse_colors(f); return 0; }
static int rfile_parse_dos(rfile *f, char *str, const char *dirpath) { char *e, *cf = str; char ampm[3]="xx"; int m, d, y, h, mm; NEXT_FIELD; if(sscanf(e, "%d-%d-%d", &m, &d, &y) != 3) return -1; m--; if(y < 70) y += 100; NEXT_FIELD; if(sscanf(e, "%d:%2d%2s", &h, &mm, ampm) != 3) return -1; if(strcasecmp(ampm, "PM") == 0) h += 12; { struct tm mt; f->mtime = (time_t)-1; mt.tm_sec = 0; mt.tm_min = mm; mt.tm_hour = h; mt.tm_mday = d; mt.tm_mon = m; mt.tm_year = y; mt.tm_isdst = -1; f->mtime = mktime(&mt); } { time_t now; time(&now); bool success = true; if(f->mtime != (time_t)-1 && (now > f->mtime + 6L * 30L * 24L * 60L * 60L /* Old. */ || now < f->mtime - 60L * 60L)) /* In the future. */ { success = asprintf(&f->date, "%s %2d %5d", month_name[m], d, y + 1900) != -1; } else { success = asprintf(&f->date, "%s %2d %02d:%02d", month_name[m], d, h, mm) != -1; } if (!success) { f->date = NULL; return -1; } } f->perm = xstrdup("-rw-r--r--"); NEXT_FIELD; if(strcasecmp(e, "<DIR>") == 0) { f->perm[0] = 'd'; f->size = 0L; } else { f->size = strtoull(e,NULL,10); } f->nhl = 1; f->owner = xstrdup("owner"); f->group = xstrdup("group"); f->link = 0; while(cf && *cf == ' ') ++cf; if (asprintf(&f->path, "%s/%s", strcmp(dirpath, "/") ? dirpath : "", cf) == -1) { f->path = NULL; return -1; } rfile_parse_colors(f); return 0; }
/* This is a total mess! */ static int rfile_parse_unix(rfile *f, char *str, const char *dirpath) { char *cf; char *e; char *m=0, *d=0, *y=0; char *saved_field[5]; bool time_parsed = false; /* real unix ls listing: * * saved_field[0] == nhl * saved_field[1] == owner * saved_field[2] == group * saved_field[3] == size * saved_field[4] == month * * * unix w/o group listing: * * saved_field[0] == nhl * saved_field[1] == owner * saved_field[2] == size * saved_field[3] == month * saved_field[4] == date * * * strange MacOS WebStar thingy: * * saved_field[0] == size or "folder" * saved_field[1] == zero or date if [0]=="folder" * saved_field[2] == size (again!?) or month * saved_field[3] == month or date * saved_field[4] == date or time (or year?) * * * Linux netkit FTP server with LANG=sv_SE (ISO date&time format): * (-rw------- 1 mhe mhe 1422 2002-09-24 22:30 asdf.txt) * * saved_field[0] == nhl * saved_field[1] == owner * saved_field[2] == group * saved_field[3] == size * saved_field[4] == YYYY-MM-DD * */ if(strncmp(str, "total ", 6) == 0) return 1; if(strncmp(str, "insgesamt ", 10) == 0) // de "overall" return 1; cf = str; /* NEXT_FIELD; f->perm = xstrdup(e);*/ /* the above doesn't work here: * drwxrwxr-x156 31 20 29696 Apr 26 19:00 gnu * ----------^ * so we assume the permission string is exactly 10 characters */ f->perm = xstrndup(cf, 10); cf += 10; /* drwxr-s---+ 78 0 228 1536 Jul 10 15:36 private */ if(*cf == '+') ++cf; NEXT_FIELD; saved_field[0] = xstrdup(e); NEXT_FIELD; saved_field[1] = xstrdup(e); NEXT_FIELD; saved_field[2] = xstrdup(e); NEXT_FIELD; /* special device? */ if(e[strlen(e)-1] == ',') { NEXT_FIELD; } saved_field[3] = xstrdup(e); NEXT_FIELD; saved_field[4] = xstrdup(e); /* distinguish the different ls variants by looking * for the month field */ if(month_number(saved_field[4]) != -1) { /* ls -l */ f->nhl = atoi(saved_field[0]); free(saved_field[0]); f->owner = saved_field[1]; f->group = saved_field[2]; f->size = strtoull(saved_field[3],NULL,10); free(saved_field[3]); m = saved_field[4]; NEXT_FIELD2; d = xstrdup(e); NEXT_FIELD2; y = xstrdup(e); } else if(month_number(saved_field[3]) != -1) { /* ls -lG */ f->nhl = atoi(saved_field[0]); free(saved_field[0]); f->owner = saved_field[1]; f->group = xstrdup("group"); f->size = strtoull(saved_field[2],NULL,10); free(saved_field[2]); m = saved_field[3]; d = saved_field[4]; NEXT_FIELD2; y = xstrdup(e); } else if(month_number(saved_field[2]) != -1) { free(saved_field[0]); f->nhl = 0; f->owner = xstrdup("owner");; f->group = xstrdup("group"); f->size = strtoull(saved_field[1],NULL,10); free(saved_field[1]); m = saved_field[2]; d = saved_field[3]; y = saved_field[4]; } else { int iy, im, id, ih = 0, imin = 0; if(sscanf(saved_field[4], "%d-%d-%d", &iy, &im, &id) == 3) { /* date on the form YYYY-MM-DD */ im -= 1; /* should be 0-based */ f->nhl = atoi(saved_field[0]); free(saved_field[0]); f->owner = saved_field[1]; f->group = saved_field[2]; f->size = strtoull(saved_field[3],NULL,10); free(saved_field[3]); free(saved_field[4]); e = strqsep(&cf, ' '); /* HH:MM */ sscanf(e, "%d:%d", &ih, &imin); { struct tm mt; time_t now; f->mtime = (time_t)-1; mt.tm_sec = 0; mt.tm_min = imin; mt.tm_hour = ih; mt.tm_mday = id; mt.tm_mon = im; mt.tm_year = iy; mt.tm_isdst = -1; f->mtime = mktime(&mt); time(&now); bool success = true; if(f->mtime != (time_t)-1 && (now > f->mtime + 6L * 30L * 24L * 60L * 60L /* Old. */ || now < f->mtime - 60L * 60L)) /* In the future. */ { success = asprintf(&f->date, "%s %2d %5d", month_name[im], id, iy) != -1; } else { success = asprintf(&f->date, "%s %2d %02d:%02d", month_name[im], id, ih, imin) != -1; } if (!success) { f->date = NULL; return -1; } time_parsed = true; } } else { free(saved_field[0]); free(saved_field[1]); free(saved_field[2]); free(saved_field[3]); free(saved_field[4]); return -1; } } if(!time_parsed) { if (asprintf(&f->date, "%s %2s %5s", m, d, y) == -1) { free(m); free(d); free(y); f->date = NULL; return -1; } rfile_parse_time(f, m, d, y); if(f->mtime == (time_t)-1) ftp_trace("rfile_parse_time failed! date == '%s'\n", f->date); free(m); free(d); free(y); } if(!cf) return -1; e = strstr(cf, " -> "); if(e) { *e = 0; f->link = xstrdup(e+4); } if (asprintf(&f->path, "%s/%s", strcmp(dirpath, "/") ? dirpath : "", cf) == -1) { f->path = NULL; return -1; } rfile_parse_colors(f); return 0; }