Add a skeleton for the fsutil tool.
As a proof of concept, implement fsutil dirty query.
More to follow ;-).

svn path=/trunk/; revision=75764
This commit is contained in:
Pierre Schweitzer 2017-09-05 12:56:45 +00:00
parent a81f0507f2
commit 7f463d43db
6 changed files with 227 additions and 0 deletions

View file

@ -6,6 +6,7 @@ add_subdirectory(dbgprint)
add_subdirectory(doskey)
add_subdirectory(eventcreate)
add_subdirectory(find)
add_subdirectory(fsutil)
add_subdirectory(help)
add_subdirectory(hostname)
add_subdirectory(lodctr)

View file

@ -0,0 +1,9 @@
list(APPEND SOURCE
dirty.c
fsutil.c
fsutil.h)
add_executable(fsutil ${SOURCE} fsutil.rc)
set_module_type(fsutil win32cui UNICODE)
add_importlibs(fsutil msvcrt kernel32 ntdll)
add_pch(fsutil fsutil.h SOURCE)
add_cd_file(TARGET fsutil DESTINATION reactos/system32 FOR all)

View file

@ -0,0 +1,126 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS FS utility tool
* FILE: base/applications/cmdutils/dirty.c
* PURPOSE: FSutil dirty bit handling
* PROGRAMMERS: Pierre Schweitzer <pierre@reactos.org>
*/
#include "fsutil.h"
#include <winioctl.h>
/* Add handlers here for subcommands */
static int QueryMain(int argc, const TCHAR *argv[]);
static int SetMain(int argc, const TCHAR *argv[]);
static HandlerItem HandlersList[] =
{
/* Proc, name, help */
{ QueryMain, _T("query"), _T("Show the dirty bit") },
{ SetMain, _T("set"), _T("Set the dirty bit") },
};
static int
QueryMain(int argc, const TCHAR *argv[])
{
HANDLE Volume;
TCHAR VolumeID[PATH_MAX];
ULONG VolumeStatus, BytesRead;
/* We need a volume (letter or GUID) */
if (argc < 2)
{
_ftprintf(stderr, _T("Usage: fsutil dirty query <volume>\n"));
_ftprintf(stderr, _T("\tFor example: fsutil dirty query c:\n"));
return 1;
}
/* Create full name */
_stprintf(VolumeID, _T("\\\\.\\%s"), argv[1]);
/* Open the volume */
Volume = CreateFile(VolumeID, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (Volume == INVALID_HANDLE_VALUE)
{
_ftprintf(stderr, _T("Error: %d\n"), GetLastError());
return 1;
}
/* And query the dirty status */
if (DeviceIoControl(Volume, FSCTL_IS_VOLUME_DIRTY, NULL, 0, &VolumeStatus,
sizeof(ULONG), &BytesRead, NULL) == FALSE)
{
_ftprintf(stderr, _T("Error: %d\n"), GetLastError());
CloseHandle(Volume);
return 1;
}
CloseHandle(Volume);
/* Print the status */
_ftprintf(stdout, _T("The %s volume is %s\n"), argv[1], (VolumeStatus & VOLUME_IS_DIRTY ? _T("dirty") : _T("clean")));
return 1;
}
static int
SetMain(int argc, const TCHAR *argv[])
{
/* FIXME */
_ftprintf(stderr, _T("Not implemented\n"));
return 1;
}
static void
PrintUsage(const TCHAR * Command)
{
int i;
/* If we were given a command, print it's not supported */
if (Command != NULL)
{
_ftprintf(stderr, _T("Unhandled DIRTY command: %s\n"), Command);
}
/* And dump any available command */
_ftprintf(stderr, _T("---- Handled DIRTY commands ----\n\n"));
for (i = 0; i < (sizeof(HandlersList) / sizeof(HandlersList[0])); ++i)
{
_ftprintf(stderr, _T("%s\t%s\n"), HandlersList[i].Command, HandlersList[i].Desc);
}
}
int
DirtyMain(int argc, const TCHAR *argv[])
{
int i;
int ret;
const TCHAR * Command;
ret = 1;
Command = NULL;
i = (sizeof(HandlersList) / sizeof(HandlersList[0]));
/* If we have a command, does it match a known one? */
if (argc > 1)
{
/* Browse all the known commands finding the right one */
Command = argv[1];
for (i = 0; i < (sizeof(HandlersList) / sizeof(HandlersList[0])); ++i)
{
if (_tcsicmp(Command, HandlersList[i].Command) == 0)
{
ret = HandlersList[i].Handler(argc - 1, &argv[1]);
break;
}
}
}
/* We failed finding someone to handle the caller's needs, print out */
if (i == (sizeof(HandlersList) / sizeof(HandlersList[0])))
{
PrintUsage(Command);
}
return ret;
}

View file

@ -0,0 +1,72 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS FS utility tool
* FILE: base/applications/cmdutils/fsutil.c
* PURPOSE: FSutil main
* PROGRAMMERS: Pierre Schweitzer <pierre@reactos.org>
*/
#include "fsutil.h"
/* Add handlers here for commands */
int DirtyMain(int argc, const TCHAR *argv[]);
static HandlerItem HandlersList[] =
{
/* Proc, name, help */
{ DirtyMain, _T("dirty"), _T("Manipulates the dirty bit") },
};
static void
PrintUsage(const TCHAR * Command)
{
int i;
/* If we were given a command, print it's not supported */
if (Command != NULL)
{
_ftprintf(stderr, _T("Unhandled command: %s\n"), Command);
}
/* And dump any available command */
_ftprintf(stderr, _T("---- Handled commands ----\n\n"));
for (i = 0; i < (sizeof(HandlersList) / sizeof(HandlersList[0])); ++i)
{
_ftprintf(stderr, _T("%s\t%s\n"), HandlersList[i].Command, HandlersList[i].Desc);
}
}
int
__cdecl
_tmain(int argc, const TCHAR *argv[])
{
int i;
int ret;
const TCHAR * Command;
ret = 1;
Command = NULL;
i = (sizeof(HandlersList) / sizeof(HandlersList[0]));
/* If we have a command, does it match a known one? */
if (argc > 1)
{
/* Browse all the known commands finding the right one */
Command = argv[1];
for (i = 0; i < (sizeof(HandlersList) / sizeof(HandlersList[0])); ++i)
{
if (_tcsicmp(Command, HandlersList[i].Command) == 0)
{
ret = HandlersList[i].Handler(argc - 1, &argv[1]);
break;
}
}
}
/* We failed finding someone to handle the caller's needs, print out */
if (i == (sizeof(HandlersList) / sizeof(HandlersList[0])))
{
PrintUsage(Command);
}
return ret;
}

View file

@ -0,0 +1,15 @@
#ifndef __FSUTIL_H__
#define __FSUTIL_H__
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
typedef struct
{
int (*Handler)(int argc, const TCHAR *argv[]);
const TCHAR * Command;
const TCHAR * Desc;
} HandlerItem;
#endif

View file

@ -0,0 +1,4 @@
#define REACTOS_STR_FILE_DESCRIPTION "FS utility\0"
#define REACTOS_STR_INTERNAL_NAME "fsutil\0"
#define REACTOS_STR_ORIGINAL_FILENAME "fsutil.exe\0"
#include <reactos/version.rc>