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 */
12 static HandlerProc DismountMain;
13 static HandlerProc DiskFreeMain;
14 static 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
21 static int
LockOrUnlockVolume(HANDLE Volume,BOOLEAN Lock)22 LockOrUnlockVolume(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
38 static int
DismountMain(int argc,const TCHAR * argv[])39 DismountMain(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
85 static int
DiskFreeMain(int argc,const TCHAR * argv[])86 DiskFreeMain(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
111 static void
PrintUsage(const TCHAR * Command)112 PrintUsage(const TCHAR * Command)
113 {
114 PrintDefaultUsage(_T(" VOLUME "), Command, (HandlerItem *)&HandlersList,
115 (sizeof(HandlersList) / sizeof(HandlersList[0])));
116 }
117
118 int
VolumeMain(int argc,const TCHAR * argv[])119 VolumeMain(int argc, const TCHAR *argv[])
120 {
121 return FindHandler(argc, argv, (HandlerItem *)&HandlersList,
122 (sizeof(HandlersList) / sizeof(HandlersList[0])),
123 PrintUsage);
124 }
125