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; }
/* 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; }