update for HEAD-2003091401
[reactos.git] / subsys / system / cmd / free.c
1 /*
2  *  FREE.C - internal command.
3  *
4  *
5  *  History:
6  *
7  *    01-Sep-1999 (Eric Kohl)
8  *        Started.
9  */
10
11 #include "config.h"
12
13 #ifdef INCLUDE_CMD_FREE
14
15 #include <windows.h>
16 #include <tchar.h>
17 #include <string.h>
18 #include <stdio.h>
19 #include <ctype.h>
20
21 #include "cmd.h"
22
23
24 /*
25  * convert
26  *
27  * insert commas into a number
28  */
29
30 static INT
31 ConvertULargeInteger (ULARGE_INTEGER num, LPTSTR des, INT len)
32 {
33         TCHAR temp[32];
34         INT c = 0;
35         INT n = 0;
36
37         if (num.QuadPart == 0)
38         {
39                 des[0] = _T('0');
40                 des[1] = _T('\0');
41                 n = 1;
42         }
43         else
44         {
45                 temp[31] = 0;
46                 while (num.QuadPart > 0)
47                 {
48                         if (((c + 1) % (nNumberGroups + 1)) == 0)
49                                 temp[30 - c++] = cThousandSeparator;
50                         temp[30 - c++] = (TCHAR)(num.QuadPart % 10) + _T('0');
51                         num.QuadPart /= 10;
52                 }
53
54                 for (n = 0; n <= c; n++)
55                         des[n] = temp[31 - c + n];
56         }
57
58         return n;
59 }
60
61
62 static VOID
63 PrintDiskInfo (LPTSTR szDisk)
64 {
65         TCHAR szRootPath[4] = _T("A:\\");
66         TCHAR szDrive[2] = _T("A");
67         TCHAR szVolume[64];
68         TCHAR szSerial[10];
69         TCHAR szTotal[40];
70         TCHAR szUsed[40];
71         TCHAR szFree[40];
72         DWORD dwSerial;
73         ULARGE_INTEGER uliSize;
74         DWORD dwSecPerCl;
75         DWORD dwBytPerSec;
76         DWORD dwFreeCl;
77         DWORD dwTotCl;
78
79         if (_tcslen (szDisk) < 2 || szDisk[1] != _T(':'))
80         {
81                 ConErrPrintf (_T("Invalid drive %s\n"), szDisk);
82                 return;
83         }
84
85         szRootPath[0] = szDisk[0];
86         szDrive[0] = _totupper (szRootPath[0]);
87
88         if (!GetVolumeInformation (szRootPath, szVolume, 64, &dwSerial,
89                                    NULL, NULL, NULL, 0))
90         {
91                 ConErrPrintf (_T("Invalid drive %s:\n"), szDrive);
92                 return;
93         }
94
95         if (szVolume[0] == _T('\0'))
96                 _tcscpy (szVolume, _T("unlabeled"));
97
98         _stprintf (szSerial,
99                    _T("%04X-%04X"),
100                    HIWORD(dwSerial),
101                    LOWORD(dwSerial));
102
103         if (!GetDiskFreeSpace (szRootPath, &dwSecPerCl,
104                                &dwBytPerSec, &dwFreeCl, &dwTotCl))
105         {
106                 ConErrPrintf (_T("Invalid drive %s:\n"), szDrive);
107                 return;
108         }
109
110         uliSize.QuadPart = dwSecPerCl * dwBytPerSec * dwTotCl;
111         ConvertULargeInteger (uliSize, szTotal, 40);
112
113         uliSize.QuadPart = dwSecPerCl * dwBytPerSec * (dwTotCl - dwFreeCl);
114         ConvertULargeInteger (uliSize, szUsed, 40);
115
116         uliSize.QuadPart = dwSecPerCl * dwBytPerSec * dwFreeCl;
117         ConvertULargeInteger (uliSize, szFree, 40);
118
119         ConOutPrintf (_T("\n"
120                          " Volume in drive %s is %-11s   Serial number is %s\n"
121                          "  %16s bytes total disk space\n"
122                          "  %16s bytes used\n"
123                          "  %16s bytes free\n"),
124                       szDrive, szVolume, szSerial,
125                       szTotal, szUsed, szFree);
126 }
127
128
129 INT CommandFree (LPTSTR cmd, LPTSTR param)
130 {
131         LPTSTR szParam;
132         TCHAR  szDefPath[MAX_PATH];
133         INT argc, i;
134         LPTSTR *arg;
135
136         if (!_tcsncmp (param, _T("/?"), 2))
137         {
138                 ConOutPuts (_T("Displays drive information.\n"
139                                "\n"
140                                "FREE [drive: ...]"));
141                 return 0;
142         }
143
144         if (!param || *param == _T('\0'))
145         {
146                 GetCurrentDirectory (MAX_PATH, szDefPath);
147                 szDefPath[2] = _T('\0');
148                 szParam = szDefPath;
149         }
150         else
151                 szParam = param;
152
153         arg = split (szParam, &argc, FALSE);
154
155         for (i = 0; i < argc; i++)
156                 PrintDiskInfo (arg[i]);
157
158         freep (arg);
159
160         return 0;
161 }
162
163 #endif /* INCLUDE_CMD_FREE */
164
165 /* EOF */