Beispiel #1
0
bool FindFile::Next(FindData *fd,bool GetSymLink)
{
  fd->Error=false;
  if (*FindMask==0)
    return false;
#ifdef _WIN_ALL
  if (FirstCall)
  {
    if ((hFind=Win32Find(INVALID_HANDLE_VALUE,FindMask,fd))==INVALID_HANDLE_VALUE)
      return false;
  }
  else
    if (Win32Find(hFind,FindMask,fd)==INVALID_HANDLE_VALUE)
      return false;
#else
  if (FirstCall)
  {
    wchar DirName[NM];
    wcsncpyz(DirName,FindMask,ASIZE(DirName));
    RemoveNameFromPath(DirName);
    if (*DirName==0)
      wcscpy(DirName,L".");
    char DirNameA[NM];
    WideToChar(DirName,DirNameA,ASIZE(DirNameA));
    if ((dirp=opendir(DirNameA))==NULL)
    {
      fd->Error=(errno!=ENOENT);
      return false;
    }
  }
  while (1)
  {
    struct dirent *ent=readdir(dirp);
    if (ent==NULL)
      return false;
    if (strcmp(ent->d_name,".")==0 || strcmp(ent->d_name,"..")==0)
      continue;
    wchar Name[NM];
    if (!CharToWide(ent->d_name,Name,ASIZE(Name)))
      Log(NULL,St(MInvalidName),Name);

    if (CmpName(FindMask,Name,MATCH_NAMES))
    {
      wchar FullName[NM];
      wcscpy(FullName,FindMask);
      *PointToName(FullName)=0;
      if (wcslen(FullName)+wcslen(Name)>=ASIZE(FullName)-1)
      {
#ifndef SILENT
        Log(NULL,L"\n%ls%ls",FullName,Name);
        Log(NULL,St(MPathTooLong));
#endif
        return false;
      }
      wcscat(FullName,Name);
      if (!FastFind(FullName,fd,GetSymLink))
      {
        ErrHandler.OpenErrorMsg(NULL,FullName);
        continue;
      }
      wcscpy(fd->Name,FullName);
      break;
    }
  }
#endif
  fd->Flags=0;
  fd->IsDir=IsDir(fd->FileAttr);
  fd->IsLink=IsLink(fd->FileAttr);

  FirstCall=false;
  wchar *NameOnly=PointToName(fd->Name);
  if (wcscmp(NameOnly,L".")==0 || wcscmp(NameOnly,L"..")==0)
    return Next(fd);
  return true;
}
Beispiel #2
0
int main(int argc, char **argv)
{
	int cnt, x, y, i = 0, verbose = 0;
	Window win = 0;
	Bool keysymMappingInitialized = False;
	int rc = 0;
	int inputEvents[100];
	int inputEventsIndex = 0;
	int iEvent = 0;

	if (argc == 1)
		usage(argv[0]);

	const char* log_file = NULL;
	if (streq(argv[1],"-o") || streq(argv[1],"--logfile")) {
		i++;

		if (++i > argc)
			usage(argv[0]);

		log_file = argv[i];
	}
	report_init(log_file);

	if (!xhandler_init(getenv("DISPLAY")))
		exit(1);

	report_add_message(xhandler_get_server_time(), "Startup\n");

	/* initialize subsystems */
	xemu_init(xhandler.display);
	scheduler_init(xhandler.display);
	window_init(xhandler.display);
	application_init();

	/*
	 * Process the command line options.
	 * Skip emulation options (--click, --drag, --key, --type), but remember they index
	 * and process them later.
	 */
	while (++i < argc) {

		if (streq(argv[i],"-v") || streq(argv[i],"--verbose")) {
			verbose = 1;
			continue;
		}

		if (streq(argv[i], "-id") || streq(argv[i], "--id")) {
			char name[PATH_MAX];
			if (++i >= argc)
				usage(argv[0]);

			cnt = sscanf(argv[i], "0x%lx", &win);
			if (cnt < 1) {
				cnt = sscanf(argv[i], "%lu", &win);
			}
			if (cnt < 1) {
				fprintf(stderr, "*** invalid window id '%s'\n", argv[i]);
				usage(argv[0]);
			}
			sprintf(name, "0x%lx", win);
			if (!window_add(win, application_monitor(name))) {
				fprintf(stderr, "Could not setup damage monitoring for window 0x%lx!\n", win);
				exit(1);
			}
			if (verbose)
				report_add_message(REPORT_LAST_TIMESTAMP, "Monitoring window 0x%lx\n", win);

			continue;
		}

		if (streq(argv[i], "-a") || streq(argv[i], "--application")) {
			if (++i >= argc)
				usage(argv[0]);

			response.application = application_monitor(argv[i]);
			if (response.application && verbose) {
				report_add_message(REPORT_LAST_TIMESTAMP, "Monitoring application '%s'\n", argv[i]);
			}
			if (!strcmp(argv[i], "*")) {
				application_set_monitor_all(true);
			}
			continue;
		}

		if (streq("-c", argv[i]) || streq("--click", argv[i])) {
			if (!xemu.pointer.dev) {
				fprintf(stderr, "Failed to open pointer device, unable to simulate pointer events.\n");
				exit(-1);
			}
			if (inputEventsIndex == ASIZE(inputEvents)) {
				fprintf(stderr, "Too many input events specified\n");
				exit(-1);
			}
			if (!argv[i + 1] || !match_regex(argv[i + 1], "^[0-9]+x[0-9]+(,[0-9]+)?$")) {
				fprintf(stderr, "Failed to parse --c options: %s\n", argv[i + 1]);
				exit(-1);
			}
			inputEvents[inputEventsIndex++] = i;
			if (++i >= argc)
				usage(argv[0]);

			continue;
		}

		if (streq("-l", argv[i]) || streq("--level", argv[i])) {
			if (++i >= argc)
				usage(argv[0]);

			if (!strcmp(argv[i], "raw")) {
				window_set_damage_level(XDamageReportRawRectangles);
			} else if (!strcmp(argv[i], "delta")) {
				window_set_damage_level(XDamageReportDeltaRectangles);
			} else if (!strcmp(argv[i], "box")) {
				window_set_damage_level(XDamageReportDeltaRectangles);
			} else if (!strcmp(argv[i], "nonempty")) {
				window_set_damage_level(XDamageReportNonEmpty);
			} else {
				fprintf(stderr, "Unrecongnized damage level: %s\n", argv[i]);
				usage(argv[0]);
			}
			if (verbose)
				report_add_message(REPORT_LAST_TIMESTAMP, "Setting damage report level to %s\n", argv[i]);
			continue;
		}

		if (streq("-x", argv[i]) || streq("--exclude", argv[i])) {
			char* exclude[] = { "none", "less", "greater" };

			if (options.exclude_rules != EXCLUDE_NONE) {
				fprintf(stderr, "Duplicated --exclude parameter detected. Aborting\n");
				exit(-1);
			}

			if (++i >= argc)
				usage(argv[0]);
			char rules[32] = "";
			if ((cnt = sscanf(argv[i], "%ux%u,%s", &options.exclude_rect.width, &options.exclude_rect.height, rules)) >= 2) {
				options.exclude_size = 0;
			} else if ((cnt = sscanf(argv[i], "%u,%s", &options.exclude_size, rules)) >= 1) {
				options.exclude_rect.width = 0;
				options.exclude_rect.height = 0;
			} else {
				fprintf(stderr, "*** failed to parse '%s'\n", argv[i]);
				usage(argv[0]);
			}
			options.exclude_rules = *rules && !strcmp(rules, "greater") ? EXCLUDE_GREATER : EXCLUDE_LESS;
			if (verbose) {
				if (options.exclude_size) {
					report_add_message(REPORT_LAST_TIMESTAMP, "Excluding damage areas %s than %d pixels\n", exclude[options.exclude_rules],
							options.exclude_size);
				} else {
					report_add_message(REPORT_LAST_TIMESTAMP, "Excluding damage areas %s than (%dx%d)\n", exclude[options.exclude_rules],
							options.exclude_rect.width, options.exclude_rect.height);
				}
			}
			continue;
		}

		if (streq("-m", argv[i]) || streq("--monitor", argv[i])) {
			if (options.interested_damage_rect.width || options.interested_damage_rect.height || options.interested_damage_rect.x
					|| options.interested_damage_rect.y) {
				fprintf(stderr, "Duplicated --monitor parameter detected. Aborting\n");
				exit(-1);
			}
			if (++i >= argc)
				usage(argv[0]);

			if ((cnt = sscanf(argv[i], "%ux%u+%u+%u", &options.interested_damage_rect.width, &options.interested_damage_rect.height,
					&options.interested_damage_rect.x, &options.interested_damage_rect.y)) != 4) {
				fprintf(stderr, "*** failed to parse '%s'\n", argv[i]);
				usage(argv[0]);
			}
			if (verbose) {
				report_add_message(REPORT_LAST_TIMESTAMP, "Set monitor rect to %ix%i+%i+%i\n", options.interested_damage_rect.width,
						options.interested_damage_rect.height, options.interested_damage_rect.x, options.interested_damage_rect.y);
			}
			continue;
		}

		if (streq("-w", argv[i]) || streq("--wait", argv[i])) {
			if (++i >= argc)
				usage(argv[0]);

			if (options.damage_wait_secs >= 0) {
				fprintf(stderr, "Duplicate -w(--wait) option detected. Discarding the previous value\n");
			}
			if ((options.damage_wait_secs = atoi(argv[i])) < 0) {
				fprintf(stderr, "*** failed to parse '%s'\n", argv[i]);
				usage(argv[0]);
			}
			if (verbose)
				report_add_message(REPORT_LAST_TIMESTAMP, "Set event timeout to %isecs\n", options.damage_wait_secs);

			continue;
		}

		if (streq("-b", argv[i]) || streq("--break", argv[i])) {
			if (options.break_timeout || options.break_on_damage) {
				fprintf(stderr, "Duplicate -b(--break)option detected. Discarding the previous value\n");
				options.break_timeout = 0;
				options.break_on_damage = 0;
			}
			if (++i >= argc)
				usage(argv[0]);

			if (!strncmp(argv[i], "damage", 6)) {
				sscanf(argv[i] + 6, ",%d", &options.break_on_damage);
				if (!options.break_on_damage)
					options.break_on_damage = 1;
				if (verbose)
					report_add_message(REPORT_LAST_TIMESTAMP, "Break wait on the %d damage event\n", options.break_on_damage);
			} else {
				if ((options.break_timeout = atoi(argv[i])) < 0) {
					fprintf(stderr, "*** failed to parse '%s'\n", argv[i]);
					usage(argv[0]);
				}
				if (verbose)
					report_add_message(REPORT_LAST_TIMESTAMP, "Set break timout to %imsecs\n", options.break_timeout);
			}
			continue;
		}

		if (streq("-d", argv[i]) || streq("--drag", argv[i])) {
			if (!xemu.pointer.dev) {
				fprintf(stderr, "Failed to open pointer device, unable to simulate pointer events.\n");
				exit(-1);
			}
			if (inputEventsIndex == ASIZE(inputEvents)) {
				fprintf(stderr, "Too many input events specified\n");
				exit(-1);
			}
			if (!argv[i + 1] || (!match_regex(argv[i + 1], "^([0-9]+,)?(([0-9]+x[0-9]+,([0-9]+,)?)+[0-9]+x[0-9]+)$") &&
				 (!match_regex(argv[i + 1], "[0-9]+x[0-9]+-[0-9]+x[0-9]+") ||
				  !match_regex(argv[i + 1], "^(((([0-9]+,)?([0-9]+x[0-9]+)|([0-9]+x[0-9]+-[0-9]+x[0-9]+(\\*[0-9]+)?(\\+[1-9][0-9]*)?)),?)+)$") ) ) ) {
				fprintf(stderr, "Failed to parse --drag options: %s\n", argv[i + 1]);
				exit(-1);
			}
			inputEvents[inputEventsIndex++] = i;

			if (++i >= argc)
				usage(argv[0]);
			continue;
		}

		if (streq("-k", argv[i]) || streq("--key", argv[i])) {
			if (!xemu.keyboard.dev) {
				fprintf(stderr, "Failed to open keyboard device, unable to simulate keyboard events.\n");
				exit(-1);
			}
			if (inputEventsIndex == ASIZE(inputEvents)) {
				fprintf(stderr, "Too many input events specified\n");
				exit(-1);
			}
			inputEvents[inputEventsIndex++] = i;
			if (++i >= argc)
				usage(argv[0]);

			continue;
		}

		if (streq("-t", argv[i]) || streq("--type", argv[i])) {
			if (!xemu.keyboard.dev) {
				fprintf(stderr, "Failed to open keyboard device, unable to simulate keyboard events.\n");
				exit(-1);
			}
			if (inputEventsIndex == ASIZE(inputEvents)) {
				fprintf(stderr, "Too many input events specified\n");
				exit(-1);
			}
			inputEvents[inputEventsIndex++] = i;
			if (++i >= argc)
				usage(argv[0]);

			if (!keysymMappingInitialized) {
				xemu_load_keycodes();
				keysymMappingInitialized = True;
			}

			continue;
		}

		/* since moving from command sequence approach the inspect parameter is deprecated */
		if (streq("-i", argv[i]) || streq("--inspect", argv[i])) {
			if (verbose)
				report_add_message(REPORT_LAST_TIMESTAMP, "Just displaying damage events until timeout\n");
			continue;
		}

		/* */
		if (streq("-u", argv[i]) || streq("--user", argv[i]) ||
				(xrecord.motion = (streq("-U", argv[i]) || streq("--user-all", argv[i])) ) ) {
			xinput_init(xhandler.display);
			if (verbose)
				report_add_message(REPORT_LAST_TIMESTAMP, "Reporting user input events\n");

			continue;
		}

		if (streq(argv[i], "-r") || streq(argv[i], "--response")) {
			if (++i >= argc)
				usage(argv[0]);
			char option[500];
			cnt = sscanf(argv[i], "%u,%s", &response.timeout, option);
			if (cnt < 1) {
				fprintf(stderr, "*** invalid response timeout value '%s'\n", argv[i]);
				usage(argv[0]);
			}
			if (cnt < 2) {
				report_set_silent(true);
			} else {
				if (strcmp(option, "verbose")) {
					fprintf(stderr, "*** invalid response option '%s'\n", argv[i]);
					usage(argv[0]);
				}
			}
			application_monitor_screen();
			xinput_init(xhandler.display);
			if (verbose)
				report_add_message(REPORT_LAST_TIMESTAMP, "Monitoring application response time\n");

			continue;
		}

		fprintf(stderr, "*** Dont understand  %s\n", argv[i]);
		usage(argv[0]);
	}

	/* start monitoring the root window if no targets are specified */
	if ((window_empty() && application_empty()) || response.timeout) {
		application_monitor(ROOT_WINDOW_RESOURCE);
	}

	window_monitor_all();
	application_start_monitor();

	/* eat first damage event when options.break_on_damage set */
	if (options.break_on_damage)
		xhandler_eat_damage();

	/* monitor the whole screen of no area is specified */
	if (!options.interested_damage_rect.width && !options.interested_damage_rect.height && !options.interested_damage_rect.x
			&& !options.interested_damage_rect.y) {
		options.interested_damage_rect.x = 0;
		options.interested_damage_rect.y = 0;
		options.interested_damage_rect.width = DisplayWidth(xhandler.display, DefaultScreen(xhandler.display));
		options.interested_damage_rect.height = DisplayHeight(xhandler.display, DefaultScreen(xhandler.display));
	}

	/* emulate user input */

	for (iEvent = 0; iEvent < inputEventsIndex; iEvent++) {
		i = inputEvents[iEvent];

		if (!strcmp("-c", argv[i]) || !strcmp("--click", argv[i])) {
			unsigned long delay = 0;
			Time start = 0;
			cnt = sscanf(argv[++i], "%ux%u,%lu", &x, &y, &delay);
			if (cnt == 2) {
				start = xhandler_get_server_time();
				report_add_message(start, "Using no delay between press/release\n");
				delay = 0;
			} else if (cnt != 3) {
				fprintf(stderr, "cnt: %d\n", cnt);
				fprintf(stderr, "*** failed to parse '%s'\n", argv[i]);
				usage(argv[0]);
			}
			/* Send the event */
			start = xemu_button_event(x, y, delay);
			report_add_message(start, "Clicked %ix%i\n", x, y);

			continue;
		}

		if (!strcmp("-d", argv[i]) || !strcmp("--drag", argv[i])) {
			Time drag_time;
			char *s = NULL, *p = NULL;
			int button_state = XR_BUTTON_STATE_PRESS;

			s = p = argv[++i];
			int delay = DEFAULT_DRAG_DELAY;
			int x1, y1, x2, y2;
			while (p) {
				p = strchr(s, ',');
				if (p) {
					*p++ = '\0';
				}
				int count = DEFAULT_DRAG_COUNT;
				cnt = sscanf(s, "%ix%i-%ix%i*%i+%i", &x1, &y1, &x2, &y2, &delay, &count);
				if (cnt >= 4) {
					drag_time = xemu_drag_event(x1, y1, button_state, delay);
					button_state = XR_BUTTON_STATE_NONE;
					report_add_message(drag_time, "Dragged to %ix%i\n", x1, y1);

					int xdev = (x2 - x1) / (count + 1);
					int ydev = (y2 - y1) / (count + 1);
					for (i = 1; i <= count; i++) {
						x = x1 + xdev * i;
						y = y1 + ydev * i;
						drag_time = xemu_drag_event(x, y, button_state, delay);
						report_add_message(drag_time, "Dragged to %ix%i\n", x, y);
					}
					if (!p) button_state = XR_BUTTON_STATE_RELEASE;
					drag_time = xemu_drag_event(x2, y2, button_state, delay);
					report_add_message(drag_time, "Dragged to %ix%i\n", x2, y2);
				}
				else if (cnt == 2) {
					/* Send the event */
					if (!p) {
						if (button_state == XR_BUTTON_STATE_PRESS) {
							fprintf(stderr, "*** Need at least 2 drag points!\n");
							usage(argv[0]);
						}
						button_state = XR_BUTTON_STATE_RELEASE;
					}
					drag_time = xemu_drag_event(x1, y1, button_state, delay);
					report_add_message(drag_time, "Dragged to %ix%i\n", x1, y1);

					/* Make sure button state set to none after first point */
					button_state = XR_BUTTON_STATE_NONE;

					/* reset the delay to default value */
					delay = DEFAULT_DRAG_DELAY;
				} else if (cnt == 1) {
					delay = x1;
				} else {
					fprintf(stderr, "*** failed to parse '%s'\n", argv[i]);
					usage(argv[0]);
				}
				s = p;
			}
			continue;
		}

		if (!strcmp("-k", argv[i]) || !strcmp("--key", argv[i])) {
			char *key = NULL;
			char separator;
			unsigned long delay = 0;
			Time start = 0;

			cnt = sscanf(argv[++i], "%a[^,]%c%lu", &key, &separator, &delay);
			if (cnt == 1) {
				report_add_message(REPORT_LAST_TIMESTAMP, "Using default delay between press/release\n", delay);
				delay = DEFAULT_KEY_DELAY;
			} else if (cnt != 3 || separator != ',') {
				fprintf(stderr, "cnt: %d\n", cnt);
				fprintf(stderr, "*** failed to parse '%s'\n", argv[i]);
				if (key != NULL)
					free(key);
				usage(argv[0]);
			}
			start = xemu_send_key(key, delay);
			report_add_message(start, "Simulating keypress/-release pair (keycode '%s')\n", key);
			free(key);

			continue;
		}

		if (!strcmp("-t", argv[i]) || !strcmp("--type", argv[i])) {
			Time start = xemu_send_string(argv[++i]);
			report_add_message(start, "Simulated keys for '%s'\n", argv[i]);

			continue;
		}

	}

	/* setting the default wait period */
	if (options.damage_wait_secs < 0) {
		options.damage_wait_secs = 5;
	}

	signal(SIGINT, abort_wait);
	/* wait for damage events */
	rc = wait_response();

	scheduler_fini();

	report_flush_queue();
	report_fini();
	xinput_fini();
	xemu_fini();

	window_fini();
	application_fini();

	xhandler_fini();


	return rc;
}
Beispiel #3
0
int main(int argc, char* argv[])
{
#ifdef _UNIX
    setlocale(LC_ALL, "");
#endif
#if defined(_EMX) && !defined(_DJGPP)
    uni_init(0);
#endif
#if !defined(_SFX_RTL_) && !defined(_WIN_ALL)
    setbuf(stdout, NULL);
#endif
#if !defined(SFX_MODULE) && defined(_EMX)
    EnumConfigPaths(argv[0], -1);
#endif
    ErrHandler.SetSignalHandlers(true);
    RARInitData();
#ifdef SFX_MODULE
    char ModuleNameA[NM];
    wchar ModuleNameW[NM];
#ifdef _WIN_ALL
    GetModuleFileNameW(NULL, ModuleNameW, ASIZE(ModuleNameW));
    WideToChar(ModuleNameW, ModuleNameA);
#else
    strcpy(ModuleNameA, argv[0]);
    *ModuleNameW = 0;
#endif
#endif
#ifdef _WIN_ALL
    SetErrorMode(SEM_NOALIGNMENTFAULTEXCEPT | SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
#endif
#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SHELL_EXT)
    bool ShutdownOnClose;
#endif
#ifdef ALLOW_EXCEPTIONS

    try
#endif
    {
        CommandData Cmd;
#ifdef SFX_MODULE
        strcpy(Cmd.Command, "X");
        char* Switch = NULL;
#ifdef _SFX_RTL_
        char* CmdLine = GetCommandLineA();

        if (CmdLine != NULL && *CmdLine == '\"')
            CmdLine = strchr(CmdLine + 1, '\"');

        if (CmdLine != NULL && (CmdLine = strpbrk(CmdLine, " /")) != NULL)
        {
            while (IsSpace(*CmdLine))
                CmdLine++;

            Switch = CmdLine;
        }

#else
        Switch = argc > 1 ? argv[1] : NULL;
#endif

        if (Switch != NULL && Cmd.IsSwitch(Switch[0]))
        {
            int UpperCmd = etoupper(Switch[1]);

            switch (UpperCmd)
            {
                case 'T':
                case 'V':
                    Cmd.Command[0] = UpperCmd;
                    break;

                case '?':
                    Cmd.OutHelp();
                    break;
            }
        }

        Cmd.AddArcName(ModuleNameA, ModuleNameW);
#else

        if (Cmd.IsConfigEnabled(argc, argv))
        {
            Cmd.ReadConfig(argc, argv);
            Cmd.ParseEnvVar();
        }

        for (int I = 1; I < argc; I++)
            Cmd.ParseArg(argv[I], NULL);

#endif
        Cmd.ParseDone();
#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SHELL_EXT)
        ShutdownOnClose = Cmd.Shutdown;
#endif
        InitConsoleOptions(Cmd.MsgStream, Cmd.Sound);
        InitLogOptions(Cmd.LogName);
        ErrHandler.SetSilent(Cmd.AllYes || Cmd.MsgStream == MSG_NULL);
        ErrHandler.SetShutdown(Cmd.Shutdown);
        Cmd.OutTitle();
        Cmd.ProcessCommand();
    }

#ifdef ALLOW_EXCEPTIONS

    catch (int ErrCode)
    {
        ErrHandler.SetErrorCode(ErrCode);
    }

#ifdef ENABLE_BAD_ALLOC

    catch (bad_alloc)
    {
        ErrHandler.SetErrorCode(MEMORY_ERROR);
    }

#endif

    catch (...)
    {
        ErrHandler.SetErrorCode(FATAL_ERROR);
    }

#endif
    File::RemoveCreated();
#if defined(SFX_MODULE) && defined(_DJGPP)
    _chmod(ModuleNameA, 1, 0x20);
#endif
#if defined(_EMX) && !defined(_DJGPP)
    uni_done();
#endif
#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SHELL_EXT)

    if (ShutdownOnClose)
        Shutdown();

#endif
    return(ErrHandler.GetErrorCode());
}
Beispiel #4
0
// We should return 'true' even if resulting path is shorter than MAX_PATH,
// because we can also use this function to open files with non-standard
// characters, even if their path length is normal.
bool GetWinLongPath(const wchar *Src,wchar *Dest,size_t MaxSize)
{
  if (*Src==0)
    return false;
  const wchar *Prefix=L"\\\\?\\";
  const size_t PrefixLength=4;
  bool FullPath=IsDiskLetter(Src) && IsPathDiv(Src[2]);
  size_t SrcLength=wcslen(Src);
  if (IsFullPath(Src)) // Paths in d:\path\name format.
  {
    if (IsDiskLetter(Src))
    {
      if (MaxSize<=PrefixLength+SrcLength)
        return false;
      wcsncpy(Dest,Prefix,PrefixLength);
      wcscpy(Dest+PrefixLength,Src);
      return true;
    }
    else
      if (Src[0]=='\\' && Src[1]=='\\')
      {
        if (MaxSize<=PrefixLength+SrcLength+2)
          return false;
        wcsncpy(Dest,Prefix,PrefixLength);
        wcscpy(Dest+PrefixLength,L"UNC");
        wcscpy(Dest+PrefixLength+3,Src+1);
        return true;
      }
    // We may be here only if we modify IsFullPath in the future.
    return false;
  }
  else
  {
    wchar CurDir[NM];
    DWORD DirCode=GetCurrentDirectory(ASIZE(CurDir)-1,CurDir);
    if (DirCode==0 || DirCode>ASIZE(CurDir)-1)
      return false;

    if (IsPathDiv(Src[0])) // Paths in \path\name format.
    {
      if (MaxSize<=PrefixLength+SrcLength+2)
        return false;
      wcsncpy(Dest,Prefix,PrefixLength);
      wcsncpy(Dest+PrefixLength,CurDir,2); // Copy drive letter 'd:'.
      wcscpy(Dest+PrefixLength+2,Src);
      return true;
    }
    else  // Paths in path\name format.
    {
      AddEndSlash(CurDir,ASIZE(CurDir));
      if (MaxSize<=PrefixLength+wcslen(CurDir)+SrcLength)
        return false;
      wcsncpy(Dest,Prefix,PrefixLength);
      wcscpy(Dest+PrefixLength,CurDir);

      if (Src[0]=='.' && IsPathDiv(Src[1])) // Remove leading .\ in pathname.
        Src+=2;

      wcsncatz(Dest,Src,MaxSize);
      return true;
    }
  }
  return false;
}
Beispiel #5
0
size_t Archive::ReadHeader15()
{
  RawRead Raw(this);

  bool Decrypt=Encrypted && CurBlockPos>(int64)SFXSize+SIZEOF_MARKHEAD3;

  if (Decrypt)
  {
#ifdef RAR_NOCRYPT // For rarext.dll and unrar_nocrypt.dll.
    return 0;
#else
    RequestArcPassword();

    byte Salt[SIZE_SALT30];
    if (Read(Salt,SIZE_SALT30)!=SIZE_SALT30)
    {
      UnexpEndArcMsg();
      return(0);
    }
    HeadersCrypt.SetCryptKeys(false,CRYPT_RAR30,&Cmd->Password,Salt,NULL,0,NULL,NULL);
    Raw.SetCrypt(&HeadersCrypt);
#endif
  }

  Raw.Read(SIZEOF_SHORTBLOCKHEAD);
  if (Raw.Size()==0)
  {
    UnexpEndArcMsg();
    return 0;
  }

  ShortBlock.HeadCRC=Raw.Get2();

  ShortBlock.Reset();

  uint HeaderType=Raw.Get1();
  ShortBlock.Flags=Raw.Get2();
  ShortBlock.SkipIfUnknown=(ShortBlock.Flags & SKIP_IF_UNKNOWN)!=0;
  ShortBlock.HeadSize=Raw.Get2();

  ShortBlock.HeaderType=(HEADER_TYPE)HeaderType;
  if (ShortBlock.HeadSize<SIZEOF_SHORTBLOCKHEAD)
  {
    BrokenHeaderMsg();
    return(0);
  }

  // For simpler further processing we map header types common
  // for RAR 1.5 and 5.0 formats to RAR 5.0 values. It does not include
  // header types specific for RAR 1.5 - 4.x only.
  switch(ShortBlock.HeaderType)
  {
    case HEAD3_MAIN:    ShortBlock.HeaderType=HEAD_MAIN;     break;
    case HEAD3_FILE:    ShortBlock.HeaderType=HEAD_FILE;     break;
    case HEAD3_SERVICE: ShortBlock.HeaderType=HEAD_SERVICE;  break;
    case HEAD3_ENDARC:  ShortBlock.HeaderType=HEAD_ENDARC;   break;
    default: break;
  }
  CurHeaderType=ShortBlock.HeaderType;

  if (ShortBlock.HeaderType==HEAD3_CMT)
  {
    // Old style (up to RAR 2.9) comment header embedded into main
    // or file header. We must not read the entire ShortBlock.HeadSize here
    // to not break the comment processing logic later.
    Raw.Read(SIZEOF_COMMHEAD-SIZEOF_SHORTBLOCKHEAD);
  }
  else
    if (ShortBlock.HeaderType==HEAD_MAIN && (ShortBlock.Flags & MHD_COMMENT)!=0)
    {
      // Old style (up to RAR 2.9) main archive comment embedded into
      // the main archive header found. While we can read the entire 
      // ShortBlock.HeadSize here and remove this part of "if", it would be
      // waste of memory, because we'll read and process this comment data
      // in other function anyway and we do not need them here now.
      Raw.Read(SIZEOF_MAINHEAD3-SIZEOF_SHORTBLOCKHEAD);
    }
    else
      Raw.Read(ShortBlock.HeadSize-SIZEOF_SHORTBLOCKHEAD);

  NextBlockPos=CurBlockPos+FullHeaderSize(ShortBlock.HeadSize);

  switch(ShortBlock.HeaderType)
  {
    case HEAD_MAIN:
      MainHead.Reset();
      *(BaseBlock *)&MainHead=ShortBlock;
      MainHead.HighPosAV=Raw.Get2();
      MainHead.PosAV=Raw.Get4();

      Volume=(MainHead.Flags & MHD_VOLUME)!=0;
      Solid=(MainHead.Flags & MHD_SOLID)!=0;
      Locked=(MainHead.Flags & MHD_LOCK)!=0;
      Protected=(MainHead.Flags & MHD_PROTECT)!=0;
      Encrypted=(MainHead.Flags & MHD_PASSWORD)!=0;
      Signed=MainHead.PosAV!=0 || MainHead.HighPosAV!=0;
      MainHead.CommentInHeader=(MainHead.Flags & MHD_COMMENT)!=0;
    
      // Only for encrypted 3.0+ archives. 2.x archives did not have this
      // flag, so for non-encrypted archives, we'll set it later based on
      // file attributes.
      FirstVolume=(MainHead.Flags & MHD_FIRSTVOLUME)!=0;

      NewNumbering=(MainHead.Flags & MHD_NEWNUMBERING)!=0;
      break;
    case HEAD_FILE:
    case HEAD_SERVICE:
      {
        bool FileBlock=ShortBlock.HeaderType==HEAD_FILE;
        FileHeader *hd=FileBlock ? &FileHead:&SubHead;
        hd->Reset();

        *(BaseBlock *)hd=ShortBlock;

        hd->SplitBefore=(hd->Flags & LHD_SPLIT_BEFORE)!=0;
        hd->SplitAfter=(hd->Flags & LHD_SPLIT_AFTER)!=0;
        hd->Encrypted=(hd->Flags & LHD_PASSWORD)!=0;
        hd->SaltSet=(hd->Flags & LHD_SALT)!=0;
        hd->Solid=FileBlock && (hd->Flags & LHD_SOLID)!=0;
        hd->SubBlock=!FileBlock && (hd->Flags & LHD_SOLID)!=0;
        hd->Dir=(hd->Flags & LHD_WINDOWMASK)==LHD_DIRECTORY;
        hd->WinSize=hd->Dir ? 0:0x10000<<((hd->Flags & LHD_WINDOWMASK)>>5);
        hd->CommentInHeader=(hd->Flags & LHD_COMMENT)!=0;
        hd->Version=(hd->Flags & LHD_VERSION)!=0;
        
        hd->DataSize=Raw.Get4();
        uint LowUnpSize=Raw.Get4();
        hd->HostOS=Raw.Get1();

        hd->FileHash.Type=HASH_CRC32;
        hd->FileHash.CRC32=Raw.Get4();

        uint FileTime=Raw.Get4();
        hd->UnpVer=Raw.Get1();
        hd->Method=Raw.Get1()-0x30;
        size_t NameSize=Raw.Get2();
        hd->FileAttr=Raw.Get4();

        hd->CryptMethod=CRYPT_NONE;
        if (hd->Encrypted)
          switch(hd->UnpVer)
          {
            case 13: hd->CryptMethod=CRYPT_RAR13; break;
            case 15: hd->CryptMethod=CRYPT_RAR15; break;
            case 20: 
            case 26: hd->CryptMethod=CRYPT_RAR20; break;
            default: hd->CryptMethod=CRYPT_RAR30; break;
          }

        hd->HSType=HSYS_UNKNOWN;
        if (hd->HostOS==HOST_UNIX || hd->HostOS==HOST_BEOS)
          hd->HSType=HSYS_UNIX;
        else
          if (hd->HostOS<HOST_MAX)
            hd->HSType=HSYS_WINDOWS;

        hd->RedirType=FSREDIR_NONE;

        // RAR 4.x Unix symlink.
        if (hd->HostOS==HOST_UNIX && (hd->FileAttr & 0xF000)==0xA000)
        {
          hd->RedirType=FSREDIR_UNIXSYMLINK;
          *hd->RedirName=0;
        }

        hd->Inherited=!FileBlock && (hd->SubFlags & SUBHEAD_FLAGS_INHERITED)!=0;
        
        hd->LargeFile=(hd->Flags & LHD_LARGE)!=0;

        uint HighPackSize,HighUnpSize;
        if (hd->LargeFile)
        {
          HighPackSize=Raw.Get4();
          HighUnpSize=Raw.Get4();
          hd->UnknownUnpSize=(LowUnpSize==0xffffffff && HighUnpSize==0xffffffff);
        }
        else 
        {
          HighPackSize=HighUnpSize=0;
          // UnpSize equal to 0xffffffff without LHD_LARGE flag indicates
          // that we do not know the unpacked file size and must unpack it
          // until we find the end of file marker in compressed data.
          hd->UnknownUnpSize=(LowUnpSize==0xffffffff);
        }
        hd->PackSize=INT32TO64(HighPackSize,hd->DataSize);
        hd->UnpSize=INT32TO64(HighUnpSize,LowUnpSize);
        if (hd->UnknownUnpSize)
          hd->UnpSize=INT64NDF;

        char FileName[NM*4];
        size_t ReadNameSize=Min(NameSize,ASIZE(FileName)-1);
        Raw.GetB((byte *)FileName,ReadNameSize);
        FileName[ReadNameSize]=0;

        if (FileBlock)
        {
          if ((hd->Flags & LHD_UNICODE)!=0)
          {
            EncodeFileName NameCoder;
            size_t Length=strlen(FileName);
            if (Length==NameSize)
              UtfToWide(FileName,hd->FileName,ASIZE(hd->FileName)-1);
            else
            {
              Length++;
              NameCoder.Decode(FileName,(byte *)FileName+Length,
                               NameSize-Length,hd->FileName,
                               ASIZE(hd->FileName));
            }
          }
          else
            *hd->FileName=0;

          char AnsiName[NM];
          IntToExt(FileName,AnsiName,ASIZE(AnsiName));
          GetWideName(AnsiName,hd->FileName,hd->FileName,ASIZE(hd->FileName));

#ifndef SFX_MODULE
          ConvertNameCase(hd->FileName);
#endif
          ConvertFileHeader(hd);
        }
        else
        {
          CharToWide(FileName,hd->FileName,ASIZE(hd->FileName));

          // Calculate the size of optional data.
          int DataSize=int(hd->HeadSize-NameSize-SIZEOF_FILEHEAD3);
          if ((hd->Flags & LHD_SALT)!=0)
            DataSize-=SIZE_SALT30;

          if (DataSize>0)
          {
            // Here we read optional additional fields for subheaders.
            // They are stored after the file name and before salt.
            hd->SubData.Alloc(DataSize);
            Raw.GetB(&hd->SubData[0],DataSize);
            if (hd->CmpName(SUBHEAD_TYPE_RR))
            {
              byte *D=&hd->SubData[8];
              RecoverySize=D[0]+((uint)D[1]<<8)+((uint)D[2]<<16)+((uint)D[3]<<24);
              RecoverySize*=512; // Sectors to size.
              int64 CurPos=Tell();
              RecoveryPercent=ToPercent(RecoverySize,CurPos);
              // Round fractional percent exceeding .5 to upper value.
              if (ToPercent(RecoverySize+CurPos/200,CurPos)>RecoveryPercent)
                RecoveryPercent++;
            }
          }

          if (hd->CmpName(SUBHEAD_TYPE_CMT))
            MainComment=true;
        }
        if ((hd->Flags & LHD_SALT)!=0)
          Raw.GetB(hd->Salt,SIZE_SALT30);
        hd->mtime.SetDos(FileTime);
        if ((hd->Flags & LHD_EXTTIME)!=0)
        {
          ushort Flags=Raw.Get2();
          RarTime *tbl[4];
          tbl[0]=&FileHead.mtime;
          tbl[1]=&FileHead.ctime;
          tbl[2]=&FileHead.atime;
          tbl[3]=NULL; // Archive time is not used now.
          for (int I=0;I<4;I++)
          {
            RarTime *CurTime=tbl[I];
            uint rmode=Flags>>(3-I)*4;
            if ((rmode & 8)==0 || CurTime==NULL)
              continue;
            if (I!=0)
            {
              uint DosTime=Raw.Get4();
              CurTime->SetDos(DosTime);
            }
            RarLocalTime rlt;
            CurTime->GetLocal(&rlt);
            if (rmode & 4)
              rlt.Second++;
            rlt.Reminder=0;
            int count=rmode&3;
            for (int J=0;J<count;J++)
            {
              byte CurByte=Raw.Get1();
              rlt.Reminder|=(((uint)CurByte)<<((J+3-count)*8));
            }
            CurTime->SetLocal(&rlt);
          }
        }
        NextBlockPos+=hd->PackSize;
        bool CRCProcessedOnly=hd->CommentInHeader;
        ushort HeaderCRC=Raw.GetCRC15(CRCProcessedOnly);
        if (hd->HeadCRC!=HeaderCRC)
        {
          BrokenHeader=true;
          ErrHandler.SetErrorCode(RARX_WARNING);

          // If we have a broken encrypted header, we do not need to display
          // the error message here, because it will be displayed for such
          // headers later in this function. Also such headers are unlikely
          // to have anything sensible in file name field, so it is useless
          // to display the file name.
          if (!Decrypt)
          {
#ifndef SHELL_EXT
            Log(Archive::FileName,St(MLogFileHead),hd->FileName);
#endif
          }
        }
      }
      break;
    case HEAD_ENDARC:
      *(BaseBlock *)&EndArcHead=ShortBlock;
      EndArcHead.NextVolume=(EndArcHead.Flags & EARC_NEXT_VOLUME)!=0;
      EndArcHead.DataCRC=(EndArcHead.Flags & EARC_DATACRC)!=0;
      EndArcHead.RevSpace=(EndArcHead.Flags & EARC_REVSPACE)!=0;
      EndArcHead.StoreVolNumber=(EndArcHead.Flags & EARC_VOLNUMBER)!=0;
      if (EndArcHead.DataCRC)
        EndArcHead.ArcDataCRC=Raw.Get4();
      if (EndArcHead.StoreVolNumber)
        VolNumber=EndArcHead.VolNumber=Raw.Get2();
      break;
#ifndef SFX_MODULE
    case HEAD3_CMT:
      *(BaseBlock *)&CommHead=ShortBlock;
      CommHead.UnpSize=Raw.Get2();
      CommHead.UnpVer=Raw.Get1();
      CommHead.Method=Raw.Get1();
      CommHead.CommCRC=Raw.Get2();
      break;
    case HEAD3_SIGN:
      *(BaseBlock *)&SignHead=ShortBlock;
      SignHead.CreationTime=Raw.Get4();
      SignHead.ArcNameSize=Raw.Get2();
      SignHead.UserNameSize=Raw.Get2();
      break;
    case HEAD3_AV:
      *(BaseBlock *)&AVHead=ShortBlock;
      AVHead.UnpVer=Raw.Get1();
      AVHead.Method=Raw.Get1();
      AVHead.AVVer=Raw.Get1();
      AVHead.AVInfoCRC=Raw.Get4();
      break;
    case HEAD3_PROTECT:
      *(BaseBlock *)&ProtectHead=ShortBlock;
      ProtectHead.DataSize=Raw.Get4();
      ProtectHead.Version=Raw.Get1();
      ProtectHead.RecSectors=Raw.Get2();
      ProtectHead.TotalBlocks=Raw.Get4();
      Raw.GetB(ProtectHead.Mark,8);
      NextBlockPos+=ProtectHead.DataSize;
      RecoverySize=ProtectHead.RecSectors*512;
      break;
    case HEAD3_OLDSERVICE:
      *(BaseBlock *)&SubBlockHead=ShortBlock;
      SubBlockHead.DataSize=Raw.Get4();
      NextBlockPos+=SubBlockHead.DataSize;
      SubBlockHead.SubType=Raw.Get2();
      SubBlockHead.Level=Raw.Get1();
      switch(SubBlockHead.SubType)
      {
        case UO_HEAD:
          *(SubBlockHeader *)&UOHead=SubBlockHead;
          UOHead.OwnerNameSize=Raw.Get2();
          UOHead.GroupNameSize=Raw.Get2();
          if (UOHead.OwnerNameSize>=ASIZE(UOHead.OwnerName))
            UOHead.OwnerNameSize=ASIZE(UOHead.OwnerName)-1;
          if (UOHead.GroupNameSize>=ASIZE(UOHead.GroupName))
            UOHead.GroupNameSize=ASIZE(UOHead.GroupName)-1;
          Raw.GetB(UOHead.OwnerName,UOHead.OwnerNameSize);
          Raw.GetB(UOHead.GroupName,UOHead.GroupNameSize);
          UOHead.OwnerName[UOHead.OwnerNameSize]=0;
          UOHead.GroupName[UOHead.GroupNameSize]=0;
          break;
        case MAC_HEAD:
          *(SubBlockHeader *)&MACHead=SubBlockHead;
          MACHead.fileType=Raw.Get4();
          MACHead.fileCreator=Raw.Get4();
          break;
        case EA_HEAD:
        case BEEA_HEAD:
        case NTACL_HEAD:
          *(SubBlockHeader *)&EAHead=SubBlockHead;
          EAHead.UnpSize=Raw.Get4();
          EAHead.UnpVer=Raw.Get1();
          EAHead.Method=Raw.Get1();
          EAHead.EACRC=Raw.Get4();
          break;
        case STREAM_HEAD:
          *(SubBlockHeader *)&StreamHead=SubBlockHead;
          StreamHead.UnpSize=Raw.Get4();
          StreamHead.UnpVer=Raw.Get1();
          StreamHead.Method=Raw.Get1();
          StreamHead.StreamCRC=Raw.Get4();
          StreamHead.StreamNameSize=Raw.Get2();
          if (StreamHead.StreamNameSize>=ASIZE(StreamHead.StreamName))
            StreamHead.StreamNameSize=ASIZE(StreamHead.StreamName)-1;
          Raw.GetB(StreamHead.StreamName,StreamHead.StreamNameSize);
          StreamHead.StreamName[StreamHead.StreamNameSize]=0;
          break;
      }
      break;
#endif
    default:
      if (ShortBlock.Flags & LONG_BLOCK)
        NextBlockPos+=Raw.Get4();
      break;
  }
Beispiel #6
0
void ExtractStreams20(Archive &Arc,const wchar *FileName)
{
  if (Arc.BrokenHeader)
  {
    uiMsg(UIERROR_STREAMBROKEN,Arc.FileName,FileName);
    ErrHandler.SetErrorCode(RARX_CRC);
    return;
  }

  if (Arc.StreamHead.Method<0x31 || Arc.StreamHead.Method>0x35 || Arc.StreamHead.UnpVer>VER_PACK)
  {
    uiMsg(UIERROR_STREAMUNKNOWN,Arc.FileName,FileName);
    ErrHandler.SetErrorCode(RARX_WARNING);
    return;
  }

  wchar StreamName[NM+2];
  if (FileName[0]!=0 && FileName[1]==0)
  {
    wcscpy(StreamName,L".\\");
    wcscpy(StreamName+2,FileName);
  }
  else
    wcscpy(StreamName,FileName);
  if (wcslen(StreamName)+strlen(Arc.StreamHead.StreamName)>=ASIZE(StreamName) ||
      Arc.StreamHead.StreamName[0]!=':')
  {
    uiMsg(UIERROR_STREAMBROKEN,Arc.FileName,FileName);
    ErrHandler.SetErrorCode(RARX_CRC);
    return;
  }

  wchar StoredName[NM];
  CharToWide(Arc.StreamHead.StreamName,StoredName,ASIZE(StoredName));
  ConvertPath(StoredName+1,StoredName+1);

  wcsncatz(StreamName,StoredName,ASIZE(StreamName));

  FindData fd;
  bool Found=FindFile::FastFind(FileName,&fd);

  if ((fd.FileAttr & FILE_ATTRIBUTE_READONLY)!=0)
    SetFileAttr(FileName,fd.FileAttr & ~FILE_ATTRIBUTE_READONLY);

  File CurFile;
  if (CurFile.WCreate(StreamName))
  {
    ComprDataIO DataIO;
    Unpack Unpack(&DataIO);
    Unpack.Init(0x10000,false);

    DataIO.SetPackedSizeToRead(Arc.StreamHead.DataSize);
    DataIO.EnableShowProgress(false);
    DataIO.SetFiles(&Arc,&CurFile);
    DataIO.UnpHash.Init(HASH_CRC32,1);
    Unpack.SetDestSize(Arc.StreamHead.UnpSize);
    Unpack.DoUnpack(Arc.StreamHead.UnpVer,false);

    if (Arc.StreamHead.StreamCRC!=DataIO.UnpHash.GetCRC32())
    {
      uiMsg(UIERROR_STREAMBROKEN,Arc.FileName,StreamName);
      ErrHandler.SetErrorCode(RARX_CRC);
    }
    else
      CurFile.Close();
  }
  File HostFile;
  if (Found && HostFile.Open(FileName,FMF_OPENSHARED|FMF_UPDATE))
    SetFileTime(HostFile.GetHandle(),&fd.ftCreationTime,&fd.ftLastAccessTime,
                &fd.ftLastWriteTime);
  if ((fd.FileAttr & FILE_ATTRIBUTE_READONLY)!=0)
    SetFileAttr(FileName,fd.FileAttr);
}
Beispiel #7
0
bool ScanTree::GetNextMask()
{
  if (!FileMasks->GetString(CurMask,CurMaskW,ASIZE(CurMask)))
    return(false);

  if (*CurMask==0 && *CurMaskW!=0)
  {
    // Unicode only mask is present. It is very unlikely in console tools,
    // but possible if called from GUI WinRAR. We still need to have
    // ASCII mask, because we use ASCII only mask in some checks later.
    // So let's convert Unicode to ASCII.
    WideToChar(CurMaskW,CurMask,ASIZE(CurMask));
  }

  CurMask[ASIZE(CurMask)-1]=0;
  CurMaskW[ASIZE(CurMaskW)-1]=0;
#ifdef _WIN_ALL
  UnixSlashToDos(CurMask);
#endif

  // We wish to scan entire disk if mask like c:\ is specified
  // regardless of recursion mode. Use c:\*.* mask when need to scan only 
  // the root directory.
  ScanEntireDisk=IsDiskLetter(CurMask) && IsPathDiv(CurMask[2]) && CurMask[3]==0;

  char *Name=PointToName(CurMask);
  if (*Name==0)
    strcat(CurMask,MASKALL);
  if (Name[0]=='.' && (Name[1]==0 || Name[1]=='.' && Name[2]==0))
  {
    AddEndSlash(CurMask);
    strcat(CurMask,MASKALL);
  }
  SpecPathLength=Name-CurMask;

  bool WideName=(*CurMaskW!=0);

  if (WideName)
  {
    wchar *NameW=PointToName(CurMaskW);
    if (*NameW==0)
      wcscat(CurMaskW,MASKALLW);
    if (NameW[0]=='.' && (NameW[1]==0 || NameW[1]=='.' && NameW[2]==0))
    {
      AddEndSlash(CurMaskW);
      wcscat(CurMaskW,MASKALLW);
    }
    SpecPathLengthW=NameW-CurMaskW;
  }
  else
  {
    wchar WideMask[NM];
    CharToWide(CurMask,WideMask);
    SpecPathLengthW=PointToName(WideMask)-WideMask;
  }
  Depth=0;

  strcpy(OrigCurMask,CurMask);
  wcscpy(OrigCurMaskW,CurMaskW);

  return(true);
}
Beispiel #8
0
void CmdExtract::ExtrCreateDir(Archive &Arc,const wchar *ArcFileName)
{
  return;	// OPENMPT ADDITION
  if (Cmd->Test)
  {
#ifndef GUI
    mprintf(St(MExtrTestFile),ArcFileName);
    mprintf(L" %s",St(MOk));
#endif
    return;
  }

  MKDIR_CODE MDCode=MakeDir(DestFileName,!Cmd->IgnoreGeneralAttr,Arc.FileHead.FileAttr);
  bool DirExist=false;
  if (MDCode!=MKDIR_SUCCESS)
  {
    DirExist=FileExist(DestFileName);
    if (DirExist && !IsDir(GetFileAttr(DestFileName)))
    {
      // File with name same as this directory exists. Propose user
      // to overwrite it.
      bool UserReject;
      FileCreate(Cmd,NULL,DestFileName,ASIZE(DestFileName),&UserReject,Arc.FileHead.UnpSize,&Arc.FileHead.mtime);
      DirExist=false;
    }
    if (!DirExist)
    {
      CreatePath(DestFileName,true);
      MDCode=MakeDir(DestFileName,!Cmd->IgnoreGeneralAttr,Arc.FileHead.FileAttr);
    }
  }
  if (MDCode==MKDIR_SUCCESS)
  {
#ifndef GUI
    mprintf(St(MCreatDir),DestFileName);
    mprintf(L" %s",St(MOk));
#endif
    PrevExtracted=true;
  }
  else
    if (DirExist)
    {
      if (!Cmd->IgnoreGeneralAttr)
        SetFileAttr(DestFileName,Arc.FileHead.FileAttr);
      PrevExtracted=true;
    }
    else
    {
      uiMsg(UIERROR_DIRCREATE,Arc.FileName,DestFileName);
      ErrHandler.SysErrMsg();
#ifdef RARDLL
      Cmd->DllError=ERAR_ECREATE;
#endif
      ErrHandler.SetErrorCode(RARX_CREATE);
    }
  if (PrevExtracted)
  {
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
    if (Cmd->SetCompressedAttr &&
        (Arc.FileHead.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0 && WinNT())
      SetFileCompression(DestFileName,true);
#endif
    SetDirTime(DestFileName,
      Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.FileHead.mtime,
      Cmd->xctime==EXTTIME_NONE ? NULL:&Arc.FileHead.ctime,
      Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.FileHead.atime);
  }
}
Beispiel #9
0
int
print_insn_pj (bfd_vma addr, struct disassemble_info *info)
{
  fprintf_ftype fprintf_fn = info->fprintf_func;
  void *stream = info->stream;
  unsigned char opcode;
  int status;

  if ((status = info->read_memory_func (addr, &opcode, 1, info)))
    goto fail;

  if (opcode == 0xff)
    {
      unsigned char byte_2;

      if ((status = info->read_memory_func (addr + 1, &byte_2, 1, info)))
	goto fail;
      fprintf_fn (stream, "%s\t", pj_opc_info[opcode + byte_2].u.name);
      return 2;
    }
  else
    {
      char *sep = "\t";
      int insn_start = addr;
      const pj_opc_info_t *op = &pj_opc_info[opcode];
      int a;

      addr++;
      fprintf_fn (stream, "%s", op->u.name);

      /* The tableswitch instruction is followed by the default
	 address, low value, high value and the destinations.  */

      if (strcmp (op->u.name, "tableswitch") == 0)
	{
	  int lowval;
	  int highval;
	  int val;

	  addr = (addr + 3) & ~3;
	  if ((status = get_int (addr, &val, info)))
	    goto fail;

	  fprintf_fn (stream, " default: ");
	  (*info->print_address_func) (val + insn_start, info);
	  addr += 4;

	  if ((status = get_int (addr, &lowval, info)))
	    goto fail;
	  addr += 4;

	  if ((status = get_int (addr, &highval, info)))
	    goto fail;
	  addr += 4;

	  while (lowval <= highval)
	    {
	      if ((status = get_int (addr, &val, info)))
		goto fail;
	      fprintf_fn (stream, " %d:[", lowval);
	      (*info->print_address_func) (val + insn_start, info);
	      fprintf_fn (stream, " ]");
	      addr += 4;
	      lowval++;
	    }
	  return addr - insn_start;
	}

      /* The lookupswitch instruction is followed by the default
	 address, element count and pairs of values and
	 addresses.  */
      if (strcmp (op->u.name, "lookupswitch") == 0)
	{
	  int count;
	  int val;

	  addr = (addr + 3) & ~3;
	  if ((status = get_int (addr, &val, info)))
	    goto fail;
	  addr += 4;

	  fprintf_fn (stream, " default: ");
	  (*info->print_address_func) (val + insn_start, info);

	  if ((status = get_int (addr, &count, info)))
	    goto fail;
	  addr += 4;

	  while (count--)
	    {
	      if ((status = get_int (addr, &val, info)))
		goto fail;
	      addr += 4;
	      fprintf_fn (stream, " %d:[", val);

	      if ((status = get_int (addr, &val, info)))
		goto fail;
	      addr += 4;

	      (*info->print_address_func) (val + insn_start, info);
	      fprintf_fn (stream, " ]");
	    }
	  return addr - insn_start;
	}

      for (a = 0; op->arg[a]; a++)
	{
	  unsigned char data[4];
	  int val = 0;
	  int i;
	  int size = ASIZE (op->arg[a]);

	  if ((status = info->read_memory_func (addr, data, size, info)))
	    goto fail;

	  val = (UNS (op->arg[0]) || ((data[0] & 0x80) == 0)) ? 0 : -1;

	  for (i = 0; i < size; i++)
	    val = (val << 8) | (data[i] & 0xff);

	  if (PCREL (op->arg[a]))
	    (*info->print_address_func) (val + insn_start, info);
	  else
	    fprintf_fn (stream, "%s%d", sep, val);

	  sep = ",";
	  addr += size;
	}
      return op->len;
    }

 fail:
  info->memory_error_func (status, addr, info);
  return -1;
}
Beispiel #10
0
EXTRACT_ARC_CODE CmdExtract::ExtractArchive()
{
  Archive Arc(Cmd);
  if (!Arc.WOpen(ArcName))
    return EXTRACT_ARC_NEXT;

  if (!Arc.IsArchive(true))
  {
#ifndef GUI
    mprintf(St(MNotRAR),ArcName);
#endif
    if (CmpExt(ArcName,L"rar"))
      ErrHandler.SetErrorCode(RARX_WARNING);
    return EXTRACT_ARC_NEXT;
  }

  if (Arc.FailedHeaderDecryption) // Bad archive password.
    return EXTRACT_ARC_NEXT;

#ifndef SFX_MODULE
  if (Arc.Volume && !Arc.FirstVolume)
  {
    wchar FirstVolName[NM];
    VolNameToFirstName(ArcName,FirstVolName,ASIZE(FirstVolName),Arc.NewNumbering);

    // If several volume names from same volume set are specified
    // and current volume is not first in set and first volume is present
    // and specified too, let's skip the current volume.
    if (wcsicomp(ArcName,FirstVolName)!=0 && FileExist(FirstVolName) &&
        Cmd->ArcNames.Search(FirstVolName,false))
      return EXTRACT_ARC_NEXT;
  }
#endif

  int64 VolumeSetSize=0; // Total size of volumes after the current volume.

  if (Arc.Volume)
  {
    // Calculate the total size of all accessible volumes.
    // This size is necessary to display the correct total progress indicator.

    wchar NextName[NM];
    wcscpy(NextName,Arc.FileName);

    while (true)
    {
      // First volume is already added to DataIO.TotalArcSize 
      // in initial TotalArcSize calculation in DoExtract.
      // So we skip it and start from second volume.
      NextVolumeName(NextName,ASIZE(NextName),!Arc.NewNumbering);
      FindData FD;
      if (FindFile::FastFind(NextName,&FD))
        VolumeSetSize+=FD.Size;
      else
        break;
    }
    DataIO.TotalArcSize+=VolumeSetSize;
  }

  ExtractArchiveInit(Arc);

  if (*Cmd->Command=='T' || *Cmd->Command=='I')
    Cmd->Test=true;


  if (*Cmd->Command=='I')
  {
#ifndef GUI   
    Cmd->DisablePercentage=true;
#endif
  }
  else
    uiStartArchiveExtract(!Cmd->Test,ArcName);

  Arc.ViewComment();


  while (1)
  {
    size_t Size=Arc.ReadHeader();


    bool Repeat=false;
    if (!ExtractCurrentFile(Arc,Size,Repeat))
      if (Repeat)
      {
        // If we started extraction from not first volume and need to
        // restart it from first, we must correct DataIO.TotalArcSize
        // for correct total progress display. We subtract the size
        // of current volume and all volumes after it and add the size
        // of new (first) volume.
        FindData OldArc,NewArc;
        if (FindFile::FastFind(Arc.FileName,&OldArc) &&
            FindFile::FastFind(ArcName,&NewArc))
          DataIO.TotalArcSize-=VolumeSetSize+OldArc.Size-NewArc.Size;
        return EXTRACT_ARC_REPEAT;
      }
      else
        break;
  }


  return EXTRACT_ARC_NEXT;
}
Beispiel #11
0
bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
{
  wchar Command=Cmd->Command[0];
  if (HeaderSize==0)
    if (DataIO.UnpVolume)
    {
#ifdef NOVOLUME
      return false;
#else
      if (!MergeArchive(Arc,&DataIO,false,Command))
      {
        ErrHandler.SetErrorCode(RARX_WARNING);
        return false;
      }
#endif
    }
    else
      return false;
  HEADER_TYPE HeaderType=Arc.GetHeaderType();
  if (HeaderType!=HEAD_FILE)
  {
#ifndef SFX_MODULE
    if (HeaderType==HEAD3_OLDSERVICE && PrevExtracted)
      SetExtraInfo20(Cmd,Arc,DestFileName);
#endif
    if (HeaderType==HEAD_SERVICE && PrevExtracted)
      SetExtraInfo(Cmd,Arc,DestFileName);
    if (HeaderType==HEAD_ENDARC)
      if (Arc.EndArcHead.NextVolume)
      {
#ifndef NOVOLUME
        if (!MergeArchive(Arc,&DataIO,false,Command))
        {
          ErrHandler.SetErrorCode(RARX_WARNING);
          return false;
        }
#endif
        Arc.Seek(Arc.CurBlockPos,SEEK_SET);
        return true;
      }
      else
        return false;
    Arc.SeekToNext();
    return true;
  }
  PrevExtracted=false;

  if (!Cmd->Recurse && MatchedArgs>=Cmd->FileArgs.ItemsCount() && AllMatchesExact)
    return false;

  int MatchType=MATCH_WILDSUBPATH;

  bool EqualNames=false;
  int MatchNumber=Cmd->IsProcessFile(Arc.FileHead,&EqualNames,MatchType);
  bool ExactMatch=MatchNumber!=0;
#ifndef SFX_MODULE
  if (Cmd->ExclPath==EXCL_BASEPATH)
  {
    *Cmd->ArcPath=0;
    if (ExactMatch)
    {
      Cmd->FileArgs.Rewind();
      if (Cmd->FileArgs.GetString(Cmd->ArcPath,ASIZE(Cmd->ArcPath),MatchNumber-1))
        *PointToName(Cmd->ArcPath)=0;
    }
  }
#endif
  if (ExactMatch && !EqualNames)
    AllMatchesExact=false;

  Arc.ConvertAttributes();

#if !defined(SFX_MODULE) && !defined(RARDLL)
  if (Arc.FileHead.SplitBefore && FirstFile)
  {
    wchar CurVolName[NM];
    wcsncpyz(CurVolName,ArcName,ASIZE(CurVolName));
    VolNameToFirstName(ArcName,ArcName,ASIZE(ArcName),Arc.NewNumbering);

    if (wcsicomp(ArcName,CurVolName)!=0 && FileExist(ArcName))
    {
      // If first volume name does not match the current name and if such
      // volume name really exists, let's unpack from this first volume.
      Repeat=true;
      return false;
    }
#ifndef RARDLL
    if (!ReconstructDone)
    {
      ReconstructDone=true;
      if (RecVolumesRestore(Cmd,Arc.FileName,true))
      {
        Repeat=true;
        return false;
      }
    }
#endif
    wcsncpyz(ArcName,CurVolName,ASIZE(ArcName));
  }
#endif

  wchar ArcFileName[NM];
  ConvertPath(Arc.FileHead.FileName,ArcFileName);

  if (Arc.FileHead.Version)
  {
    if (Cmd->VersionControl!=1 && !EqualNames)
    {
      if (Cmd->VersionControl==0)
        ExactMatch=false;
      int Version=ParseVersionFileName(ArcFileName,false);
      if (Cmd->VersionControl-1==Version)
        ParseVersionFileName(ArcFileName,true);
      else
        ExactMatch=false;
    }
  }
  else
    if (!Arc.IsArcDir() && Cmd->VersionControl>1)
      ExactMatch=false;

  DataIO.UnpVolume=Arc.FileHead.SplitAfter;
  DataIO.NextVolumeMissing=false;

  Arc.Seek(Arc.NextBlockPos-Arc.FileHead.PackSize,SEEK_SET);

  bool ExtrFile=false;
  bool SkipSolid=false;

#ifndef SFX_MODULE
  if (FirstFile && (ExactMatch || Arc.Solid) && Arc.FileHead.SplitBefore)
  {
    if (ExactMatch)
    {
      uiMsg(UIERROR_NEEDPREVVOL,Arc.FileName,ArcFileName);
#ifdef RARDLL
      Cmd->DllError=ERAR_BAD_DATA;
#endif
      ErrHandler.SetErrorCode(RARX_OPEN);
    }
    ExactMatch=false;
  }

  FirstFile=false;
#endif

  if (ExactMatch || (SkipSolid=Arc.Solid)!=0)
  {
    // First common call of uiStartFileExtract. It is done before overwrite
    // prompts, so if SkipSolid state is changed below, we'll need to make
    // additional uiStartFileExtract calls with updated parameters.
    if (!uiStartFileExtract(ArcFileName,!Cmd->Test,Cmd->Test && Command!='I',SkipSolid))
      return false;

    ExtrPrepareName(Arc,ArcFileName,DestFileName,ASIZE(DestFileName));

    // DestFileName can be set empty in case of excessive -ap switch.
    ExtrFile=!SkipSolid && *DestFileName!=0 && !Arc.FileHead.SplitBefore;

    /*	// OPENMPT ADDITION
    if ((Cmd->FreshFiles || Cmd->UpdateFiles) && (Command=='E' || Command=='X'))
    {
      FindData FD;
      if (FindFile::FastFind(DestFileName,&FD))
      {
        if (FD.mtime >= Arc.FileHead.mtime)
        {
          // If directory already exists and its modification time is newer 
          // than start of extraction, it is likely it was created 
          // when creating a path to one of already extracted items. 
          // In such case we'll better update its time even if archived 
          // directory is older.

          if (!FD.IsDir || FD.mtime<StartTime)
            ExtrFile=false;
        }
      }
      else
        if (Cmd->FreshFiles)
          ExtrFile=false;
    }
    */	// OPENMPT ADDITION

    if (Arc.FileHead.Encrypted)
    {
#ifdef RARDLL
      if (!ExtrDllGetPassword())
        return false;
#else
      if (!ExtrGetPassword(Arc,ArcFileName))
      {
        PasswordCancelled=true;
        return false;
      }
#endif
      // Skip only the current encrypted file if empty password is entered.
      if (!Password.IsSet())
      {
        ErrHandler.SetErrorCode(RARX_WARNING);
#ifdef RARDLL
        Cmd->DllError=ERAR_MISSING_PASSWORD;
#endif
        ExtrFile=false;
      }
    }

#ifdef RARDLL
    if (*Cmd->DllDestName!=0)
    {
      wcsncpyz(DestFileName,Cmd->DllDestName,ASIZE(DestFileName));

//      Do we need this code?
//      if (Cmd->DllOpMode!=RAR_EXTRACT)
//        ExtrFile=false;
    }
#endif

    if (!CheckUnpVer(Arc,ArcFileName))
    {
      ExtrFile=false;
      ErrHandler.SetErrorCode(RARX_FATAL);
#ifdef RARDLL
      Cmd->DllError=ERAR_UNKNOWN_FORMAT;
#endif
    }

    
    File CurFile;

    bool LinkEntry=Arc.FileHead.RedirType!=FSREDIR_NONE;
    if (LinkEntry && Arc.FileHead.RedirType!=FSREDIR_FILECOPY)
    {
      if (ExtrFile && Command!='P' && !Cmd->Test)
      {
        // Overwrite prompt for symbolic and hard links.
        bool UserReject=false;
        if (FileExist(DestFileName) && !UserReject)
          FileCreate(Cmd,NULL,DestFileName,ASIZE(DestFileName),&UserReject,Arc.FileHead.UnpSize,&Arc.FileHead.mtime);
        if (UserReject)
          ExtrFile=false;
      }
    }
    else
      if (Arc.IsArcDir())
      {
        if (!ExtrFile || Command=='P' || Command=='I' || Command=='E' || Cmd->ExclPath==EXCL_SKIPWHOLEPATH)
          return true;
        TotalFileCount++;
        ExtrCreateDir(Arc,ArcFileName);
        return true;
      }
      else
        if (ExtrFile) // Create files and file copies (FSREDIR_FILECOPY).
          ExtrFile=ExtrCreateFile(Arc,CurFile);

    if (!ExtrFile && Arc.Solid)
    {
      SkipSolid=true;
      ExtrFile=true;

      // We changed SkipSolid, so we need to call uiStartFileExtract
      // with "Skip" parameter to change the operation status 
      // from "extracting" to "skipping". For example, it can be necessary
      // if user answered "No" to overwrite prompt when unpacking
      // a solid archive.
      if (!uiStartFileExtract(ArcFileName,false,false,true))
        return false;
    }
    if (ExtrFile)
    {
      bool TestMode=Cmd->Test || SkipSolid; // Unpack to memory, not to disk.

      if (!SkipSolid)
      {
        if (!TestMode && Command!='P' && CurFile.IsDevice())
        {
          uiMsg(UIERROR_INVALIDNAME,Arc.FileName,DestFileName);
          ErrHandler.WriteError(Arc.FileName,DestFileName);
        }
        TotalFileCount++;
      }
      FileCount++;
#ifndef GUI
      if (Command!='I')
        if (SkipSolid)
          mprintf(St(MExtrSkipFile),ArcFileName);
        else
          switch(Cmd->Test ? 'T':Command) // "Test" can be also enabled by -t switch.
          {
            case 'T':
              mprintf(St(MExtrTestFile),ArcFileName);
              break;
#ifndef SFX_MODULE
            case 'P':
              mprintf(St(MExtrPrinting),ArcFileName);
              break;
#endif
            case 'X':
            case 'E':
              mprintf(St(MExtrFile),DestFileName);
              break;
          }
      if (!Cmd->DisablePercentage)
        mprintf(L"     ");
#endif

      SecPassword FilePassword=Password;
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
      ConvertDosPassword(Arc,FilePassword);
#endif

      byte PswCheck[SIZE_PSWCHECK];
      DataIO.SetEncryption(false,Arc.FileHead.CryptMethod,&FilePassword,
             Arc.FileHead.SaltSet ? Arc.FileHead.Salt:NULL,
             Arc.FileHead.InitV,Arc.FileHead.Lg2Count,
             PswCheck,Arc.FileHead.HashKey);
      bool WrongPassword=false;

      // If header is damaged, we cannot rely on password check value,
      // because it can be damaged too.
      if (Arc.FileHead.Encrypted && Arc.FileHead.UsePswCheck &&
          memcmp(Arc.FileHead.PswCheck,PswCheck,SIZE_PSWCHECK)!=0 &&
          !Arc.BrokenHeader)
      {
        uiMsg(UIERROR_BADPSW,Arc.FileName);
        ErrHandler.SetErrorCode(RARX_BADPWD);
        WrongPassword=true;
      }
      DataIO.CurUnpRead=0;
      DataIO.CurUnpWrite=0;
      DataIO.UnpHash.Init(Arc.FileHead.FileHash.Type,Cmd->Threads);
      DataIO.PackedDataHash.Init(Arc.FileHead.FileHash.Type,Cmd->Threads);
      DataIO.SetPackedSizeToRead(Arc.FileHead.PackSize);
      DataIO.SetFiles(&Arc,&CurFile);
      DataIO.SetTestMode(TestMode);
      DataIO.SetSkipUnpCRC(SkipSolid);
      if (!TestMode && !WrongPassword && !Arc.BrokenHeader &&
          (Arc.FileHead.PackSize<<11)>Arc.FileHead.UnpSize &&
          (Arc.FileHead.UnpSize<100000000 || Arc.FileLength()>Arc.FileHead.PackSize))
        CurFile.Prealloc(Arc.FileHead.UnpSize);

      CurFile.SetAllowDelete(!Cmd->KeepBroken);

      bool FileCreateMode=!TestMode && !SkipSolid && Command!='P';
      bool ShowChecksum=true; // Display checksum verification result.

      bool LinkSuccess=true; // Assume success for test mode.
      if (LinkEntry)
      {
        /*	// OPENMPT ADDITION
        FILE_SYSTEM_REDIRECT Type=Arc.FileHead.RedirType;

        if (Type==FSREDIR_HARDLINK || Type==FSREDIR_FILECOPY)
        {
          wchar NameExisting[NM];
          ExtrPrepareName(Arc,Arc.FileHead.RedirName,NameExisting,ASIZE(NameExisting));
          if (FileCreateMode && *NameExisting!=0) // *NameExisting can be 0 in case of excessive -ap switch.
            if (Type==FSREDIR_HARDLINK)
              LinkSuccess=ExtractHardlink(DestFileName,NameExisting,ASIZE(NameExisting));
            else
              LinkSuccess=ExtractFileCopy(CurFile,Arc.FileName,DestFileName,NameExisting,ASIZE(NameExisting));
        }
        else
          if (Type==FSREDIR_UNIXSYMLINK || Type==FSREDIR_WINSYMLINK || Type==FSREDIR_JUNCTION)
          {
            if (FileCreateMode)
              LinkSuccess=ExtractSymlink(Cmd,DataIO,Arc,DestFileName);
          }
          else
          {
            uiMsg(UIERROR_UNKNOWNEXTRA, Arc.FileName, DestFileName);
            LinkSuccess=false;
          }
          
          if (!LinkSuccess || Arc.Format==RARFMT15 && !FileCreateMode)
          {
            // RAR 5.x links have a valid data checksum even in case of
            // failure, because they do not store any data.
            // We do not want to display "OK" in this case.
            // For 4.x symlinks we verify the checksum only when extracting,
            // but not when testing an archive.
            ShowChecksum=false;
          }
          PrevExtracted=FileCreateMode && LinkSuccess;
          */	// OPENMPT ADDITION
      }
      else
        if (!Arc.FileHead.SplitBefore && !WrongPassword)
          if (Arc.FileHead.Method==0)
            UnstoreFile(DataIO,Arc.FileHead.UnpSize);
          else
          {
#ifdef _ANDROID
            // malloc and new do not report memory allocation errors
            // in Android, so if free memory is set, check it here
            // trying to prevent crash.
            if (Cmd->FreeMem!=0 && Cmd->FreeMem < Arc.FileHead.WinSize)
              throw std::bad_alloc();
#endif
            Unp->Init(Arc.FileHead.WinSize,Arc.FileHead.Solid);
            Unp->SetDestSize(Arc.FileHead.UnpSize);
#ifndef SFX_MODULE
            if (Arc.Format!=RARFMT50 && Arc.FileHead.UnpVer<=15)
              Unp->DoUnpack(15,FileCount>1 && Arc.Solid);
            else
#endif
              Unp->DoUnpack(Arc.FileHead.UnpVer,Arc.FileHead.Solid);
          }

      Arc.SeekToNext();

      bool ValidCRC=DataIO.UnpHash.Cmp(&Arc.FileHead.FileHash,Arc.FileHead.UseHashKey ? Arc.FileHead.HashKey:NULL);

      // We set AnySolidDataUnpackedWell to true if we found at least one
      // valid non-zero solid file in preceding solid stream. If it is true
      // and if current encrypted file is broken, we do not need to hint
      // about a wrong password and can report CRC error only.
      if (!Arc.FileHead.Solid)
        AnySolidDataUnpackedWell=false; // Reset the flag, because non-solid file is found.
      else
        if (Arc.FileHead.Method!=0 && Arc.FileHead.UnpSize>0 && ValidCRC)
          AnySolidDataUnpackedWell=true;
 
      bool BrokenFile=false;
      
      // Checksum is not calculated in skip solid mode for performance reason.
      if (!SkipSolid && ShowChecksum)
      {
        if (!WrongPassword && ValidCRC)
        {
#ifndef GUI
          if (Command!='P' && Command!='I')
            mprintf(L"%s%s ",Cmd->DisablePercentage ? L" ":L"\b\b\b\b\b ",
              Arc.FileHead.FileHash.Type==HASH_NONE ? L"  ?":St(MOk));
#endif
        }
        else
        {
          if (!WrongPassword)
            if (Arc.FileHead.Encrypted && (!Arc.FileHead.UsePswCheck || 
                Arc.BrokenHeader) && !AnySolidDataUnpackedWell)
              uiMsg(UIERROR_CHECKSUMENC,Arc.FileName,ArcFileName);
            else
              uiMsg(UIERROR_CHECKSUM,Arc.FileName,ArcFileName);
          BrokenFile=true;
          ErrHandler.SetErrorCode(RARX_CRC);
#ifdef RARDLL
          // If we already have ERAR_EOPEN as result of missing volume,
          // we should not replace it with less precise ERAR_BAD_DATA.
          if (Cmd->DllError!=ERAR_EOPEN)
            Cmd->DllError=WrongPassword ? ERAR_BAD_PASSWORD : ERAR_BAD_DATA;
#endif
        }
      }
#ifndef GUI
      else
        mprintf(L"\b\b\b\b\b     ");
#endif

      /*	// OPENMPT ADDITION
      if (!TestMode && !WrongPassword && (Command=='X' || Command=='E') &&
          (!LinkEntry || Arc.FileHead.RedirType==FSREDIR_FILECOPY && LinkSuccess) && 
          (!BrokenFile || Cmd->KeepBroken))
      {
        // We could preallocate more space that really written to broken file.
        if (BrokenFile)
          CurFile.Truncate();

#if defined(_WIN_ALL) || defined(_EMX)
        if (Cmd->ClearArc)
          Arc.FileHead.FileAttr&=~FILE_ATTRIBUTE_ARCHIVE;
#endif


        CurFile.SetOpenFileTime(
          Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.FileHead.mtime,
          Cmd->xctime==EXTTIME_NONE ? NULL:&Arc.FileHead.ctime,
          Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.FileHead.atime);
        CurFile.Close();
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
        if (Cmd->SetCompressedAttr &&
            (Arc.FileHead.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0)
          SetFileCompression(CurFile.FileName,true);
#endif
#ifdef _UNIX
        if (Cmd->ProcessOwners && Arc.Format==RARFMT50 && Arc.FileHead.UnixOwnerSet)
          SetUnixOwner(Arc,CurFile.FileName);
#endif

        CurFile.SetCloseFileTime(
          Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.FileHead.mtime,
          Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.FileHead.atime);
        if (!Cmd->IgnoreGeneralAttr && !SetFileAttr(CurFile.FileName,Arc.FileHead.FileAttr))
          uiMsg(UIERROR_FILEATTR,Arc.FileName,CurFile.FileName);

        PrevExtracted=true;
      }
      */	// OPENMPT ADDITION
    }
  }
  if (ExactMatch)
    MatchedArgs++;
  if (DataIO.NextVolumeMissing)
    return false;
  if (!ExtrFile)
    if (!Arc.Solid)
      Arc.SeekToNext();
    else
      if (!SkipSolid)
        return false;
  return true;
}
Beispiel #12
0
bool FindFile::Next(struct FindData *fd,bool GetSymLink)
{
  fd->Error=false;
  if (*FindMask==0)
    return(false);
#ifdef _WIN_32
  if (FirstCall)
  {
    if ((hFind=Win32Find(INVALID_HANDLE_VALUE,FindMask,FindMaskW,fd))==INVALID_HANDLE_VALUE)
      return(false);
  }
  else
    if (Win32Find(hFind,FindMask,FindMaskW,fd)==INVALID_HANDLE_VALUE)
      return(false);
#else
  if (FirstCall)
  {
    char DirName[NM];
    strcpy(DirName,FindMask);
    RemoveNameFromPath(DirName);
    if (*DirName==0)
      strcpy(DirName,".");
/*
    else
    {
      int Length=strlen(DirName);
      if (Length>1 && DirName[Length-1]==CPATHDIVIDER && (Length!=3 || !IsDriveDiv(DirName[1])))
        DirName[Length-1]=0;
    }
*/
    if ((dirp=opendir(DirName))==NULL)
    {
      fd->Error=(errno!=ENOENT);
      return(false);
    }
  }
  while (1)
  {
    struct dirent *ent=readdir(dirp);
    if (ent==NULL)
      return(false);
    if (strcmp(ent->d_name,".")==0 || strcmp(ent->d_name,"..")==0)
      continue;
    if (CmpName(FindMask,ent->d_name,MATCH_NAMES))
    {
      char FullName[NM];
      strcpy(FullName,FindMask);
      *PointToName(FullName)=0;
      if (strlen(FullName)+strlen(ent->d_name)>=ASIZE(FullName)-1)
      {
#ifndef SILENT
        Log(NULL,"\n%s%s",FullName,ent->d_name);
        Log(NULL,St(MPathTooLong));
#endif
        return(false);
      }
      strcat(FullName,ent->d_name);
      if (!FastFind(FullName,NULL,fd,GetSymLink))
      {
        ErrHandler.OpenErrorMsg(FullName);
        continue;
      }
      strcpy(fd->Name,FullName);
      break;
    }
  }
  *fd->NameW=0;
#ifdef _APPLE
  if (!LowAscii(fd->Name))
    UtfToWide(fd->Name,fd->NameW,sizeof(fd->NameW));
#elif defined(UNICODE_SUPPORTED)
  if (!LowAscii(fd->Name) && UnicodeEnabled())
    CharToWide(fd->Name,fd->NameW);
#endif
#endif
  fd->IsDir=IsDir(fd->FileAttr);
  FirstCall=FALSE;
  char *Name=PointToName(fd->Name);
  if (strcmp(Name,".")==0 || strcmp(Name,"..")==0)
    return(Next(fd));
  return(true);
}
Beispiel #13
0
void InitLogOptions(const wchar *LogFileName,RAR_CHARSET CSet)
{
  wcsncpyz(LogName,LogFileName,ASIZE(LogName));
  LogCharset=CSet;
}
Beispiel #14
0
int init_gpio(void)
{
	char *btn_list[] = { "btn_rst_gpio", "btn_wps_gpio", "fan_gpio", "have_fan_gpio"
#ifdef RTCONFIG_WIRELESS_SWITCH
		, "btn_wifi_gpio"
#endif
#ifdef RTCONFIG_WIFI_TOG_BTN
		, "btn_wltog_gpio"
#endif
#ifdef RTCONFIG_SWMODE_SWITCH
#if defined(PLAC66U)
		, "btn_swmode1_gpio"
#else
		, "btn_swmode1_gpio", "btn_swmode2_gpio", "btn_swmode3_gpio"
#endif	/* Mode */
#endif	/* RTCONFIG_SWMODE_SWITCH */
#ifdef RTCONFIG_TURBO
		, "btn_turbo_gpio"
#endif
#ifdef RTCONFIG_LED_BTN
		, "btn_led_gpio"
#endif
#ifdef RTCONFIG_INTERNAL_GOBI
		, "btn_lte_gpio"
#endif
	};
	char *led_list[] = { "led_turbo_gpio", "led_pwr_gpio", "led_usb_gpio", "led_wps_gpio", "fan_gpio", "have_fan_gpio", "led_lan_gpio", "led_wan_gpio", "led_usb3_gpio", "led_2g_gpio", "led_5g_gpio" 
#ifdef RTCONFIG_LAN4WAN_LED
		, "led_lan1_gpio", "led_lan2_gpio", "led_lan3_gpio", "led_lan4_gpio"
#endif  /* LAN4WAN_LED */
#ifdef RTCONFIG_LED_ALL
		, "led_all_gpio"
#endif
		, "led_wan_red_gpio"
#ifdef RTCONFIG_QTN
		, "reset_qtn_gpio"
#endif
#ifdef RTCONFIG_USBRESET
		, "pwr_usb_gpio"
		, "pwr_usb_gpio2"
#endif
#ifdef RTCONFIG_WIFIPWR
		, "pwr_2g_gpio"
		, "pwr_5g_gpio"
#endif
#ifdef RTCONFIG_INTERNAL_GOBI
		, "led_3g_gpio", "led_lte_gpio", "led_sig1_gpio", "led_sig2_gpio", "led_sig3_gpio", "led_sig4_gpio"
#endif
#if (defined(PLN12) || defined(PLAC56))
		, "plc_wake_gpio"
		, "led_pwr_red_gpio"
		, "led_2g_green_gpio", "led_2g_orange_gpio", "led_2g_red_gpio"
		, "led_5g_green_gpio", "led_5g_orange_gpio", "led_5g_red_gpio"
#endif
#ifdef RTCONFIG_MMC_LED
		, "led_mmc_gpio"
#endif
#if defined(RTCONFIG_RTAC5300) || defined(RTCONFIG_RTAC5300R)
		, "rpm_fan_gpio"
#endif
#ifdef RTCONFIG_RESET_SWITCH
		, "reset_switch_gpio"
#endif
			   };
	int use_gpio, gpio_pin;
	int enable, disable;
	int i;

#ifdef RTCONFIG_INTERNAL_GOBI
	void get_gpio_values_once(int);
	get_gpio_values_once(0);		// for filling data to led_gpio_table[]
#endif	/* RTCONFIG_INTERNAL_GOBI */

	/* btn input */
	for(i = 0; i < ASIZE(btn_list); i++)
	{
		if (!nvram_get(btn_list[i]))
			continue;
		use_gpio = nvram_get_int(btn_list[i]);
		if((gpio_pin = use_gpio & 0xff) == 0xff)
			continue;
		gpio_dir(gpio_pin, GPIO_DIR_IN);
	}

	/* led output */
	for(i = 0; i < ASIZE(led_list); i++)
	{
		if (!nvram_get(led_list[i]))
			continue;
#if defined(RTCONFIG_ETRON_XHCI_USB3_LED)
		if (!strcmp(led_list[i], "led_usb3_gpio") && nvram_match("led_usb3_gpio", "etron")) {
			led_control(LED_USB3, LED_OFF);
			continue;
		}
#endif
		use_gpio = nvram_get_int(led_list[i]);

		if((gpio_pin = use_gpio & 0xff) == 0xff)
			continue;

#if defined(RTCONFIG_RALINK_MT7620)
		if(gpio_pin == 72)	//skip 2g wifi led NOT to be gpio LED
			continue;
#endif

		disable = (use_gpio&GPIO_ACTIVE_LOW)==0 ? 0: 1;
		gpio_dir(gpio_pin, GPIO_DIR_OUT);

		/* If WAN RED LED is defined, keep it on until Internet connection ready in router mode. */
		if (!strcmp(led_list[i], "led_wan_red_gpio") && nvram_get_int("sw_mode") == SW_MODE_ROUTER)
			disable = !disable;

		set_gpio(gpio_pin, disable);
#ifdef RTCONFIG_INTERNAL_GOBI	// save setting value
		{ int i; char led[16]; for(i=0; i<LED_ID_MAX; i++) if(gpio_pin == (led_gpio_table[i]&0xff)){snprintf(led, sizeof(led), "led%02d", i); nvram_set_int(led, LED_OFF); break;}}
#endif	/* RTCONFIG_INTERNAL_GOBI */
	}

#if (defined(PLN12) || defined(PLAC56))
	if((gpio_pin = (use_gpio = nvram_get_int("led_pwr_red_gpio")) & 0xff) != 0xff)
#else
	if((gpio_pin = (use_gpio = nvram_get_int("led_pwr_gpio")) & 0xff) != 0xff)
#endif
	{
		enable = (use_gpio&GPIO_ACTIVE_LOW)==0 ? 1 : 0;
		set_gpio(gpio_pin, enable);
#ifdef RTCONFIG_INTERNAL_GOBI	// save setting value
		{ int i; char led[16]; for(i=0; i<LED_ID_MAX; i++) if(gpio_pin == (led_gpio_table[i]&0xff)){snprintf(led, sizeof(led), "led%02d", i); nvram_set_int(led, LED_ON); break;}}
#endif	/* RTCONFIG_INTERNAL_GOBI */
	}

	// Power of USB.
	if((gpio_pin = (use_gpio = nvram_get_int("pwr_usb_gpio")) & 0xff) != 0xff){
		enable = (use_gpio&GPIO_ACTIVE_LOW)==0 ? 1 : 0;
		set_gpio(gpio_pin, enable);
	}
	if((gpio_pin = (use_gpio = nvram_get_int("pwr_usb_gpio2")) & 0xff) != 0xff){
		enable = (use_gpio&GPIO_ACTIVE_LOW)==0 ? 1 : 0;
		set_gpio(gpio_pin, enable);
	}

#if defined(RTCONFIG_RTAC5300) || defined(RTCONFIG_RTAC5300R)
	// RPM of FAN
	if((gpio_pin = (use_gpio = nvram_get_int("rpm_fan_gpio")) & 0xff) != 0xff){
	enable = (use_gpio&GPIO_ACTIVE_LOW)==0 ? 1 : 0;
	set_gpio(gpio_pin, enable);
	}
#endif

#ifdef PLAC56
	if((gpio_pin = (use_gpio = nvram_get_int("plc_wake_gpio")) & 0xff) != 0xff){
		enable = (use_gpio&GPIO_ACTIVE_LOW)==0 ? 1 : 0;
		set_gpio(gpio_pin, enable);
	}
#endif

	// TODO: system dependent initialization
	return 0;
}
Beispiel #15
0
// If we find a file, which short name is equal to 'Name', we try to change
// its short name, while preserving the long name. It helps when unpacking
// an archived file, which long name is equal to short name of already
// existing file. Otherwise we would overwrite the already existing file,
// even though its long name does not match the name of unpacking file.
bool UpdateExistingShortName(wchar *Name)
{
  // 'Name' is the name of file which we want to create. Let's check
  // if file with such name is exist. If it does not, we return.
  FindData fd;
  if (!FindFile::FastFind(NULL,Name,&fd))
    return(false);

  // We continue only if file has a short name, which does not match its
  // long name, and this short name is equal to name of file which we need
  // to create.
  if (*fd.ShortName==0 || wcsicomp(PointToName(fd.NameW),fd.ShortName)==0 ||
      wcsicomp(PointToName(Name),fd.ShortName)!=0)
    return(false);

  // Generate the temporary new name for existing file.
  wchar NewName[NM];
  *NewName=0;
  for (int I=0;I<10000 && *NewName==0;I+=123)
  {
    // Here we copy the path part of file to create. We'll make the temporary
    // file in the same folder.
    wcsncpyz(NewName,Name,ASIZE(NewName));

    // Here we set the random name part.
    sprintfw(PointToName(NewName),ASIZE(NewName),L"rtmp%d",I);
    
    // If such file is already exist, try next random name.
    if (FileExist(NULL,NewName))
      *NewName=0;
  }

  // If we could not generate the name not used by any other file, we return.
  if (*NewName==0)
    return(false);
  
  // FastFind returns the name without path, but we need the fully qualified
  // name for renaming, so we use the path from file to create and long name
  // from existing file.
  wchar FullName[NM];
  wcsncpyz(FullName,Name,ASIZE(FullName));
  wcscpy(PointToName(FullName),PointToName(fd.NameW));
  
  // Rename the existing file to randomly generated name. Normally it changes
  // the short name too.
  if (!MoveFileW(FullName,NewName))
    return(false);

  // Now we need to create the temporary empty file with same name as
  // short name of our already existing file. We do it to occupy its previous
  // short name and not allow to use it again when renaming the file back to
  // its original long name.
  File KeepShortFile;
  bool Created=false;
  if (!FileExist(NULL,Name))
    Created=KeepShortFile.Create(NULL,Name);

  // Now we rename the existing file from temporary name to original long name.
  // Since its previous short name is occupied by another file, it should
  // get another short name.
  MoveFileW(NewName,FullName);

  if (Created)
  {
    // Delete the temporary zero length file occupying the short name,
    KeepShortFile.Close();
    KeepShortFile.Delete();
  }
  // We successfully changed the short name. Maybe sometimes we'll simplify
  // this function by use of SetFileShortName Windows API call.
  // But SetFileShortName is not available in older Windows.
  return(true);
}
Beispiel #16
0
void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bool Technical,bool Bare)
{
  wchar *Name=hd.FileName;
  RARFORMAT Format=Arc.Format;

  if (Bare)
  {
    mprintf(L"%s\n",Name);
    return;
  }

  if (!TitleShown && !Technical)
  {
    if (Verbose)
    {
      mprintf(L"\n%ls",St(MListTitleV));
      mprintf(L"\n----------- ---------  -------- ----- ---------- -----  --------  ----");
    }
    else
    {
      mprintf(L"\n%ls",St(MListTitleL));
      mprintf(L"\n----------- ---------  ---------- -----  ----");
    }
    TitleShown=true;
  }

  wchar UnpSizeText[20],PackSizeText[20];
  if (hd.UnpSize==INT64NDF)
    wcscpy(UnpSizeText,L"?");
  else
    itoa(hd.UnpSize,UnpSizeText,ASIZE(UnpSizeText));
  itoa(hd.PackSize,PackSizeText,ASIZE(PackSizeText));

  wchar AttrStr[30];
  if (hd.HeaderType==HEAD_SERVICE)
    swprintf(AttrStr,ASIZE(AttrStr),L"%cB",hd.Inherited ? 'I' : '.');
  else
    ListFileAttr(hd.FileAttr,hd.HSType,AttrStr,ASIZE(AttrStr));

  wchar RatioStr[10];

  if (hd.SplitBefore && hd.SplitAfter)
    wcscpy(RatioStr,L"<->");
  else
    if (hd.SplitBefore)
      wcscpy(RatioStr,L"<--");
    else
      if (hd.SplitAfter)
        wcscpy(RatioStr,L"-->");
      else
        swprintf(RatioStr,ASIZE(RatioStr),L"%d%%",ToPercentUnlim(hd.PackSize,hd.UnpSize));

  wchar DateStr[50];
  hd.mtime.GetText(DateStr,ASIZE(DateStr),Technical);

  if (Technical)
  {
    mprintf(L"\n%12s: %s",St(MListName),Name);

    bool FileBlock=hd.HeaderType==HEAD_FILE;

    if (!FileBlock && Arc.SubHead.CmpName(SUBHEAD_TYPE_STREAM))
    {
      mprintf(L"\n%12ls: %ls",St(MListType),St(MListStream));
      wchar StreamName[NM];
      GetStreamNameNTFS(Arc,StreamName,ASIZE(StreamName));
      mprintf(L"\n%12ls: %ls",St(MListTarget),StreamName);
    }
    else
    {
      const wchar *Type=St(FileBlock ? (hd.Dir ? MListDir:MListFile):MListService);
    
      if (hd.RedirType!=FSREDIR_NONE)
        switch(hd.RedirType)
        {
          case FSREDIR_UNIXSYMLINK:
            Type=St(MListUSymlink); break;
          case FSREDIR_WINSYMLINK:
            Type=St(MListWSymlink); break;
          case FSREDIR_JUNCTION:
            Type=St(MListJunction); break;
          case FSREDIR_HARDLINK:
            Type=St(MListHardlink); break;
          case FSREDIR_FILECOPY:
            Type=St(MListCopy);     break;
        }
      mprintf(L"\n%12ls: %ls",St(MListType),Type);
      if (hd.RedirType!=FSREDIR_NONE)
        if (Format==RARFMT15)
        {
          char LinkTargetA[NM];
          if (Arc.FileHead.Encrypted)
          {
            // Link data are encrypted. We would need to ask for password
            // and initialize decryption routine to display the link target.
            strncpyz(LinkTargetA,"*<-?->",ASIZE(LinkTargetA));
          }
          else
          {
            int DataSize=(int)Min(hd.PackSize,ASIZE(LinkTargetA)-1);
            Arc.Read(LinkTargetA,DataSize);
            LinkTargetA[DataSize > 0 ? DataSize : 0] = 0;
          }
          wchar LinkTarget[NM];
          CharToWide(LinkTargetA,LinkTarget,ASIZE(LinkTarget));
          mprintf(L"\n%12ls: %ls",St(MListTarget),LinkTarget);
        }
        else
          mprintf(L"\n%12ls: %ls",St(MListTarget),hd.RedirName);
    }
    if (!hd.Dir)
    {
      mprintf(L"\n%12ls: %ls",St(MListSize),UnpSizeText);
      mprintf(L"\n%12ls: %ls",St(MListPacked),PackSizeText);
      mprintf(L"\n%12ls: %ls",St(MListRatio),RatioStr);
    }
    if (hd.mtime.IsSet())
      mprintf(L"\n%12ls: %ls",St(MListMtime),DateStr);
    if (hd.ctime.IsSet())
    {
      hd.ctime.GetText(DateStr,ASIZE(DateStr),true);
      mprintf(L"\n%12ls: %ls",St(MListCtime),DateStr);
    }
    if (hd.atime.IsSet())
    {
      hd.atime.GetText(DateStr,ASIZE(DateStr),true);
      mprintf(L"\n%12ls: %ls",St(MListAtime),DateStr);
    }
    mprintf(L"\n%12ls: %ls",St(MListAttr),AttrStr);
    if (hd.FileHash.Type==HASH_CRC32)
      mprintf(L"\n%12ls: %8.8X",
        hd.UseHashKey ? L"CRC32 MAC":hd.SplitAfter ? L"Pack-CRC32":L"CRC32",
        hd.FileHash.CRC32);
    if (hd.FileHash.Type==HASH_BLAKE2)
    {
      wchar BlakeStr[BLAKE2_DIGEST_SIZE*2+1];
      BinToHex(hd.FileHash.Digest,BLAKE2_DIGEST_SIZE,NULL,BlakeStr,ASIZE(BlakeStr));
      mprintf(L"\n%12ls: %ls",
        hd.UseHashKey ? L"BLAKE2 MAC":hd.SplitAfter ? L"Pack-BLAKE2":L"BLAKE2",
        BlakeStr);
    }

    const wchar *HostOS=L"";
    if (Format==RARFMT50 && hd.HSType!=HSYS_UNKNOWN)
      HostOS=hd.HSType==HSYS_WINDOWS ? L"Windows":L"Unix";
    if (Format==RARFMT15)
    {
      static const wchar *RarOS[]={
        L"DOS",L"OS/2",L"Windows",L"Unix",L"Mac OS",L"BeOS",L"WinCE",L"",L"",L""
      };
      if (hd.HostOS<ASIZE(RarOS))
        HostOS=RarOS[hd.HostOS];
    }
    if (*HostOS!=0)
      mprintf(L"\n%12ls: %ls",St(MListHostOS),HostOS);

    mprintf(L"\n%12ls: RAR %ls(v%d) -m%d -md=%d%s",St(MListCompInfo),
            Format==RARFMT15 ? L"3.0":L"5.0",hd.UnpVer,hd.Method,
            hd.WinSize>=0x100000 ? hd.WinSize/0x100000:hd.WinSize/0x400,
            hd.WinSize>=0x100000 ? L"M":L"K");

    if (hd.Solid || hd.Encrypted)
    {
      mprintf(L"\n%12ls: ",St(MListFlags));
      if (hd.Solid)
        mprintf(L"%ls ",St(MListSolid));
      if (hd.Encrypted)
        mprintf(L"%ls ",St(MListEnc));
    }

    if (hd.Version)
    {
      uint Version=ParseVersionFileName(Name,false);
      if (Version!=0)
        mprintf(L"\n%12ls: %u",St(MListFileVer),Version);
    }

    if (hd.UnixOwnerSet)
    {
      mprintf(L"\n%12ls: ",L"Unix owner");
      if (*hd.UnixOwnerName!=0)
        mprintf(L"%ls:",GetWide(hd.UnixOwnerName));
      if (*hd.UnixGroupName!=0)
        mprintf(L"%ls",GetWide(hd.UnixGroupName));
      if ((*hd.UnixOwnerName!=0 || *hd.UnixGroupName!=0) && (hd.UnixOwnerNumeric || hd.UnixGroupNumeric))
        mprintf(L"  ");
      if (hd.UnixOwnerNumeric)
        mprintf(L"#%d:",hd.UnixOwnerID);
      if (hd.UnixGroupNumeric)
        mprintf(L"#%d:",hd.UnixGroupID);
    }

    mprintf(L"\n");
    return;
  }

  mprintf(L"\n%c%10ls %9ls ",hd.Encrypted ? '*' : ' ',AttrStr,UnpSizeText);

  if (Verbose)
    mprintf(L"%9ls %4ls ",PackSizeText,RatioStr);

  mprintf(L" %ls  ",DateStr);

  if (Verbose)
  {
    if (hd.FileHash.Type==HASH_CRC32)
      mprintf(L"%8.8X  ",hd.FileHash.CRC32);
    else
      if (hd.FileHash.Type==HASH_BLAKE2)
      {
        byte *S=hd.FileHash.Digest;
        mprintf(L"%02x%02x..%02x  ",S[0],S[1],S[31]);
      }
      else
        mprintf(L"????????  ");
  }
  mprintf(L"%-12ls",Name);
}
Beispiel #17
0
bool FileCreate(RAROptions *Cmd,File *NewFile,char *Name,wchar *NameW,
                OVERWRITE_MODE Mode,bool *UserReject,int64 FileSize,
                uint FileTime,bool WriteOnly)
{
  if (UserReject!=NULL)
    *UserReject=false;
#if defined(_WIN_ALL) && !defined(_WIN_CE)
  bool ShortNameChanged=false;
#endif
  while (FileExist(Name,NameW))
  {
#if defined(_WIN_ALL) && !defined(_WIN_CE)
    if (!ShortNameChanged)
    {
      // Avoid the infinite loop if UpdateExistingShortName returns
      // the same name.
      ShortNameChanged=true;

      // Maybe our long name matches the short name of existing file.
      // Let's check if we can change the short name.
      wchar WideName[NM];
      GetWideName(Name,NameW,WideName,ASIZE(WideName));
      if (UpdateExistingShortName(WideName))
      {
        if (Name!=NULL && *Name!=0)
          WideToChar(WideName,Name);
        if (NameW!=NULL && *NameW!=0)
          wcscpy(NameW,WideName);
        continue;
      }
    }
    // Allow short name check again. It is necessary, because rename and
    // autorename below can change the name, so we need to check it again.
    ShortNameChanged=false;
#endif
    if (Mode==OVERWRITE_NONE)
    {
      if (UserReject!=NULL)
        *UserReject=true;
      return(false);
    }

    // Must be before Cmd->AllYes check or -y switch would override -or.
    if (Mode==OVERWRITE_AUTORENAME)
    {
      if (!GetAutoRenamedName(Name,NameW))
        Mode=OVERWRITE_DEFAULT;
      continue;
    }

#ifdef SILENT
    Mode=OVERWRITE_ALL;
#endif

    // This check must be after OVERWRITE_AUTORENAME processing or -y switch
    // would override -or.
    if (Cmd->AllYes || Mode==OVERWRITE_ALL)
      break;

    if (Mode==OVERWRITE_DEFAULT || Mode==OVERWRITE_FORCE_ASK)
    {
      char NewName[NM];
      wchar NewNameW[NM];
      *NewNameW=0;
      eprintf(St(MFileExists),Name);
      int Choice=Ask(St(MYesNoAllRenQ));
      if (Choice==1)
        break;
      if (Choice==2)
      {
        if (UserReject!=NULL)
          *UserReject=true;
        return(false);
      }
      if (Choice==3)
      {
        Cmd->Overwrite=OVERWRITE_ALL;
        break;
      }
      if (Choice==4)
      {
        if (UserReject!=NULL)
          *UserReject=true;
        Cmd->Overwrite=OVERWRITE_NONE;
        return(false);
      }
      if (Choice==5)
      {
#ifndef GUI
        mprintf(St(MAskNewName));

#ifdef  _WIN_ALL
        File SrcFile;
        SrcFile.SetHandleType(FILE_HANDLESTD);
        int Size=SrcFile.Read(NewName,sizeof(NewName)-1);
        NewName[Size]=0;
        OemToCharA(NewName,NewName);
#else
        if (fgets(NewName,sizeof(NewName),stdin)==NULL)
        {
          // Process fgets failure as if user answered 'No'.
          if (UserReject!=NULL)
            *UserReject=true;
          return(false);
        }
#endif
        RemoveLF(NewName);
#endif
        if (PointToName(NewName)==NewName)
          strcpy(PointToName(Name),NewName);
        else
          strcpy(Name,NewName);

        if (NameW!=NULL)
        {
          if (PointToName(NewNameW)==NewNameW)
            wcscpy(PointToName(NameW),NewNameW);
          else
            wcscpy(NameW,NewNameW);
        }
        continue;
      }
      if (Choice==6)
        ErrHandler.Exit(RARX_USERBREAK);
    }
  }
  uint FileMode=WriteOnly ? FMF_WRITE|FMF_SHAREREAD:FMF_UPDATE|FMF_SHAREREAD;
  if (NewFile!=NULL && NewFile->Create(Name,NameW,FileMode))
    return(true);
  PrepareToDelete(Name,NameW);
  CreatePath(Name,NameW,true);
  return(NewFile!=NULL ? NewFile->Create(Name,NameW,FileMode):DelFile(Name,NameW));
}
Beispiel #18
0
void ListArchive(CommandData *Cmd)
{
  int64 SumPackSize=0,SumUnpSize=0;
  uint ArcCount=0,SumFileCount=0;
  bool Technical=(Cmd->Command[1]=='T');
  bool ShowService=Technical && Cmd->Command[2]=='A';
  bool Bare=(Cmd->Command[1]=='B');
  bool Verbose=(Cmd->Command[0]=='V');

  wchar ArcName[NM];
  while (Cmd->GetArcName(ArcName,ASIZE(ArcName)))
  {
    if (Cmd->ManualPassword)
      Cmd->Password.Clean(); // Clean user entered password before processing next archive.

    Archive Arc(Cmd);
#ifdef _WIN_ALL
    Arc.RemoveSequentialFlag();
#endif
    if (!Arc.WOpen(ArcName))
      continue;
    bool FileMatched=true;
    while (1)
    {
      int64 TotalPackSize=0,TotalUnpSize=0;
      uint FileCount=0;
      if (Arc.IsArchive(true))
      {
        bool TitleShown=false;
        if (!Bare)
        {
          Arc.ViewComment();
          mprintf(L"\n%s: %s",St(MListArchive),Arc.FileName);
          mprintf(L"\n%s: ",St(MListDetails));
          uint SetCount=0;
          const wchar *Fmt=Arc.Format==RARFMT14 ? L"RAR 1.4":(Arc.Format==RARFMT15 ? L"RAR 4":L"RAR 5");
          mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", Fmt);
          if (Arc.Solid)
            mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", St(MListSolid));
          if (Arc.SFXSize>0)
            mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", St(MListSFX));
          if (Arc.Volume)
            if (Arc.Format==RARFMT50)
            {
              // RAR 5.0 archives store the volume number in main header,
              // so it is already available now.
              if (SetCount++ > 0)
                mprintf(L", ");
              mprintf(St(MVolumeNumber),Arc.VolNumber+1);
            }
            else
              mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", St(MListVolume));
          if (Arc.Protected)
            mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", St(MListRR));
          if (Arc.Locked)
            mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", St(MListLock));
          if (Arc.Encrypted)
            mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", St(MListEncHead));
          mprintf(L"\n");
        }

        wchar VolNumText[50];
        *VolNumText=0;
        while(Arc.ReadHeader()>0)
        {
          HEADER_TYPE HeaderType=Arc.GetHeaderType();
          if (HeaderType==HEAD_ENDARC)
          {
#ifndef SFX_MODULE
            // Only RAR 1.5 archives store the volume number in end record.
            if (Arc.EndArcHead.StoreVolNumber && Arc.Format==RARFMT15)
              swprintf(VolNumText,ASIZE(VolNumText),L"%.10ls %d",St(MListVolume),Arc.VolNumber+1);
#endif
            if (Technical && ShowService)
            {
              mprintf(L"\n%12ls: %ls",St(MListService),L"EOF");
              if (*VolNumText!=0)
                mprintf(L"\n%12ls: %ls",St(MListFlags),VolNumText);
              mprintf(L"\n");
            }
            break;
          }
          switch(HeaderType)
          {
            case HEAD_FILE:
              FileMatched=Cmd->IsProcessFile(Arc.FileHead)!=0;
              if (FileMatched)
              {
                ListFileHeader(Arc,Arc.FileHead,TitleShown,Verbose,Technical,Bare);
                if (!Arc.FileHead.SplitBefore)
                {
                  TotalUnpSize+=Arc.FileHead.UnpSize;
                  FileCount++;
                }
                TotalPackSize+=Arc.FileHead.PackSize;
              }
              break;
            case HEAD_SERVICE:
              if (FileMatched && !Bare)
              {
                if (Technical && ShowService)
                  ListFileHeader(Arc,Arc.SubHead,TitleShown,Verbose,true,false);
              }
              break;
          }
          Arc.SeekToNext();
        }
        if (!Bare && !Technical)
          if (TitleShown)
          {
            wchar UnpSizeText[20];
            itoa(TotalUnpSize,UnpSizeText,ASIZE(UnpSizeText));
        
            wchar PackSizeText[20];
            itoa(TotalPackSize,PackSizeText,ASIZE(PackSizeText));
        
            if (Verbose)
            {
              mprintf(L"\n----------- ---------  -------- ----- ---------- -----  --------  ----");
              mprintf(L"\n%21ls %9ls %3d%%  %-27ls %u",UnpSizeText,
                      PackSizeText,ToPercentUnlim(TotalPackSize,TotalUnpSize),
                      VolNumText,FileCount);
            }
            else
            {
              mprintf(L"\n----------- ---------  ---------- -----  ----");
              mprintf(L"\n%21ls  %-16ls  %u",UnpSizeText,VolNumText,FileCount);
            }

            SumFileCount+=FileCount;
            SumUnpSize+=TotalUnpSize;
            SumPackSize+=TotalPackSize;
            mprintf(L"\n");
          }
          else
            mprintf(St(MListNoFiles));

        ArcCount++;

#ifndef NOVOLUME
        if (Cmd->VolSize!=0 && (Arc.FileHead.SplitAfter ||
            Arc.GetHeaderType()==HEAD_ENDARC && Arc.EndArcHead.NextVolume) &&
            MergeArchive(Arc,NULL,false,Cmd->Command[0]))
        {
          Arc.Seek(0,SEEK_SET);
        }
        else
#endif
          break;
      }
      else
      {
        if (Cmd->ArcNames.ItemsCount()<2 && !Bare)
          mprintf(St(MNotRAR),Arc.FileName);
        break;
      }
    }
  }

  // Clean user entered password. Not really required, just for extra safety.
  if (Cmd->ManualPassword)
    Cmd->Password.Clean();

  if (ArcCount>1 && !Bare && !Technical)
  {
    wchar UnpSizeText[20],PackSizeText[20];
    itoa(SumUnpSize,UnpSizeText,ASIZE(UnpSizeText));
    itoa(SumPackSize,PackSizeText,ASIZE(PackSizeText));

    if (Verbose)
      mprintf(L"%21ls %9ls %3d%% %28ls %u",UnpSizeText,PackSizeText,
              ToPercentUnlim(SumPackSize,SumUnpSize),L"",SumFileCount);
    else
      mprintf(L"%21ls %18s %lu",UnpSizeText,L"",SumFileCount);
  }
}
Beispiel #19
0
void RarTime::GetLocal(RarLocalTime *lt)
{
#ifdef _WIN_ALL
  FILETIME ft;
  GetWin32(&ft);
  FILETIME lft;

  if (WinNT() < WNT_VISTA)
  {
    // SystemTimeToTzSpecificLocalTime based code produces 1 hour error on XP.
    FileTimeToLocalFileTime(&ft,&lft);
  }
  else
  {
    // We use these functions instead of FileTimeToLocalFileTime according to
    // MSDN recommendation: "To account for daylight saving time
    // when converting a file time to a local time ..."
    SYSTEMTIME st1,st2;
    FileTimeToSystemTime(&ft,&st1);
    SystemTimeToTzSpecificLocalTime(NULL,&st1,&st2);
    SystemTimeToFileTime(&st2,&lft);

    // Correct precision loss (low 4 decimal digits) in FileTimeToSystemTime.
    FILETIME rft;
    SystemTimeToFileTime(&st1,&rft);
    int64 Corrected=INT32TO64(ft.dwHighDateTime,ft.dwLowDateTime)-
                    INT32TO64(rft.dwHighDateTime,rft.dwLowDateTime)+
                    INT32TO64(lft.dwHighDateTime,lft.dwLowDateTime);
    lft.dwLowDateTime=(DWORD)Corrected;
    lft.dwHighDateTime=(DWORD)(Corrected>>32);
  }

  SYSTEMTIME st;
  FileTimeToSystemTime(&lft,&st);
  lt->Year=st.wYear;
  lt->Month=st.wMonth;
  lt->Day=st.wDay;
  lt->Hour=st.wHour;
  lt->Minute=st.wMinute;
  lt->Second=st.wSecond;
  lt->wDay=st.wDayOfWeek;
  lt->yDay=lt->Day-1;

  static int mdays[12]={31,28,31,30,31,30,31,31,30,31,30,31};
  for (uint I=1;I<lt->Month && I<=ASIZE(mdays);I++)
    lt->yDay+=mdays[I-1];

  if (lt->Month>2 && IsLeapYear(lt->Year))
    lt->yDay++;

  st.wMilliseconds=0;
  FILETIME zft;
  SystemTimeToFileTime(&st,&zft);

  // Calculate the time reminder, which is the part of time smaller
  // than 1 second, represented in 100-nanosecond intervals.
  lt->Reminder=INT32TO64(lft.dwHighDateTime,lft.dwLowDateTime)-
               INT32TO64(zft.dwHighDateTime,zft.dwLowDateTime);
#else
  time_t ut=GetUnix();
  struct tm *t;
  t=localtime(&ut);

  lt->Year=t->tm_year+1900;
  lt->Month=t->tm_mon+1;
  lt->Day=t->tm_mday;
  lt->Hour=t->tm_hour;
  lt->Minute=t->tm_min;
  lt->Second=t->tm_sec;
  lt->Reminder=itime % 10000000;
  lt->wDay=t->tm_wday;
  lt->yDay=t->tm_yday;
#endif
}
Beispiel #20
0
void Unpack::Unpack29(bool Solid)
{
  static unsigned char LDecode[]={0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224};
  static unsigned char LBits[]=  {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4,  4,  5,  5,  5,  5};
  static int DDecode[DC];
  static byte DBits[DC];
  static int DBitLengthCounts[]= {4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,14,0,12};
  static unsigned char SDDecode[]={0,4,8,16,32,64,128,192};
  static unsigned char SDBits[]=  {2,2,3, 4, 5, 6,  6,  6};
  unsigned int Bits;

  if (DDecode[1]==0)
  {
    int Dist=0,BitLength=0,Slot=0;
    for (int I=0;I<ASIZE(DBitLengthCounts);I++,BitLength++)
      for (int J=0;J<DBitLengthCounts[I];J++,Slot++,Dist+=(1<<BitLength))
      {
        DDecode[Slot]=Dist;
        DBits[Slot]=BitLength;
      }
  }

  FileExtracted=true;

  if (!Suspended)
  {
    UnpInitData(Solid);
    if (!UnpReadBuf30())
      return;
    if ((!Solid || !TablesRead) && !ReadTables30())
      return;
  }

  while (true)
  {
    UnpPtr&=MaxWinMask;

    if (Inp.InAddr>ReadBorder)
    {
      if (!UnpReadBuf30())
        break;
    }
    if (((WrPtr-UnpPtr) & MaxWinMask)<260 && WrPtr!=UnpPtr)
    {
      UnpWriteBuf30();
      if (WrittenFileSize>DestUnpSize)
        return;
      if (Suspended)
      {
        FileExtracted=false;
        return;
      }
    }
    if (UnpBlockType==BLOCK_PPM)
    {
      // Here speed is critical, so we do not use SafePPMDecodeChar,
      // because sometimes even the inline function can introduce
      // some additional penalty.
      int Ch=PPM.DecodeChar();
      if (Ch==-1)              // Corrupt PPM data found.
      {
        PPM.CleanUp();         // Reset possibly corrupt PPM data structures.
        UnpBlockType=BLOCK_LZ; // Set faster and more fail proof LZ mode.
        break;
      }
      if (Ch==PPMEscChar)
      {
        int NextCh=SafePPMDecodeChar();
        if (NextCh==0)  // End of PPM encoding.
        {
          if (!ReadTables30())
            break;
          continue;
        }
        if (NextCh==-1) // Corrupt PPM data found.
          break;
        if (NextCh==2)  // End of file in PPM mode.
          break;
        if (NextCh==3)  // Read VM code.
        {
          if (!ReadVMCodePPM())
            break;
          continue;
        }
        if (NextCh==4) // LZ inside of PPM.
        {
          unsigned int Distance=0,Length;
          bool Failed=false;
          for (int I=0;I<4 && !Failed;I++)
          {
            int Ch=SafePPMDecodeChar();
            if (Ch==-1)
              Failed=true;
            else
              if (I==3)
                Length=(byte)Ch;
              else
                Distance=(Distance<<8)+(byte)Ch;
          }
          if (Failed)
            break;

          CopyString(Length+32,Distance+2);
          continue;
        }
        if (NextCh==5) // One byte distance match (RLE) inside of PPM.
        {
          int Length=SafePPMDecodeChar();
          if (Length==-1)
            break;
          CopyString(Length+4,1);
          continue;
        }
        // If we are here, NextCh must be 1, what means that current byte
        // is equal to our 'escape' byte, so we just store it to Window.
      }
      Window[UnpPtr++]=Ch;
      continue;
    }

    int Number=DecodeNumber(Inp,&BlockTables.LD);
    if (Number<256)
    {
      Window[UnpPtr++]=(byte)Number;
      continue;
    }
    if (Number>=271)
    {
      int Length=LDecode[Number-=271]+3;
      if ((Bits=LBits[Number])>0)
      {
        Length+=Inp.getbits()>>(16-Bits);
        Inp.addbits(Bits);
      }

      int DistNumber=DecodeNumber(Inp,&BlockTables.DD);
      unsigned int Distance=DDecode[DistNumber]+1;
      if ((Bits=DBits[DistNumber])>0)
      {
        if (DistNumber>9)
        {
          if (Bits>4)
          {
            Distance+=((Inp.getbits()>>(20-Bits))<<4);
            Inp.addbits(Bits-4);
          }
          if (LowDistRepCount>0)
          {
            LowDistRepCount--;
            Distance+=PrevLowDist;
          }
          else
          {
            int LowDist=DecodeNumber(Inp,&BlockTables.LDD);
            if (LowDist==16)
            {
              LowDistRepCount=LOW_DIST_REP_COUNT-1;
              Distance+=PrevLowDist;
            }
            else
            {
              Distance+=LowDist;
              PrevLowDist=LowDist;
            }
          }
        }
        else
        {
Beispiel #21
0
static void GenArcName(wchar *ArcName,const wchar *GenerateMask,uint ArcNumber,bool &ArcNumPresent)
{
  bool Prefix=false;
  if (*GenerateMask=='+')
  {
    Prefix=true;    // Add the time string before the archive name.
    GenerateMask++; // Skip '+' in the beginning of time mask.
  }

  wchar Mask[MAX_GENERATE_MASK];
  wcsncpyz(Mask,*GenerateMask!=0 ? GenerateMask:L"yyyymmddhhmmss",ASIZE(Mask));

  bool QuoteMode=false,Hours=false;
  for (uint I=0;Mask[I]!=0;I++)
  {
    if (Mask[I]=='{' || Mask[I]=='}')
    {
      QuoteMode=(Mask[I]=='{');
      continue;
    }
    if (QuoteMode)
      continue;
    int CurChar=toupperw(Mask[I]);
    if (CurChar=='H')
      Hours=true;

    if (Hours && CurChar=='M')
    {
      // Replace minutes with 'I'. We use 'M' both for months and minutes,
      // so we treat as minutes only those 'M' which are found after hours.
      Mask[I]='I';
    }
    if (CurChar=='N')
    {
      uint Digits=GetDigits(ArcNumber);
      uint NCount=0;
      while (toupperw(Mask[I+NCount])=='N')
        NCount++;

      // Here we ensure that we have enough 'N' characters to fit all digits
      // of archive number. We'll replace them by actual number later
      // in this function.
      if (NCount<Digits)
      {
        wmemmove(Mask+I+Digits,Mask+I+NCount,wcslen(Mask+I+NCount)+1);
        wmemset(Mask+I,'N',Digits);
      }
      I+=Max(Digits,NCount)-1;
      ArcNumPresent=true;
      continue;
    }
  }

  RarTime CurTime;
  CurTime.SetCurrentTime();
  RarLocalTime rlt;
  CurTime.GetLocal(&rlt);

  wchar Ext[NM],*Dot=GetExt(ArcName);
  *Ext=0;
  if (Dot==NULL)
    wcscpy(Ext,*PointToName(ArcName)==0 ? L".rar":L"");
  else
  {
    wcsncpyz(Ext,Dot,ASIZE(Ext));
    *Dot=0;
  }

  int WeekDay=rlt.wDay==0 ? 6:rlt.wDay-1;
  int StartWeekDay=rlt.yDay-WeekDay;
  if (StartWeekDay<0)
    if (StartWeekDay<=-4)
      StartWeekDay+=IsLeapYear(rlt.Year-1) ? 366:365;
    else
      StartWeekDay=0;
  int CurWeek=StartWeekDay/7+1;
  if (StartWeekDay%7>=4)
    CurWeek++;

  char Field[10][6];

  sprintf(Field[0],"%04d",rlt.Year);
  sprintf(Field[1],"%02d",rlt.Month);
  sprintf(Field[2],"%02d",rlt.Day);
  sprintf(Field[3],"%02d",rlt.Hour);
  sprintf(Field[4],"%02d",rlt.Minute);
  sprintf(Field[5],"%02d",rlt.Second);
  sprintf(Field[6],"%02d",CurWeek);
  sprintf(Field[7],"%d",WeekDay+1);
  sprintf(Field[8],"%03d",rlt.yDay+1);
  sprintf(Field[9],"%05d",ArcNumber);

  const wchar *MaskChars=L"YMDHISWAEN";

  int CField[sizeof(Field)/sizeof(Field[0])];
  memset(CField,0,sizeof(CField));
  QuoteMode=false;
  for (int I=0;Mask[I]!=0;I++)
  {
    if (Mask[I]=='{' || Mask[I]=='}')
    {
      QuoteMode=(Mask[I]=='{');
      continue;
    }
    if (QuoteMode)
      continue;
    const wchar *ChPtr=wcschr(MaskChars,toupperw(Mask[I]));
    if (ChPtr!=NULL)
      CField[ChPtr-MaskChars]++;
   }

  wchar DateText[MAX_GENERATE_MASK];
  *DateText=0;
  QuoteMode=false;
  for (size_t I=0,J=0;Mask[I]!=0 && J<ASIZE(DateText)-1;I++)
  {
    if (Mask[I]=='{' || Mask[I]=='}')
    {
      QuoteMode=(Mask[I]=='{');
      continue;
    }
    const wchar *ChPtr=wcschr(MaskChars,toupperw(Mask[I]));
    if (ChPtr==NULL || QuoteMode)
    {
      DateText[J]=Mask[I];
#ifdef _WIN_ALL
      // We do not allow ':' in Windows because of NTFS streams.
      // Users had problems after specifying hh:mm mask.
      if (DateText[J]==':')
        DateText[J]='_';
#endif
    }
    else
    {
      size_t FieldPos=ChPtr-MaskChars;
      int CharPos=(int)strlen(Field[FieldPos])-CField[FieldPos]--;
      if (FieldPos==1 && toupperw(Mask[I+1])=='M' && toupperw(Mask[I+2])=='M')
      {
        wcsncpyz(DateText+J,GetMonthName(rlt.Month-1),ASIZE(DateText)-J);
        J=wcslen(DateText);
        I+=2;
        continue;
      }
      if (CharPos<0)
        DateText[J]=Mask[I];
      else
        DateText[J]=Field[FieldPos][CharPos];
    }
    DateText[++J]=0;
  }

  if (Prefix)
  {
    wchar NewName[NM];
    GetFilePath(ArcName,NewName,ASIZE(NewName));
    AddEndSlash(NewName,ASIZE(NewName));
    wcsncatz(NewName,DateText,ASIZE(NewName));
    wcsncatz(NewName,PointToName(ArcName),ASIZE(NewName));
    wcscpy(ArcName,NewName);
  }
  else
    wcscat(ArcName,DateText);
  wcscat(ArcName,Ext);
}
Beispiel #22
0
size_t Archive::ReadHeader()
{
  // Once we failed to decrypt an encrypted block, there is no reason to
  // attempt to do it further. We'll never be successful and only generate
  // endless errors.
  if (FailedHeaderDecryption)
    return 0;

  CurBlockPos=Tell();

#ifndef SFX_MODULE
  if (OldFormat)
    return(ReadOldHeader());
#endif

  RawRead Raw(this);

  bool Decrypt=Encrypted && CurBlockPos>=(int64)SFXSize+SIZEOF_MARKHEAD+SIZEOF_NEWMHD;

  if (Decrypt)
  {
#if defined(SHELL_EXT) || defined(RAR_NOCRYPT)
    return(0);
#else
    if (Read(HeadersSalt,SALT_SIZE)!=SALT_SIZE)
    {
      UnexpEndArcMsg();
      return(0);
    }
    if (*Cmd->Password==0)
    {
#ifdef RARDLL
      char PasswordA[MAXPASSWORD];
      if (Cmd->Callback==NULL ||
          Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LPARAM)PasswordA,ASIZE(PasswordA))==-1)
      {
        Close();
        ErrHandler.Exit(USER_BREAK);
      }
      GetWideName(PasswordA,NULL,Cmd->Password,ASIZE(Cmd->Password));
#else
      if (!GetPassword(PASSWORD_ARCHIVE,FileName,FileNameW,Cmd->Password,ASIZE(Cmd->Password)))
      {
        Close();
        ErrHandler.Exit(USER_BREAK);
      }
#endif
    }
    HeadersCrypt.SetCryptKeys(Cmd->Password,HeadersSalt,false,false,NewMhd.EncryptVer>=36);
    Raw.SetCrypt(&HeadersCrypt);
#endif
  }

  Raw.Read(SIZEOF_SHORTBLOCKHEAD);
  if (Raw.Size()==0)
  {
    UnexpEndArcMsg();
    return(0);
  }

  Raw.Get(ShortBlock.HeadCRC);
  byte HeadType;
  Raw.Get(HeadType);
  ShortBlock.HeadType=(HEADER_TYPE)HeadType;
  Raw.Get(ShortBlock.Flags);
  Raw.Get(ShortBlock.HeadSize);
  if (ShortBlock.HeadSize<SIZEOF_SHORTBLOCKHEAD)
  {
#ifndef SHELL_EXT
    Log(FileName,St(MLogFileHead),"???");
#endif
    BrokenFileHeader=true;
    ErrHandler.SetErrorCode(CRC_ERROR);
    return(0);
  }

  if (ShortBlock.HeadType==COMM_HEAD)
  {
    // Old style (up to RAR 2.9) comment header embedded into main
    // or file header. We must not read the entire ShortBlock.HeadSize here
    // to not break the comment processing logic later.
    Raw.Read(SIZEOF_COMMHEAD-SIZEOF_SHORTBLOCKHEAD);
  }
  else
    if (ShortBlock.HeadType==MAIN_HEAD && (ShortBlock.Flags & MHD_COMMENT)!=0)
    {
      // Old style (up to RAR 2.9) main archive comment embedded into
      // the main archive header found. While we can read the entire 
      // ShortBlock.HeadSize here and remove this part of "if", it would be
      // waste of memory, because we'll read and process this comment data
      // in other function anyway and we do not need them here now.
      Raw.Read(SIZEOF_NEWMHD-SIZEOF_SHORTBLOCKHEAD);
    }
    else
      Raw.Read(ShortBlock.HeadSize-SIZEOF_SHORTBLOCKHEAD);

  NextBlockPos=CurBlockPos+ShortBlock.HeadSize;

  switch(ShortBlock.HeadType) //this is where the type of header that is found, can be executed properly
  {
    case MAIN_HEAD:
      *(BaseBlock *)&NewMhd=ShortBlock;
      Raw.Get(NewMhd.HighPosAV);
      Raw.Get(NewMhd.PosAV);
      if (NewMhd.Flags & MHD_ENCRYPTVER)
        Raw.Get(NewMhd.EncryptVer);
      break;
    case ENDARC_HEAD:
      *(BaseBlock *)&EndArcHead=ShortBlock;
      if (EndArcHead.Flags & EARC_DATACRC)
        Raw.Get(EndArcHead.ArcDataCRC);
      if (EndArcHead.Flags & EARC_VOLNUMBER)
        Raw.Get(EndArcHead.VolNumber);
      break;
    case FILE_HEAD:
    case NEWSUB_HEAD:
      {
        FileHeader *hd=ShortBlock.HeadType==FILE_HEAD ? &NewLhd:&SubHead;
        *(BaseBlock *)hd=ShortBlock;
        Raw.Get(hd->PackSize);
        Raw.Get(hd->UnpSize);
        Raw.Get(hd->HostOS);
        Raw.Get(hd->FileCRC);
        Raw.Get(hd->FileTime);
        Raw.Get(hd->UnpVer);
        Raw.Get(hd->Method);
        Raw.Get(hd->NameSize);
        Raw.Get(hd->FileAttr);
        if (hd->Flags & LHD_LARGE)
        {
          Raw.Get(hd->HighPackSize);
          Raw.Get(hd->HighUnpSize);
        }
        else 
        {
          hd->HighPackSize=hd->HighUnpSize=0;
          if (hd->UnpSize==0xffffffff)
          {
            // UnpSize equal to 0xffffffff without LHD_LARGE flag indicates
            // that we do not know the unpacked file size and must unpack it
            // until we find the end of file marker in compressed data.
            hd->UnpSize=(uint)(INT64NDF);
            hd->HighUnpSize=(uint)(INT64NDF>>32);
          }
        }
        hd->FullPackSize=INT32TO64(hd->HighPackSize,hd->PackSize);
        hd->FullUnpSize=INT32TO64(hd->HighUnpSize,hd->UnpSize);

        char FileName[NM*4];
        size_t NameSize=Min(hd->NameSize,sizeof(FileName)-1);
        Raw.Get((byte *)FileName,NameSize);
        FileName[NameSize]=0;

        strncpyz(hd->FileName,FileName,ASIZE(hd->FileName));

        if (hd->HeadType==NEWSUB_HEAD)
        {
          // Let's calculate the size of optional data.
          int DataSize=hd->HeadSize-hd->NameSize-SIZEOF_NEWLHD;
          if (hd->Flags & LHD_SALT)
            DataSize-=SALT_SIZE;

          if (DataSize>0)
          {
            // Here we read optional additional fields for subheaders.
            // They are stored after the file name and before salt.
            hd->SubData.Alloc(DataSize);
            Raw.Get(&hd->SubData[0],DataSize);
            if (hd->CmpName(SUBHEAD_TYPE_RR))
            {
              byte *D=&hd->SubData[8];
              RecoverySectors=D[0]+((uint)D[1]<<8)+((uint)D[2]<<16)+((uint)D[3]<<24);
            }
          }
        }
        else
          if (hd->HeadType==FILE_HEAD)
          {
            if (hd->Flags & LHD_UNICODE)
            {
              EncodeFileName NameCoder;
              size_t Length=strlen(FileName);
              if (Length==hd->NameSize)
              {
                UtfToWide(FileName,hd->FileNameW,sizeof(hd->FileNameW)/sizeof(hd->FileNameW[0])-1);
                WideToChar(hd->FileNameW,hd->FileName,sizeof(hd->FileName)/sizeof(hd->FileName[0])-1);
                ExtToInt(hd->FileName,hd->FileName);
              }
              else
              {
                Length++;
                NameCoder.Decode(FileName,(byte *)FileName+Length,
                                 hd->NameSize-Length,hd->FileNameW,
                                 sizeof(hd->FileNameW)/sizeof(hd->FileNameW[0]));
              }
              if (*hd->FileNameW==0)
                hd->Flags &= ~LHD_UNICODE;
            }
            else
              *hd->FileNameW=0;
#ifndef SFX_MODULE
            ConvertNameCase(hd->FileName);
            ConvertNameCase(hd->FileNameW);
#endif
            ConvertUnknownHeader();
          }
        if (hd->Flags & LHD_SALT)
          Raw.Get(hd->Salt,SALT_SIZE);
        hd->mtime.SetDos(hd->FileTime);
        hd->ctime.Reset();
        hd->atime.Reset();
        hd->arctime.Reset();
        if (hd->Flags & LHD_EXTTIME)
        {
          ushort Flags;
          Raw.Get(Flags);
          RarTime *tbl[4];
          tbl[0]=&NewLhd.mtime;
          tbl[1]=&NewLhd.ctime;
          tbl[2]=&NewLhd.atime;
          tbl[3]=&NewLhd.arctime;
          for (int I=0;I<4;I++)
          {
            RarTime *CurTime=tbl[I];
            uint rmode=Flags>>(3-I)*4;
            if ((rmode & 8)==0)
              continue;
            if (I!=0)
            {
              uint DosTime;
              Raw.Get(DosTime);
              CurTime->SetDos(DosTime);
            }
            RarLocalTime rlt;
            CurTime->GetLocal(&rlt);
            if (rmode & 4)
              rlt.Second++;
            rlt.Reminder=0;
            int count=rmode&3;
            for (int J=0;J<count;J++)
            {
              byte CurByte;
              Raw.Get(CurByte);
              rlt.Reminder|=(((uint)CurByte)<<((J+3-count)*8));
            }
            CurTime->SetLocal(&rlt);
          }
        }
        NextBlockPos+=hd->FullPackSize;
        bool CRCProcessedOnly=(hd->Flags & LHD_COMMENT)!=0;
        HeaderCRC=~Raw.GetCRC(CRCProcessedOnly)&0xffff;
        if (hd->HeadCRC!=HeaderCRC)
        {
          if (hd->HeadType==NEWSUB_HEAD && strlen(hd->FileName)<ASIZE(hd->FileName)-5)
            strcat(hd->FileName,"- ???");
          BrokenFileHeader=true;
          ErrHandler.SetErrorCode(WARNING);

          // If we have a broken encrypted header, we do not need to display
          // the error message here, because it will be displayed for such
          // headers later in this function. Also such headers are unlikely
          // to have anything sensible in file name field, so it is useless
          // to display the file name.
          bool EncBroken=Decrypt && ShortBlock.HeadCRC!=(~Raw.GetCRC(false)&0xffff);
          if (!EncBroken)
          {
#ifndef SHELL_EXT
            Log(Archive::FileName,St(MLogFileHead),IntNameToExt(hd->FileName));
            Alarm();
#endif
          }
        }
      }
Beispiel #23
0
void ExtractStreamsNew(Archive& Arc, char* FileName, wchar* FileNameW)
{
    if (!WinNT())
        return;

    wchar NameW[NM];

    if (FileNameW != NULL && *FileNameW != 0)
        wcscpy(NameW, FileNameW);

    else
        CharToWide(FileName, NameW);

    wchar StreamNameW[NM + 2];

    if (NameW[0] != 0 && NameW[1] == 0)
    {
        wcscpy(StreamNameW, L".\\");
        wcscpy(StreamNameW + 2, NameW);
    }

    else
        wcscpy(StreamNameW, NameW);

    wchar* DestName = StreamNameW + wcslen(StreamNameW);
    byte* SrcName = &Arc.SubHead.SubData[0];
    size_t DestSize = Arc.SubHead.SubData.Size() / 2;

    if (wcslen(StreamNameW) + DestSize >= ASIZE(StreamNameW))
    {
#if !defined(SILENT) && !defined(SFX_MODULE)
        Log(Arc.FileName, St(MStreamBroken), FileName);
#endif
        ErrHandler.SetErrorCode(CRC_ERROR);
        return;
    }

    RawToWide(SrcName, DestName, DestSize);
    DestName[DestSize] = 0;

    if (*DestName != ':')
    {
#if !defined(SILENT) && !defined(SFX_MODULE)
        Log(Arc.FileName, St(MStreamBroken), FileName);
#endif
        ErrHandler.SetErrorCode(CRC_ERROR);
        return;
    }

    ConvertPath(DestName + 1, DestName + 1);
    FindData fd;
    bool Found = FindFile::FastFind(FileName, FileNameW, &fd);

    if (fd.FileAttr & FILE_ATTRIBUTE_READONLY)
        SetFileAttr(FileName, FileNameW, fd.FileAttr & ~FILE_ATTRIBUTE_READONLY);

    char StreamName[NM];
    WideToChar(StreamNameW, StreamName);
    File CurFile;

    if (CurFile.WCreate(StreamName, StreamNameW) && Arc.ReadSubData(NULL, &CurFile))
        CurFile.Close();

    File HostFile;

    if (Found && HostFile.Open(FileName, FileNameW, true, true))
        SetFileTime(HostFile.GetHandle(), &fd.ftCreationTime, &fd.ftLastAccessTime,
                    &fd.ftLastWriteTime);

    // Restoring original file attributes. Important if file was read only
    // or did not have "Archive" attribute
    SetFileAttr(FileName, FileNameW, fd.FileAttr);
}
Beispiel #24
0
bool DllVolChange(RAROptions *Cmd,wchar *NextName,size_t NameSize)
{
  bool DllVolChanged=false,DllVolAborted=false;

  if (Cmd->Callback!=NULL)
  {
    wchar CurName[NM];
    wcscpy(CurName,NextName);
    if (Cmd->Callback(UCM_CHANGEVOLUMEW,Cmd->UserData,(LPARAM)NextName,RAR_VOL_ASK)==-1)
      DllVolAborted=true;
    else
      if (wcscmp(CurName,NextName)!=0)
        DllVolChanged=true;
      else
      {
        char NextNameA[NM];
        WideToChar(NextName,NextNameA,ASIZE(NextNameA));
        if (Cmd->Callback(UCM_CHANGEVOLUME,Cmd->UserData,(LPARAM)NextNameA,RAR_VOL_ASK)==-1)
          DllVolAborted=true;
        else
        {
          CharToWide(NextNameA,NextName,NameSize);
          if (wcscmp(CurName,NextName)!=0)
            DllVolChanged=true;
        }
      }
  }
  if (!DllVolChanged && Cmd->ChangeVolProc!=NULL)
  {
    char NextNameA[NM];
    WideToChar(NextName,NextNameA,ASIZE(NextNameA));
    // Here we preserve ESP value. It is necessary for those developers,
    // who still define ChangeVolProc callback as "C" type function,
    // even though in year 2001 we announced in unrar.dll whatsnew.txt
    // that it will be PASCAL type (for compatibility with Visual Basic).
#if defined(_MSC_VER)
#ifndef _WIN_64
    __asm mov ebx,esp
#endif
#elif defined(_WIN_ALL) && defined(__BORLANDC__)
    _EBX=_ESP;
#endif
    int RetCode=Cmd->ChangeVolProc(NextNameA,RAR_VOL_ASK);

    // Restore ESP after ChangeVolProc with wrongly defined calling
    // convention broken it.
#if defined(_MSC_VER)
#ifndef _WIN_64
    __asm mov esp,ebx
#endif
#elif defined(_WIN_ALL) && defined(__BORLANDC__)
    _ESP=_EBX;
#endif
    if (RetCode==0)
      DllVolAborted=true;
    else
      CharToWide(NextNameA,NextName,ASIZE(NextName));
  }

  // We quit only on 'abort' condition, but not on 'name not changed'.
  // It is legitimate for program to return the same name when waiting
  // for currently non-existent volume.
  if (DllVolAborted)
  {
    Cmd->DllError=ERAR_EOPEN;
    return false;
  }
  return true;
}
Beispiel #25
0
void CryptData::SetKey30(bool Encrypt,SecPassword *Password,const wchar *PwdW,const byte *Salt)
{
  byte AESKey[16],AESInit[16];

  bool Cached=false;
  for (uint I=0;I<ASIZE(KDF3Cache);I++)
    if (KDF3Cache[I].Pwd==*Password &&
        (Salt==NULL && !KDF3Cache[I].SaltPresent || Salt!=NULL &&
        KDF3Cache[I].SaltPresent && memcmp(KDF3Cache[I].Salt,Salt,SIZE_SALT30)==0))
    {
      memcpy(AESKey,KDF3Cache[I].Key,sizeof(AESKey));
      memcpy(AESInit,KDF3Cache[I].Init,sizeof(AESInit));
      Cached=true;
      break;
    }

  if (!Cached)
  {
    byte RawPsw[2*MAXPASSWORD+SIZE_SALT30];
    WideToRaw(PwdW,RawPsw,ASIZE(RawPsw));
    size_t RawLength=2*wcslen(PwdW);
    if (Salt!=NULL)
    {
      memcpy(RawPsw+RawLength,Salt,SIZE_SALT30);
      RawLength+=SIZE_SALT30;
    }
    sha1_context c;
    sha1_init(&c);

    const int HashRounds=0x40000;
    for (int I=0;I<HashRounds;I++)
    {
      sha1_process( &c, RawPsw, RawLength, false);
      byte PswNum[3];
      PswNum[0]=(byte)I;
      PswNum[1]=(byte)(I>>8);
      PswNum[2]=(byte)(I>>16);
      sha1_process( &c, PswNum, 3, false);
      if (I%(HashRounds/16)==0)
      {
        sha1_context tempc=c;
        uint32 digest[5];
        sha1_done( &tempc, digest, false);
        AESInit[I/(HashRounds/16)]=(byte)digest[4];
      }
    }
    uint32 digest[5];
    sha1_done( &c, digest, false);
    for (int I=0;I<4;I++)
      for (int J=0;J<4;J++)
        AESKey[I*4+J]=(byte)(digest[I]>>(J*8));

    KDF3Cache[KDF3CachePos].Pwd=*Password;
    if ((KDF3Cache[KDF3CachePos].SaltPresent=(Salt!=NULL))==true)
      memcpy(KDF3Cache[KDF3CachePos].Salt,Salt,SIZE_SALT30);
    memcpy(KDF3Cache[KDF3CachePos].Key,AESKey,sizeof(AESKey));
    memcpy(KDF3Cache[KDF3CachePos].Init,AESInit,sizeof(AESInit));
    KDF3CachePos=(KDF3CachePos+1)%ASIZE(KDF3Cache);

    cleandata(RawPsw,sizeof(RawPsw));
  }
Beispiel #26
0
bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,wchar Command)
{
  RAROptions *Cmd=Arc.GetRAROptions();

  HEADER_TYPE HeaderType=Arc.GetHeaderType();
  FileHeader *hd=HeaderType==HEAD_SERVICE ? &Arc.SubHead:&Arc.FileHead;
  bool SplitHeader=(HeaderType==HEAD_FILE || HeaderType==HEAD_SERVICE) &&
                   hd->SplitAfter;

  if (DataIO!=NULL && SplitHeader)
  {
    bool PackedHashPresent=Arc.Format==RARFMT50 || 
         hd->UnpVer>=20 && hd->FileHash.CRC32!=0xffffffff;
    if (PackedHashPresent && 
        !DataIO->PackedDataHash.Cmp(&hd->FileHash,hd->UseHashKey ? hd->HashKey:NULL))
      uiMsg(UIERROR_CHECKSUMPACKED, Arc.FileName, hd->FileName);
  }

  int64 PosBeforeClose=Arc.Tell();

  if (DataIO!=NULL)
    DataIO->ProcessedArcSize+=Arc.FileLength();


  Arc.Close();

  wchar NextName[NM];
  wcscpy(NextName,Arc.FileName);
  NextVolumeName(NextName,ASIZE(NextName),!Arc.NewNumbering);

#if !defined(SFX_MODULE) && !defined(RARDLL)
  bool RecoveryDone=false;
#endif
  bool FailedOpen=false,OldSchemeTested=false;

#if !defined(GUI) && !defined(SILENT)
  // In -vp mode we force the pause before next volume even if it is present
  // and even if we are on the hard disk. It is important when user does not
  // want to process partially downloaded volumes preliminary.
  if (Cmd->VolumePause && !uiAskNextVolume(NextName,ASIZE(NextName)))
    FailedOpen=true;
#endif

  uint OpenMode = Cmd->OpenShared ? FMF_OPENSHARED : 0;

  if (!FailedOpen)
    while (!Arc.Open(NextName,OpenMode))
    {
      // We need to open a new volume which size was not calculated
      // in total size before, so we cannot calculate the total progress
      // anymore. Let's reset the total size to zero and stop 
      // the total progress.
      if (DataIO!=NULL)
        DataIO->TotalArcSize=0;

      if (!OldSchemeTested)
      {
        // Checking for new style volumes renamed by user to old style
        // name format. Some users did it for unknown reason.
        wchar AltNextName[NM];
        wcscpy(AltNextName,Arc.FileName);
        NextVolumeName(AltNextName,ASIZE(AltNextName),true);
        OldSchemeTested=true;
        if (Arc.Open(AltNextName,OpenMode))
        {
          wcscpy(NextName,AltNextName);
          break;
        }
      }
#ifdef RARDLL
      if (!DllVolChange(Cmd,NextName,ASIZE(NextName)))
      {
        FailedOpen=true;
        break;
      }
#else // !RARDLL

#ifndef SFX_MODULE
      if (!RecoveryDone)
      {
        RecVolumesRestore(Cmd,Arc.FileName,true);
        RecoveryDone=true;
        continue;
      }
#endif

#ifndef GUI
      if (!Cmd->VolumePause && !IsRemovable(NextName))
      {
        FailedOpen=true;
        break;
      }
#endif
#ifndef SILENT
      if (Cmd->AllYes || !uiAskNextVolume(NextName,ASIZE(NextName)))
#endif
      {
        FailedOpen=true;
        break;
      }

#endif // RARDLL
    }
  
  if (FailedOpen)
  {
    uiMsg(UIERROR_MISSINGVOL,NextName);
    Arc.Open(Arc.FileName,OpenMode);
    Arc.Seek(PosBeforeClose,SEEK_SET);
    return false;
  }

  if (Command=='T' || Command=='X' || Command=='E')
    mprintf(St(Command=='T' ? MTestVol:MExtrVol),Arc.FileName);


  Arc.CheckArc(true);
#ifdef RARDLL
  if (!DllVolNotify(Cmd,NextName))
    return false;
#endif

  if (SplitHeader)
    Arc.SearchBlock(HeaderType);
  else
    Arc.ReadHeader();
  if (Arc.GetHeaderType()==HEAD_FILE)
  {
    Arc.ConvertAttributes();
    Arc.Seek(Arc.NextBlockPos-Arc.FileHead.PackSize,SEEK_SET);
  }
#ifndef GUI
  if (ShowFileName)
  {
    mprintf(St(MExtrPoints),Arc.FileHead.FileName);
    if (!Cmd->DisablePercentage)
      mprintf(L"     ");
  }
#endif
  if (DataIO!=NULL)
  {
    if (HeaderType==HEAD_ENDARC)
      DataIO->UnpVolume=false;
    else
    {
      DataIO->UnpVolume=hd->SplitAfter;
      DataIO->SetPackedSizeToRead(hd->PackSize);
    }
#ifdef SFX_MODULE
    DataIO->UnpArcSize=Arc.FileLength();
#endif
    
    // Reset the size of packed data read from current volume. It is used
    // to display the total progress and preceding volumes are already
    // compensated with ProcessedArcSize, so we need to reset this variable.
    DataIO->CurUnpRead=0;

    DataIO->PackedDataHash.Init(hd->FileHash.Type,Cmd->Threads);
  }
  return true;
}
Beispiel #27
0
int main(int argc, char *argv[])
{

#ifdef _UNIX
  setlocale(LC_ALL,"");
#endif

  InitConsole();
  ErrHandler.SetSignalHandlers(true);

#ifdef SFX_MODULE
  wchar ModuleName[NM];
#ifdef _WIN_ALL
  GetModuleFileName(NULL,ModuleName,ASIZE(ModuleName));
#else
  CharToWide(argv[0],ModuleName,ASIZE(ModuleName));
#endif
#endif

#ifdef _WIN_ALL
  SetErrorMode(SEM_NOALIGNMENTFAULTEXCEPT|SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);


#endif

#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SHELL_EXT)
  // Must be initialized, normal initialization can be skipped in case of
  // exception.
  bool ShutdownOnClose=false;
#endif

  try 
  {
  
    CommandData *Cmd=new CommandData;
#ifdef SFX_MODULE
    wcscpy(Cmd->Command,L"X");
    char *Switch=NULL;
#ifdef _SFX_RTL_
    char *CmdLine=GetCommandLineA();
    if (CmdLine!=NULL && *CmdLine=='\"')
      CmdLine=strchr(CmdLine+1,'\"');
    if (CmdLine!=NULL && (CmdLine=strpbrk(CmdLine," /"))!=NULL)
    {
      while (IsSpace(*CmdLine))
        CmdLine++;
      Switch=CmdLine;
    }
#else
    Switch=argc>1 ? argv[1]:NULL;
#endif
    if (Switch!=NULL && Cmd->IsSwitch(Switch[0]))
    {
      int UpperCmd=etoupper(Switch[1]);
      switch(UpperCmd)
      {
        case 'T':
        case 'V':
          Cmd->Command[0]=UpperCmd;
          break;
        case '?':
          Cmd->OutHelp(RARX_SUCCESS);
          break;
      }
    }
    Cmd->AddArcName(ModuleName);
    Cmd->ParseDone();
#else // !SFX_MODULE
    Cmd->ParseCommandLine(true,argc,argv);
    if (!Cmd->ConfigDisabled)
    {
      Cmd->ReadConfig();
      Cmd->ParseEnvVar();
    }
    Cmd->ParseCommandLine(false,argc,argv);
#endif

#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SHELL_EXT)
    ShutdownOnClose=Cmd->Shutdown;
#endif

    InitConsoleOptions(Cmd->MsgStream,Cmd->Sound);
    InitLogOptions(Cmd->LogName,Cmd->ErrlogCharset);
    ErrHandler.SetSilent(Cmd->AllYes || Cmd->MsgStream==MSG_NULL);
    ErrHandler.SetShutdown(Cmd->Shutdown);

    Cmd->OutTitle();
    Cmd->ProcessCommand();
    delete Cmd;
  }
  catch (RAR_EXIT ErrCode)
  {
    ErrHandler.SetErrorCode(ErrCode);
  }
  catch (std::bad_alloc)
  {
    ErrHandler.MemoryErrorMsg();
    ErrHandler.SetErrorCode(RARX_MEMORY);
  }
  catch (...)
  {
    ErrHandler.SetErrorCode(RARX_FATAL);
  }

#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SHELL_EXT)
  if (ShutdownOnClose)
    Shutdown();
#endif
  return ErrHandler.GetErrorCode();
}
Beispiel #28
0
bool CreateReparsePoint(CommandData *Cmd,const wchar *Name,FileHeader *hd)
{
  static bool PrivSet=false;
  if (!PrivSet)
  {
    SetPrivilege(SE_RESTORE_NAME);
    // Not sure if we really need it, but let's request anyway.
    SetPrivilege(SE_CREATE_SYMBOLIC_LINK_NAME);
    PrivSet=true;
  }

  const DWORD BufSize=sizeof(REPARSE_DATA_BUFFER)+2*NM+1024;
  Array<byte> Buf(BufSize);
  REPARSE_DATA_BUFFER *rdb=(REPARSE_DATA_BUFFER *)&Buf[0];

  wchar SubstName[NM];
  wcsncpyz(SubstName,hd->RedirName,ASIZE(SubstName));
  size_t SubstLength=unrar_wcslen(SubstName);

  wchar PrintName[NM],*PrintNameSrc=SubstName,*PrintNameDst=PrintName;
  bool WinPrefix=unrar_wcsncmp(PrintNameSrc,L"\\??\\",4)==0;
  if (WinPrefix)
    PrintNameSrc+=4;
  if (WinPrefix && unrar_wcsncmp(PrintNameSrc,L"UNC\\",4)==0)
  {
    *(PrintNameDst++)='\\'; // Insert second \ in beginning of share name.
    PrintNameSrc+=3;
  }
  unrar_wcscpy(PrintNameDst,PrintNameSrc);

  size_t PrintLength=unrar_wcslen(PrintName);

  bool AbsPath=WinPrefix;
  // IsFullPath is not really needed here, AbsPath check is enough.
  // We added it just for extra safety, in case some Windows version would
  // allow to create absolute targets with SYMLINK_FLAG_RELATIVE.
  if (!Cmd->AbsoluteLinks && (AbsPath || IsFullPath(hd->RedirName) ||
      !IsRelativeSymlinkSafe(hd->FileName,hd->RedirName)))
    return false;

#ifndef NOFILECREATE
  CreatePath(Name,true);

  // 'DirTarget' check is important for Unix symlinks to directories.
  // Unix symlinks do not have their own 'directory' attribute.
  if (hd->Dir || hd->DirTarget)
  {
    if (!CreateDirectory(Name,NULL))
      return false;
  }
  else
  {
    HANDLE hFile=CreateFile(Name,GENERIC_WRITE,0,NULL,CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
    if (hFile == INVALID_HANDLE_VALUE)
      return false;
    CloseHandle(hFile);
  }
#endif

  if (hd->RedirType==FSREDIR_JUNCTION)
  {
    rdb->ReparseTag=IO_REPARSE_TAG_MOUNT_POINT;
    rdb->ReparseDataLength=USHORT(
      sizeof(rdb->MountPointReparseBuffer.SubstituteNameOffset)+
      sizeof(rdb->MountPointReparseBuffer.SubstituteNameLength)+
      sizeof(rdb->MountPointReparseBuffer.PrintNameOffset)+
      sizeof(rdb->MountPointReparseBuffer.PrintNameLength)+
      (SubstLength+1)*sizeof(WCHAR)+(PrintLength+1)*sizeof(WCHAR));
    rdb->Reserved=0;

    rdb->MountPointReparseBuffer.SubstituteNameOffset=0;
    rdb->MountPointReparseBuffer.SubstituteNameLength=USHORT(SubstLength*sizeof(WCHAR));
    unrar_wcscpy(rdb->MountPointReparseBuffer.PathBuffer,SubstName);

    rdb->MountPointReparseBuffer.PrintNameOffset=USHORT((SubstLength+1)*sizeof(WCHAR));
    rdb->MountPointReparseBuffer.PrintNameLength=USHORT(PrintLength*sizeof(WCHAR));
    unrar_wcscpy(rdb->MountPointReparseBuffer.PathBuffer+SubstLength+1,PrintName);
  }
  else
    if (hd->RedirType==FSREDIR_WINSYMLINK || hd->RedirType==FSREDIR_UNIXSYMLINK)
    {
      rdb->ReparseTag=IO_REPARSE_TAG_SYMLINK;
      rdb->ReparseDataLength=USHORT(
        sizeof(rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset)+
        sizeof(rdb->SymbolicLinkReparseBuffer.SubstituteNameLength)+
        sizeof(rdb->SymbolicLinkReparseBuffer.PrintNameOffset)+
        sizeof(rdb->SymbolicLinkReparseBuffer.PrintNameLength)+
        sizeof(rdb->SymbolicLinkReparseBuffer.Flags)+
        (SubstLength+1)*sizeof(WCHAR)+(PrintLength+1)*sizeof(WCHAR));
      rdb->Reserved=0;

      rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset=0;
      rdb->SymbolicLinkReparseBuffer.SubstituteNameLength=USHORT(SubstLength*sizeof(WCHAR));
      unrar_wcscpy(rdb->SymbolicLinkReparseBuffer.PathBuffer,SubstName);

      rdb->SymbolicLinkReparseBuffer.PrintNameOffset=USHORT((SubstLength+1)*sizeof(WCHAR));
      rdb->SymbolicLinkReparseBuffer.PrintNameLength=USHORT(PrintLength*sizeof(WCHAR));
      unrar_wcscpy(rdb->SymbolicLinkReparseBuffer.PathBuffer+SubstLength+1,PrintName);

      rdb->SymbolicLinkReparseBuffer.Flags=AbsPath ? 0:SYMLINK_FLAG_RELATIVE;
    }
    else
      return false;

  HANDLE hFile=CreateFile(Name,GENERIC_READ|GENERIC_WRITE,0,NULL,
               OPEN_EXISTING,FILE_FLAG_OPEN_REPARSE_POINT| 
               FILE_FLAG_BACKUP_SEMANTICS,NULL);
  if (hFile==INVALID_HANDLE_VALUE)
    return false;

  DWORD Returned;
  if (!DeviceIoControl(hFile,FSCTL_SET_REPARSE_POINT,rdb, 
      FIELD_OFFSET(REPARSE_DATA_BUFFER,GenericReparseBuffer)+
      rdb->ReparseDataLength,NULL,0,&Returned,NULL))
  { 
    CloseHandle(hFile);
    uiMsg(UIERROR_SLINKCREATE,UINULL,Name);
    if (GetLastError()==ERROR_PRIVILEGE_NOT_HELD)
      uiMsg(UIERROR_NEEDADMIN);
    ErrHandler.SysErrMsg();
    ErrHandler.SetErrorCode(RARX_CREATE);

    if (hd->Dir)
      RemoveDirectory(Name);
    else
      DeleteFile(Name);
    return false;
  }
  File LinkFile;
  LinkFile.SetHandle(hFile);
  LinkFile.SetOpenFileTime(
    Cmd->xmtime==EXTTIME_NONE ? NULL:&hd->mtime,
    Cmd->xctime==EXTTIME_NONE ? NULL:&hd->ctime,
    Cmd->xatime==EXTTIME_NONE ? NULL:&hd->atime);
  LinkFile.Close();
#ifndef NOFILECREATE
  if (!Cmd->IgnoreGeneralAttr)
    SetFileAttr(Name,hd->FileAttr);
#endif
  return true;
}
Beispiel #29
0
bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,char Command)
{
  RAROptions *Cmd=Arc.GetRAROptions();

  int HeaderType=Arc.GetHeaderType();
  FileHeader *hd=HeaderType==NEWSUB_HEAD ? &Arc.SubHead:&Arc.NewLhd;
  bool SplitHeader=(HeaderType==FILE_HEAD || HeaderType==NEWSUB_HEAD) &&
                   (hd->Flags & LHD_SPLIT_AFTER)!=0;

  if (DataIO!=NULL && SplitHeader && hd->UnpVer>=20 &&
      hd->FileCRC!=0xffffffff && DataIO->PackedCRC!=~hd->FileCRC)
  {
    Log(Arc.FileName,St(MDataBadCRC),hd->FileName,Arc.FileName);
  }

  int64 PosBeforeClose=Arc.Tell();

  if (DataIO!=NULL)
    DataIO->ProcessedArcSize+=Arc.FileLength();

  Arc.Close();

  char NextName[NM];
  wchar NextNameW[NM];
  strcpy(NextName,Arc.FileName);
  strcpyw(NextNameW,Arc.FileNameW);
  NextVolumeName(NextName,NextNameW,ASIZE(NextName),(Arc.NewMhd.Flags & MHD_NEWNUMBERING)==0 || Arc.OldFormat);

#if !defined(SFX_MODULE) && !defined(RARDLL)
  bool RecoveryDone=false;
#endif
  bool FailedOpen=false,OldSchemeTested=false;

  while (!Arc.Open(NextName,NextNameW))
  {
    // We need to open a new volume which size was not calculated
    // in total size before, so we cannot calculate the total progress
    // anymore. Let's reset the total size to zero and stop 
    // the total progress.
    if (DataIO!=NULL)
      DataIO->TotalArcSize=0;

    if (!OldSchemeTested)
    {
      // Checking for new style volumes renamed by user to old style
      // name format. Some users did it for unknown reason.
      char AltNextName[NM];
      wchar AltNextNameW[NM];
      strcpy(AltNextName,Arc.FileName);
      strcpyw(AltNextNameW,Arc.FileNameW);
      NextVolumeName(AltNextName,AltNextNameW,ASIZE(AltNextName),true);
      OldSchemeTested=true;
      if (Arc.Open(AltNextName,AltNextNameW))
      {
        strcpy(NextName,AltNextName);
        strcpyw(NextNameW,AltNextNameW);
        break;
      }
    }
#ifdef RARDLL
    if (Cmd->Callback==NULL && Cmd->ChangeVolProc==NULL ||
        Cmd->Callback!=NULL && Cmd->Callback(UCM_CHANGEVOLUME,Cmd->UserData,(LPARAM)NextName,RAR_VOL_ASK)==-1)
    {
      Cmd->DllError=ERAR_EOPEN;
      FailedOpen=true;
      break;
    }
    if (Cmd->ChangeVolProc!=NULL)
    {
      // Here we preserve ESP value. It is necessary for those developers,
      // who still define ChangeVolProc callback as "C" type function,
      // even though in year 2001 we announced in unrar.dll whatsnew.txt
      // that it will be PASCAL type (for compatibility with Visual Basic).
#if defined(_MSC_VER)
#ifndef _M_X64
      __asm mov ebx,esp
#endif
#elif defined(_WIN_32) && defined(__BORLANDC__)
      _EBX=_ESP;
#endif
      int RetCode=Cmd->ChangeVolProc(NextName,RAR_VOL_ASK);

      // Restore ESP after ChangeVolProc with wrongly defined calling
      // convention broken it.
#if defined(_MSC_VER)
#ifndef _M_X64
      __asm mov esp,ebx
#endif
#elif defined(_WIN_32) && defined(__BORLANDC__)
      _ESP=_EBX;
#endif
      if (RetCode==0)
      {
        Cmd->DllError=ERAR_EOPEN;
        FailedOpen=true;
        break;
      }
    }
#else // RARDLL

#if !defined(SFX_MODULE) && !defined(_WIN_CE)
    if (!RecoveryDone)
    {
      RecVolumes RecVol;
      RecVol.Restore(Cmd,Arc.FileName,Arc.FileNameW,true);
      RecoveryDone=true;
      continue;
    }
#endif

#ifndef GUI
    if (!Cmd->VolumePause && !IsRemovable(NextName))
    {
      FailedOpen=true;
      break;
    }
#endif
#ifndef SILENT
    if (Cmd->AllYes || !AskNextVol(NextName))
#endif
    {
      FailedOpen=true;
      break;
    }

#endif // RARDLL
    *NextNameW=0;
  }
  if (FailedOpen)
  {
#if !defined(SILENT) && !defined(_WIN_CE)
      Log(Arc.FileName,St(MAbsNextVol),NextName);
#endif
    Arc.Open(Arc.FileName,Arc.FileNameW);
    Arc.Seek(PosBeforeClose,SEEK_SET);
    return(false);
  }
  Arc.CheckArc(true);
#ifdef RARDLL
  if (Cmd->Callback!=NULL &&
      Cmd->Callback(UCM_CHANGEVOLUME,Cmd->UserData,(LPARAM)NextName,RAR_VOL_NOTIFY)==-1)
    return(false);
  if (Cmd->ChangeVolProc!=NULL)
  {
#if defined(_WIN_32) && !defined(_MSC_VER) && !defined(__MINGW32__)
    _EBX=_ESP;
#endif
    int RetCode=Cmd->ChangeVolProc(NextName,RAR_VOL_NOTIFY);
#if defined(_WIN_32) && !defined(_MSC_VER) && !defined(__MINGW32__)
    _ESP=_EBX;
#endif
    if (RetCode==0)
      return(false);
  }
#endif

  if (Command=='T' || Command=='X' || Command=='E')
    mprintf(St(Command=='T' ? MTestVol:MExtrVol),Arc.FileName);
  if (SplitHeader)
    Arc.SearchBlock(HeaderType);
  else
    Arc.ReadHeader();
  if (Arc.GetHeaderType()==FILE_HEAD)
  {
    Arc.ConvertAttributes();
    Arc.Seek(Arc.NextBlockPos-Arc.NewLhd.FullPackSize,SEEK_SET);
  }
#ifndef GUI
  if (ShowFileName)
  {
    char OutName[NM];
    IntToExt(Arc.NewLhd.FileName,OutName);
#ifdef UNICODE_SUPPORTED
    bool WideName=(Arc.NewLhd.Flags & LHD_UNICODE) && UnicodeEnabled();
    if (WideName)
    {
      wchar NameW[NM];
      ConvertPath(Arc.NewLhd.FileNameW,NameW);
      char Name[NM];
      if (WideToChar(NameW,Name) && IsNameUsable(Name))
        strcpy(OutName,Name);
    }
#endif
    mprintf(St(MExtrPoints),OutName);
    if (!Cmd->DisablePercentage)
      mprintf("     ");
  }
#endif
  if (DataIO!=NULL)
  {
    if (HeaderType==ENDARC_HEAD)
      DataIO->UnpVolume=false;
    else
    {
      DataIO->UnpVolume=(hd->Flags & LHD_SPLIT_AFTER)!=0;
      DataIO->SetPackedSizeToRead(hd->FullPackSize);
    }
#ifdef SFX_MODULE
    DataIO->UnpArcSize=Arc.FileLength();
#endif
    
    // Reset the size of packed data read from current volume. It is used
    // to display the total progress and preceding volumes are already
    // compensated with ProcessedArcSize, so we need to reset this variable.
    DataIO->CurUnpRead=0;

    DataIO->PackedCRC=0xffffffff;
//    DataIO->SetFiles(&Arc,NULL);
  }
  return(true);
}
Beispiel #30
0
void
set_frame_menubar (struct frame *f, bool first_time, bool deep_p)
{
  HMENU menubar_widget = f->output_data.w32->menubar_widget;
  Lisp_Object items;
  widget_value *wv, *first_wv, *prev_wv = 0;
  int i, last_i;
  int *submenu_start, *submenu_end;
  int *submenu_top_level_items, *submenu_n_panes;

  /* We must not change the menubar when actually in use.  */
  if (f->output_data.w32->menubar_active)
    return;

  XSETFRAME (Vmenu_updating_frame, f);

  if (! menubar_widget)
    deep_p = true;

  if (deep_p)
    {
      /* Make a widget-value tree representing the entire menu trees.  */

      struct buffer *prev = current_buffer;
      Lisp_Object buffer;
      ptrdiff_t specpdl_count = SPECPDL_INDEX ();
      int previous_menu_items_used = f->menu_bar_items_used;
      Lisp_Object *previous_items
	= (Lisp_Object *) alloca (previous_menu_items_used
				  * word_size);

      /* If we are making a new widget, its contents are empty,
	 do always reinitialize them.  */
      if (! menubar_widget)
	previous_menu_items_used = 0;

      buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->contents;
      specbind (Qinhibit_quit, Qt);
      /* Don't let the debugger step into this code
	 because it is not reentrant.  */
      specbind (Qdebug_on_next_call, Qnil);

      record_unwind_save_match_data ();

      if (NILP (Voverriding_local_map_menu_flag))
	{
	  specbind (Qoverriding_terminal_local_map, Qnil);
	  specbind (Qoverriding_local_map, Qnil);
	}

      set_buffer_internal_1 (XBUFFER (buffer));

      /* Run the hooks.  */
      safe_run_hooks (Qactivate_menubar_hook);
      safe_run_hooks (Qmenu_bar_update_hook);
      fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));

      items = FRAME_MENU_BAR_ITEMS (f);

      /* Save the frame's previous menu bar contents data.  */
      if (previous_menu_items_used)
	memcpy (previous_items, XVECTOR (f->menu_bar_vector)->contents,
		previous_menu_items_used * word_size);

      /* Fill in menu_items with the current menu bar contents.
	 This can evaluate Lisp code.  */
      save_menu_items ();

      menu_items = f->menu_bar_vector;
      menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0;
      submenu_start = (int *) alloca (ASIZE (items) * sizeof (int));
      submenu_end = (int *) alloca (ASIZE (items) * sizeof (int));
      submenu_n_panes = (int *) alloca (ASIZE (items) * sizeof (int));
      submenu_top_level_items = (int *) alloca (ASIZE (items) * sizeof (int));
      init_menu_items ();
      for (i = 0; i < ASIZE (items); i += 4)
	{
	  Lisp_Object key, string, maps;

	  last_i = i;

	  key = AREF (items, i);
	  string = AREF (items, i + 1);
	  maps = AREF (items, i + 2);
	  if (NILP (string))
	    break;

	  submenu_start[i] = menu_items_used;

	  menu_items_n_panes = 0;
	  submenu_top_level_items[i]
	    = parse_single_submenu (key, string, maps);
	  submenu_n_panes[i] = menu_items_n_panes;

	  submenu_end[i] = menu_items_used;
	}

      finish_menu_items ();

      /* Convert menu_items into widget_value trees
	 to display the menu.  This cannot evaluate Lisp code.  */

      wv = make_widget_value ("menubar", NULL, true, Qnil);
      wv->button_type = BUTTON_TYPE_NONE;
      first_wv = wv;

      for (i = 0; i < last_i; i += 4)
	{
	  menu_items_n_panes = submenu_n_panes[i];
	  wv = digest_single_submenu (submenu_start[i], submenu_end[i],
				      submenu_top_level_items[i]);
	  if (prev_wv)
	    prev_wv->next = wv;
	  else
	    first_wv->contents = wv;
	  /* Don't set wv->name here; GC during the loop might relocate it.  */
	  wv->enabled = true;
	  wv->button_type = BUTTON_TYPE_NONE;
	  prev_wv = wv;
	}

      set_buffer_internal_1 (prev);

      /* If there has been no change in the Lisp-level contents
	 of the menu bar, skip redisplaying it.  Just exit.  */

      for (i = 0; i < previous_menu_items_used; i++)
	if (menu_items_used == i
	    || (!EQ (previous_items[i], AREF (menu_items, i))))
	  break;
      if (i == menu_items_used && i == previous_menu_items_used && i != 0)
	{
	  free_menubar_widget_value_tree (first_wv);
	  discard_menu_items ();
          unbind_to (specpdl_count, Qnil);
	  return;
	}

      fset_menu_bar_vector (f, menu_items);
      f->menu_bar_items_used = menu_items_used;

      /* This undoes save_menu_items.  */
      unbind_to (specpdl_count, Qnil);

      /* Now GC cannot happen during the lifetime of the widget_value,
	 so it's safe to store data from a Lisp_String, as long as
	 local copies are made when the actual menu is created.
	 Windows takes care of this for normal string items, but
	 not for owner-drawn items or additional item-info.  */
      wv = first_wv->contents;
      for (i = 0; i < ASIZE (items); i += 4)
	{
	  Lisp_Object string;
	  string = AREF (items, i + 1);
	  if (NILP (string))
	    break;
	  wv->name = SSDATA (string);
	  update_submenu_strings (wv->contents);
	  wv = wv->next;
	}
    }
  else
    {
      /* Make a widget-value tree containing
	 just the top level menu bar strings.  */

      wv = make_widget_value ("menubar", NULL, true, Qnil);
      wv->button_type = BUTTON_TYPE_NONE;
      first_wv = wv;

      items = FRAME_MENU_BAR_ITEMS (f);
      for (i = 0; i < ASIZE (items); i += 4)
	{
	  Lisp_Object string;

	  string = AREF (items, i + 1);
	  if (NILP (string))
	    break;

	  wv = make_widget_value (SSDATA (string), NULL, true, Qnil);
	  wv->button_type = BUTTON_TYPE_NONE;
	  /* This prevents lwlib from assuming this
	     menu item is really supposed to be empty.  */
	  /* The EMACS_INT cast avoids a warning.
	     This value just has to be different from small integers.  */
	  wv->call_data = (void *) (EMACS_INT) (-1);

	  if (prev_wv)
	    prev_wv->next = wv;
	  else
	    first_wv->contents = wv;
	  prev_wv = wv;
	}

      /* Forget what we thought we knew about what is in the
	 detailed contents of the menu bar menus.
	 Changing the top level always destroys the contents.  */
      f->menu_bar_items_used = 0;
    }

  /* Create or update the menu bar widget.  */

  block_input ();

  if (menubar_widget)
    {
      /* Empty current menubar, rather than creating a fresh one.  */
      while (DeleteMenu (menubar_widget, 0, MF_BYPOSITION))
	;
    }
  else
    {
      menubar_widget = CreateMenu ();
    }
  fill_in_menu (menubar_widget, first_wv->contents);

  free_menubar_widget_value_tree (first_wv);

  {
    HMENU old_widget = f->output_data.w32->menubar_widget;

    f->output_data.w32->menubar_widget = menubar_widget;
    SetMenu (FRAME_W32_WINDOW (f), f->output_data.w32->menubar_widget);
    /* Causes flicker when menu bar is updated
    DrawMenuBar (FRAME_W32_WINDOW (f)); */

    /* Force the window size to be recomputed so that the frame's text
       area remains the same, if menubar has just been created.  */
    if (old_widget == NULL)
      {
	windows_or_buffers_changed = 23;
	adjust_frame_size (f, -1, -1, 2, false, Qmenu_bar_lines);
      }
  }

  unblock_input ();
}