int main(const int argc, const char *argv[]) { char version_string[256]; static struct s_hardware hardware; snprintf(version_string, sizeof version_string, "%s %s (%s)", PRODUCT_NAME, VERSION, CODENAME); /* Cleaning structures */ init_hardware(&hardware); /* Detecting Syslinux version */ detect_syslinux(&hardware); /* Detecting parameters */ detect_parameters(argc, argv, &hardware); /* Opening the Syslinux console */ init_console(&hardware); /* Detect hardware */ detect_hardware(&hardware); /* Clear the screen and reset position of the cursor */ clear_screen(); printf("\033[1;1H"); more_printf("%s\n", version_string); int return_code = 0; if (!menumode || automode) start_cli_mode(&hardware); else { return_code = start_menu_mode(&hardware, version_string); if (return_code == HDT_RETURN_TO_CLI) start_cli_mode(&hardware); } /* Do we got request to do something at exit time ? */ if (strlen(hardware.postexec)>0) { more_printf("Executing postexec instructions : %s\n",hardware.postexec); runsyslinuxcmd(hardware.postexec); } return return_code; }
int start_menu_mode(struct s_hardware *hardware, char *version_string) { struct s_hdt_menu hdt_menu; memset(&hdt_menu, 0, sizeof(hdt_menu)); /* Setup the menu system */ setup_menu(version_string); /* Compute all submenus */ compute_submenus(&hdt_menu, hardware); /* Compute the main menu */ compute_main_menu(&hdt_menu, hardware); #ifdef WITH_MENU_DISPLAY t_menuitem *curr; char cmd[160]; if (!quiet) more_printf("Starting Menu (%d menus)\n", hdt_menu.total_menu_count); curr = showmenus(hdt_menu.main_menu.menu); /* When we exit the menu, do we have something to do? */ if (curr) { /* When want to execute something */ if (curr->action == OPT_RUN) { /* Tweak, we want to switch to the cli */ if (!strncmp (curr->data, HDT_SWITCH_TO_CLI, sizeof(HDT_SWITCH_TO_CLI))) { return HDT_RETURN_TO_CLI; } /* Tweak, we want to start the dump mode */ if (!strncmp (curr->data, HDT_DUMP, sizeof(HDT_DUMP))) { dump(hardware); return 0; } if (!strncmp (curr->data, HDT_REBOOT, sizeof(HDT_REBOOT))) { syslinux_reboot(1); } strcpy(cmd, curr->data); /* Use specific syslinux call if needed */ if (issyslinux()) runsyslinuxcmd(cmd); else csprint(cmd, 0x07); return 1; // Should not happen when run from SYSLINUX } } #endif return 0; }
/** * show_partition_information - print information about a partition * @ptab: part_entry describing the partition * @i: Partition number (UI purposes only) * @ptab_root: part_entry describing the root partition (extended only) * @drive_info: driveinfo struct describing the drive on which the partition * is * * Note on offsets (from hpa, see chain.c32): * * To make things extra confusing: data partition offsets are relative to where * the data partition record is stored, whereas extended partition offsets * are relative to the beginning of the extended partition all the way back * at the MBR... but still not absolute! **/ static void show_partition_information(struct driveinfo *drive_info, struct part_entry *ptab, int partition_offset, int nb_partitions_seen) { char size[11]; char bootloader_name[9]; char *parttype; unsigned int start, end; int i = nb_partitions_seen; reset_more_printf(); start = partition_offset; end = start + ptab->length - 1; if (ptab->length > 0) sectors_to_size(ptab->length, size); else memset(size, 0, sizeof size); if (i == 1) more_printf(" # B Start End Size Id Type\n"); get_label(ptab->ostype, &parttype); more_printf("%2d %s %11d %11d %s %02X %s", i, (ptab->active_flag == 0x80) ? "x" : " ", start, end, size, ptab->ostype, parttype); /* Extra info */ if (ptab->ostype == 0x82 && swsusp_check(drive_info, ptab)) more_printf("%s", " (Swsusp sig. detected)"); if (get_bootloader_string(drive_info, ptab, bootloader_name, 9) == 0) more_printf("%-46s %s %s", " ", "Bootloader:", bootloader_name); more_printf("\n"); free(parttype); }
// // Get exhaustive info on the file. Slow on network disks (avoid). // // Requires full canonical path (for UNC) // static int _get_full_file_info(char *szFullPath, struct cache_entry *ce) { HANDLE hFile; BY_HANDLE_FILE_INFORMATION bhfi; if (ce->ce_bGotFullInfo) { return 0; } ce->ce_bGotFullInfo = TRUE; if (gbReg) { // registry keys have no additional info return 0; } // // Open file with 0 access rights. // // FILE_FLAG_BACKUP_SEMANTICS is required to open directories // (not supported on Win9x) // if ((hFile = CreateFile(szFullPath, /*STANDARD_RIGHTS_READ | SYNCHRONIZE*/0, 0, 0, OPEN_EXISTING, ((ce->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? FILE_FLAG_BACKUP_SEMANTICS : 0), 0)) == INVALID_HANDLE_VALUE) { #ifdef DEBUG_FINDFIRST more_printf("_get_full_file_info: CreateFile(%s) failed\n", szFullPath); more_fflush(stdmore); #endif MapWin32ErrorToPosixErrno(); return -1; } memset(&bhfi, 0, sizeof(bhfi)); if (!GetFileInformationByHandle(hFile, &bhfi)) { MapWin32ErrorToPosixErrno(); CloseHandle(hFile); return -1; } CloseHandle(hFile); ce->dwVolumeSerialNumber = bhfi.dwVolumeSerialNumber; ce->nNumberOfLinks = bhfi.nNumberOfLinks; ce->ce_ino = _to_unsigned_int64(bhfi.nFileIndexLow, bhfi.nFileIndexHigh); return 0; }
BOOL print_registry_value(struct cache_entry *ce) { struct find_reg *fr; struct _finddatai64_t fd; wchar_t wszName[FILENAME_MAX]; DWORD dwSize=0; DWORD dwType; DWORD dwGotType=0; LONG lErrCode; typedef LONG (WINAPI *PFNREGQUERYREFLECTIONKEY)( HKEY hBase, BOOL *pbIsReflectionDisabled // BUG in MSDN doc: BOOL ); static PFNREGQUERYREFLECTIONKEY pfnRegQueryReflectionKey; fr = (struct find_reg*)xmalloc(sizeof(*fr)); memset(fr, 0, sizeof(*fr)); fr->fr_magic = FR_MAGIC; if (ce->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { dwType = DT_DIR; } else { dwType = DT_REG; } if (!_PrepReg(ce->ce_abspath, fr, dwType)) { _RegFindClose((long)fr); return FALSE; } if (!_LookupReg(fr, &fd)) { _RegFindClose((long)fr); return FALSE; } if (dwType == DT_DIR) { // // Reg key: show the class name if any. // if (fr->fr_szClass != NULL) { more_printf(" Class Name: \"%s\"\n", fr->fr_szClass); } // // Reg key: report if 64-bit <-> 32-bit reflection is enabled. // // The reflection is between HKLM\Software and // HKLM\Software\Wow6432Node. // if (gbIsWindowsWOW64) { if (DynaLoad("ADVAPI32.DLL", "RegQueryReflectionKey", (PPFN)&pfnRegQueryReflectionKey)) { // // BUG: Documented as bReflectionEnabled but really // is bReflectionDisabled! // // Note: Always FALSE if !gbIsWindowsWOW64 // // See http://www.codeproject.com/system/Reflection.asp // BOOL bReflectionDisabled = FALSE; // BUG: Reversed if ((*pfnRegQueryReflectionKey)(fr->fr_hKey, &bReflectionDisabled) == ERROR_SUCCESS) { if (!IsWindows7) { // Windows 7 disables all reflection always if (bReflectionDisabled) { // BUG: Reversed more_printf(" Reflection is disabled.\n"); } } } } } _RegFindClose((long)fr); return TRUE; } // // Show the reg value // if (fr->fr_szValue == NULL) { _RegFindClose((long)fr); return FALSE; } // // Query a single value - just check existance and get size // // BUG: Must use Unicode as the RegA functions wrongly // use the Ansi code page. if (::MultiByteToWideChar(get_codepage(), 0, fr->fr_szValue, -1, wszName, FILENAME_MAX) == 0) { _RegFindClose((long)fr); return FALSE; } if (wcscmp(wszName, L"[default]") == 0) { wszName[0] = L'\0'; } dwSize = (DWORD)(fd.size); dwSize = (dwSize + 10) * sizeof(WCHAR); BOOL bUnicode = TRUE; PBYTE pbData = (PBYTE) alloca(dwSize); memset(pbData, 0, dwSize); // // Note: RegQueryValueExW will fail on Win9x // if ((lErrCode = ::RegQueryValueExW(fr->fr_hKey, wszName, 0, &dwGotType, pbData, &dwSize)) != ERROR_SUCCESS) { if (lErrCode != ERROR_NOT_SUPPORTED && lErrCode != ERROR_CALL_NOT_IMPLEMENTED) { ::SetLastError((DWORD)lErrCode); _RegFindClose((long)fr); return FALSE; } // // Win9x: Try again using the ANSI version. // Note that this will wrongly convert OEM chars. // if ((lErrCode = ::RegQueryValueExA(fr->fr_hKey, fr->fr_szValue, 0, &dwGotType, pbData, &dwSize)) != ERROR_SUCCESS) { ::SetLastError((DWORD)lErrCode); _RegFindClose((long)fr); return FALSE; } bUnicode = FALSE; } BOOL bExpandedMui = FALSE; if (IsVista && gbExpandMui) { if ((dwGotType == REG_SZ || dwGotType == REG_EXPAND_SZ || dwGotType == REG_MULTI_SZ) && dwSize >= sizeof(WCHAR) && ((LPCWSTR)pbData)[0] == L'@' && DynaLoad("ADVAPI32.DLL", "RegLoadMUIStringW", (PPFN)&pfnRegLoadMUIStringW)) { PBYTE pbMuiData = NULL; // // Get the required buffer size for the expanded MUI string // DWORD dwMuiLen = 0; // byte len WCHAR wszDummy[4]; // dummy buffer wszDummy[0] = L'\0'; if ((lErrCode = (*pfnRegLoadMUIStringW)(fr->fr_hKey, wszName, wszDummy, 0, &dwMuiLen, 0, NULL)) != ERROR_MORE_DATA) { goto NoMui; // Use the @-string as-is } pbMuiData = (PBYTE) alloca(dwMuiLen+8); // // Now read the data for real // // dwMuiLen will be overwritten with the actual length // if ((lErrCode = (*pfnRegLoadMUIStringW)(fr->fr_hKey, wszName, (LPWSTR)pbMuiData, dwMuiLen, &dwMuiLen, 0, NULL)) != ERROR_SUCCESS) { goto NoMui; // Use the @-string as-is } // // Replace pbData with the expanded MUI data // pbData = pbMuiData; dwSize = dwMuiLen; bExpandedMui = TRUE; } } NoMui: fd.size = dwSize; _RegFindClose((long)fr); switch (dwGotType) { case REG_SZ: case REG_EXPAND_SZ: { DWORD dwLen, dwStrLen=0; LPSTR szBuf; more_fputs((dwGotType == REG_SZ ? " REG_SZ=\"" : " REG_EXPAND_SZ=\""), stdmore); if (!bUnicode) { more_fputs((LPCSTR)pbData, stdmore); dwLen = dwSize; dwStrLen = strlen((LPCSTR)pbData) + 1; } else { dwLen = dwSize+10; szBuf = (LPSTR)alloca(dwLen); if ((dwLen = ::WideCharToMultiByte(get_codepage(), 0, (LPCWSTR)pbData, dwSize/2, szBuf, dwLen, NULL, NULL)) == 0) { more_fputs("???", stdmore); } else { more_fputs(szBuf, stdmore); dwStrLen = strlen(szBuf) + 1; } } more_fputs("\"\n", stdmore); if (dwLen != dwStrLen) { // // Warn if the string length does not match the registry // buffer size. Could indicate hidden data after \0 // more_printf(" *** String length with \\0 (%u) <> registry length (%u) ***\n", dwStrLen, dwLen); } break; } case REG_NONE: case REG_BINARY: case REG_LINK: case REG_MULTI_SZ: case REG_RESOURCE_LIST: case REG_FULL_RESOURCE_DESCRIPTOR: case REG_RESOURCE_REQUIREMENTS_LIST: default: { DWORD dwBytes, i; char ch; switch (dwGotType) { case REG_NONE: more_printf(" REG_NONE (%u bytes)\n", dwSize); break; case REG_BINARY: more_printf(" REG_BINARY (%u bytes)\n", dwSize); break; case REG_LINK: more_printf(" REG_LINK (%u bytes)\n", dwSize); break; case REG_MULTI_SZ: more_printf(" REG_MULTI_SZ (%u bytes)\n", dwSize); break; case REG_RESOURCE_LIST: more_printf(" REG_RESOURCE_LIST (%u bytes)\n", dwSize); break; case REG_FULL_RESOURCE_DESCRIPTOR: more_printf(" REG_FULL_RESOURCE_DESCRIPTOR (%u bytes)\n", dwSize); break; case REG_RESOURCE_REQUIREMENTS_LIST: more_printf(" REG_RESOURCE_REQUIREMENTS_LIST (%u bytes)\n", dwSize); break; default: more_printf(" Unknown type (%u), size %u bytes.\n", dwGotType, dwSize); break; } for (unsigned long l=0; l < dwSize; l += 16) { more_printf("%8x: ", l); dwBytes = ((dwSize - l < 16) ? (dwSize - l) : 16); for (i=0; i < dwBytes; ++i) { more_printf("%02.2x ", pbData[l+i]); } for (; i < 16; ++i) { more_fputs(" ", stdmore); } more_fputs(" ", stdmore); for (i=0; i < dwBytes; ++i) { if ((ch = pbData[l+i]) < 040 || ch > 0176) { ch = '.'; } more_putc(ch, stdmore); } for (; i < 16; ++i) { more_putc(' ', stdmore); } more_putc('\n', stdmore); } break; } case REG_DWORD: more_printf(" REG_DWORD=%u (0x%08X)\n", *(PDWORD)pbData, *(PDWORD)pbData); if (dwSize != sizeof(DWORD)) { more_printf(" *** DWORD length (%u) is not standard. ***\n", dwSize); } break; case REG_QWORD: more_printf(" REG_QWORD=%I64u (0x%I64X)\n", *(unsigned __int64 *)pbData, *(unsigned __int64 *)pbData); if (dwSize != sizeof(unsigned __int64)) { more_printf(" *** QWORD length (%u) is not standard. ***\n", dwSize); } break; } if (bExpandedMui) { more_printf(" Expanded MUI string.\n"); } return TRUE; }
static BOOL _LookupReg(struct find_reg *fr, struct _finddatai64_t *pfd) { char szClass[128]; DWORD dwClassLen = 128; DWORD lErrCode; DWORD dwSize=0; DWORD dwLen=0, dwGotType=0; FILETIME ftWrite; pfd->attrib = 0; pfd->time_create = -1L; pfd->time_access = _cached_now(); pfd->time_write = -1L; pfd->size = 0; if (fr->fr_bRootKeys) { // // Enumerate root keys. Must do by hand // pfd->attrib = FILE_ATTRIBUTE_DIRECTORY; if (fr->fr_bEof) { // if singleton strcpy(pfd->name, "\\"); // synthetic root return TRUE; } switch (fr->fr_dwIndex) { case 0: strcpy(pfd->name, "HKLM"); break; case 1: strcpy(pfd->name, "HKCU"); break; case 2: strcpy(pfd->name, "HKU"); break; #ifdef UNDEFINED // dont walk by default because it is so huge case 3: strcpy(pfd->name, "HKCR"); break; #endif default: fr->fr_bEof = TRUE; ::SetLastError(ERROR_NO_MORE_FILES); return FALSE; } fr->fr_dwIndex++; return TRUE; } if (fr->fr_hKey == NULL) { // if first time if (fr->fr_szKey == NULL) { // if no intermediate key fr->fr_hKey = fr->fr_hRoot; // use root } else { // open intermediate key DWORD dwAccess = KEY_READ; if (gbIsWindowsWOW64 && !gb32bit) { // Allow access to 64 bit keys dwAccess |= 0x0100; // KEY_WOW64_64KEY } if (_EnableSecurityPrivilege()) { dwAccess |= ACCESS_SYSTEM_SECURITY; } if ((lErrCode = ::RegOpenKeyExA(fr->fr_hRoot, fr->fr_szKey, 0, dwAccess, &fr->fr_hKey)) != ERROR_SUCCESS) { ::SetLastError((DWORD)lErrCode); return FALSE; } } // // Get last-write time and class name // if ((lErrCode = ::RegQueryInfoKeyA(fr->fr_hKey, szClass, &dwClassLen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &ftWrite)) != 0) { ::SetLastError((DWORD)lErrCode); return FALSE; } if (dwClassLen > 0) { fr->fr_szClass = xstrdup(szClass); } fr->fr_fd.attrib = FILE_ATTRIBUTE_DIRECTORY; fr->fr_fd.time_write = ConvertFileTimeToTimeT(&ftWrite); fr->fr_fd.time_create = fr->fr_fd.time_write; fr->fr_fd.time_access = _cached_now(); fr->fr_fd.size = 0; if (fr->fr_szKey != NULL) { // // strip to last component for returned name // LPCSTR sz; if ((sz = (char *)strrchr((unsigned char *)fr->fr_szKey, '\\')) != NULL) { ++sz; } else { sz = fr->fr_szKey; } strcpy(fr->fr_fd.name, sz); } // otherwise use the original fd.name from PrepReg() // Note: Use "REG.EXE FLAGS hklm\software\XXX" to view ControlFlags //#ifdef UNDEFINED NTSTATUS Status; if (IsWindowsXP) { if (DynaLoad("NTDLL.DLL", "NtQueryKey", (PPFN)&pfnNtQueryKey)) { // // Query the key flags // Available on Vista, possibly XP // // ControlFlags = REG_KEY_xxx // KEY_FLAGS_INFORMATION kfi; ULONG ulResultLen = sizeof(kfi); memset(&kfi, 0, sizeof(kfi)); Status = (*pfnNtQueryKey)(fr->fr_hKey, KeyFlagsInformation, &kfi, sizeof(kfi), &ulResultLen); #ifdef _DEBUG if (fr->fr_szKey != NULL) { more_printf("%s\n", fr->fr_szKey); } #endif if (NT_SUCCESS(Status)) { #ifdef _DEBUG more_printf("Wow64Flags=%08X, KeyFlags=%08X, ControlFlags=%08X\n", kfi.Wow64Flags, kfi.KeyFlags, kfi.ControlFlags); #endif } if (IsVista) { // // BUG: KeyVirtualizationInformation returns // all zeros for every key on Vista if not running // in virtual mode. // KEY_VIRTUALIZATION_INFORMATION kvi; ulResultLen = sizeof(kvi); memset(&kvi, 0, sizeof(kvi)); Status = (*pfnNtQueryKey)(fr->fr_hKey, KeyVirtualizationInformation, &kvi, sizeof(kvi), &ulResultLen); if (NT_SUCCESS(Status)) { if (kvi.VirtualStore) { // // The key is mirrored. Only when --virtual // fr->fr_fd.attrib |= FILE_ATTRIBUTE_VIRTUAL; } #ifdef _DEBUG more_printf("VirtualizationCandidate=%u, VirtualizationEnabled=%u\n", kvi.VirtualizationCandidate, kvi.VirtualizationEnabled); more_printf("VirtualTarget=%u, VirtualStore=%u, VirtualSource=%u\n", kvi.VirtualTarget, kvi.VirtualStore, kvi.VirtualSource); more_printf("Reserved=%08X\n", kvi.Reserved); #endif } } // IsVista #ifdef _DEBUG more_printf("\n"); #endif } } // IsWindowsXP //#endif // UNDEFINED } // if first time *pfd = fr->fr_fd; // struct copy LPCSTR szValue = fr->fr_szValue; if (szValue != NULL) { if (strcmp(szValue, "[default]") == 0) { szValue = ""; } // // Query a single value - just check existance and get size // if ((lErrCode = ::RegQueryValueExA(fr->fr_hKey, szValue, 0, &dwGotType, NULL, &dwSize)) != ERROR_SUCCESS) { ::SetLastError((DWORD)lErrCode); return FALSE; } pfd->size = dwSize; // 64 bit pfd->attrib &= ~FILE_ATTRIBUTE_DIRECTORY; strcpy(pfd->name, szValue); return TRUE; } if (fr->fr_bEof) { // // Query a single key - already did above, so quit // return TRUE; } if (!fr->fr_bReturnedDot) { // // Return a synthetic dot "." // Required by dirent() // fr->fr_bReturnedDot = TRUE; strcpy(pfd->name, "."); pfd->attrib |= FILE_ATTRIBUTE_DIRECTORY; pfd->time_write = _cached_now(); pfd->time_create = _cached_now(); pfd->time_access = _cached_now(); pfd->size = 0; return TRUE; } if (!fr->fr_bEnumValues) { // // Enumerate subkeys first // dwLen = FILENAME_MAX; if ((lErrCode = ::RegEnumKeyExA(fr->fr_hKey, fr->fr_dwIndex, pfd->name, &dwLen, NULL, NULL, NULL, &ftWrite)) != ERROR_SUCCESS) { if (lErrCode == ERROR_NO_MORE_ITEMS) { fr->fr_bEnumValues = TRUE; fr->fr_dwIndex = 0; goto enum_values; } ::SetLastError((DWORD)lErrCode); return FALSE; } pfd->attrib |= FILE_ATTRIBUTE_DIRECTORY; // // The recursive call to _LookupReg() will determine the virtual status. // pfd->attrib &= ~FILE_ATTRIBUTE_VIRTUAL; pfd->time_write = ConvertFileTimeToTimeT(&ftWrite); pfd->time_create = fr->fr_fd.time_write; pfd->time_access = _cached_now(); pfd->size = 0; fr->fr_dwIndex++; return TRUE; } enum_values: // // Enumerate values second // dwLen = FILENAME_MAX; dwSize = 0; if ((lErrCode = ::RegEnumValueA(fr->fr_hKey, fr->fr_dwIndex, pfd->name, &dwLen, NULL, NULL, NULL, &dwSize)) != ERROR_SUCCESS) { if (lErrCode == ERROR_NO_MORE_ITEMS) { fr->fr_bEof = TRUE; lErrCode = ERROR_NO_MORE_FILES; // expected by caller } if (lErrCode != ERROR_MORE_DATA) { // ok, because no data buf ::SetLastError(lErrCode); return FALSE; } } pfd->attrib &= ~FILE_ATTRIBUTE_VIRTUAL; if (virtual_view && fr->fr_szKey != NULL && (fr->fr_fd.attrib & FILE_ATTRIBUTE_VIRTUAL)) { // // Query the virtual store to determine if the registry value is // really mirrored // // Open HKCU\Software\Classes\VirtualStore\Machine\SOFTWARE\xxx // LPSTR szVirtStore = (LPSTR)alloca(strlen(fr->fr_szKey) + 80); strcpy(szVirtStore, "Software\\Classes\\VirtualStore\\MACHINE\\"); strcat(szVirtStore, fr->fr_szKey); HKEY hVirtKey= (HKEY)INVALID_HANDLE_VALUE; DWORD dwAccess = KEY_READ; if (gbIsWindowsWOW64 && !gb32bit) { // Allow access to 64 bit keys dwAccess |= 0x0100; // KEY_WOW64_64KEY } // // DESIGN BUG: Querying HKCU\Classes\VirtualStore returns the merged // view when --virtual! // // WORKAROUND: Temporarily turn off virtual mode so we can inspect // the actual HKCU\Classes\VirtualStore. // SetVirtualView(FALSE/*bEnable*/, FALSE/*bVerify*/); if ((lErrCode = ::RegOpenKeyExA(HKEY_CURRENT_USER, szVirtStore, 0, dwAccess, &hVirtKey)) == ERROR_SUCCESS) { DWORD dwValueLen=0; if (::RegQueryValueExA(hVirtKey, pfd->name, 0, NULL, NULL, &dwValueLen) == ERROR_SUCCESS) { // // Found the value in the VirtualStore // pfd->attrib |= FILE_ATTRIBUTE_VIRTUAL; } ::RegCloseKey(hVirtKey); } // // Turn virtual mode back on // SetVirtualView(TRUE/*bEnable*/, FALSE/*bVerify*/); } if (pfd->name[0] == '\0') { strcpy(pfd->name, "[default]"); } pfd->size = fr->fr_fd.size = dwSize; pfd->attrib &= ~FILE_ATTRIBUTE_DIRECTORY; // Use the key's timestamp for the value's timestamp pfd->time_create = fr->fr_fd.time_create; pfd->time_access = fr->fr_fd.time_access; pfd->time_write = fr->fr_fd.time_write; //fr->fr_fd.size = 0; fr->fr_dwIndex++; return TRUE; }
// // Query a symbolic registry link // // Also do --regsetval and --regdelval // char * _GetRegistryLink(struct cache_entry *ce, char *szPath) { struct find_reg *fr; if ((ce->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { return NULL; // regval } fr = (struct find_reg*)xmalloc(sizeof(*fr)); memset(fr, 0, sizeof(*fr)); fr->fr_magic = FR_MAGIC; DWORD dwType = DT_DIR; if (!_PrepReg(ce->ce_abspath, fr, dwType) || fr->fr_szKey == NULL) { _RegFindClose((long)fr); return NULL; } wchar_t wszPath[FILENAME_MAX+1]; // // Convert the registry path to Unicode // if (MultiByteToWideChar(get_codepage(), 0, fr->fr_szKey, -1, wszPath, FILENAME_MAX) == 0) { _RegFindClose((long)fr); return NULL; } LONG lErrCode; DWORD dwDisposition = 0; HKEY hkLink = NULL; DWORD dwAccess = KEY_READ; if (gbRegDelVal || gbRegSetVal) { dwAccess |= KEY_WRITE; } if (gbIsWindowsWOW64 && !gb32bit) { // Allow access to 64 bit keys dwAccess |= 0x0100; // KEY_WOW64_64KEY } // // Must use RegCreateKeyExW to pass REG_OPTION_OPEN_LINK // lErrCode = RegCreateKeyExW(fr->fr_hRoot, wszPath, 0, NULL/*wszClass*/, REG_OPTION_OPEN_LINK, dwAccess, NULL, &hkLink, &dwDisposition); if (lErrCode != 0) { _RegFindClose((long)fr); return NULL; } dwType = 0; WCHAR wszData[FILENAME_MAX+1]; DWORD dwLen = FILENAME_MAX*sizeof(WCHAR); wszData[0] = L'\0'; lErrCode = RegQueryValueExW(hkLink, L"SymbolicLinkValue", NULL, &dwType, (PBYTE)wszData, &dwLen); if (gbRegDelVal) { // // --regdelval Delete a test value for exploring registry reflection // and registry redirection. // ::RegDeleteValueW(hkLink, L"TestValue"); } if (gbRegSetVal) { // // --regsetval Set a test value for exploring registry reflection // and registry redirection. // DWORD dwVal = 1; ::RegSetValueExW(hkLink, L"TestValue", 0, REG_DWORD, (PBYTE)&dwVal, sizeof(dwVal)); } RegCloseKey(hkLink); hkLink = NULL; // // Sanity check: If we somehow created a new key accidentally // via RegCreateKeyEx, bail immediately! // if (dwDisposition == REG_CREATED_NEW_KEY) { more_printf("Error: Created new key by mistake: %s\n", fr->fr_szKey); _RegFindClose((long)fr); exit(1); } _RegFindClose((long)fr); if (lErrCode != 0) { return NULL; } wszData[dwLen/2] = L'\0'; // BUG: Not NULL terminated // // Convert from wchar_t to multibyte string // if (!WideCharToMultiByte(get_codepage(), 0, wszData, -1, szPath, FILENAME_MAX-1, NULL, NULL)) { return NULL; } return szPath; }
// // Opendir with wildcard pattern, for network speedup // // Called by glob.c // static DIR* __opendir_with_pat(const char* szPath, const char* szPat, BOOL bCache) { char szBuf[FILENAME_MAX]; char szFullDirPath[FILENAME_MAX]; char szPatBuf[FILENAME_MAX+10]; char* sz; struct cache_dir *cd; struct cache_entry *ce; DIR* pDir; long hFind; struct _finddatai64_t fd; BOOL bShowStreams = (show_streams == yes_arg); BOOL bFixedDisk = FALSE; BOOL bGetFullFileInfoOk = TRUE; // // Delete the previous non-cached dir, if any // if (_dir_nocache != NULL) { _delete_dir(_dir_nocache); _dir_nocache = NULL; } lstrcpyn(szBuf, szPath, sizeof(szBuf)); // // Change forward slashes to backward slashes // for (sz = szBuf; *sz; ++sz) { if (*sz == '/') { *sz = '\\'; } } // // Strip trailing backslashes // for (--sz; sz > szBuf; --sz) { if (*sz != '\\') { break; } if (sz == szBuf+2 && szBuf[1] == ':') { break; // stop if C:\ } *sz = '\0'; } if (!gbReg) { // // See if the pattern contains any UNIX-style glob chars // other than *? // // Note that '!' is legal in an NTFS file name. // // Note that all glob chars are legal in registry names. // if (_mbspbrk(szPat, "[]+@") != NULL) { szPat = "*"; // punt } } // // Return cached dir if available // if ((cd = _find_cache_dir(szBuf, szPat)) != NULL) { pDir = xmalloc(sizeof(DIR)); memset(pDir, 0, sizeof(pDir)); pDir->dd_cd = cd; pDir->dd_next_entry = cd->cd_entry_first; return pDir; } // // Get the absolute path of the directory for FindFirst // if (_GetAbsolutePath(szBuf, szFullDirPath, FILENAME_MAX, &bFixedDisk) < 0) { return NULL; } // // Do not show streams if --fast on a non-fixed disk // if (run_fast && !bFixedDisk) { bShowStreams = FALSE; } // // See if the resulting path is too long // if (strlen(szBuf) + strlen(szPat) + 2 > sizeof(szBuf)) { errno = ENAMETOOLONG; return NULL; } // // Create a new directory node // cd = (struct cache_dir *)xmalloc(sizeof(struct cache_dir)); memset(cd, 0, sizeof(*cd)); cd->cd_dirname = xstrdup(szBuf); // *not* abs path - must match for caching cd->cd_pat = xstrdup(szPat); // // Append search pattern for FindFirstFile. // Use absolute path to make sure it works w/UNC // strcpy(szPatBuf, szFullDirPath); if (*right(szPatBuf, 1) != '\\') { // if not already strcat(szPatBuf, "\\"); } strcat(szPatBuf, szPat); #ifdef UNDEFINED // // BUG: FindFirst("\\server\share") fails! Must append // a backslash, "\\server\share\" // if (_IsServerRootPath(szPatBuf)) { sz = szPatBuf + strlen(szPatBuf) - 1; if (*sz != '\\') { *++sz = '\\'; *++sz = '\0'; } } #endif #ifdef _DEBUG #define DEBUG_FINDFIRST #endif #ifdef DEBUG_FINDFIRST more_printf("opendir: findfirst on \"%s\"\n", szPatBuf); more_fflush(stdmore); #endif // // Always guaranteed to return at least "." and "..", otherwise // not a directory or not found. // if ((hFind = _xfindfirsti64(szPatBuf, &fd, bShowStreams, DT_DIR)) == (long)INVALID_HANDLE_VALUE) { MapWin32ErrorToPosixErrno(); free(cd->cd_dirname); free(cd->cd_pat); free(cd); return NULL; } if (bCache) { // // Append new directory to the dir cache list // if (_dir_first == NULL) { _dir_first = _dir_last = cd; } else { _dir_last->cd_next = cd; _dir_last = cd; } _dir_nocache = NULL; } else { // // Save as non-cached // _dir_nocache = cd; } do { // // Append each file entry to the dir // ce = (struct cache_entry *)xmalloc(sizeof(*ce)); memset(ce, 0, sizeof(*ce)); if (cd->cd_entry_first == NULL) { cd->cd_entry_first = cd->cd_entry_last = ce; } else { cd->cd_entry_last->ce_next = ce; cd->cd_entry_last = ce; } ce->ce_filename = (char *)xstrdup(fd.name); ce->ce_size = fd.size; ce->ce_ino = 1; // requires GetFileInformationByHandle - uintmax_t ce->dwFileAttributes = fd.attrib; // FILE_ATTRIBUTE_NORMAL maps to 0 ce->ce_atime = fd.time_access; ce->ce_mtime = fd.time_write; ce->ce_ctime = fd.time_create; ce->nNumberOfLinks = 1; if (bFixedDisk) { ce->dwFileAttributes |= FILE_ATTRIBUTE_FIXED_DISK; } // Flag reparse points and .LNK shortcuts as symbolic links if ((ce->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0 || _mbsicmp(right(fd.name, 4), ".lnk") == 0) { ce->ce_bIsSymlink = TRUE; } // // If we are reparse point, or need full info, // or phys size, or short names, or ls -l // if ((ce->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0 || gbReg || !run_fast || bFixedDisk || print_inode || phys_size || short_names) { char szBuf2[FILENAME_MAX], szBuf3[FILENAME_MAX]; // // Build dir\file // if (strlen(szFullDirPath) + strlen(fd.name) + 2 < sizeof(szBuf2)) { strcpy(szBuf2, szFullDirPath); // directory path if (*right(szBuf2, 1) != '\\') { // if not already strcat(szBuf2, "\\"); } strcat(szBuf2, fd.name); // // Get the absolute path // if (_GetAbsolutePath(szBuf2, szBuf3, FILENAME_MAX, NULL) >= 0) { // // Squirrel away our abs path for later lookup by security.cpp // ce->ce_abspath = xstrdup(szBuf3); if (gbReg && (ce->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { // For registry keys we must test each regkey explicitly _follow_symlink(ce); } if ((!run_fast || bFixedDisk || print_inode) && bGetFullFileInfoOk) { // // Get inode and hardlink info // (requires absolute path) // bGetFullFileInfoOk = (_get_full_file_info(szBuf3, ce) == 0); } } // // Get the physical size too if requested // if (phys_size) { ce->ce_size = _get_phys_size(szBuf2, ce->ce_size); } if (short_names) { // // Get the short path, then extract the rightmost // component and stuff it into ce->ce_filename // _get_short_path(szBuf2); if ((sz = strrchr(szBuf2, '\\')) != NULL) { ++sz; free(ce->ce_filename); ce->ce_filename = (char *)xstrdup(sz); } } } } } while (_xfindnexti64(hFind, &fd, bShowStreams) != -1); if (GetLastError() != ERROR_NO_MORE_FILES) { // network fail during walk DWORD dwError = GetLastError(); _xfindclose(hFind, bShowStreams); SetLastError(dwError); MapWin32ErrorToPosixErrno(); return NULL; } if (_xfindclose(hFind, bShowStreams) == -1) { MapWin32ErrorToPosixErrno(); return NULL; } // // Build and return DIR // pDir = xmalloc(sizeof(DIR)); memset(pDir, 0, sizeof(pDir)); pDir->dd_cd = cd; pDir->dd_next_entry = cd->cd_entry_first; return pDir; }
// // Return the symlink if followable, otherwise return the current // node again // static struct cache_entry * _follow_symlink(struct cache_entry *ce) { char *sz, *szFullPath; char szPath[FILENAME_MAX+10]; struct cache_entry *symce; long hFind; struct _finddatai64_t fd; BOOL bFixedDisk = FALSE; if (!gbReg && !ce->ce_bIsSymlink) { // not a symlink return ce; } if (ce->ce_symlink != NULL) { return ce->ce_symlink; // return whatever we got earlier } if (ce->ce_bBadSymlink) { // // Already tried and failed // return ce; } ce->ce_bBadSymlink = TRUE; // provisionally mark as bad if (ce->ce_abspath == NULL) { // if earlier _ExpandPath failed return ce; // bail } if (gbReg) { if ((sz = _GetRegistryLink(ce, szPath)) == NULL) { return ce; // bail } } else if ((ce->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) { // // Query the reparse point // if ((sz = _GetReparseTarget(ce, szPath)) == NULL) { return ce; // bail } } else { // // Query the .LNK shortcut // if ((sz = _GetShortcutTarget(ce, szPath)) == NULL) { return ce; // bail } } if (!gbReg && short_names) { _get_short_path(sz); // update in place } // // Build the symbolic link cache_entry // symce = (struct cache_entry *)xmalloc(sizeof(*symce)); memset(symce, 0, sizeof(*symce)); // // Store relative path for later readlink() (not just last component) // symce->ce_filename = (char *)xstrdup(sz); ce->ce_symlink = symce; // point to symlink ce->ce_bIsSymlink = TRUE; symce->ce_ino = 1; // requires GetFileInformationByHandle - uintmax_t symce->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY; // we know this.. symce->nNumberOfLinks = 1; // // Errors after this point are not very important. At worst // we might lose st_mode, st_size and st_time info. // ce->ce_bBadSymlink = FALSE; // link is ok // // Get the absolute path // if (_GetAbsolutePath(symce->ce_filename, szPath, FILENAME_MAX, &bFixedDisk) < 0) { return symce; // bail } // // Squirrel away the absolute path for security.cpp // // BUG? should be symce->ce_abspath = xstrdup(szPath); ?? ce->ce_abspath = xstrdup(szPath); if (gbReg) { return symce; // done } szFullPath = szPath; #ifdef DEBUG_FINDFIRST more_printf("_follow_symlink: findfirst on \"%s\"\n", szFullPath); more_fflush(stdmore); #endif // // Do a singleton FindFirst to get WIN32_FILE_DATA // if ((hFind = _xfindfirsti64(szFullPath, &fd, FALSE/*bShowStreams*/, DT_UNKNOWN)) != (long)INVALID_HANDLE_VALUE) { // Suceeded if (_xfindclose(hFind, FALSE/*bShowStreams*/) == -1) { MapWin32ErrorToPosixErrno(); return symce; // bail } } else { // // FindFirst failed. This is a normal error (sic) for root folders // e.g., C:\ and sometimes \\server\share\ // if ((szFullPath[1] == ':' && szFullPath[2] == '\\' && szFullPath[3] == '\0') || _IsServerRootPath(szFullPath)) { // // Fake an entry for the root folder // time_t t; memset(&fd, 0, sizeof(fd)); t = time(0); fd.attrib = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_SYSTEM; strcpy(fd.name, "\\"); fd.time_access = t; fd.time_write = t; fd.time_create = t; } else { MapWin32ErrorToPosixErrno(); return symce; } } // // Fill in more data for the symlink target // symce->ce_size = fd.size; symce->dwFileAttributes = fd.attrib; // FILE_ATTRIBUTE_NORMAL maps to 0 symce->ce_atime = fd.time_access; symce->ce_mtime = fd.time_write; symce->ce_ctime = fd.time_create; if (bFixedDisk) { symce->dwFileAttributes |= FILE_ATTRIBUTE_FIXED_DISK; } // Flag reparse points and .LNK shortcuts as symbolic links if ((symce->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0 || _mbsicmp(right(fd.name, 4), ".lnk") == 0) { symce->ce_bIsSymlink = TRUE; // symlink pointing to a symlink (rare) } if (phys_size) { symce->ce_size = _get_phys_size(szFullPath, symce->ce_size); } // // Tah dah! // ce->ce_bBadSymlink = FALSE; return symce; }
static int __xstat(const char *szPath, struct xstat *st, unsigned long dwType, BOOL bCache, BOOL bFollowSymlink) { char szFullPath[FILENAME_MAX], szBuf[FILENAME_MAX]; char szDirBuf[FILENAME_MAX]; char *sz, *szDir, *szFile; struct cache_dir *cd; struct cache_entry *ce; long hFind; struct _finddatai64_t fd; BOOL bShowStreams = (show_streams == yes_arg); BOOL bFixedDisk = FALSE; lstrcpyn(szFullPath, szPath, FILENAME_MAX); // // Change forward slashes to backward slashes // for (sz = szFullPath; *sz; ++sz) { if (*sz == '/') { *sz = '\\'; } } // // Strip trailing backslashes // for (--sz; sz > szFullPath; --sz) { if (*sz != '\\') { break; } if (sz == szFullPath+2 && szFullPath[1] == ':') { break; // stop if C:\ } *sz = '\0'; } // // No FindFile wildcards allowed at this point // if (_mbspbrk(szFullPath, "?*") != NULL) { errno = ENOENT; return -1; } // // Break off dir and file components // strcpy(szBuf, szFullPath); if ((sz = strrchr(szBuf, '\\')) == NULL) { if (szBuf[1] == ':') { if (szBuf[2] == '\0') { // ls C: szDir = szBuf; // C: szFile = "."; } else { // ls C:foo szDirBuf[0] = szBuf[0]; szDirBuf[1] = szBuf[1]; szDirBuf[2] = '\0'; szDir = szDirBuf; // C: szFile = szBuf+2; // foo } } else { // ls foo szDir = "."; szFile = szBuf; } } else { // ls dir\foo szFile = sz+1; // // Strip trailing backslashes from the dir component // strcpy(szDirBuf, szBuf); // copy to avoid stomping on szFile szDir = szDirBuf; sz = szDir + (sz-szBuf); *(sz+1) = '\0'; // ensure termination for (; *sz == '\\' && sz > szDirBuf; --sz) { if (sz == szDirBuf+2 && szDirBuf[1] == ':') { break; // stop if C:\ } *sz = '\0'; } } if ((cd = _find_cache_dir(szDir, szFile)) != NULL) { // // Found hit from previous opendir()/readdir() // for (ce = cd->cd_entry_first; ce; ce = ce->ce_next) { if (ce->ce_filename[0] == szFile[0] && _mbsicmp(ce->ce_filename, szFile) == 0) { // // Found file // goto cache_hit; } } errno = ENOENT; // not in cache dir return -1; } // // Get the canonical path for use in security.cpp // if (_GetAbsolutePath(szFullPath, szBuf, FILENAME_MAX, &bFixedDisk) < 0) { return -1; } strcpy(szFullPath, szBuf); // // Check the partial stat cache against the abs path // for (ce = _stat_first; ce; ce = ce->ce_next) { if (ce->ce_abspath && _mbsicmp(ce->ce_abspath, szFullPath) == 0) { goto cache_hit; } } // // Do not show streams if --fast on a non-fixed disk // if (run_fast && !bFixedDisk) { bShowStreams = FALSE; } #ifdef DEBUG_FINDFIRST more_printf("stat: findfirst on \"%s\"\n", szFullPath); more_fflush(stdmore); #endif // // Do a singleton FindFirst to get WIN32_FILE_DATA // if ((hFind = _xfindfirsti64(szFullPath, &fd, bShowStreams, dwType)) != (long)INVALID_HANDLE_VALUE) { // Succeeded if (_xfindclose(hFind, bShowStreams) == -1) { MapWin32ErrorToPosixErrno(); return -1; } } else { // // FindFirst failed. This is a normal (sic) error for root folders // e.g., C:\ and sometimes \\server\share\ // if ((szFullPath[1] == ':' && szFullPath[2] == '\\' && szFullPath[3] == '\0') || _IsServerRootPath(szFullPath)) { // // Fake an entry for the root folder // time_t t; memset(&fd, 0, sizeof(fd)); t = time(0); fd.attrib = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_SYSTEM; strcpy(fd.name, "\\"); fd.time_access = t; fd.time_write = t; fd.time_create = t; } else { MapWin32ErrorToPosixErrno(); return -1; } } ce = (struct cache_entry *)xmalloc(sizeof(*ce)); memset(ce, 0, sizeof(*ce)); if (bCache) { // // Put on the partial stat cache // if (_stat_first == NULL) { _stat_first = _stat_last = ce; } else { _stat_last->ce_next = ce; _stat_last = ce; } } if (short_names) { _get_short_path(szFullPath); // update in place } ce->ce_filename = (char *)xstrdup(fd.name); // last component only ce->ce_size = fd.size; ce->ce_ino = 1; // requires GetFileInformationByHandle - uintmax_t ce->dwFileAttributes = fd.attrib; // FILE_ATTRIBUTE_NORMAL maps to 0 ce->ce_atime = fd.time_access; ce->ce_mtime = fd.time_write; ce->ce_ctime = fd.time_create; ce->nNumberOfLinks = 1; if (bFixedDisk) { ce->dwFileAttributes |= FILE_ATTRIBUTE_FIXED_DISK; } // // Squirrel away the canonical path // ce->ce_abspath = xstrdup(szFullPath); // Flag reparse points and .LNK shortcuts as symbolic links if ((ce->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0 || _mbsicmp(right(fd.name, 4), ".lnk") == 0) { ce->ce_bIsSymlink = TRUE; } if (phys_size) { ce->ce_size = _get_phys_size(szFullPath, ce->ce_size); } if (!run_fast || bFixedDisk || print_inode) { // // Get inode and hardlink info // _get_full_file_info(szFullPath, ce); } cache_hit: if (bFollowSymlink) { ce = _follow_symlink(ce); } memset(st, 0, sizeof(*st)); st->st_ino = ce->ce_ino; st->st_size = ce->ce_size; st->st_atime = ce->ce_atime; st->st_mtime = ce->ce_mtime; st->st_ctime = ce->ce_ctime; st->st_nlink = (short)ce->nNumberOfLinks; st->st_mode = _MapMode(ce); st->st_ce = ce; return 0; }
/** * dump - dump info **/ void dump(struct s_hardware *hardware) { if (hardware->is_pxe_valid==false) { printf("PXE stack was not detected, Dump feature is not available\n"); return; } const union syslinux_derivative_info *sdi = syslinux_derivative_info(); int err=0; ZZJSON *json = NULL; ZZJSON_CONFIG config = { ZZJSON_VERY_STRICT, NULL, (int(*)(void*)) fgetc, NULL, malloc, calloc, free, realloc, stderr, NULL, stdout, (int(*)(void *,const char*,...)) dumpprintf, (int(*)(int,void*)) fputc }; memset(&p_buf,0,sizeof(p_buf)); /* By now, we only support TFTP reporting */ upload=&upload_tftp; upload->name="tftp"; /* The following defines the behavior of the reporting */ char *arg[64]; char filename[512]={0}; compute_filename(hardware, filename, sizeof(filename)); /* The filename */ arg[0] = filename; /* The server to upload the file */ if (strlen(hardware->tftp_ip) != 0) { arg[1] = hardware->tftp_ip; arg[2] = NULL; } else { arg[1] = NULL; snprintf(hardware->tftp_ip, sizeof(hardware->tftp_ip), "%u.%u.%u.%u", ((uint8_t *)&sdi->pxe.ipinfo->serverip)[0], ((uint8_t *)&sdi->pxe.ipinfo->serverip)[1], ((uint8_t *)&sdi->pxe.ipinfo->serverip)[2], ((uint8_t *)&sdi->pxe.ipinfo->serverip)[3]); } /* We initiate the cpio to send */ cpio_init(upload,(const char **)arg); dump_cpu(hardware, &config, &json); dump_pxe(hardware, &config, &json); dump_syslinux(hardware, &config, &json); dump_vpd(hardware, &config, &json); dump_vesa(hardware, &config, &json); dump_disks(hardware, &config, &json); dump_dmi(hardware, &config, &json); dump_memory(hardware, &config, &json); dump_pci(hardware, &config, &json); dump_acpi(hardware, &config, &json); dump_kernel(hardware, &config, &json); dump_hdt(hardware, &config, &json); /* We close & flush the file to send */ cpio_close(upload); if ((err=flush_data(upload)) != TFTP_OK) { /* As we manage a tftp connection, let's display the associated error message */ more_printf("Dump failed !\n"); more_printf("TFTP ERROR on : %s:/%s \n",hardware->tftp_ip, filename); more_printf("TFTP ERROR msg : %s \n",tftp_string_error_message[-err]); } else { more_printf("Dump file sent at %s:/%s\n",hardware->tftp_ip, filename); } }
void main_show_disk(int argc, char **argv, struct s_hardware *hardware) { if (!argc) { more_printf("Which disk?\n"); return; } int drive = strtol(argv[0], (char **)NULL, 16); if (drive < 0x80 || drive >= 0xff) { more_printf("Invalid disk: %d.\n", drive); return; } int i = drive - 0x80; struct driveinfo *d = &hardware->disk_info[i]; char disk_size[11]; char mbr_name[50]; reset_more_printf(); if (!hardware->disk_info[i].cbios) { more_printf("No disk found\n"); return; /* Invalid geometry */ } get_mbr_string(hardware->mbr_ids[i], &mbr_name, 50); if ((int)d->edd_params.sectors > 0) sectors_to_size((int)d->edd_params.sectors, disk_size); else memset(disk_size, 0, sizeof disk_size); more_printf("DISK 0x%X:\n" " C/H/S: %d cylinders, %d heads, %d sectors/track\n" " EDD: Version: %X\n" " Size: %s, %d bytes/sector, %d sectors/track\n" " Host bus: %s, Interface type: %s\n" " MBR: %s (id 0x%X)\n\n", d->disk, d->legacy_max_cylinder + 1, d->legacy_max_head + 1, d->legacy_sectors_per_track, d->edd_version, disk_size, (int)d->edd_params.bytes_per_sector, (int)d->edd_params.sectors_per_track, remove_spaces((char *)d->edd_params.host_bus_type), remove_spaces((char *)d->edd_params.interface_type), mbr_name, hardware->mbr_ids[i]); display_line_nb += 6; if (parse_partition_table(d, &show_partition_information)) { if (errno_disk) { fprintf(stderr, "I/O error parsing disk 0x%X\n", d->disk); get_error("parse_partition_table"); } else { fprintf(stderr, "Disk 0x%X: unrecognized partition layout\n", d->disk); } fprintf(stderr, "\n"); } more_printf("\n"); }