778 lines
18 KiB
C
778 lines
18 KiB
C
/*********************************************************************\
|
|
* Copyright (c) 1991 by Wen-King Su (wen-king@vlsi.cs.caltech.edu) *
|
|
* *
|
|
* You may copy or modify this file in any manner you wish, provided *
|
|
* that this notice is always included, and that you hold the author *
|
|
* harmless for any loss or damage resulting from the installation or *
|
|
* use of this software. *
|
|
\*********************************************************************/
|
|
|
|
#include "tweak.h"
|
|
#include "client_def.h"
|
|
#include "c_extern.h"
|
|
#ifdef STDC_HEADERS
|
|
#include <stdlib.h>
|
|
#endif
|
|
#include "my-string.h"
|
|
|
|
static int env_dir_malloced = 0;
|
|
const char *env_dir = "/";
|
|
const char *env_passwd = "\0";
|
|
const char *env_myport;
|
|
const char *env_host;
|
|
const char *env_port;
|
|
const char *env_local_dir;
|
|
const char *env_listen_on;
|
|
unsigned int env_timeout;
|
|
unsigned short client_buf_len;
|
|
unsigned short client_net_len;
|
|
int statworks=1;
|
|
|
|
#define TWOGIGS 0x7fffffffUL
|
|
#define FOURGIGS 0xffffffffUL
|
|
|
|
/* returns mallocated abs. path merged from s2 and env.dir */
|
|
#define APPEND_PASSWORD if(have_password) \
|
|
{ \
|
|
strcat(path,"\n"); \
|
|
strcat(path,env_passwd); \
|
|
}
|
|
char *util_abs_path (const char * s2)
|
|
{
|
|
char *path, *s, *d, *t;
|
|
int have_password = 0;
|
|
|
|
if(!env_dir) env_dir = "";
|
|
if(!s2) s2 = "";
|
|
if(strlen(env_passwd)>0)
|
|
have_password=1;
|
|
if(*s2 == '/') {
|
|
path = malloc(strlen(s2)+2+strlen(env_passwd)+1);
|
|
sprintf(path,"/%s",s2);
|
|
if(have_password)
|
|
util_junk_password(path);
|
|
} else {
|
|
path = malloc(strlen(env_dir)+strlen(s2)+3+strlen(env_passwd)+1);
|
|
sprintf(path,"/%s/%s",env_dir,s2);
|
|
if(have_password)
|
|
util_junk_password(path);
|
|
}
|
|
|
|
for(t = path; *t; ) {
|
|
if(t[0] == '/') {
|
|
while(t[1] == '/') for(d = t, (s = t+1); (*d++ = *s++); );
|
|
if(t != path && t[1] == 0) { t[0] = 0; return(path); }
|
|
}
|
|
if(t[0] == '.' && t[1] == '.') {
|
|
if(t-1 == path && t[2] == 0 ) {
|
|
*t = 0;
|
|
APPEND_PASSWORD;
|
|
return(path);
|
|
}
|
|
if(t-1 == path && t[2] == '/') {
|
|
for(d = t, s = t + 3; (*d++ = *s++); );
|
|
continue;
|
|
}
|
|
if(t[-1] == '/' && (t[2] == '/' || t[2] == 0)) {
|
|
s = t + 2; /* point to either slash or nul */
|
|
t -= 2; /* guaranteed that t >= path here */
|
|
while(t > path && t[0] != '/') t--;
|
|
if(t != path || *s == '/') for(d = t; (*d++ = *s++); );
|
|
else {
|
|
t[1] = 0;
|
|
APPEND_PASSWORD;
|
|
return(path);
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
if(t[0] == '.') {
|
|
if(t-1 == path && t[1] == 0 ) {
|
|
*t = 0;
|
|
APPEND_PASSWORD;
|
|
return(path);
|
|
}
|
|
if(t-1 == path && t[1] == '/') {
|
|
for(d = t, s = t + 2; (*d++ = *s++); );
|
|
continue;
|
|
}
|
|
if(t[-1] == '/' && (t[1] == '/' || t[1] == 0)) {
|
|
s = t + 1; /* point to either slash or nul */
|
|
for(d = t-1; (*d++ = *s++); );
|
|
t--;
|
|
continue;
|
|
}
|
|
}
|
|
t++;
|
|
}
|
|
APPEND_PASSWORD;
|
|
return(path);
|
|
}
|
|
|
|
static void util_pktstats(void)
|
|
{
|
|
fprintf(stderr,"Packets received: %lu total (%lu bad, %lu duplicate)\nPackets sent: %lu total (%lu first resends, %lu idle resends).\n",stat_ok+stat_bad+stat_dupes,stat_bad,stat_dupes,
|
|
stat_ok+stat_resends+stat_iresends,stat_resends,stat_iresends);
|
|
fprintf(stderr,"Line has %lu %% packet loss rate.\n",100*(stat_resends+stat_iresends)/(stat_ok+stat_dupes+stat_resends+stat_iresends));
|
|
}
|
|
|
|
static int util_split_path (char * path, char ** p1, char ** p2,
|
|
char ** p3)
|
|
{
|
|
char *s;
|
|
static char junk;
|
|
|
|
*p1 = "/";
|
|
if(*path == '/') {
|
|
*p2 = path;
|
|
*p3 = path+1;
|
|
} else {
|
|
*p2 = &junk;
|
|
*p3 = path;
|
|
}
|
|
|
|
for(s = *p3; *s; s++) {
|
|
if(*s == '/') {
|
|
*p1 = path;
|
|
*p2 = s;
|
|
*p3 = s+1;
|
|
}
|
|
}
|
|
|
|
if (**p3 == '\0') *p3 = ".";
|
|
return(1);
|
|
}
|
|
|
|
/* return current working directory (from environment) */
|
|
char *util_getwd (char * p)
|
|
{
|
|
if(p) strcpy(p,env_dir);
|
|
return(p);
|
|
}
|
|
|
|
static RDIRENT **get_dir_blk (char * path)
|
|
{
|
|
RDIRENT **dp;
|
|
char *p1, *p2, *fpath, buf[NBSIZE];
|
|
unsigned long pos;
|
|
int cnt, k, len, rem, acc, at_eof, rlen;
|
|
unsigned short dirblocksize;
|
|
UBUF *ub;
|
|
|
|
fpath = util_abs_path(path);
|
|
|
|
dirblocksize = 0;
|
|
|
|
for(pos = 0, at_eof = acc = cnt = 0; ; )
|
|
{
|
|
while((acc < UBUF_MAXSPACE) && !at_eof)
|
|
{
|
|
ub = client_interact(CC_GET_DIR,pos, strlen(fpath),
|
|
(unsigned char *)fpath+1, 2,
|
|
(unsigned char *)&client_net_len);
|
|
|
|
if(ub->cmd == CC_ERR) {
|
|
fprintf(stderr,"%s: %s\n",path, ub->buf);
|
|
free(fpath);
|
|
errno = EACCES;
|
|
return((RDIRENT **) 0);
|
|
}
|
|
|
|
rlen = BB_READ2(ub->bb_len);
|
|
if(dirblocksize == 0 )
|
|
dirblocksize = rlen;
|
|
else
|
|
if (rlen < dirblocksize) at_eof = 1;
|
|
/* if(rlen < RDHSIZE) at_eof = 1; */
|
|
for(p1 = ub->buf, p2 = buf + acc, k = rlen; k--; ) *p2++ = *p1++;
|
|
acc += rlen;
|
|
pos += rlen;
|
|
}
|
|
|
|
if(acc >= UBUF_MAXSPACE) len = UBUF_MAXSPACE;
|
|
else len = acc;
|
|
|
|
for(p2 = buf, rem = len, k = 0; ; k++) {
|
|
if(rem < RDHSIZE) break;
|
|
if(((RDIRENT *) p2)->type == RDTYPE_SKIP) break;
|
|
if(((RDIRENT *) p2)->type == RDTYPE_END ) { k++; break; }
|
|
p2 += RDHSIZE; rem -= (RDHSIZE+1);
|
|
while(*p2++) rem--;
|
|
while((p2 - buf) & 3) {
|
|
p2++;
|
|
rem--;
|
|
}
|
|
}
|
|
|
|
p1 = malloc(p2-buf);
|
|
if(cnt) dp = (RDIRENT **) realloc(dp,(cnt+k+1)*sizeof(RDIRENT *));
|
|
else dp = (RDIRENT **) malloc((cnt+k+1)*sizeof(RDIRENT *));
|
|
|
|
if(!p1 || !dp) {
|
|
fputs("directory reading out of memory\n",stderr);
|
|
free(fpath);
|
|
return((RDIRENT **) 0);
|
|
}
|
|
|
|
for(p2 = buf, rem = len; ; cnt++) {
|
|
if(rem < RDHSIZE) break;
|
|
if(((RDIRENT *) p2)->type == RDTYPE_SKIP) break;
|
|
if(((RDIRENT *) p2)->type == RDTYPE_END) {
|
|
dp[cnt] = 0;
|
|
free(fpath);
|
|
return(dp);
|
|
}
|
|
dp[cnt] = (RDIRENT *) p1;
|
|
|
|
for(k = RDHSIZE, rem -= (RDHSIZE+1); k--; *p1++ = *p2++);
|
|
while( (*p1++ = *p2++) ) rem--;
|
|
while((p2 - buf) & 3) {
|
|
p2++;
|
|
p1++;
|
|
rem--;
|
|
}
|
|
}
|
|
|
|
if(acc < UBUF_MAXSPACE) {
|
|
dp[cnt] = 0;
|
|
free(fpath);
|
|
return(dp);
|
|
}
|
|
for(p1 = buf + UBUF_MAXSPACE, p2 = buf, k = (acc -= UBUF_MAXSPACE); k--;)
|
|
*p2++ = *p1++;
|
|
}
|
|
free(fpath);
|
|
}
|
|
|
|
static int util_download_main (char * path, char * fpath, FILE * fp,
|
|
unsigned long start_from, int cmd)
|
|
{
|
|
unsigned long pos, started_from = start_from, downloaded;
|
|
unsigned tmax, wrote, sent_time, rlen;
|
|
UBUF *ub;
|
|
time_t t = time(NULL);
|
|
|
|
for(tmax = 1, pos = start_from, sent_time = 0; ;) {
|
|
ub = client_interact(cmd,pos,strlen(fpath),(unsigned char *)fpath+1, 2,
|
|
(unsigned char *)&client_net_len);
|
|
|
|
if(client_trace && (udp_sent_time != sent_time)) {
|
|
sent_time = udp_sent_time;
|
|
if(client_buf_len >= UBUF_SPACE) fprintf(stderr,"\r%luk ",1+(pos>>10));
|
|
else fprintf(stderr,"\r%lu ", pos);
|
|
fflush(stderr);
|
|
}
|
|
|
|
if(ub->cmd == CC_ERR) {
|
|
fprintf(stderr,"downloading %s: %s\n",path,ub->buf);
|
|
return(-1);
|
|
}
|
|
|
|
rlen = BB_READ2(ub->bb_len);
|
|
wrote = fwrite(ub->buf,1,rlen,fp);
|
|
/* check for long integer pos overflow */
|
|
#if SIZEOF_LONG > 4
|
|
if(pos+wrote>FOURGIGS)
|
|
break;
|
|
#else
|
|
if(pos+wrote<pos)
|
|
break;
|
|
#endif
|
|
pos += wrote;
|
|
|
|
if(rlen == 0)
|
|
break; /* end of file */
|
|
if(rlen != wrote)
|
|
return -1; /* write to local file failed */
|
|
}
|
|
|
|
t = time(NULL) - t;
|
|
if (t == 0) t = 1;
|
|
downloaded = pos - started_from;
|
|
if(client_trace)
|
|
{
|
|
fprintf(stderr,"\r%luk : %s [%ldB/s] \n", 1+(pos>>10), path, downloaded/t);
|
|
util_pktstats();
|
|
fflush(stderr);
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
int util_download (char * path, FILE * fp, unsigned long start_from)
|
|
{
|
|
int code, len;
|
|
char *fpath;
|
|
|
|
fpath = util_abs_path(path);
|
|
if(*env_passwd) {
|
|
strcat(fpath, "\n");
|
|
strcat(fpath, env_passwd);
|
|
len = strlen(fpath);
|
|
}
|
|
code = util_download_main(path, fpath, fp, start_from, CC_GET_FILE);
|
|
free(fpath);
|
|
return(code);
|
|
}
|
|
|
|
int util_grab_file (char * path, FILE * fp, unsigned long start_from)
|
|
{
|
|
int code, len;
|
|
char *fpath;
|
|
UBUF *ub;
|
|
|
|
fpath = util_abs_path(path);
|
|
if(*env_passwd) {
|
|
strcat(fpath, "\n");
|
|
strcat(fpath, env_passwd);
|
|
len = strlen(fpath);
|
|
}
|
|
code = util_download_main(path, fpath, fp, start_from, CC_GRAB_FILE);
|
|
if(code) {
|
|
free(fpath);
|
|
return(code);
|
|
}
|
|
|
|
ub = client_interact(CC_GRAB_DONE, 0L, len, (unsigned char *)fpath+1, 0,
|
|
(unsigned char *)NULLP);
|
|
|
|
if(ub->cmd == CC_ERR) {
|
|
fprintf(stderr,"Warning, unexpected grab error: %s\n",ub->buf);
|
|
}
|
|
|
|
free(fpath);
|
|
return(code);
|
|
}
|
|
|
|
int util_upload (char * path, FILE * fp, time_t stamp)
|
|
{
|
|
unsigned long pos;
|
|
unsigned bytes, first, tmax, sent_time;
|
|
char *fpath, buf[UBUF_MAXSPACE];
|
|
UBUF *ub;
|
|
time_t t = time(NULL);
|
|
char *dpath,*p1,*p2;
|
|
unsigned char flags;
|
|
struct stat sb;
|
|
|
|
fpath = util_abs_path(path);
|
|
util_split_path(fpath,&dpath,&p1,&p2);
|
|
*p1='\0';
|
|
|
|
/* check if we have enough rights to create file */
|
|
ub = client_interact(CC_GET_PRO,0, strlen(dpath), (unsigned char *)dpath+1, 0,
|
|
(unsigned char *)NULLP);
|
|
free(fpath);
|
|
fpath = util_abs_path(path);
|
|
if(ub->cmd == CC_ERR)
|
|
{
|
|
fprintf(stderr,"uploading %s: %s\n",path,ub->buf);
|
|
free(fpath);
|
|
return(1);
|
|
}
|
|
/* extract flags from server reply */
|
|
bytes = BB_READ2(ub->bb_len);
|
|
pos = BB_READ4(ub->bb_pos);
|
|
if(pos)
|
|
{
|
|
/* flags are in the reply */
|
|
flags = *(ub->buf+bytes);
|
|
/* check for required flags */
|
|
if(! (flags & DIR_OWNER))
|
|
{
|
|
if( ! (flags & DIR_ADD))
|
|
{
|
|
fprintf(stderr,"No permission for adding files.\n");
|
|
free(fpath);
|
|
return(1);
|
|
}
|
|
} else
|
|
{
|
|
/* owner of directory */
|
|
flags|=DIR_DEL|DIR_ADD;
|
|
}
|
|
/* check if we can overwrite an existing file */
|
|
if(! (flags & DIR_DEL))
|
|
{
|
|
if(util_stat(fpath,&sb)==0)
|
|
{
|
|
fprintf(stderr,"No permission for overwriting: %s\n",fpath);
|
|
free(fpath);
|
|
return(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
for(tmax = 1, sent_time = 0, pos = 0, first = 1; ; first = 0)
|
|
{
|
|
if((bytes = fread(buf,1,client_buf_len,fp)) || first)
|
|
{
|
|
ub = client_interact(CC_UP_LOAD,pos, bytes, (unsigned char *)buf, 0,
|
|
(unsigned char *)NULLP);
|
|
if(client_trace && (udp_sent_time != sent_time))
|
|
{
|
|
sent_time = udp_sent_time;
|
|
if(client_buf_len >= UBUF_SPACE)
|
|
fprintf(stderr,"\r%luk ",1+(pos>>10));
|
|
else fprintf(stderr,"\r%lu ", pos );
|
|
fflush(stderr);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
BB_WRITE4(buf,stamp);
|
|
ub = client_interact(CC_INSTALL,stamp==0?0:4,strlen(fpath),
|
|
(unsigned char *)fpath+1, stamp==0?0:4,
|
|
(unsigned char *)buf);
|
|
}
|
|
if(ub->cmd == CC_ERR) {
|
|
fprintf(stderr,"uploading %s: %s\n",path,ub->buf);
|
|
free(fpath);
|
|
return(1);
|
|
}
|
|
|
|
if(!bytes && !first) break;
|
|
#if SIZEOF_LONG > 4
|
|
if(pos+bytes>FOURGIGS)
|
|
break;
|
|
#else
|
|
if(pos+bytes<pos)
|
|
break;
|
|
#endif
|
|
pos += bytes;
|
|
}
|
|
|
|
t = time(NULL) - t;
|
|
if(t == 0) t = 1;
|
|
if(client_trace)
|
|
{
|
|
fprintf(stderr,"\r%luk : %s [%ldB/s] \n", 1+(pos>>10), path, pos/t);
|
|
util_pktstats();
|
|
fflush(stderr);
|
|
}
|
|
free(fpath);
|
|
return(0);
|
|
}
|
|
|
|
static void util_get_env (void)
|
|
{
|
|
char *p;
|
|
|
|
if(!(env_host = getenv("FSP_HOST"))) {
|
|
fputs("No FSP_HOST specified.\n",stderr);
|
|
exit(EX_CONFIG);
|
|
}
|
|
if(!(env_port = getenv("FSP_PORT"))) {
|
|
fputs("No FSP_PORT specified.\n",stderr);
|
|
exit(EX_CONFIG);
|
|
}
|
|
if(!(env_dir = getenv("FSP_DIR"))) {
|
|
env_dir = "/";
|
|
env_dir_malloced = 0;
|
|
}
|
|
if(!(env_myport = getenv("FSP_LOCALPORT"))) env_myport = "0";
|
|
if(!(env_listen_on = getenv("FSP_LOCALIP"))) env_listen_on = NULL;
|
|
if(!(env_passwd = getenv("FSP_PASSWORD"))) env_passwd = "\0";
|
|
client_trace = !!getenv("FSP_TRACE");
|
|
if( (p = getenv("FSP_BUF_SIZE")) ) client_buf_len = atoi(p);
|
|
else client_buf_len = UBUF_SPACE;
|
|
|
|
if(client_buf_len > UBUF_MAXSPACE) client_buf_len = UBUF_MAXSPACE;
|
|
client_net_len = htons(client_buf_len);
|
|
|
|
if( (p = getenv("FSP_DELAY")) ) target_delay = atol(p);
|
|
if(target_delay < MIN_DELAY) target_delay = MIN_DELAY;
|
|
if(target_delay > MAX_DELAY) target_delay = MAX_DELAY;
|
|
|
|
if( (p = getenv("FSP_MAXDELAY")) ) target_maxdelay = atol(p);
|
|
if(target_maxdelay < target_delay) target_maxdelay = target_delay;
|
|
if(target_maxdelay > MAX_DELAY) target_maxdelay = MAX_DELAY;
|
|
|
|
if(!(env_local_dir = getenv("FSP_LOCAL_DIR"))) env_local_dir=".";
|
|
|
|
if(!(p = getenv("FSP_TIMEOUT"))) env_timeout = DEFAULT_TIMEOUT;
|
|
else env_timeout = atol(p);
|
|
}
|
|
|
|
|
|
void env_client (void)
|
|
{
|
|
util_get_env();
|
|
init_client(env_host,atoi(env_port),atoi(env_myport));
|
|
}
|
|
|
|
static DDLIST *ddroot = 0;
|
|
|
|
RDIR *util_opendir (char * path)
|
|
{
|
|
char *fpath;
|
|
RDIRENT **dep;
|
|
DDLIST *ddp;
|
|
RDIR *rdirp;
|
|
|
|
fpath = util_abs_path(path);
|
|
|
|
for(ddp = ddroot; ddp; ddp = ddp->next)
|
|
if(!strcmp(ddp->path,fpath)) break;
|
|
|
|
if(!ddp) {
|
|
if(!(dep = get_dir_blk(fpath)))
|
|
{
|
|
free(fpath);
|
|
return((RDIR *) 0);
|
|
}
|
|
ddp = (DDLIST *) malloc(sizeof(DDLIST));
|
|
ddp->dep_root = dep;
|
|
ddp->path = fpath;
|
|
ddp->ref_cnt = 0;
|
|
ddp->next = ddroot;
|
|
ddroot = ddp;
|
|
} else free(fpath);
|
|
|
|
ddp->ref_cnt++;
|
|
|
|
rdirp = (RDIR *) malloc(sizeof(RDIR));
|
|
rdirp->ddp = ddp;
|
|
rdirp->dep = ddp->dep_root;
|
|
return(rdirp);
|
|
}
|
|
|
|
void util_closedir (RDIR * rdirp)
|
|
{
|
|
rdirp->ddp->ref_cnt--;
|
|
free(rdirp);
|
|
}
|
|
|
|
rdirent *util_readdir (RDIR * rdirp)
|
|
{
|
|
static rdirent rde;
|
|
RDIRENT **dep;
|
|
|
|
dep = rdirp->dep;
|
|
|
|
if(!*dep) return((rdirent *) 0);
|
|
|
|
rde.d_fileno = 10;
|
|
rde.d_rcdlen = 10;
|
|
rde.d_namlen = strlen((*dep)->name);
|
|
rde.d_name = (*dep)->name;
|
|
rdirp->dep = dep+1;
|
|
|
|
return(&rde);
|
|
}
|
|
|
|
/* Removes \npassword from input */
|
|
void util_junk_password(char *path)
|
|
{
|
|
char *pos;
|
|
|
|
pos=strchr(path,'\n');
|
|
if(pos != NULL)
|
|
/* terminate them! */
|
|
*pos='\0';
|
|
}
|
|
|
|
int util_stat (char * path, struct stat * sbuf)
|
|
{
|
|
RDIR *drp;
|
|
RDIRENT **dep;
|
|
DDLIST *ddp;
|
|
UBUF *ub;
|
|
char *fpath,*fpath2, *ppath, *p1, *pfile;
|
|
int cached=0;
|
|
|
|
fpath = util_abs_path(path);
|
|
fpath2 = strdup(fpath);
|
|
|
|
if(!strcmp(fpath,env_dir)) {
|
|
ppath = fpath;
|
|
pfile = ".";
|
|
} else {
|
|
util_split_path(fpath,&ppath,&p1,&pfile);
|
|
*p1='\0';
|
|
}
|
|
/* printf("ppath `%s` pfile '%s'\n",ppath,pfile); */
|
|
|
|
/* check if we have ppath cached */
|
|
/* printf("Finding `%s` in cache.\n",ppath); */
|
|
for(ddp = ddroot; ddp; ddp = ddp->next)
|
|
{
|
|
/* printf(" we have %s in cache.\n",ddp->path); */
|
|
if(!strcmp(ddp->path,ppath))
|
|
{
|
|
cached=1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* if(cached) printf("Record found in cache.\n",ppath); */
|
|
if(statworks && !cached)
|
|
{
|
|
/* send a new FSP_STAT command to server */
|
|
ub = client_interact(CC_STAT,0L, strlen(fpath2),
|
|
(unsigned char *) fpath2+1, 0, 0);
|
|
if(ub->cmd == CC_STAT)
|
|
{
|
|
sbuf->st_uid = 0;
|
|
sbuf->st_gid = 0;
|
|
sbuf->st_atime = sbuf->st_mtime =
|
|
sbuf->st_ctime = BB_READ4((ub->buf));
|
|
sbuf->st_size = BB_READ4((ub->buf+4));
|
|
if((ub->buf[8]) == RDTYPE_DIR)
|
|
{
|
|
sbuf->st_mode = 0777 | S_IFDIR;
|
|
sbuf->st_nlink = 2;
|
|
}
|
|
else
|
|
{
|
|
sbuf->st_mode = 0666 | S_IFREG;
|
|
sbuf->st_nlink = 1;
|
|
}
|
|
|
|
free(fpath);
|
|
free(fpath2);
|
|
|
|
if(ub->buf[8]==0)
|
|
{
|
|
errno = ENOENT;
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
statworks=0;
|
|
}
|
|
} /* CC_STAT */
|
|
|
|
if( (drp = util_opendir(ppath)) )
|
|
{
|
|
for(dep = drp->dep; *dep; dep++)
|
|
{
|
|
if(!strcmp((*dep)->name,pfile))
|
|
{
|
|
if((*dep)->type == RDTYPE_DIR)
|
|
sbuf->st_mode = 0777 | S_IFDIR;
|
|
else
|
|
sbuf->st_mode = 0666 | S_IFREG;
|
|
|
|
if((*dep)->type == RDTYPE_DIR)
|
|
sbuf->st_nlink = 2;
|
|
else
|
|
sbuf->st_nlink = 1;
|
|
|
|
sbuf->st_uid = 0;
|
|
sbuf->st_gid = 0;
|
|
sbuf->st_size = BB_READ4((*dep)->bb_size);
|
|
sbuf->st_atime = sbuf->st_mtime =
|
|
sbuf->st_ctime = BB_READ4((*dep)->bb_time);
|
|
util_closedir(drp);
|
|
free(fpath);
|
|
free(fpath2);
|
|
return(0);
|
|
}
|
|
}
|
|
util_closedir(drp);
|
|
}
|
|
|
|
free(fpath);
|
|
free(fpath2);
|
|
errno = ENOENT;
|
|
return(-1);
|
|
}
|
|
|
|
int util_cd (char * p)
|
|
{
|
|
char *fpath;
|
|
UBUF *ub;
|
|
DDLIST *ddp;
|
|
|
|
fpath = util_abs_path(p);
|
|
for(ddp = ddroot; ddp; ddp = ddp->next)
|
|
if(!strcmp(ddp->path,fpath)) break;
|
|
|
|
if(!ddp && strcmp(p,".") && strcmp(p,"..")) {
|
|
ub = client_interact(CC_GET_DIR,0L, strlen(fpath),
|
|
(unsigned char *) fpath+1, 2,
|
|
(unsigned char *)&client_net_len);
|
|
if(ub->cmd == CC_ERR) {
|
|
free(fpath);
|
|
fprintf(stderr,"%s: %s\n",p, ub->buf);
|
|
errno = EACCES;
|
|
return(-1);
|
|
}
|
|
}
|
|
|
|
if(env_dir_malloced) free(env_dir);
|
|
env_dir_malloced = 1;
|
|
env_dir = fpath;
|
|
return(0);
|
|
}
|
|
|
|
/* Perform a cd, but don't verify path. Assume the path has been
|
|
* pre-verified
|
|
*/
|
|
int util_cd2 (char * p)
|
|
{
|
|
char *fpath;
|
|
|
|
fpath = util_abs_path(p);
|
|
|
|
if(env_dir_malloced) free(env_dir);
|
|
env_dir_malloced = 1;
|
|
env_dir = fpath;
|
|
return(0);
|
|
}
|
|
|
|
void util_process_file(char *path, int mode,
|
|
void (*process_file)(char *,struct stat *, int, int),
|
|
int (*process_start_dir)(char *,struct stat *,u_long *),
|
|
void (*process_end_dir)(char *,int,u_long,int),
|
|
int level)
|
|
{
|
|
struct stat sbuf;
|
|
RDIR *rdir;
|
|
struct rdirent *rde;
|
|
int pathlen;
|
|
char *newname;
|
|
u_long sum;
|
|
|
|
if (util_stat(path, &sbuf) < 0) {
|
|
perror(path);
|
|
return;
|
|
}
|
|
|
|
if (S_ISREG(sbuf.st_mode)) {
|
|
if(process_file) (*process_file)(path, &sbuf, mode, level);
|
|
} else if (S_ISDIR(sbuf.st_mode)) {
|
|
sum = mode;
|
|
if (process_start_dir && (*process_start_dir)(path, &sbuf, &sum) < 0)
|
|
fprintf(stderr, "skipping remote directory `%s'\n", path);
|
|
else {
|
|
if ((rdir = util_opendir(path))) {
|
|
pathlen = strlen(path);
|
|
while ((rde = util_readdir(rdir))) {
|
|
/* skip over "." and ".." */
|
|
if (rde->d_name[0] == '.' &&
|
|
(rde->d_name[1] == '\0' ||
|
|
(rde->d_name[1] == '.' && rde->d_name[2] == '\0')))
|
|
continue;
|
|
newname = malloc(pathlen + rde->d_namlen + 2);
|
|
|
|
strcpy(newname, path);
|
|
if(newname[pathlen-1] != '/') newname[pathlen] = '/';
|
|
else pathlen--;
|
|
strcpy(newname + pathlen + 1, rde->d_name);
|
|
util_process_file(newname, mode, process_file, process_start_dir,
|
|
process_end_dir, level + 1);
|
|
free(newname);
|
|
}
|
|
util_closedir(rdir);
|
|
}
|
|
if(process_end_dir) (*process_end_dir)(path, mode, sum, level);
|
|
}
|
|
} else
|
|
fprintf(stderr, "remote file `%s' is not a file or directory!\n",path);
|
|
/* free(path); */
|
|
}
|