Reactos
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS FS utility tool
4 * FILE: base/applications/cmdutils/volume.c
5 * PURPOSE: FSutil volumes management
6 * PROGRAMMERS: Pierre Schweitzer <pierre@reactos.org>
7 */
8
9#include "fsutil.h"
10
11/* Add handlers here for subcommands */
12static HandlerProc DismountMain;
13static HandlerProc DiskFreeMain;
14static HandlerItem HandlersList[] =
15{
16 /* Proc, name, help */
17 { DismountMain, _T("dismount"), _T("Dismounts a volume") },
18 { DiskFreeMain, _T("diskfree"), _T("Prints free space on a volume") },
19};
20
21static int
22LockOrUnlockVolume(HANDLE Volume, BOOLEAN Lock)
23{
24 DWORD Operation;
25 ULONG BytesRead;
26
27 Operation = (Lock ? FSCTL_LOCK_VOLUME : FSCTL_UNLOCK_VOLUME);
28 if (DeviceIoControl(Volume, Operation, NULL, 0, NULL, 0,
29 &BytesRead, NULL) == FALSE)
30 {
31 PrintErrorMessage(GetLastError());
32 return 1;
33 }
34
35 return 0;
36}
37
38static int
39DismountMain(int argc, const TCHAR *argv[])
40{
41 HANDLE Volume;
42 ULONG BytesRead;
43
44 /* We need a volume (letter or GUID) */
45 if (argc < 2)
46 {
47 _ftprintf(stderr, _T("Usage: fsutil volume dismount <volume>\n"));
48 _ftprintf(stderr, _T("\tFor example: fsutil volume dismount d:\n"));
49 return 1;
50 }
51
52 /* Get a handle for the volume */
53 Volume = OpenVolume(argv[1], FALSE, FALSE);
54 if (Volume == INVALID_HANDLE_VALUE)
55 {
56 return 1;
57 }
58
59 /* Attempt to lock the volume */
60 if (LockOrUnlockVolume(Volume, TRUE))
61 {
62 CloseHandle(Volume);
63 return 1;
64 }
65
66 /* Issue the dismount command */
67 if (DeviceIoControl(Volume, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL,
68 0, &BytesRead, NULL) == FALSE)
69 {
70 PrintErrorMessage(GetLastError());
71 LockOrUnlockVolume(Volume, FALSE);
72 CloseHandle(Volume);
73 return 1;
74 }
75
76 /* Unlock and quit */
77 LockOrUnlockVolume(Volume, FALSE);
78 CloseHandle(Volume);
79
80 _ftprintf(stdout, _T("The %s volume has been dismounted\n"), argv[1]);
81
82 return 0;
83}
84
85static int
86DiskFreeMain(int argc, const TCHAR *argv[])
87{
88 ULARGE_INTEGER FreeAvail, TotalNumber, TotalNumberFree;
89
90 /* We need a path */
91 if (argc < 2)
92 {
93 _ftprintf(stderr, _T("Usage: fsutil volume diskfree <volume path>\n"));
94 _ftprintf(stderr, _T("\tFor example: fsutil volume diskfree c:\n"));
95 return 1;
96 }
97
98 if (!GetDiskFreeSpaceEx(argv[1], &FreeAvail, &TotalNumber, &TotalNumberFree))
99 {
100 PrintErrorMessage(GetLastError());
101 return 1;
102 }
103
104 _ftprintf(stdout, _T("Total free bytes\t\t: %I64i\n"), TotalNumberFree.QuadPart);
105 _ftprintf(stdout, _T("Total bytes\t\t\t: %I64i\n"), TotalNumber.QuadPart);
106 _ftprintf(stdout, _T("Total free available bytes\t: %I64i\n"), FreeAvail.QuadPart);
107
108 return 0;
109}
110
111static void
112PrintUsage(const TCHAR * Command)
113{
114 PrintDefaultUsage(_T(" VOLUME "), Command, (HandlerItem *)&HandlersList,
115 (sizeof(HandlersList) / sizeof(HandlersList[0])));
116}
117
118int
119VolumeMain(int argc, const TCHAR *argv[])
120{
121 return FindHandler(argc, argv, (HandlerItem *)&HandlersList,
122 (sizeof(HandlersList) / sizeof(HandlersList[0])),
123 PrintUsage);
124}