/* files.c -- handles: all the file system commands dprintf'ized, 4nov95 rewritten, 26feb96 */ #if HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include "eggdrop.h" #include "files.h" #include "proto.h" /* 'configure' is supposed to make things easier for me now */ /* PLEASE don't fail me, 'configure'! :) */ #if HAVE_DIRENT_H # include # define NAMLEN(dirent) strlen((dirent)->d_name) #else # define dirent direct # define NAMLEN(dirent) (dirent)->d_namlen # if HAVE_SYS_NDIR_H # include # endif # if HAVE_SYS_DIR_H # include # endif # if HAVE_NDIR_H # include # endif #endif /* goddamn stupid sunos 4 */ #ifndef S_IFREG #define S_IFREG 0100000 #endif #ifndef S_IFLNK #define S_IFLNK 0120000 #endif extern struct dcc_t dcc[]; extern int dcc_total; extern char dccdir[]; extern char dccin[]; extern char botname[]; extern struct userrec *userlist; extern char cx_file[]; extern int cx_line; extern char origbotname[]; /* maximum number of users can be in the file area at once */ int dcc_users=0; /* maximum number of simultaneous file downloads allowed */ int dcc_limit=3; /* low-level stuff for other modules */ int is_file(s) char *s; { struct stat ss; int i=stat(s,&ss); if (i<0) return 0; if ((ss.st_mode&S_IFREG) || (ss.st_mode&S_IFLNK)) return 1; return 0; } /* return true if this user has >= the maximum number of file xfers going */ int at_limit(nick) char *nick; { int i,x=0; for (i=0; i=dcc_limit); } /* are there too many people in the file system? */ int too_many_filers() { int i,n=0; if (dcc_users==0) return 0; for (i=0; i=dcc_users); } /* someone uploaded a file -- add it */ void add_file(dir,file,nick) char *dir,*file,*nick; { FILE *f; /* gave me a full pathname */ /* only continue if the destination is within the visible file system */ if (strncmp(dccdir,dir,strlen(dccdir))!=0) return; f=filedb_open(&dir[strlen(dccdir)]); if (f==NULL) return; filedb_add(f,file,nick); filedb_close(f); } int welcome_to_files(idx) int idx; { int atr=get_attr_handle(dcc[idx].nick); FILE *f; dprintf(idx,"\n"); /* show motd if the user went straight here without going thru the party line */ if (!(dcc[idx].u.file->chat->status&STAT_CHAT)) show_motd(idx); telltext(idx,"files",dcc[idx].u.file->chat->status&STAT_CHAT, (atr&(USER_MASTER|USER_JANITOR))); get_handle_dccdir(dcc[idx].nick,dcc[idx].u.file->dir); /* does this dir even exist any more? */ f=filedb_open(dcc[idx].u.file->dir); if (f==NULL) { dcc[idx].u.file->dir[0]=0; f=filedb_open(dcc[idx].u.file->dir); if (f==NULL) { dprintf(idx,"\nThe file system seems to be broken right now.\n"); dprintf(idx,"(The dcc-path is set to an invalid directory.)\n"); dprintf(idx,"\n\n"); dccdir[0]=0; return 0; /* failed */ } } filedb_close(f); dprintf(idx,"Current directory: /%s\n\n",dcc[idx].u.file->dir); return 1; } /* given current directory, and the desired changes, fill 'real' with */ /* the new current directory. check directory parmissions along the */ /* way. return 1 if the change can happen, 0 if not. */ int resolve_dir(current,change,real,atr) char *current,*change,*real; int atr; { char elem[512],s[1024],new[1024],*p; FILE *f; filedb *fdb; strcpy(real,current); strcpy(new,change); if (!new[0]) return 1; /* no change? */ if (new[0]=='/') { /* EVERYONE has access here */ real[0]=0; strcpy(new,&new[1]); } /* cycle thru the elements */ strcat(new,"/"); p=strchr(new,'/'); while (p!=NULL) { *p=0; p++; strcpy(elem,new); strcpy(new,p); if ((strcmp(elem,".")==0) || (!elem[0])) { /* do nothing */ } else if (strcmp(elem,"..")==0) { /* go back */ /* always allowed */ p=strrchr(real,'/'); if (p==NULL) { /* can't go back from here? */ if (!real[0]) { strcpy(real,current); return 0; } real[0]=0; } else *p=0; } else { /* allowed access here? */ f=filedb_open(real); fdb=findfile(f,elem,NULL); filedb_close(f); if (fdb==NULL) { /* non-existant */ strcpy(real,current); return 0; } if (!(fdb->stat & FILE_DIR)) { /* not a dir */ strcpy(real,current); return 0; } if (!flags_ok(fdb->flags_req,atr)) { strcpy(real,current); return 0; } strcpy(s,real); if (s[0]) if (s[strlen(s)-1]!='/') strcat(s,"/"); sprintf(real,"%s%s",s,elem); sprintf(s,"%s%s",dccdir,real); } p=strchr(new,'/'); } /* sanity check: does this dir exist? */ sprintf(s,"%s%s",dccdir,real); f=fopen(s,"r"); if (f==NULL) return 0; fclose(f); return 1; } void incr_file_gots(ppath) char *ppath; { char *p,path[256],destdir[121],fn[81]; filedb *fdb; FILE *f; long where; context; if ((ppath[0]=='*') || (ppath[0]=='/')) return; strcpy(path,ppath); p=strrchr(path,'/'); if (p!=NULL) { *p=0; strncpy(destdir,path,120); destdir[120]=0; strncpy(fn,p+1,80); fn[80]=0; *p='/'; } else { destdir[0]=0; strncpy(fn,path,80); fn[80]=0; } f=filedb_open(destdir); if (f==NULL) return; /* not my concern, then */ fdb=findfile(f,fn,&where); if (fdb==NULL) { /* file is gone now */ filedb_close(f); return; } fdb->gots++; fseek(f,where,SEEK_SET); fwrite(fdb,sizeof(filedb),1,f); filedb_close(f); } /*** COMMANDS ***/ void cmd_pwd(idx,par) int idx; char *par; { context; putlog(LOG_FILES,"*","files: #%s# pwd",dcc[idx].nick); dprintf(idx,"Current directory: /%s\n",dcc[idx].u.file->dir); } void cmd_pending(idx,par) int idx; char *par; { context; show_queued_files(idx); putlog(LOG_FILES,"*","files: #%s# pending",dcc[idx].nick); } void cmd_cancel(idx,par) int idx; char *par; { context; if (!par[0]) { dprintf(idx,"Usage: cancel \n"); return; } fileq_cancel(idx,par); putlog(LOG_FILES,"*","files: #%s# cancel %s",dcc[idx].nick,par); } void cmd_chdir(idx,msg) int idx; char *msg; { char s[121]; int atr; context; if (!msg[0]) { dprintf(idx,"Usage: cd \n"); return; } atr=get_attr_handle(dcc[idx].nick); if (!resolve_dir(dcc[idx].u.file->dir,msg,s,atr)) { dprintf(idx,"No such dir.\n"); return; } strcpy(dcc[idx].u.file->dir,s); set_handle_dccdir(userlist,dcc[idx].nick,dcc[idx].u.file->dir); putlog(LOG_FILES,"*","files: #%s# cd /%s",dcc[idx].nick, dcc[idx].u.file->dir); dprintf(idx,"Now in: /%s\n",dcc[idx].u.file->dir); } void files_ls(idx,par,showall) int idx; char *par; int showall; { char *p,s[161],destdir[161],mask[81]; int atr; FILE *f; context; atr=get_attr_handle(dcc[idx].nick); if (par[0]) { putlog(LOG_FILES,"*","files: #%s# ls %s",dcc[idx].nick,par); p=strrchr(par,'/'); if (p!=NULL) { *p=0; strncpy(s,par,160); s[160]=0; strncpy(mask,p+1,80); mask[80]=0; if (!resolve_dir(dcc[idx].u.file->dir,s,destdir,atr)) { dprintf(idx,"Illegal directory.\n"); return; } } else { strcpy(destdir,dcc[idx].u.file->dir); strncpy(mask,par,80); mask[80]=0; } f=filedb_open(destdir); filedb_ls(f,idx,atr,mask,showall); filedb_close(f); } else { putlog(LOG_FILES,"*","files: #%s# ls",dcc[idx].nick); f=filedb_open(dcc[idx].u.file->dir); filedb_ls(f,idx,atr,"*",showall); filedb_close(f); } } void cmd_ls(idx,par) int idx; char *par; { files_ls(idx,par,0); } void cmd_lsa(idx,par) int idx; char *par; { files_ls(idx,par,1); } void cmd_get(idx,par) int idx; char *par; { int atr,ok=0,i; char *p,what[512],destdir[121],s[256]; filedb *fdb; FILE *f; long where; context; if (!par[0]) { dprintf(idx,"Usage: get [nickname]\n"); return; } atr=get_attr_handle(dcc[idx].nick); nsplit(what,par); /* anything left in par is a new nickname */ if (strlen(par)>NICKLEN) { dprintf(idx,"Be reasonable.\n"); return; } p=strrchr(what,'/'); if (p!=NULL) { *p=0; strncpy(s,what,120); s[120]=0; strcpy(what,p+1); if (!resolve_dir(dcc[idx].u.file->dir,s,destdir,atr)) { dprintf(idx,"Illegal directory.\n"); return; } } else strcpy(destdir,dcc[idx].u.file->dir); f=filedb_open(destdir); where=0L; fdb=findmatch(f,what,&where); if (fdb==NULL) { filedb_close(f); dprintf(idx,"No matching files found in this directory.\n"); return; } while (fdb!=NULL) { if (!(fdb->stat&(FILE_HIDDEN|FILE_DIR))) { ok=1; if (fdb->sharelink[0]) { char bot[121],whoto[NICKLEN]; /* this is a link to a file on another bot... */ splitc(bot,fdb->sharelink,':'); if (!in_chain(bot)) { dprintf(idx,"%s isn't available right now.\n",fdb->filename); } else { i=nextbot(bot); strcpy(whoto,par); if (!whoto[0]) strcpy(whoto,dcc[idx].nick); tprintf(dcc[i].sock,"filereq %d:%s@%s %s:%s\n",dcc[idx].sock, whoto,origbotname,bot,fdb->sharelink); dprintf(idx,"Requested %s from %s ...\n",fdb->sharelink,bot); /* increase got count now (or never) */ fdb->gots++; sprintf(s,"%s:%s",bot,fdb->sharelink); strcpy(fdb->sharelink,s); fseek(f,where,SEEK_SET); fwrite(fdb,sizeof(filedb),1,f); } } else { char xx[161]; if (par[0]) sprintf(xx,"%s %s",fdb->filename,par); else strcpy(xx,fdb->filename); do_dcc_send(idx,destdir,xx); /* don't increase got count till later */ } } where+=sizeof(filedb); fdb=findmatch(f,what,&where); } filedb_close(f); if (!ok) dprintf(idx,"No matching files found in this directory.\n"); else putlog(LOG_FILES,"*","files: #%s# get %s %s",dcc[idx].nick,what,par); } void cmd_file_help(idx,par) int idx; char *par; { char s[121]; int atr; context; atr=get_attr_handle(dcc[idx].nick); if (par[0]) { putlog(LOG_FILES,"*","files: #%s# help %s",dcc[idx].nick,par); sprintf(s,"files.%s",par); tellhelp(idx,s,dcc[idx].u.file->chat->status&STAT_CHAT, (atr&(USER_MASTER|USER_JANITOR))); } else { putlog(LOG_FILES,"*","files: #%s# help",dcc[idx].nick); tellhelp(idx,"files.help",dcc[idx].u.file->chat->status&STAT_CHAT, (atr&(USER_MASTER|USER_JANITOR))); } } void cmd_hide(idx,par) int idx; char *par; { FILE *f; filedb *fdb; long where; int ok=0; context; if (!par[0]) { dprintf(idx,"Usage: hide \n"); return; } where=0L; f=filedb_open(dcc[idx].u.file->dir); fdb=findmatch(f,par,&where); if (fdb==NULL) { filedb_close(f); dprintf(idx,"No matching files found.\n"); return; } while (fdb!=NULL) { if (!(fdb->stat & FILE_HIDDEN)) { fdb->stat |= FILE_HIDDEN; ok++; dprintf(idx,"Hidden: %s\n",fdb->filename); fseek(f,where,SEEK_SET); fwrite(fdb,sizeof(filedb),1,f); } where+=sizeof(filedb); fdb=findmatch(f,par,&where); } filedb_close(f); if (!ok) dprintf(idx,"No matching files found.\n"); else { putlog(LOG_FILES,"*","files: #%s# hide %s",dcc[idx].nick,par); if (ok>1) dprintf(idx,"Hid %d file%s.\n",ok,ok==1?"":"s"); } } void cmd_unhide(idx,par) int idx; char *par; { FILE *f; filedb *fdb; long where; int ok=0; context; if (!par[0]) { dprintf(idx,"Usage: unhide \n"); return; } where=0L; f=filedb_open(dcc[idx].u.file->dir); fdb=findmatch(f,par,&where); if (fdb==NULL) { filedb_close(f); dprintf(idx,"No matching files found.\n"); return; } while (fdb!=NULL) { if (fdb->stat & FILE_HIDDEN) { fdb->stat &= ~FILE_HIDDEN; ok++; dprintf(idx,"Unhidden: %s\n",fdb->filename); fseek(f,where,SEEK_SET); fwrite(fdb,sizeof(filedb),1,f); } where+=sizeof(filedb); fdb=findmatch(f,par,&where); } filedb_close(f); if (!ok) dprintf(idx,"No matching files found.\n"); else { putlog(LOG_FILES,"*","files: #%s# unhide %s",dcc[idx].nick,par); if (ok>1) dprintf(idx,"Unhid %d file%s.\n",ok,ok==1?"":"s"); } } void cmd_share(idx,par) int idx; char *par; { FILE *f; filedb *fdb; long where; int ok=0; context; if (!par[0]) { dprintf(idx,"Usage: share \n"); return; } where=0L; f=filedb_open(dcc[idx].u.file->dir); fdb=findmatch(f,par,&where); if (fdb==NULL) { filedb_close(f); dprintf(idx,"No matching files found.\n"); return; } while (fdb!=NULL) { if (!(fdb->stat & (FILE_HIDDEN|FILE_DIR|FILE_SHARE))) { fdb->stat |= FILE_SHARE; ok++; dprintf(idx,"Sharing: %s\n",fdb->filename); fseek(f,where,SEEK_SET); fwrite(fdb,sizeof(filedb),1,f); } where+=sizeof(filedb); fdb=findmatch(f,par,&where); } filedb_close(f); if (!ok) dprintf(idx,"No matching files found.\n"); else { putlog(LOG_FILES,"*","files: #%s# share %s",dcc[idx].nick,par); if (ok>1) dprintf(idx,"Shared %d file%s.\n",ok,ok==1?"":"s"); } } void cmd_unshare(idx,par) int idx; char *par; { FILE *f; filedb *fdb; long where; int ok=0; context; if (!par[0]) { dprintf(idx,"Usage: unshare \n"); return; } where=0L; f=filedb_open(dcc[idx].u.file->dir); fdb=findmatch(f,par,&where); if (fdb==NULL) { filedb_close(f); dprintf(idx,"No matching files found.\n"); return; } while (fdb!=NULL) { if ((fdb->stat & FILE_SHARE) && !(fdb->stat & (FILE_DIR|FILE_HIDDEN))) { fdb->stat &= ~FILE_SHARE; ok++; dprintf(idx,"Unshared: %s\n",fdb->filename); fseek(f,where,SEEK_SET); fwrite(fdb,sizeof(filedb),1,f); } where+=sizeof(filedb); fdb=findmatch(f,par,&where); } filedb_close(f); if (!ok) dprintf(idx,"No matching files found.\n"); else { putlog(LOG_FILES,"*","files: #%s# unshare %s",dcc[idx].nick,par); if (ok>1) dprintf(idx,"Unshared %d file%s.\n",ok,ok==1?"":"s"); } } /* link a file from another bot */ void cmd_ln(idx,par) int idx; char *par; { char share[512],newpath[121],newfn[81],*p; FILE *f; filedb fdb,*x; long where; int atr; context; atr=get_attr_handle(dcc[idx].nick); nsplit(share,par); share[60]=0; /* correct format? */ if ((strchr(share,':')==NULL) || (!par[0])) { dprintf(idx,"Usage: ln \n"); return; } p=strrchr(par,'/'); if (p!=NULL) { *p=0; strncpy(newfn,p+1,80); newfn[80]=0; if (!resolve_dir(dcc[idx].u.file->dir,par,newpath,atr)) { dprintf(idx,"Directory does not exist.\n"); return; } } else { strcpy(newpath,dcc[idx].u.file->dir); strncpy(newfn,par,80); newfn[80]=0; } f=filedb_open(newpath); x=findfile(f,newfn,&where); if (x!=NULL) { if (!x->sharelink[0]) { dprintf(idx,"%s is already a normal file.\n",newfn); filedb_close(f); return; } strcpy(x->sharelink,share); fseek(f,where,SEEK_SET); fwrite(x,sizeof(filedb),1,f); filedb_close(f); dprintf(idx,"Changed link to %s\n",share); putlog(LOG_FILES,"*","files: #%s# ln %s %s",dcc[idx].nick,par,share); return; } /* new entry */ where=findempty(f); fdb.version=FILEVERSION; fdb.desc[0]=0; fdb.flags_req=0; fdb.size=0; fdb.gots=0; strncpy(fdb.filename,newfn,30); fdb.filename[30]=0; strcpy(fdb.uploader,dcc[idx].nick); fdb.uploaded=time(NULL); strcpy(fdb.sharelink,share); fdb.stat=0; fseek(f,where,SEEK_SET); fwrite(&fdb,sizeof(filedb),1,f); filedb_close(f); dprintf(idx,"Added link %s -> %s\n",fdb.filename,share); putlog(LOG_FILES,"*","files: #%s# ln /%s%s%s %s",dcc[idx].nick,newpath, newpath[0]?"/":"",newfn,share); } void cmd_desc(idx,par) int idx; char *par; { char fn[512],desc[301],*p,*q; int atr,ok=0,lin; FILE *f; filedb *fdb; long where; context; nsplit(fn,par); if (!fn[0]) { dprintf(idx,"Usage: desc \n"); return; } /* fix up desc */ strncpy(desc,par,299); desc[299]=0; strcat(desc,"|"); /* replace | with linefeeds, limit 5 lines */ lin=0; q=desc; while ((*q <= 32) && (*q)) strcpy(q,&q[1]); /* zapf leading spaces */ p=strchr(q,'|'); while (p!=NULL) { /* check length */ *p=0; if (strlen(q)>60) { /* cut off at last space or truncate */ *p='|'; p=q+60; while ((*p!=' ') && (p!=q)) p--; if (p==q) *(q+60)='|'; /* no space, so truncate it */ else *p='|'; p=strchr(q,'|'); /* go back, find my place, and continue */ } *p='\n'; q=p+1; lin++; while ((*q <= 32) && (*q)) strcpy(q,&q[1]); if (lin==5) { *p=0; p=NULL; } else p=strchr(q,'|'); } /* (whew!) */ if (desc[strlen(desc)-1]=='\n') desc[strlen(desc)-1]=0; atr=get_attr_handle(dcc[idx].nick); f=filedb_open(dcc[idx].u.file->dir); where=0L; fdb=findmatch(f,fn,&where); if (fdb==NULL) { filedb_close(f); dprintf(idx,"No matching files found.\n"); return; } while (fdb!=NULL) { if (!(fdb->stat&FILE_HIDDEN)) { ok=1; if ((!(atr&(USER_MASTER|USER_JANITOR))) && (strcasecmp(fdb->uploader,dcc[idx].nick)!=0)) dprintf(idx,"You didn't upload %s\n",fdb->filename); else { strcpy(fdb->desc,desc); fseek(f,where,SEEK_SET); fwrite(fdb,sizeof(filedb),1,f); if (par[0]) dprintf(idx,"Changed: %s\n",fdb->filename); else dprintf(idx,"Blanked: %s\n",fdb->filename); } } where+=sizeof(filedb); fdb=findmatch(f,fn,&where); } filedb_close(f); if (!ok) dprintf(idx,"No matching files found.\n"); else putlog(LOG_FILES,"*","files: #%s# desc %s",dcc[idx].nick,fn); } void cmd_rm(idx,par) int idx; char *par; { FILE *f; filedb *fdb; long where; int ok=0; char s[256]; context; if (!par[0]) { dprintf(idx,"Usage: rm \n"); return; } f=filedb_open(dcc[idx].u.file->dir); where=0L; fdb=findmatch(f,par,&where); if (fdb==NULL) { filedb_close(f); dprintf(idx,"No matching files found.\n"); return; } while (fdb!=NULL) { if (!(fdb->stat & (FILE_HIDDEN|FILE_DIR))) { sprintf(s,"%s%s/%s",dccdir,dcc[idx].u.file->dir,fdb->filename); fdb->stat|=FILE_UNUSED; ok++; fseek(f,where,SEEK_SET); fwrite(fdb,sizeof(filedb),1,f); /* shared file links won't be able to be unlinked */ if (!(fdb->sharelink[0])) unlink(s); dprintf(idx,"Erased: %s\n",fdb->filename); } where+=sizeof(filedb); fdb=findmatch(f,par,&where); } filedb_close(f); if (!ok) dprintf(idx,"No matching files found.\n"); else { putlog(LOG_FILES,"*","files: #%s# rm %s",dcc[idx].nick,par); if (ok>1) dprintf(idx,"Erased %d file%s.\n",ok,ok==1?"":"s"); } } void cmd_mkdir(idx,par) int idx; char *par; { char name[512],s[512]; FILE *f; filedb *fdb; long where; context; if (!par[0]) { dprintf(idx,"Usage: mkdir [required-flags]\n"); return; } nsplit(name,par); if (name[strlen(name)-1]=='/') name[strlen(name)-1]=0; f=filedb_open(dcc[idx].u.file->dir); fdb=findfile(f,name,&where); if (fdb==NULL) { filedb x; sprintf(s,"%s%s/%s",dccdir,dcc[idx].u.file->dir,name); if (mkdir(s,0755)==0) { x.version=FILEVERSION; x.stat=FILE_DIR; x.desc[0]=0; x.uploader[0]=0; strcpy(x.filename,name); x.flags_req=0; x.uploaded=time(NULL); x.size=0; x.gots=0; x.sharelink[0]=0; dprintf(idx,"Created directory /%s%s%s\n",dcc[idx].u.file->dir, dcc[idx].u.file->dir[0]?"/":"",name); if (par[0]) { x.flags_req=str2flags(par); flags2str(x.flags_req,s); dprintf(idx,"Requires +%s to access\n",s); } where=findempty(f); fseek(f,where,SEEK_SET); fwrite(&x,sizeof(filedb),1,f); filedb_close(f); putlog(LOG_FILES,"*","files: #%s# mkdir %s %s",dcc[idx].nick,name,par); return; } dprintf(idx,"Failed.\n"); filedb_close(f); return; } /* already exists! */ if (!(fdb->stat&FILE_DIR)) { dprintf(idx,"That's not a directory.\n"); filedb_close(f); return; } if (par[0]) { fdb->flags_req=str2flags(par); flags2str(fdb->flags_req,s); dprintf(idx,"Changed %s/ to require +%s to access\n",name,s); } else { fdb->flags_req=0; dprintf(idx,"Changed %s/ to require no flags to access\n",name); } fseek(f,where,SEEK_SET); fwrite(fdb,sizeof(filedb),1,f); filedb_close(f); } void cmd_rmdir(idx,par) int idx; char *par; { FILE *f; filedb *fdb; long where; char s[256],name[80]; context; strncpy(name,par,80); name[80]=0; if (name[strlen(name)-1]=='/') name[strlen(name)-1]=0; f=filedb_open(dcc[idx].u.file->dir); fdb=findfile(f,name,&where); if (fdb==NULL) { dprintf(idx,"No such directory.\n"); filedb_close(f); return; } if (!(fdb->stat & FILE_DIR)) { dprintf(idx,"That's not a directory.\n"); filedb_close(f); return; } /* erase '.filedb' and '.files' if they exist */ sprintf(s,"%s%s/%s/.filedb",dccdir,dcc[idx].u.file->dir,name); unlink(s); sprintf(s,"%s%s/%s/.files",dccdir,dcc[idx].u.file->dir,name); unlink(s); sprintf(s,"%s%s/%s",dccdir,dcc[idx].u.file->dir,name); if (rmdir(s)==0) { dprintf(idx,"Removed directory /%s%s%s\n",dcc[idx].u.file->dir, dcc[idx].u.file->dir[0]?"/":"",name); fdb->stat|=FILE_UNUSED; fseek(f,where,SEEK_SET); fwrite(fdb,sizeof(filedb),1,f); filedb_close(f); putlog(LOG_FILES,"*","files: #%s# rmdir %s",dcc[idx].nick,name); return; } dprintf(idx,"Failed.\n"); filedb_close(f); } void cmd_mv_cp(idx,par,copy) int idx; char *par; int copy; { char *p,fn[512],oldpath[161],s[161],s1[161],newfn[161],newpath[161]; int atr,ok,only_first,skip_this; FILE *f,*g; filedb *fdb,x,*z; long where,gwhere,wherez; context; atr=get_attr_handle(dcc[idx].nick); nsplit(fn,par); if (!par[0]) { dprintf(idx,"Usage: %s \n",copy?"cp":"mv"); return; } p=strrchr(fn,'/'); if (p!=NULL) { *p=0; strncpy(s,fn,160); s[160]=0; strcpy(fn,p+1); if (!resolve_dir(dcc[idx].u.file->dir,s,oldpath,atr)) { dprintf(idx,"Illegal source directory.\n"); return; } } else strcpy(oldpath,dcc[idx].u.file->dir); strncpy(s,par,160); s[160]=0; if (!resolve_dir(dcc[idx].u.file->dir,s,newpath,atr)) { /* destination is not just a directory */ p=strrchr(s,'/'); if (p==NULL) { strcpy(newfn,s); s[0]=0; } else { *p=0; strcpy(newfn,p+1); } if (!resolve_dir(dcc[idx].u.file->dir,s,newpath,atr)) { dprintf(idx,"Illegal destination directory.\n"); return; } } else newfn[0]=0; /* stupidness checks */ if ((strcmp(oldpath,newpath)==0) && ((!newfn[0]) || (strcmp(newfn,fn)==0))) { dprintf(idx,"You can't %s files on top of themselves.\n",copy?"copy": "move"); return; } /* be aware of 'cp * this.file' possibility: ONLY COPY FIRST ONE */ if (((strchr(fn,'?')!=NULL) || (strchr(fn,'*')!=NULL)) && (newfn[0])) only_first=1; else only_first=0; f=filedb_open(oldpath); if (strcmp(oldpath,newpath)==0) g=NULL; else g=filedb_open(newpath); where=0L; ok=0; fdb=findmatch(f,fn,&where); if (fdb==NULL) { dprintf(idx,"No matching files found.\n"); if (g==NULL) filedb_close(f); else { filedb_close(f); filedb_close(g); } return; } while (fdb!=NULL) { skip_this=0; if (!(fdb->stat & (FILE_HIDDEN|FILE_DIR))) { sprintf(s,"%s%s%s%s",dccdir,oldpath,oldpath[0]?"/":"",fdb->filename); sprintf(s1,"%s%s%s%s",dccdir,newpath,newpath[0]?"/":"",newfn[0]? newfn:fdb->filename); if (strcmp(s,s1)==0) { dprintf(idx,"%s /%s%s%s onto itself? Nuh uh.\n",copy?"Copy":"Move", newpath,newpath[0]?"/":"",newfn[0]?newfn:fdb->filename); skip_this=1; } /* check for existence of file with same name in new dir */ if (g==NULL) z=findfile2(f,newfn[0]?newfn:fdb->filename,&wherez); else z=findfile2(g,newfn[0]?newfn:fdb->filename,&wherez); if (z!=NULL) { /* it's ok if the entry in the new dir is a normal file (we'll */ /* just scrap the old entry and overwrite the file) -- but if */ /* it's a directory, this file has to be skipped */ if (z->stat & FILE_DIR) { /* skip */ skip_this=1; dprintf(idx,"Destination /%s%s%s exists as dir -- skipping\n", newpath,newpath[0]?"/":"",newfn[0]?newfn:fdb->filename); } else { z->stat|=FILE_UNUSED; if (g==NULL) { fseek(f,wherez,SEEK_SET); fwrite(z,sizeof(filedb),1,f); } else { fseek(g,wherez,SEEK_SET); fwrite(z,sizeof(filedb),1,g); } } } if (!skip_this) { if ((fdb->sharelink[0]) || (copyfile(s,s1)==0)) { /* raw file moved okay: create new entry for it */ ok++; if (g==NULL) gwhere=findempty(f); else gwhere=findempty(g); x.version=FILEVERSION; x.stat=fdb->stat; x.flags_req=0; strcpy(x.filename,fdb->filename); strcpy(x.desc,fdb->desc); if (newfn[0]) strcpy(x.filename,newfn); strcpy(x.uploader,fdb->uploader); x.uploaded=fdb->uploaded; x.size=fdb->size; x.gots=fdb->gots; strcpy(x.sharelink,fdb->sharelink); if (g==NULL) { fseek(f,gwhere,SEEK_SET); fwrite(&x,sizeof(filedb),1,f); } else { fseek(g,gwhere,SEEK_SET); fwrite(&x,sizeof(filedb),1,g); } if (!copy) { unlink(s); fdb->stat|=FILE_UNUSED; fseek(f,where,SEEK_SET); fwrite(fdb,sizeof(filedb),1,f); } dprintf(idx,"%s /%s%s%s to /%s%s%s\n",copy?"Copied":"Moved",oldpath, oldpath[0]?"/":"",fdb->filename,newpath,newpath[0]?"/":"", newfn[0]?newfn:fdb->filename); } else dprintf(idx,"Could not write /%s%s%s\n",newpath,newpath[0]?"/":"", newfn[0]?newfn:fdb->filename); } } where+=sizeof(filedb); fdb=findmatch(f,fn,&where); if ((ok) && (only_first)) fdb=NULL; } if (!ok) dprintf(idx,"No matching files found.\n"); else { putlog(LOG_FILES,"*","files: #%s# %s %s%s%s %s",dcc[idx].nick, copy?"cp":"mv",oldpath,oldpath[0]?"/":"",fn,par); if (ok>1) dprintf(idx,"%s %d file%s.\n",copy?"Copied":"Moved",ok, ok==1?"":"s"); } if (g==NULL) filedb_close(f); else { filedb_close(f); filedb_close(g); } } void cmd_mv(idx,par) int idx; char *par; { cmd_mv_cp(idx,par,0); } void cmd_cp(idx,par) int idx; char *par; { cmd_mv_cp(idx,par,1); } /***** Tcl stub functions *****/ int files_get(idx,fn,nick) int idx; char *fn,*nick; { int atr,i; char *p,what[512],destdir[121],s[256]; filedb *fdb; FILE *f; long where; context; atr=get_attr_handle(dcc[idx].nick); p=strrchr(fn,'/'); if (p!=NULL) { *p=0; strncpy(s,fn,120); s[120]=0; strncpy(what,p+1,80); what[80]=0; if (!resolve_dir(dcc[idx].u.file->dir,s,destdir,atr)) return 0; } else { strcpy(destdir,dcc[idx].u.file->dir); strncpy(what,fn,80); what[80]=0; } f=filedb_open(destdir); fdb=findfile(f,what,&where); if (fdb==NULL) { filedb_close(f); return 0; } if (fdb->stat&(FILE_HIDDEN|FILE_DIR)) { filedb_close(f); return 0; } if (fdb->sharelink[0]) { char bot[121],whoto[NICKLEN]; /* this is a link to a file on another bot... */ splitc(bot,fdb->sharelink,':'); if (!in_chain(bot)) { filedb_close(f); return 0; } else { i=nextbot(bot); strcpy(whoto,nick); if (!whoto[0]) strcpy(whoto,dcc[idx].nick); tprintf(dcc[i].sock,"filereq %d:%s@%s %s:%s\n",dcc[idx].sock, whoto,origbotname,bot,fdb->sharelink); dprintf(idx,"Requested %s from %s ...\n",fdb->sharelink,bot); /* increase got count now (or never) */ fdb->gots++; sprintf(s,"%s:%s",bot,fdb->sharelink); strcpy(fdb->sharelink,s); fseek(f,where,SEEK_SET); fwrite(fdb,sizeof(filedb),1,f); filedb_close(f); return 1; } } filedb_close(f); if (nick[0]) sprintf(what,"%s %s",fdb->filename,nick); else strcpy(what,fdb->filename); do_dcc_send(idx,destdir,what); /* don't increase got count till later */ return 1; } void files_setpwd(idx,where) int idx; char *where; { int atr; char s[121]; context; atr=get_attr_handle(dcc[idx].nick); if (!resolve_dir(dcc[idx].u.file->dir,where,s,atr)) return; strcpy(dcc[idx].u.file->dir,s); set_handle_dccdir(userlist,dcc[idx].nick,dcc[idx].u.file->dir); }