/* nthibr.c - tests whether an MS Windows system partition is hibernated */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2007,2008,2009,2011 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see .
*/
//======== INCLUDES ==========================================================//
//Common Utilities
#include //NULL
#include //grub_*size_t
#include //grub_disk_t, grub_disk_*()
#include //grub_file_t, grub_file_*()
#include //grub_str*(), grub_*puts(), grub_*printf()
//Module Management
#include //GRUB_MOD_*()
#include //grub_extcmd_*t, grub_*register_extcmd()
#include //grub_arg_*, ARG_TYPE_*
#include //grub_err_t, GRUB_ERR_*, grub_error()
//Internationalization
#include //N_()
//======== PRAGMAS ===========================================================//
//permit use of the zero-initializer '{0}' for structures
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
//======== TYPE DEFINITIONS ==================================================//
typedef struct grub_arg_option grub_arg_option;
//======== MODULE VARIABLES ==================================================//
GRUB_MOD_LICENSE("GPLv3+");
static grub_extcmd_t cmd;
static const grub_arg_option options[] = {
{
.longarg = "exit-codes",
.shortarg = 'x',
.flags = 0x0,
.doc = N_("Display return codes used by this command and exit."),
.arg = NULL,
.type = ARG_TYPE_NONE
},
{0} //end of list
};
//======== FUNCTIONS =========================================================//
static grub_err_t grub_cmd_nthibr (
grub_extcmd_context_t ctxt, int argc, char* args[]
){
grub_err_t status = GRUB_ERR_NONE;
char *szPartName, szFilePath[32], szFileMagic[5] = {'\0'};
grub_ssize_t length;
grub_disk_t hPart;
grub_file_t hFile = NULL;
#define ABORT(_code, _message) { \
status = grub_error((_code), (_message)); \
goto exit; \
}
//If requested, print return codes and exit; else, proceed
if (ctxt->state[0].set) {
grub_printf(
N_(
"CODE MEANING\n"
"---- -------\n"
" %2d system hibernated\n"
" %2d system not hibernated\n"
" %2d hibernation file too small\n"
" %2d hibernation file not found\n"
" %2d partition not found\n"
" %2d invalid partition specifier\n"
" %2d too few/many arguments provided\n"
),
GRUB_ERR_NONE, GRUB_ERR_TEST_FAILURE, GRUB_ERR_BAD_FILE_TYPE,
GRUB_ERR_FILE_NOT_FOUND, GRUB_ERR_BAD_FILENAME, GRUB_ERR_UNKNOWN_DEVICE,
GRUB_ERR_BAD_ARGUMENT
);
goto exit;
}
//Check argument count
if (!argc) {
ABORT( GRUB_ERR_BAD_ARGUMENT, N_("too few arguments specified") );
} else if (argc > 1) {
ABORT( GRUB_ERR_BAD_ARGUMENT, N_("too many arguments specified") );
}
szPartName = args[0];
length = (grub_ssize_t) grub_strlen(szPartName);
//Check if partition specifier 'looks right'
if (szPartName[0] != '(' || szPartName[length-1] != ')')
ABORT( GRUB_ERR_BAD_FILENAME, N_("invalid partition specifier") );
//Check if partition actually exists
szPartName[length-1] = '\0';
if (NULL == (hPart = grub_disk_open(szPartName+1))) {
ABORT( GRUB_ERR_UNKNOWN_DEVICE, N_("partition not found") );
} else {
grub_disk_close(hPart);
szPartName[length-1] = ')';
}
//Build path to 'hiberfil.sys'
grub_strncpy(szFilePath, szPartName, sizeof(szFilePath) - 1);
grub_strncat (
szFilePath,
"/hiberfil.sys",
sizeof(szFilePath) - grub_strlen(szFilePath) - 1
);
//Try to open 'hiberfil.sys'
if (NULL == (hFile = grub_file_open(szFilePath))) {
ABORT( GRUB_ERR_FILE_NOT_FOUND, N_("'hiberfil.sys' not found") );
}
//Try to read magic number of 'hiberfil.sys'
length = (grub_ssize_t) (sizeof(szFileMagic) - 1);
if (grub_file_read(hFile, szFileMagic, length) < length)
ABORT( GRUB_ERR_BAD_FILE_TYPE, N_("'hiberfil.sys' too small") );
//Return SUCCESS if magic indicates file is active; else return FAILURE
if (0 == grub_strncasecmp("hibr", szFileMagic, length)) {
grub_puts(N_("The system is hibernated."));
} else {
grub_puts(N_("The system is NOT hibernated."));
status = GRUB_ERR_TEST_FAILURE;
}
exit:
//Ensure 'hiberfil.sys' is closed
if (hFile)
grub_file_close(hFile);
#undef ABORT
return status;
} //grub_cmd_nthibr()
GRUB_MOD_INIT(nthibr) {
cmd = grub_register_extcmd (
"nthibr", //name
grub_cmd_nthibr, //function
0x0, //flags = NONE
N_("DEVICE"), //summary = NONE
N_("Test whether an NT system partition is hibernated."), //description
options //switches
);
} //GRUB_MOD_INIT()
GRUB_MOD_FINI(nthibr) {
grub_unregister_extcmd(cmd);
} //GRUB_MOD_FINI()