📄 rfile.c
字号:
/* $Id: rfile.c,v 1.13 2005/10/05 19:32:47 splicednetworks Exp $ * * rfile.c -- representation of a remote file * * Yet Another FTP Client * Copyright (C) 1998-2001, Martin Hedenfalk <mhe@stacken.kth.se> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. See COPYING for more details. */#include "syshdr.h"#include "ftp.h"#include "strq.h"rfile *rfile_create(void){ rfile *f; f = (rfile *)xmalloc(sizeof(rfile)); return f;}rfile *rfile_clone(const rfile *f){ rfile *nf = rfile_create(); nf->perm = xstrdup(f->perm); nf->owner = xstrdup(f->owner); nf->group = xstrdup(f->group); nf->color = xstrdup(f->color); nf->date = xstrdup(f->date); nf->link = xstrdup(f->link); nf->path = xstrdup(f->path); nf->size = f->size; nf->nhl = f->nhl; nf->mtime = f->mtime; return nf;}void rfile_clear(rfile *f){ free(f->perm); free(f->owner); free(f->group); free(f->color); free(f->date); free(f->link); free(f->path); f->perm = f->owner = f->group = f->color = 0; f->date = f->link = f->path = 0; f->nhl = 0; f->size = 0L; f->mtime = (time_t)0;}void rfile_destroy(rfile *f){ if(!f) return; rfile_clear(f); free(f);}bool risdir(const rfile *f){ return (f->perm[0] == 'd');}bool risdotdir(const rfile *f){ return (risdir(f) && ((strcmp(base_name_ptr(f->path), ".") == 0 || strcmp(base_name_ptr(f->path), "..") == 0)));}bool risreg(const rfile *f){ return !(risdir(f) || rispipe(f) || rischardev(f) || risblockdev(f));}bool rispipe(const rfile *f){ return (f->perm[0] == 'p');}bool risexec(const rfile *f){ return (strchr(f->perm, 'x') != 0);}bool rissock(const rfile *f){ return (f->perm[0] == 's');}bool rischardev(const rfile *f){ return (f->perm[0] == 'c');}bool risblockdev(const rfile *f){ return (f->perm[0] == 'b');}bool rislink(const rfile *f){ return (f->perm[0] == 'l');}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);}char rfile_classchar(const rfile *f){ if(risdir(f)) return '/'; if(rislink(f)) return '@'; if(rissock(f)) return '='; if(rispipe(f)) return '|'; if(risexec(f)) return '*'; return 0;}mode_t str2mode_t(const char *p){ mode_t m = 0; p++; if(*p++=='r') m|=S_IRUSR; if(*p++=='w') m|=S_IWUSR; if(*p=='x') m|=S_IXUSR; else if(*p=='S') m|=S_ISUID; else if(*p=='s') m|=(S_ISUID|S_IXUSR); p++; if(*p++=='r') m|=S_IRGRP; if(*p++=='w') m|=S_IWGRP; if(*p=='x') m|=S_IXGRP; else if(*p=='S') m|=S_ISGID; else if(*p=='s') m|=(S_ISGID|S_IXGRP); p++; if(*p++=='r') m|=S_IROTH; if(*p++=='w') m|=S_IWOTH; if(*p=='x') m|=S_IXOTH; else if(*p=='T') m|=S_ISVTX; else if(*p=='t') m|=(S_ISVTX|S_IXOTH); return m;}mode_t rfile_getmode(const rfile *f){ if(!f || !f->perm) return (mode_t)-1; return str2mode_t(f->perm);}static const char *month_name[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};/* returns month number if STR is a month abbreviation * else -1 */int month_number(const char *str){ int i; for(i=0; i<12; i++) { if(strcasecmp(str, month_name[i]) == 0) return i; } return -1;}void rfile_parse_time(rfile *f, const char *m, const char *d, const char *y){ time_t now; struct tm *tm_now; struct tm mt; int u; f->mtime = (time_t)-1; if(!m || !d || !y) return; mt.tm_sec = 0; mt.tm_mday = atoi(d); mt.tm_mon = month_number(m); if(mt.tm_mon == -1) return; time(&now); tm_now = localtime(&now); mt.tm_isdst = tm_now->tm_isdst; if(strchr(y, ':') != 0) { /* date on form "MMM DD HH:MM" */ time_t tmp; char *eh, *em; u = strtoul(y, &eh, 10); if(eh == y) return; mt.tm_hour = u; u = strtoul(eh+1, &em, 10); if(em == eh+1) return; mt.tm_min = u; mt.tm_year = tm_now->tm_year; /* might be wrong year, +- 1 * filetime is not older than 6 months * or newer than 1 hour */ tmp = mktime(&mt); if(tmp > now + 60L*60L) mt.tm_year--; if(tmp < now - 6L*30L*24L*60L*60L) mt.tm_year++; } else { /* date on form "MMM DD YYYY" */ char *ey; u = strtoul(y, &ey, 10); if(ey == y) return; mt.tm_year = u - 1900; mt.tm_hour = 0; mt.tm_min = 0; } f->mtime = mktime(&mt);}#define NEXT_FIELD \e = strqsep(&cf, ' '); \if(!e || !*e) { \ return -1; \}#define NEXT_FIELD2 \e = strqsep(&cf, ' '); \if(!e || !*e) { \ free(m); \ free(d); \ free(y); \ return -1; \}char *time_to_string(time_t t){ char *ret; time_t now; char *fmt; now = time(0); if(now > t + 6L * 30L * 24L * 60L * 60L /* Old. */ || now < t - 60L * 60L) /* In the future. */ { /* The file is fairly old or in the future. POSIX says the cutoff is 6 months old; approximate this by 6*30 days. Allow a 1 hour slop factor for what is considered "the future", to allow for NFS server/client clock disagreement. Show the year instead of the time of day. */ fmt = "%b %e %Y"; } else fmt = "%b %e %H:%M"; ret = (char *)xmalloc(42); strftime(ret, 42, fmt, localtime(&t)); return ret;}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': asprintf(&f->path, "%s/%s", strcmp(dirpath, "/") ? dirpath : "", e+1); break; } } if(f->path == 0) 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; cf = str;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -