"Fossies" - the Fresh Open Source Software Archive 
Member "unrar/cmddata.cpp" (4 May 2022, 27701 Bytes) of package /linux/misc/unrarsrc-6.1.7.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "cmddata.cpp" see the
Fossies "Dox" file reference documentation.
1 #include "rar.hpp"
2
3 #include "cmdfilter.cpp"
4 #include "cmdmix.cpp"
5
6 CommandData::CommandData()
7 {
8 Init();
9 }
10
11
12 void CommandData::Init()
13 {
14 RAROptions::Init();
15
16 *Command=0;
17 *ArcName=0;
18 FileLists=false;
19 NoMoreSwitches=false;
20
21 ListMode=RCLM_AUTO;
22
23 BareOutput=false;
24
25
26 FileArgs.Reset();
27 ExclArgs.Reset();
28 InclArgs.Reset();
29 StoreArgs.Reset();
30 ArcNames.Reset();
31 NextVolSizes.Reset();
32 }
33
34
35 // Return the pointer to next position in the string and store dynamically
36 // allocated command line parameter in Par.
37 static const wchar *AllocCmdParam(const wchar *CmdLine,wchar **Par)
38 {
39 const wchar *NextCmd=GetCmdParam(CmdLine,NULL,0);
40 if (NextCmd==NULL)
41 return NULL;
42 size_t ParSize=NextCmd-CmdLine+2; // Parameter size including the trailing zero.
43 *Par=(wchar *)malloc(ParSize*sizeof(wchar));
44 if (*Par==NULL)
45 return NULL;
46 return GetCmdParam(CmdLine,*Par,ParSize);
47 }
48
49
50 #if !defined(SFX_MODULE)
51 void CommandData::ParseCommandLine(bool Preprocess,int argc, char *argv[])
52 {
53 *Command=0;
54 NoMoreSwitches=false;
55 #ifdef CUSTOM_CMDLINE_PARSER
56 // In Windows we may prefer to implement our own command line parser
57 // to avoid replacing \" by " in standard parser. Such replacing corrupts
58 // destination paths like "dest path\" in extraction commands.
59 const wchar *CmdLine=GetCommandLine();
60
61 wchar *Par;
62 for (bool FirstParam=true;;FirstParam=false)
63 {
64 if ((CmdLine=AllocCmdParam(CmdLine,&Par))==NULL)
65 break;
66 if (!FirstParam) // First parameter is the executable name.
67 if (Preprocess)
68 PreprocessArg(Par);
69 else
70 ParseArg(Par);
71 free(Par);
72 }
73 #else
74 Array<wchar> Arg;
75 for (int I=1;I<argc;I++)
76 {
77 Arg.Alloc(strlen(argv[I])+1);
78 CharToWide(argv[I],&Arg[0],Arg.Size());
79 if (Preprocess)
80 PreprocessArg(&Arg[0]);
81 else
82 ParseArg(&Arg[0]);
83 }
84 #endif
85 if (!Preprocess)
86 ParseDone();
87 }
88 #endif
89
90
91 #if !defined(SFX_MODULE)
92 void CommandData::ParseArg(wchar *Arg)
93 {
94 if (IsSwitch(*Arg) && !NoMoreSwitches)
95 if (Arg[1]=='-' && Arg[2]==0)
96 NoMoreSwitches=true;
97 else
98 ProcessSwitch(Arg+1);
99 else
100 if (*Command==0)
101 {
102 wcsncpyz(Command,Arg,ASIZE(Command));
103
104
105 *Command=toupperw(*Command);
106 // 'I' and 'S' commands can contain case sensitive strings after
107 // the first character, so we must not modify their case.
108 // 'S' can contain SFX name, which case is important in Unix.
109 if (*Command!='I' && *Command!='S')
110 wcsupper(Command);
111 if (*Command=='P') // Enforce -idq for print command.
112 {
113 MsgStream=MSG_ERRONLY;
114 SetConsoleMsgStream(MSG_ERRONLY);
115 }
116 }
117 else
118 if (*ArcName==0)
119 wcsncpyz(ArcName,Arg,ASIZE(ArcName));
120 else
121 {
122 // Check if last character is the path separator.
123 size_t Length=wcslen(Arg);
124 wchar EndChar=Length==0 ? 0:Arg[Length-1];
125 bool EndSeparator=IsDriveDiv(EndChar) || IsPathDiv(EndChar);
126
127 wchar CmdChar=toupperw(*Command);
128 bool Add=wcschr(L"AFUM",CmdChar)!=NULL;
129 bool Extract=CmdChar=='X' || CmdChar=='E';
130 bool Repair=CmdChar=='R' && Command[1]==0;
131 if (EndSeparator && !Add)
132 wcsncpyz(ExtrPath,Arg,ASIZE(ExtrPath));
133 else
134 if ((Add || CmdChar=='T') && (*Arg!='@' || ListMode==RCLM_REJECT_LISTS))
135 FileArgs.AddString(Arg);
136 else
137 {
138 FindData FileData;
139 bool Found=FindFile::FastFind(Arg,&FileData);
140 if ((!Found || ListMode==RCLM_ACCEPT_LISTS) &&
141 ListMode!=RCLM_REJECT_LISTS && *Arg=='@' && !IsWildcard(Arg+1))
142 {
143 FileLists=true;
144
145 ReadTextFile(Arg+1,&FileArgs,false,true,FilelistCharset,true,true,true);
146
147 }
148 else // We use 'destpath\' when extracting and reparing.
149 if (Found && FileData.IsDir && (Extract || Repair) && *ExtrPath==0)
150 {
151 wcsncpyz(ExtrPath,Arg,ASIZE(ExtrPath));
152 AddEndSlash(ExtrPath,ASIZE(ExtrPath));
153 }
154 else
155 FileArgs.AddString(Arg);
156 }
157 }
158 }
159 #endif
160
161
162 void CommandData::ParseDone()
163 {
164 if (FileArgs.ItemsCount()==0 && !FileLists)
165 FileArgs.AddString(MASKALL);
166 wchar CmdChar=toupperw(Command[0]);
167 bool Extract=CmdChar=='X' || CmdChar=='E' || CmdChar=='P';
168 if (Test && Extract)
169 Test=false; // Switch '-t' is senseless for 'X', 'E', 'P' commands.
170
171 // Suppress the copyright message and final end of line for 'lb' and 'vb'.
172 if ((CmdChar=='L' || CmdChar=='V') && Command[1]=='B')
173 BareOutput=true;
174 }
175
176
177 #if !defined(SFX_MODULE)
178 void CommandData::ParseEnvVar()
179 {
180 char *EnvStr=getenv("RAR");
181 if (EnvStr!=NULL)
182 {
183 Array<wchar> EnvStrW(strlen(EnvStr)+1);
184 CharToWide(EnvStr,&EnvStrW[0],EnvStrW.Size());
185 ProcessSwitchesString(&EnvStrW[0]);
186 }
187 }
188 #endif
189
190
191
192 #if !defined(SFX_MODULE)
193 // Preprocess those parameters, which must be processed before the rest of
194 // command line. Return 'false' to stop further processing.
195 void CommandData::PreprocessArg(const wchar *Arg)
196 {
197 if (IsSwitch(Arg[0]) && !NoMoreSwitches)
198 {
199 Arg++;
200 if (Arg[0]=='-' && Arg[1]==0) // Switch "--".
201 NoMoreSwitches=true;
202 if (wcsicomp(Arg,L"cfg-")==0)
203 ConfigDisabled=true;
204 if (wcsnicomp(Arg,L"ilog",4)==0)
205 {
206 // Ensure that correct log file name is already set
207 // if we need to report an error when processing the command line.
208 ProcessSwitch(Arg);
209 InitLogOptions(LogName,ErrlogCharset);
210 }
211 if (wcsnicomp(Arg,L"sc",2)==0)
212 {
213 // Process -sc before reading any file lists.
214 ProcessSwitch(Arg);
215 if (*LogName!=0)
216 InitLogOptions(LogName,ErrlogCharset);
217 }
218 }
219 else
220 if (*Command==0)
221 wcsncpy(Command,Arg,ASIZE(Command)); // Need for rar.ini.
222 }
223 #endif
224
225
226 #if !defined(SFX_MODULE)
227 void CommandData::ReadConfig()
228 {
229 StringList List;
230 if (ReadTextFile(DefConfigName,&List,true))
231 {
232 wchar *Str;
233 while ((Str=List.GetString())!=NULL)
234 {
235 while (IsSpace(*Str))
236 Str++;
237 if (wcsnicomp(Str,L"switches=",9)==0)
238 ProcessSwitchesString(Str+9);
239 if (*Command!=0)
240 {
241 wchar Cmd[16];
242 wcsncpyz(Cmd,Command,ASIZE(Cmd));
243 wchar C0=toupperw(Cmd[0]);
244 wchar C1=toupperw(Cmd[1]);
245 if (C0=='I' || C0=='L' || C0=='M' || C0=='S' || C0=='V')
246 Cmd[1]=0;
247 if (C0=='R' && (C1=='R' || C1=='V'))
248 Cmd[2]=0;
249 wchar SwName[16+ASIZE(Cmd)];
250 swprintf(SwName,ASIZE(SwName),L"switches_%ls=",Cmd);
251 size_t Length=wcslen(SwName);
252 if (wcsnicomp(Str,SwName,Length)==0)
253 ProcessSwitchesString(Str+Length);
254 }
255 }
256 }
257 }
258 #endif
259
260
261 #if !defined(SFX_MODULE)
262 void CommandData::ProcessSwitchesString(const wchar *Str)
263 {
264 wchar *Par;
265 while ((Str=AllocCmdParam(Str,&Par))!=NULL)
266 {
267 if (IsSwitch(*Par))
268 ProcessSwitch(Par+1);
269 free(Par);
270 }
271 }
272 #endif
273
274
275 #if !defined(SFX_MODULE)
276 void CommandData::ProcessSwitch(const wchar *Switch)
277 {
278
279 switch(toupperw(Switch[0]))
280 {
281 case '@':
282 ListMode=Switch[1]=='+' ? RCLM_ACCEPT_LISTS:RCLM_REJECT_LISTS;
283 break;
284 case 'A':
285 switch(toupperw(Switch[1]))
286 {
287 case 'C':
288 ClearArc=true;
289 break;
290 case 'D':
291 if (Switch[2]==0)
292 AppendArcNameToPath=APPENDARCNAME_DESTPATH;
293 else
294 if (Switch[2]=='1')
295 AppendArcNameToPath=APPENDARCNAME_OWNSUBDIR;
296 else
297 if (Switch[2]=='2')
298 AppendArcNameToPath=APPENDARCNAME_OWNDIR;
299 break;
300 #ifndef SFX_MODULE
301 case 'G':
302 if (Switch[2]=='-' && Switch[3]==0)
303 GenerateArcName=0;
304 else
305 if (toupperw(Switch[2])=='F')
306 wcsncpyz(DefGenerateMask,Switch+3,ASIZE(DefGenerateMask));
307 else
308 {
309 GenerateArcName=true;
310 wcsncpyz(GenerateMask,Switch+2,ASIZE(GenerateMask));
311 }
312 break;
313 #endif
314 case 'I':
315 IgnoreGeneralAttr=true;
316 break;
317 case 'N': // Reserved for archive name.
318 break;
319 case 'O':
320 AddArcOnly=true;
321 break;
322 case 'P':
323 wcsncpyz(ArcPath,Switch+2,ASIZE(ArcPath));
324 break;
325 case 'S':
326 SyncFiles=true;
327 break;
328 default:
329 BadSwitch(Switch);
330 break;
331 }
332 break;
333 case 'C':
334 if (Switch[2]==0)
335 switch(toupperw(Switch[1]))
336 {
337 case '-':
338 DisableComment=true;
339 break;
340 case 'U':
341 ConvertNames=NAMES_UPPERCASE;
342 break;
343 case 'L':
344 ConvertNames=NAMES_LOWERCASE;
345 break;
346 }
347 break;
348 case 'D':
349 if (Switch[2]==0)
350 switch(toupperw(Switch[1]))
351 {
352 case 'S':
353 DisableSortSolid=true;
354 break;
355 case 'H':
356 OpenShared=true;
357 break;
358 case 'F':
359 DeleteFiles=true;
360 break;
361 }
362 break;
363 case 'E':
364 switch(toupperw(Switch[1]))
365 {
366 case 'P':
367 switch(Switch[2])
368 {
369 case 0:
370 ExclPath=EXCL_SKIPWHOLEPATH;
371 break;
372 case '1':
373 ExclPath=EXCL_BASEPATH;
374 break;
375 case '2':
376 ExclPath=EXCL_SAVEFULLPATH;
377 break;
378 case '3':
379 ExclPath=EXCL_ABSPATH;
380 break;
381 case '4':
382 wcsncpyz(ExclArcPath,Switch+3,ASIZE(ExclArcPath));
383 break;
384 }
385 break;
386 default:
387 if (Switch[1]=='+')
388 {
389 InclFileAttr|=GetExclAttr(Switch+2,InclDir);
390 InclAttrSet=true;
391 }
392 else
393 ExclFileAttr|=GetExclAttr(Switch+1,ExclDir);
394 break;
395 }
396 break;
397 case 'F':
398 if (Switch[1]==0)
399 FreshFiles=true;
400 else
401 BadSwitch(Switch);
402 break;
403 case 'H':
404 switch (toupperw(Switch[1]))
405 {
406 case 'P':
407 EncryptHeaders=true;
408 if (Switch[2]!=0)
409 {
410 if (wcslen(Switch+2)>=MAXPASSWORD)
411 uiMsg(UIERROR_TRUNCPSW,MAXPASSWORD-1);
412 Password.Set(Switch+2);
413 cleandata((void *)Switch,wcslen(Switch)*sizeof(Switch[0]));
414 }
415 else
416 if (!Password.IsSet())
417 {
418 uiGetPassword(UIPASSWORD_GLOBAL,NULL,&Password);
419 eprintf(L"\n");
420 }
421 break;
422 default :
423 BadSwitch(Switch);
424 break;
425 }
426 break;
427 case 'I':
428 if (wcsnicomp(Switch+1,L"LOG",3)==0)
429 {
430 wcsncpyz(LogName,Switch[4]!=0 ? Switch+4:DefLogName,ASIZE(LogName));
431 break;
432 }
433 if (wcsnicomp(Switch+1,L"SND",3)==0)
434 {
435 Sound=Switch[4]=='-' ? SOUND_NOTIFY_OFF : SOUND_NOTIFY_ON;
436 break;
437 }
438 if (wcsicomp(Switch+1,L"ERR")==0)
439 {
440 MsgStream=MSG_STDERR;
441 // Set it immediately when parsing the command line, so it also
442 // affects messages issued while parsing the command line.
443 SetConsoleMsgStream(MSG_STDERR);
444 break;
445 }
446 if (wcsnicomp(Switch+1,L"EML",3)==0)
447 {
448 wcsncpyz(EmailTo,Switch[4]!=0 ? Switch+4:L"@",ASIZE(EmailTo));
449 break;
450 }
451 if (wcsicomp(Switch+1,L"M")==0) // For compatibility with pre-WinRAR 6.0 -im syntax. Replaced with -idv.
452 {
453 VerboseOutput=true;
454 break;
455 }
456 if (wcsicomp(Switch+1,L"NUL")==0)
457 {
458 MsgStream=MSG_NULL;
459 SetConsoleMsgStream(MSG_NULL);
460 break;
461 }
462 if (toupperw(Switch[1])=='D')
463 {
464 for (uint I=2;Switch[I]!=0;I++)
465 switch(toupperw(Switch[I]))
466 {
467 case 'Q':
468 MsgStream=MSG_ERRONLY;
469 SetConsoleMsgStream(MSG_ERRONLY);
470 break;
471 case 'C':
472 DisableCopyright=true;
473 break;
474 case 'D':
475 DisableDone=true;
476 break;
477 case 'P':
478 DisablePercentage=true;
479 break;
480 case 'N':
481 DisableNames=true;
482 break;
483 case 'V':
484 VerboseOutput=true;
485 break;
486 }
487 break;
488 }
489 if (wcsnicomp(Switch+1,L"OFF",3)==0)
490 {
491 switch(Switch[4])
492 {
493 case 0:
494 case '1':
495 Shutdown=POWERMODE_OFF;
496 break;
497 case '2':
498 Shutdown=POWERMODE_HIBERNATE;
499 break;
500 case '3':
501 Shutdown=POWERMODE_SLEEP;
502 break;
503 case '4':
504 Shutdown=POWERMODE_RESTART;
505 break;
506 }
507 break;
508 }
509 if (wcsicomp(Switch+1,L"VER")==0)
510 {
511 PrintVersion=true;
512 break;
513 }
514 break;
515 case 'K':
516 switch(toupperw(Switch[1]))
517 {
518 case 'B':
519 KeepBroken=true;
520 break;
521 case 0:
522 Lock=true;
523 break;
524 }
525 break;
526 case 'M':
527 switch(toupperw(Switch[1]))
528 {
529 case 'C':
530 {
531 const wchar *Str=Switch+2;
532 if (*Str=='-')
533 for (uint I=0;I<ASIZE(FilterModes);I++)
534 FilterModes[I].State=FILTER_DISABLE;
535 else
536 while (*Str!=0)
537 {
538 int Param1=0,Param2=0;
539 FilterState State=FILTER_AUTO;
540 FilterType Type=FILTER_NONE;
541 if (IsDigit(*Str))
542 {
543 Param1=atoiw(Str);
544 while (IsDigit(*Str))
545 Str++;
546 }
547 if (*Str==':' && IsDigit(Str[1]))
548 {
549 Param2=atoiw(++Str);
550 while (IsDigit(*Str))
551 Str++;
552 }
553 switch(toupperw(*(Str++)))
554 {
555 case 'T': Type=FILTER_PPM; break;
556 case 'E': Type=FILTER_E8; break;
557 case 'D': Type=FILTER_DELTA; break;
558 case 'A': Type=FILTER_AUDIO; break;
559 case 'C': Type=FILTER_RGB; break;
560 case 'R': Type=FILTER_ARM; break;
561 }
562 if (*Str=='+' || *Str=='-')
563 State=*(Str++)=='+' ? FILTER_FORCE:FILTER_DISABLE;
564 FilterModes[Type].State=State;
565 FilterModes[Type].Param1=Param1;
566 FilterModes[Type].Param2=Param2;
567 }
568 }
569 break;
570 case 'M':
571 break;
572 case 'D':
573 break;
574 case 'E':
575 if (toupperw(Switch[2])=='S' && Switch[3]==0)
576 SkipEncrypted=true;
577 break;
578 case 'S':
579 {
580 wchar StoreNames[1024];
581 wcsncpyz(StoreNames,(Switch[2]==0 ? DefaultStoreList:Switch+2),ASIZE(StoreNames));
582 wchar *Names=StoreNames;
583 while (*Names!=0)
584 {
585 wchar *End=wcschr(Names,';');
586 if (End!=NULL)
587 *End=0;
588 if (*Names=='.')
589 Names++;
590 wchar Mask[NM];
591 if (wcspbrk(Names,L"*?.")==NULL)
592 swprintf(Mask,ASIZE(Mask),L"*.%ls",Names);
593 else
594 wcsncpyz(Mask,Names,ASIZE(Mask));
595 StoreArgs.AddString(Mask);
596 if (End==NULL)
597 break;
598 Names=End+1;
599 }
600 }
601 break;
602 #ifdef RAR_SMP
603 case 'T':
604 Threads=atoiw(Switch+2);
605 if (Threads>MaxPoolThreads || Threads<1)
606 BadSwitch(Switch);
607 else
608 {
609 }
610 break;
611 #endif
612 default:
613 Method=Switch[1]-'0';
614 if (Method>5 || Method<0)
615 BadSwitch(Switch);
616 break;
617 }
618 break;
619 case 'N':
620 case 'X':
621 if (Switch[1]!=0)
622 {
623 StringList *Args=toupperw(Switch[0])=='N' ? &InclArgs:&ExclArgs;
624 if (Switch[1]=='@' && !IsWildcard(Switch))
625 ReadTextFile(Switch+2,Args,false,true,FilelistCharset,true,true,true);
626 else
627 Args->AddString(Switch+1);
628 }
629 break;
630 case 'O':
631 switch(toupperw(Switch[1]))
632 {
633 case '+':
634 Overwrite=OVERWRITE_ALL;
635 break;
636 case '-':
637 Overwrite=OVERWRITE_NONE;
638 break;
639 case 0:
640 Overwrite=OVERWRITE_FORCE_ASK;
641 break;
642 #ifdef _WIN_ALL
643 case 'C':
644 SetCompressedAttr=true;
645 break;
646 #endif
647 case 'H':
648 SaveHardLinks=true;
649 break;
650
651
652 #ifdef SAVE_LINKS
653 case 'L':
654 SaveSymLinks=true;
655 if (toupperw(Switch[2])=='A')
656 AbsoluteLinks=true;
657 break;
658 #endif
659 #ifdef _WIN_ALL
660 case 'N':
661 if (toupperw(Switch[2])=='I')
662 AllowIncompatNames=true;
663 break;
664 #endif
665 case 'P':
666 wcsncpyz(ExtrPath,Switch+2,ASIZE(ExtrPath));
667 AddEndSlash(ExtrPath,ASIZE(ExtrPath));
668 break;
669 case 'R':
670 Overwrite=OVERWRITE_AUTORENAME;
671 break;
672 #ifdef _WIN_ALL
673 case 'S':
674 SaveStreams=true;
675 break;
676 #endif
677 case 'W':
678 ProcessOwners=true;
679 break;
680 default :
681 BadSwitch(Switch);
682 break;
683 }
684 break;
685 case 'P':
686 if (Switch[1]==0)
687 {
688 uiGetPassword(UIPASSWORD_GLOBAL,NULL,&Password);
689 eprintf(L"\n");
690 }
691 else
692 {
693 if (wcslen(Switch+1)>=MAXPASSWORD)
694 uiMsg(UIERROR_TRUNCPSW,MAXPASSWORD-1);
695 Password.Set(Switch+1);
696 cleandata((void *)Switch,wcslen(Switch)*sizeof(Switch[0]));
697 }
698 break;
699 #ifndef SFX_MODULE
700 case 'Q':
701 if (toupperw(Switch[1])=='O')
702 switch(toupperw(Switch[2]))
703 {
704 case 0:
705 QOpenMode=QOPEN_AUTO;
706 break;
707 case '-':
708 QOpenMode=QOPEN_NONE;
709 break;
710 case '+':
711 QOpenMode=QOPEN_ALWAYS;
712 break;
713 default:
714 BadSwitch(Switch);
715 break;
716 }
717 else
718 BadSwitch(Switch);
719 break;
720 #endif
721 case 'R':
722 switch(toupperw(Switch[1]))
723 {
724 case 0:
725 Recurse=RECURSE_ALWAYS;
726 break;
727 case '-':
728 Recurse=RECURSE_DISABLE;
729 break;
730 case '0':
731 Recurse=RECURSE_WILDCARDS;
732 break;
733 case 'I':
734 {
735 Priority=atoiw(Switch+2);
736 if (Priority<0 || Priority>15)
737 BadSwitch(Switch);
738 const wchar *ChPtr=wcschr(Switch+2,':');
739 if (ChPtr!=NULL)
740 {
741 SleepTime=atoiw(ChPtr+1);
742 if (SleepTime>1000)
743 BadSwitch(Switch);
744 InitSystemOptions(SleepTime);
745 }
746 SetPriority(Priority);
747 }
748 break;
749 }
750 break;
751 case 'S':
752 if (IsDigit(Switch[1]))
753 {
754 Solid|=SOLID_COUNT;
755 SolidCount=atoiw(&Switch[1]);
756 }
757 else
758 switch(toupperw(Switch[1]))
759 {
760 case 0:
761 Solid|=SOLID_NORMAL;
762 break;
763 case '-':
764 Solid=SOLID_NONE;
765 break;
766 case 'E':
767 Solid|=SOLID_FILEEXT;
768 break;
769 case 'V':
770 Solid|=Switch[2]=='-' ? SOLID_VOLUME_DEPENDENT:SOLID_VOLUME_INDEPENDENT;
771 break;
772 case 'D':
773 Solid|=SOLID_VOLUME_DEPENDENT;
774 break;
775 case 'I':
776 ProhibitConsoleInput();
777 wcsncpyz(UseStdin,Switch[2] ? Switch+2:L"stdin",ASIZE(UseStdin));
778 break;
779 case 'L':
780 if (IsDigit(Switch[2]))
781 FileSizeLess=atoilw(Switch+2);
782 break;
783 case 'M':
784 if (IsDigit(Switch[2]))
785 FileSizeMore=atoilw(Switch+2);
786 break;
787 case 'C':
788 {
789 bool AlreadyBad=false; // Avoid reporting "bad switch" several times.
790
791 RAR_CHARSET rch=RCH_DEFAULT;
792 switch(toupperw(Switch[2]))
793 {
794 case 'A':
795 rch=RCH_ANSI;
796 break;
797 case 'O':
798 rch=RCH_OEM;
799 break;
800 case 'U':
801 rch=RCH_UNICODE;
802 break;
803 case 'F':
804 rch=RCH_UTF8;
805 break;
806 default :
807 BadSwitch(Switch);
808 AlreadyBad=true;
809 break;
810 };
811 if (!AlreadyBad)
812 if (Switch[3]==0)
813 CommentCharset=FilelistCharset=ErrlogCharset=RedirectCharset=rch;
814 else
815 for (uint I=3;Switch[I]!=0 && !AlreadyBad;I++)
816 switch(toupperw(Switch[I]))
817 {
818 case 'C':
819 CommentCharset=rch;
820 break;
821 case 'L':
822 FilelistCharset=rch;
823 break;
824 case 'R':
825 RedirectCharset=rch;
826 break;
827 default:
828 BadSwitch(Switch);
829 AlreadyBad=true;
830 break;
831 }
832 // Set it immediately when parsing the command line, so it also
833 // affects messages issued while parsing the command line.
834 SetConsoleRedirectCharset(RedirectCharset);
835 }
836 break;
837
838 }
839 break;
840 case 'T':
841 switch(toupperw(Switch[1]))
842 {
843 case 'K':
844 ArcTime=ARCTIME_KEEP;
845 break;
846 case 'L':
847 ArcTime=ARCTIME_LATEST;
848 break;
849 case 'O':
850 SetTimeFilters(Switch+2,true,true);
851 break;
852 case 'N':
853 SetTimeFilters(Switch+2,false,true);
854 break;
855 case 'B':
856 SetTimeFilters(Switch+2,true,false);
857 break;
858 case 'A':
859 SetTimeFilters(Switch+2,false,false);
860 break;
861 case 'S':
862 SetStoreTimeMode(Switch+2);
863 break;
864 case '-':
865 Test=false;
866 break;
867 case 0:
868 Test=true;
869 break;
870 default:
871 BadSwitch(Switch);
872 break;
873 }
874 break;
875 case 'U':
876 if (Switch[1]==0)
877 UpdateFiles=true;
878 else
879 BadSwitch(Switch);
880 break;
881 case 'V':
882 switch(toupperw(Switch[1]))
883 {
884 case 'P':
885 VolumePause=true;
886 break;
887 case 'E':
888 if (toupperw(Switch[2])=='R')
889 VersionControl=atoiw(Switch+3)+1;
890 break;
891 case '-':
892 VolSize=0;
893 break;
894 default:
895 VolSize=VOLSIZE_AUTO; // UnRAR -v switch for list command.
896 break;
897 }
898 break;
899 case 'W':
900 wcsncpyz(TempPath,Switch+1,ASIZE(TempPath));
901 AddEndSlash(TempPath,ASIZE(TempPath));
902 break;
903 case 'Y':
904 AllYes=true;
905 break;
906 case 'Z':
907 if (Switch[1]==0)
908 {
909 // If comment file is not specified, we read data from stdin.
910 wcsncpyz(CommentFile,L"stdin",ASIZE(CommentFile));
911 }
912 else
913 wcsncpyz(CommentFile,Switch+1,ASIZE(CommentFile));
914 break;
915 case '?' :
916 OutHelp(RARX_SUCCESS);
917 break;
918 default :
919 BadSwitch(Switch);
920 break;
921 }
922 }
923 #endif
924
925
926 #if !defined(SFX_MODULE)
927 void CommandData::BadSwitch(const wchar *Switch)
928 {
929 mprintf(St(MUnknownOption),Switch);
930 ErrHandler.Exit(RARX_USERERROR);
931 }
932 #endif
933
934
935 void CommandData::ProcessCommand()
936 {
937 #ifndef SFX_MODULE
938
939 const wchar *SingleCharCommands=L"FUADPXETK";
940 if (Command[0]!=0 && Command[1]!=0 && wcschr(SingleCharCommands,Command[0])!=NULL || *ArcName==0)
941 OutHelp(*Command==0 ? RARX_SUCCESS:RARX_USERERROR); // Return 'success' for 'rar' without parameters.
942
943 const wchar *ArcExt=GetExt(ArcName);
944 #ifdef _UNIX
945 if (ArcExt==NULL && (!FileExist(ArcName) || IsDir(GetFileAttr(ArcName))))
946 wcsncatz(ArcName,L".rar",ASIZE(ArcName));
947 #else
948 if (ArcExt==NULL)
949 wcsncatz(ArcName,L".rar",ASIZE(ArcName));
950 #endif
951 // Treat arcname.part1 as arcname.part1.rar.
952 if (ArcExt!=NULL && wcsnicomp(ArcExt,L".part",5)==0 && IsDigit(ArcExt[5]) &&
953 !FileExist(ArcName))
954 {
955 wchar Name[NM];
956 wcsncpyz(Name,ArcName,ASIZE(Name));
957 wcsncatz(Name,L".rar",ASIZE(Name));
958 if (FileExist(Name))
959 wcsncpyz(ArcName,Name,ASIZE(ArcName));
960 }
961
962 if (wcschr(L"AFUMD",*Command)==NULL && *UseStdin==0)
963 {
964 if (GenerateArcName)
965 {
966 const wchar *Mask=*GenerateMask!=0 ? GenerateMask:DefGenerateMask;
967 GenerateArchiveName(ArcName,ASIZE(ArcName),Mask,false);
968 }
969
970 StringList ArcMasks;
971 ArcMasks.AddString(ArcName);
972 ScanTree Scan(&ArcMasks,Recurse,SaveSymLinks,SCAN_SKIPDIRS);
973 FindData FindData;
974 while (Scan.GetNext(&FindData)==SCAN_SUCCESS)
975 AddArcName(FindData.Name);
976 }
977 else
978 AddArcName(ArcName);
979 #endif
980
981 switch(Command[0])
982 {
983 case 'P':
984 case 'X':
985 case 'E':
986 case 'T':
987 {
988 CmdExtract Extract(this);
989 Extract.DoExtract();
990 }
991 break;
992 #ifndef SILENT
993 case 'V':
994 case 'L':
995 ListArchive(this);
996 break;
997 default:
998 OutHelp(RARX_USERERROR);
999 #endif
1000 }
1001 if (!BareOutput)
1002 mprintf(L"\n");
1003 }
1004
1005
1006 void CommandData::AddArcName(const wchar *Name)
1007 {
1008 ArcNames.AddString(Name);
1009 }
1010
1011
1012 bool CommandData::GetArcName(wchar *Name,int MaxSize)
1013 {
1014 return ArcNames.GetString(Name,MaxSize);
1015 }
1016
1017
1018 bool CommandData::IsSwitch(int Ch)
1019 {
1020 #if defined(_WIN_ALL) || defined(_EMX)
1021 return Ch=='-' || Ch=='/';
1022 #else
1023 return Ch=='-';
1024 #endif
1025 }
1026
1027
1028 #ifndef SFX_MODULE
1029 uint CommandData::GetExclAttr(const wchar *Str,bool &Dir)
1030 {
1031 if (IsDigit(*Str))
1032 return wcstol(Str,NULL,0);
1033
1034 uint Attr=0;
1035 while (*Str!=0)
1036 {
1037 switch(toupperw(*Str))
1038 {
1039 case 'D':
1040 Dir=true;
1041 break;
1042 #ifdef _UNIX
1043 case 'V':
1044 Attr|=S_IFCHR;
1045 break;
1046 #elif defined(_WIN_ALL) || defined(_EMX)
1047 case 'R':
1048 Attr|=0x1;
1049 break;
1050 case 'H':
1051 Attr|=0x2;
1052 break;
1053 case 'S':
1054 Attr|=0x4;
1055 break;
1056 case 'A':
1057 Attr|=0x20;
1058 break;
1059 #endif
1060 }
1061 Str++;
1062 }
1063 return Attr;
1064 }
1065 #endif
1066
1067
1068
1069
1070 #ifndef SFX_MODULE
1071 bool CommandData::CheckWinSize()
1072 {
1073 // Define 0x100000000 as macro to avoid troubles with older compilers.
1074 const uint64 MaxDictSize=INT32TO64(1,0);
1075 // Limit the dictionary size to 4 GB.
1076 for (uint64 I=0x10000;I<=MaxDictSize;I*=2)
1077 if (WinSize==I)
1078 return true;
1079 WinSize=0x400000;
1080 return false;
1081 }
1082 #endif
1083
1084
1085 #ifndef SFX_MODULE
1086 void CommandData::ReportWrongSwitches(RARFORMAT Format)
1087 {
1088 if (Format==RARFMT15)
1089 {
1090 if (HashType!=HASH_CRC32)
1091 uiMsg(UIERROR_INCOMPATSWITCH,L"-ht",4);
1092 #ifdef _WIN_ALL
1093 if (SaveSymLinks)
1094 uiMsg(UIERROR_INCOMPATSWITCH,L"-ol",4);
1095 #endif
1096 if (SaveHardLinks)
1097 uiMsg(UIERROR_INCOMPATSWITCH,L"-oh",4);
1098
1099 #ifdef _WIN_ALL
1100 // Do not report a wrong dictionary size here, because we are not sure
1101 // yet about archive format. We can switch to RAR5 mode later
1102 // if we update RAR5 archive.
1103
1104
1105 #endif
1106 if (QOpenMode!=QOPEN_AUTO)
1107 uiMsg(UIERROR_INCOMPATSWITCH,L"-qo",4);
1108 }
1109 if (Format==RARFMT50)
1110 {
1111 }
1112 }
1113 #endif