blob: f4df0a542e70aeaace68ec909e8b32c6729ed6e8 [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001// MorgenGrauen MUDlib
2//
3//fileedit.c
4//
5// $Id: fileedit.c 9142 2015-02-04 22:17:29Z Zesstra $
6#pragma strict_types
7#pragma save_types
8//#pragma range_check
9#pragma no_clone
10#pragma pedantic
11
12#include <wizlevels.h>
13#include <input_to.h>
14
15#define NEED_PROTOTYPES
16#include <magier.h>
17#include <player.h>
18#include <files.h>
19
20// ###################
21//######################### INITIALISIERUNG #############################
22// ###################
23
24mixed _query_localcmds()
25{
26 return ({ ({"cp","_cp",0,WIZARD_LVL}),
27 ({"mv","_cp",0,WIZARD_LVL}),
28 ({"rm","_rm",0,WIZARD_LVL}),
29 ({"rmdir","_rmdir",0,WIZARD_LVL}),
30 ({"mkdir","_mkdir",0,WIZARD_LVL}),
31 ({"ed","_ed",0,WIZARD_LVL})});
32}
33
34// ######
35//################################ ED ###################################
36// ######
37
38
39//
40// _ed_file: Mehrere Files hintereinander editieren
41//
42
43private nosave string *_ed_cache;
44
45private void _ed_file()
46{
47 if (!sizeof(_ed_cache)) return;
48 printf("ed: Naechste Datei: %s\n",_ed_cache[0]);
49 ed(_ed_cache[0],"_ed_file");
50 _ed_cache=_ed_cache[1..];
51 return;
52}
53
54#if __VERSION__ < "3.2.9"
55private mixed _ed_size_filter(mixed *arg)
56{
57 if (arg[FILESIZE]>=-1) return arg[FULLNAME];
58 printf("%s ist ein Verzeichnis.\n",arg[FULLNAME]);
59 return 0;
60}
61#endif
62
63//
64// _more: Dateien anzeigen
65// cmdline: Kommandozeile
66//
67
68static int _ed(string cmdline)
69{
70 mixed *args,*args2;
71 int flags,i,arg_size;
72 cmdline=_unparsed_args();
73 args=parseargs(cmdline,&flags,"",1);
74 if (flags==-1||!(arg_size=sizeof(args)))
75 return USAGE("ed <datei> [<datei2>..]");
76 while(arg_size--)
77 {
78 if (sizeof(args2=file_list(args[arg_size..arg_size],MODE_ED,0,"/")))
79 args[arg_size..arg_size]=args2;
80 else
81 args[arg_size]=({ "" , -1, 0 , (string)
82 call_other(master(),"_get_path",args[arg_size],
83 getuid())});
84 }
85#if __VERSION__ < "3.2.9"
86 args=map(args,#'_ed_size_filter)-({0});
87#else
88 args=map(args,(:
89 if ($1[FILESIZE]>=-1) return $1[FULLNAME];
90 printf("%s ist ein Verzeichnis.\n",$1[FULLNAME]);
91 return 0; :))-({0});
92#endif
93 if (flags==-1||!sizeof(args)) return USAGE("ed <datei> [<datei2>..]");
94 _ed_cache=args;
95 _ed_file();
96 return 1;
97}
98
99
100// ###########
101//############################## CP & MV ################################
102// ###########
103
104static void _cp_ask_copy(mixed *filedata,int dummy, int flags);
105static void _cp_ask_overwrite(mixed *filedata, int mode, int flags);
106static void _mv_ask_overwrite(mixed *filedata, int mode, int flags);
107
108static mixed cp_file(mixed filedata,int move,int flags, mixed *do_delete)
109{
110 string source,dest;
111 source=(string)filedata[FULLNAME];
112 dest=(string)filedata[DESTNAME];
113 if (source==dest) return ERROR(SAME_FILE,source,RET_FAIL);
114 if (!MAY_READ(source)) return ERROR(NO_READ,source,RET_JUMP);
115 if (!MAY_WRITE(dest)) return ERROR(NO_WRITE,dest,RET_JUMP);
116 if (filedata[FILESIZE]==-1) return ERROR(DOESNT_EXIST,source,RET_JUMP);
117 if (filedata[FILESIZE]==-2) // Quelle ist Verzeichnis
118 {
119 switch(file_size(dest))
120 {
121 case -1:
122 if (move)
123 {
124 if (rename(source,dest)) return ERROR(NO_CREATE_DIR,dest,RET_JUMP);
125 if (flags&CP_V) printf(FILE_MOVED,source);
126 return RET_JUMP;
127 }
128 if (!mkdir(dest)) return ERROR(NO_CREATE_DIR,dest,RET_JUMP);
129 if (flags&CP_V) printf(DIR_CREATED,dest);
130 case -2:
131 if (!move) return RET_OK;
132 if (filedata[SUBDIRSIZE]>0) return RET_DELETE;
133 if (!rmdir(source)) return ERROR(NO_DELETE,source,RET_FAIL);
134 if (flags&MV_V) printf("mv: %s: Quellverzeichnis wurde "
135 "geloescht.\n",source);
136 return RET_OK;
137 default: return ERROR(NO_DIRS,dest,RET_JUMP);
138 }
139 }
140 switch(file_size(dest))
141 {
142 case -2: return ERROR(DEST_IS_DIR,dest,RET_FAIL);
143 default:
144 if (flags&CP_F)
145 {
146 if (!rm(dest)) return ERROR(DEST_NO_DELETE,dest,RET_FAIL);
147 if (flags&CP_V) printf(FILE_DELETED,dest);
148 }
149 else
150 {
151 if (move) return #'_mv_ask_overwrite;
152 else return #'_cp_ask_overwrite;
153 }
154 case -1:
155 if (move)
156 {
157 if (rename(source,dest)) return ERROR(NO_MOVE,source,RET_FAIL);
158 if (flags&CP_V) printf(FILE_MOVED,source);
159 return RET_OK;
160 }
161 if (copy_file(source,dest)) return ERROR(NO_COPY,source,RET_FAIL);
162 if (flags&CP_V) printf(FILE_COPIED,source);
163 return RET_OK;
164 }
165 return 0; // not-reached
166}
167
168static void _cp_ask_overwrite2(string input, mixed *filedata,
169 int interactive,int flags,int move)
170{
171 if (!sizeof(input)) input=" ";
172 input=lower_case(input);
173 switch(input[0])
174 {
175 case 'q':
176 printf("%s abgebrochen!\n",move?"Bewegen":"Kopieren");
177 return;
178 case 'a':
179 flags|=CP_F;
180 if (!(flags&CP_I))
181 {
182 asynchron(filedata,#'cp_file,move,flags,0);
183 return;
184 }
185 case 'y':
186 case 'j':
187 if (!rm(filedata[0][DESTNAME]))
188 printf(DEST_NO_DELETE "Uebergehe Datei...\n",filedata[0][DESTNAME]);
189 else
190 {
191 if (flags&CP_V) printf(FILE_DELETED,filedata[0][DESTNAME]);
192 if (move)
193 {
194 if (rename(filedata[0][FULLNAME],filedata[0][DESTNAME]))
195 printf(NO_MOVE "Uebergehe Datei...\n",filedata[0][FULLNAME]);
196 }
197 else
198 {
199 if (copy_file(filedata[0][FULLNAME],filedata[0][DESTNAME]))
200 printf(NO_COPY "Uebergehe Datei...\n",filedata[0][FULLNAME]);
201 }
202 }
203 case 'n':
204 if (flags&CP_I)
205 _cp_ask_copy(filedata[1+filedata[0][SUBDIRSIZE]..],move,flags);
206 else
207 asynchron(filedata[1+filedata[0][SUBDIRSIZE]..],
208 #'cp_file,move,flags,0);
209 return;
210 default:
211 printf("Kommando nicht verstanden.\n");
212 _cp_ask_overwrite(filedata,interactive,flags);
213 return;
214 }
215
216}
217
218static void _cp_ask_overwrite(mixed *filedata, int interactive, int flags)
219{
220 printf("Die Datei '%s' existiert schon.\n",
221 filedata[0][DESTNAME]);
222 input_to("_cp_ask_overwrite2",INPUT_PROMPT,"Ueberschreiben? (j,n,a,q): ",
223 filedata,interactive,flags,0);
224 return;
225}
226
227static void _mv_ask_overwrite(mixed *filedata, int interactive, int flags)
228{
229 printf("Die Datei '%s' existiert schon.",
230 filedata[0][DESTNAME]);
231 input_to("_cp_ask_overwrite2",INPUT_PROMPT,"Ueberschreiben? (j,n,a,q): ",
232 filedata,interactive,flags,1);
233 return;
234}
235
236static void _cp_ask_copy2(string input,mixed *filedata,int mode,
237 int flags,int move)
238{
239 if (!sizeof(input)) input=" ";
240 input=lower_case(input);
241 switch(input[0])
242 {
243 case 'y':
244 case 'j':
245 if (mode==1)
246 {
247 if (!(flags&CP_F))
248 {
249 if (move) _mv_ask_overwrite(filedata,1,flags);
250 else _cp_ask_overwrite(filedata,1,flags);
251 return;
252 }
253 if (!rm(filedata[0][DESTNAME]))
254 {
255 printf(DEST_NO_DELETE "Uebergehe Datei...\n",
256 filedata[0][DESTNAME]);
257 _cp_ask_copy(filedata[1..],move,flags);
258 return;
259 }
260 if (flags&CP_V) printf(FILE_DELETED,filedata[0][DESTNAME]);
261 }
262 if (mode<2)
263 {
264 if (move) rename(filedata[0][FULLNAME],filedata[0][DESTNAME]);
265 else copy_file(filedata[0][FULLNAME],filedata[0][DESTNAME]);
266 _cp_ask_copy(filedata[1..],move,flags);
267 return;
268 }
269 if (mode==2)
270 {
271 if (move)
272 {
273 if (rename(filedata[0][FULLNAME],filedata[0][DESTNAME]))
274 printf(NO_MOVE "Uebergehe Verzeichnis...\n",
275 filedata[0][FULLNAME]);
276 _cp_ask_copy(filedata[1+filedata[0][SUBDIRSIZE]..],move,flags);
277 return;
278 }
279 if (mkdir(filedata[0][DESTNAME]))
280 {
281 _cp_ask_copy(filedata[1..],0,flags);
282 return;
283 }
284 printf(NO_CREATE_DIR "Uebergehe Verzeichnis...\n",
285 filedata[0][DESTNAME]);
286 }
287 case 'n':
288 _cp_ask_copy(filedata[(1+filedata[0][SUBDIRSIZE])..],0,flags);
289 return;
290 case 'q':
291 printf("Kopieren abgebrochen!\n");
292 return;
293 case 'a':
294 flags&=~CP_I;
295 asynchron(filedata,#'cp_file,move,flags,0);
296 return;
297 default:
298 printf("Kommando nicht verstanden.\n");
299 _cp_ask_copy(filedata,0,flags);
300 return;
301 }
302}
303
304static void _cp_ask_copy(mixed *filedata,int move, int flags)
305{
306 mixed data;
307 string dest,source;
308 int delete_subs,jump;
309
310 if(!sizeof(filedata))
311 {
312 printf("%s: abgeschlossen.\n",move?"mv":"cp");
313 return;
314 }
315 dest=filedata[0][DESTNAME];
316 source=filedata[0][FULLNAME];
317 switch(0) // break wirkt damit wie ein goto end_of_switch
318 {
319 default:
320 case 0: // Sinnlos, aber er compiliert sonst nicht :(
321 jump=filedata[0][SUBDIRSIZE];
322 if (source==dest)
323 {
324 printf(SAME_FILE,source);
325 break;
326 }
327 if (!MAY_READ(source))
328 {
329 printf(NO_READ,source);
330 break;
331 }
332 if (!MAY_WRITE(dest))
333 {
334 printf(NO_WRITE,dest);
335 jump=0;
336 break;
337 }
338 if (filedata[0][FILESIZE]==-1)
339 {
340 printf(DOESNT_EXIST,source);
341 break;
342 }
343 if (filedata[0][FILESIZE]==-2) // Quelle ist Verzeichnis
344 {
345 if (file_size(dest)>-1)
346 {
347 printf(NO_DIRS,dest);
348 break;
349 }
350 if (file_size(dest)==-2)
351 {
352 jump=0;
353 break;
354 }
355 printf("Verzeichnis '%s' %s?\n",source,
356 move?"bewegen":"kopieren");
357 input_to("_cp_ask_copy2",INPUT_PROMPT, "(j,n,a,q) ",
358 filedata,2,flags,move);
359 return;
360 }
361 if (file_size(dest)==-2)
362 {
363 printf(DEST_IS_DIR,dest);
364 break;
365 }
366 printf("'%s' %s?\n",source,move?"bewegen":"kopieren");
367 input_to("_cp_ask_copy2",INPUT_PROMPT, "(j,n,a,q) ",
368 filedata,(file_size(dest)!=-1),flags,move);
369 return;
370 }
371 _cp_ask_copy(filedata[1+jump..],move,flags);
372 return;
373}
374
375
376static int _cp(string cmdline)
377{
378 mixed *args;
379 int flags;
380 string mask;
381 string dest,*dest2;
382 cmdline=_unparsed_args();
383 args=parseargs(cmdline,&flags,CP_OPTS,0);
384 if (flags==-1||!sizeof(args))
385 return USAGE(query_verb()+" [-" CP_OPTS
386 "] <datei/verz> [<datei2/verz2> ... ] <ziel> [<maske>]");
387 if (flags&CP_M)
388 {
389 mask=args[<1];
390 args=args[0..<2];
391 }
392 if (!dest=to_filename(args[<1]))
393 return USAGE(query_verb()+" [-" CP_OPTS
394 "] <datei/verz> [<datei2/verz2> ... ] <ziel> [<maske>]");
395 if (file_size(dest)==-1)
396 {
397 dest2=explode(dest,"/");
398 if (file_size(implode(dest2[0..<2],"/"))==-2)
399 {
400 if (dest2[<1]=="*")
401 dest=implode(dest2[0..<2],"/");
402 else
403 if (member(dest2[<1],'*')>-1||
404 member(dest2[<1],'?')>-1)
405 return notify_fail(
406 sprintf("%s: Keine * und ? im Zielnamen erlaubt.\n",query_verb())),0;
407 }
408 else
409 return notify_fail(
410 sprintf("%s: Der angegebene Zielpfad existiert nicht.\n",
411 query_verb())),0;
412 }
413 args=args[0..<2];
414 if (file_size(dest)!=-2&&sizeof(args)>1)
415 return notify_fail(
416 sprintf("%s: Bei mehreren Quellen muss das Ziel ein Verzeichnis "
417 "sein.\n",query_verb())),0;
418 if (!sizeof(args=map(args,#'to_filename)-({0})))
419 return USAGE(query_verb()+" [-" CP_OPTS
420 "] <datei/verz> [<datei2/verz2> ... ] <ziel> [<maske>]");
421 // DEBUG("DEST: " + dest + " : FLAGS: " + flags);
422 args=file_list(args,MODE_CP,(flags&CP_R),dest+"/",mask);
423 if (!sizeof(args))
424 return notify_fail(sprintf("%s: Keine passenden Dateien gefunden.\n",
425 query_verb())),0;
426
427 if (sizeof(args)>1&&(args[0][FILESIZE]>=0)&&file_size(dest)!=-2)
428 return notify_fail(
429 sprintf("%s: Bei mehreren Quellen muss das Ziel ein Verzeichnis "
430 "sein.\n",query_verb())),0;
431 if (sizeof(args)==1&&file_size(dest)!=-2)
432 args[0][DESTNAME]=dest;
433 if (!(flags&CP_I))
434 {
435 asynchron(args,#'cp_file,(query_verb()=="mv"),flags,0);
436 return 1;
437 }
438 if (query_verb()=="cp")
439 _cp_ask_copy(args,0,flags);
440 else
441 _cp_ask_copy(args,1,flags);
442 return 1;
443}
444
445// #########
446//############################### RMDIR #################################
447// #########
448
449
450//
451// _rmdir: Verzeichnis loeschen
452// cmdline: Kommandozeilenargumente
453//
454
455
456#if __VERSION__ < "3.2.9"
457
458private int _dir_filter(mixed arg)
459{
460 return (arg[FILESIZE]==-2);
461}
462
463#endif
464
465static int _rmdir(string cmdline)
466{
467 string dest,tmp;
468 int flags;
469 mixed *args;
470
471 cmdline=_unparsed_args();
472 args=parseargs(cmdline,&flags,RMDIR_OPTS,1);
473 if (flags==-1||!sizeof(args))
474 return USAGE("rmdir [-" RMDIR_OPTS "] <Verzeichnis>");
475 if (sizeof(args)>1)
476 return
477 notify_fail("Mit 'rmdir' kann nur jeweils EIN Verzeichnis geloescht "
478 "werden.\nDer Befehl 'rm' bietet erweiterte Moeglichkeiten.\n"),0;
479 dest=args[0];
480 if (dest!="/")
481 {
482 args=file_list(({dest}),MODE_RMDIR,0,"/");
483#if __VERSION__ < "3.2.9"
484 args=filter(args,#'_dir_filter);
485#else
486 args=filter(args,(: ($1[FILESIZE]==-2) :));
487#endif
488 if (!sizeof(args))
489 return notify_fail(
490 sprintf("rmdir: %s: Kein solches Verzeichnis gefunden.\n",dest)),0;
491 if (sizeof(args)>1)
492 return notify_fail(
493 sprintf("rmdir: %s: Maske ist nicht eindeutig.\n",dest)),0;
494 dest=args[0][FULLNAME];
495 if (!MAY_WRITE(dest)) return ERROR(NO_WRITE,dest,1);
496 if (!rmdir(dest))
497 {
498 if (sizeof((get_dir(dest+"/*")||({}))-({".",".."})))
499 printf("rmdir: %s: Verzeichnis ist nicht leer.\n",dest);
500 }
501 else
502 {
503 if (flags&&RMDIR_V) printf(FILE_DELETED,dest);
504 }
505 return 1;
506 }
507 return ERROR(NO_DELETE,dest,1);
508}
509
510// #########
511//############################### MKDIR #################################
512// #########
513
514
515//
516// _mkdir: Verzeichnis erstellen
517// cmdline: Kommandozeilenargumente
518//
519
520static int _mkdir(string cmdline)
521{
522 string dest,tmp;
523 int flags,i;
524 string *args;
525
526 cmdline=_unparsed_args();
527 args=parseargs(cmdline,&flags,MKDIR_OPTS,1);
528 if (flags==-1) return 0;
529 if (!sizeof(args))
530 return USAGE("mkdir [-" MKDIR_OPTS "] <Verzeichnis>");
531 if (sizeof(args)>1)
532 return notify_fail("Mit 'mkdir' kann nur jeweils EIN Verzeichnis "
533 "erstellt werden.\n"),0;
534 dest=args[0];
535
536 if ((i=file_size(implode((args=explode(dest,"/"))[0..<2],"/")))==FSIZE_DIR)
537 {
538 if (!mkdir(dest)) return ERROR(NO_CREATE_DIR,dest,1);
539 if (flags&MKDIR_V) printf(DIR_CREATED,dest,1);
540 printf("mkdir: abgeschlossen.\n");
541 return 1;
542 }
543
544 if (i==FSIZE_NOFILE)
545 {
546 if (flags&MKDIR_R)
547 {
548 if (mkdirp(dest) != 1)
549 return ERROR(NO_CREATE_DIR,dest,1);
550 if (flags&MKDIR_V)
551 printf(DIR_CREATED,implode(args[0..i],"/"));
552 printf("mkdir: abgeschlossen.\n");
553 return 1;
554 }
555 return ERROR(DOESNT_EXIST,implode(args[0..<2],"/"),1);
556 }
557 return ERROR(ALREADY_EXISTS,dest,1);
558}
559
560// ######
561//################################ RM ###################################
562// ######
563
564private void _rm_ask_delete(mixed *filedata, int flags);
565
566static void _rm_ask_delete2(string input,mixed *filedata,int flags)
567{
568 int i;
569 if (!sizeof(input)) input=" ";
570 input=lower_case(input);
571 switch(input[0])
572 {
573 case 'q':
574 printf("Loeschen abgebrochen!\n");
575 return;
576 case 'y':
577 case 'j':
578 if (filedata[0][FILESIZE]==-2)
579 {
580 if (i=filedata[0][SUBDIRSIZE]) // Dir-Eintrag nach hinten schieben
581 {
582 mixed temp;
583 int j;
584 temp=filedata[0];
585 temp[SUBDIRSIZE]=0;
586 for(j=0;j<i;j++) filedata[j]=filedata[j+1];
587 filedata[j]=temp;
588 _rm_ask_delete(filedata,flags);
589 return;
590 }
591 if (!rmdir(filedata[0][FULLNAME]))
592 printf(NO_DELETE,filedata[0][FULLNAME]);
593 else if (flags&RM_V) printf(FILE_DELETED,filedata[0][FULLNAME]);
594 }
595 else // Datei existiert
596 {
597 if (!rm(filedata[0][FULLNAME]))
598 printf(DEST_NO_DELETE "Uebergehe Datei...\n",
599 filedata[0][FULLNAME]);
600 else if (flags&RM_V) printf(FILE_DELETED,filedata[0][FULLNAME]);
601
602 }
603 case 'n':
604 _rm_ask_delete(filedata[1+filedata[0][SUBDIRSIZE]..],flags);
605 return;
606 default:
607 printf("Kommando nicht verstanden.\n");
608 _rm_ask_delete(filedata,flags);
609 return;
610 }
611 return;
612}
613
614private void _rm_ask_delete(mixed *filedata, int flags)
615{
616 int i;
617 mixed temp;
618 if (!sizeof(filedata))
619 {
620 printf("rm: abgeschlossen.\n");
621 return;
622 }
623 switch(filedata[0][FILESIZE])
624 {
625 case -1:
626 if (flags&RM_V) printf(DOESNT_EXIST,filedata[0][FULLNAME]);
627 _rm_ask_delete(filedata[1..],flags);
628 return;
629 case -2:
630 if (i=filedata[0][SUBDIRSIZE])
631 printf("Ins Verzeichnis '%s' hinabsteigen?\n",
632 filedata[0][FULLNAME]);
633 else
634 printf("Verzeichnis '%s' loeschen?\n",
635 filedata[0][FULLNAME]);
636 input_to("_rm_ask_delete2",INPUT_PROMPT, "(j,n,q) ",
637 filedata,flags);
638 return;
639 default:
640 printf("'%s' loeschen? (j,n,q)\n",
641 filedata[0][FULLNAME]);
642 input_to("_rm_ask_delete2",INPUT_PROMPT, "(j,n,q) ",
643 filedata,flags);
644 return;
645 }
646}
647
648
649private void rm_file(mixed filedata, mixed notused, int flags)
650{
651 string dest;
652 dest=filedata[FULLNAME];
653 if (!MAY_WRITE(dest))
654 {
655 printf(NO_WRITE,dest);
656 return;
657 }
658 switch(filedata[FILESIZE])
659 {
660 case -1:
661 if (flags&RM_V) printf(DOESNT_EXIST,dest);
662 return;
663 case -2:
664 if (!rmdir(dest)) printf(DEST_NO_DELETE,dest);
665 else
666 {
667 if (flags&RM_V) printf(FILE_DELETED,dest);
668 }
669 return;
670 default:
671 if (!rm(dest)) printf(DEST_NO_DELETE,dest);
672 else
673 {
674 if (flags&RM_V) printf(FILE_DELETED,dest);
675 }
676 return;
677 }
678}
679
680static int _rm(string cmdline)
681{
682 mixed *args,*args2;
683 int flags,i;
684 string mask;
685
686 cmdline=_unparsed_args();
687 args=parseargs(cmdline,&flags,RM_OPTS,0);
688 if (flags==-1||!sizeof(args))
689 return USAGE("rm [-" RM_OPTS
690 "] <datei/verz> [<datei2/verz2> ... ] [<maske>]");
691 if (flags&RM_M)
692 {
693 mask=args[<1];
694 args=args[0..<2];
695 }
696 args=map(args,#'to_filename)-({0});
697 args=file_list(args,MODE_RM,(flags&RM_R),"/",mask);
698 if (!(i=sizeof(args)))
699 return printf("Keine passende Datei gefunden.\n"),1;
700 if (!(flags&RM_I))
701 {
702 if (i>1) // Umdrehen
703 {
704 mixed temp;
705 i>>=1;
706 while(i)
707 {
708 temp=args[<(i--)];
709 args[<(i+1)]=args[i];
710 args[i]=temp;
711 }
712 }
713 asynchron(args,#'rm_file,args,flags,0);
714 return 1;
715 }
716 _rm_ask_delete(args,flags);
717 return 1;
718}