// MakeFile.cpp : Defines the entry point for the console application.
//
//History
// 2011-04-02: v. 1.3.
// [+] New switch "-l" added - given size - is how much space should be left on storage
// [+] New unit added "%" - percents of free space
//
// 2010-05-23: v. 1.2.
// [~] Change creation file method for increase the creation speed.
// [!] Not all allocated memory clears.
//
// 2010-05-23: v. 1.1
// [+] Add Command Line parameter -a - set custom attributes for new file
// [+] If size of new file more or equal to destination volume size, check if this volume is removable. Against request confirmation.
//
// 2010-05-22: v. 1.0
// [] First beta
#include "stdafx.h"
#include "makefile.h"
#include <iostream>
#include <io.h>
#include "windows.h"
#include "fcntl.h"
//** 2010-05-19 22-23-23 Rett Pop [+]: Program version
#define PROGRAM_NAME "MKEF"
#define VER_MAJOR 1
#define VER_MINOR 3
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
//** 2010-05-19 22-23-13 Rett Pop [+]: Some variables
__int64 giFSize = 0;
__int64 iVolFSpace = 0; //** 2010-05-22 21-43-19 Rett Pop [+]: Volume free space
int giMult = MULTIPL_M;
_TCHAR* cpDestPath = NULL;
_TCHAR* cpFName = NULL;
bool blDelDPath = false; //** 2010-05-23 14-01-58 Rett Pop [+]: Do we have to delete cpDestPath var?
bool blLeftSpace = false;
UINT iVolType = DRIVE_UNKNOWN;
DWORD wFAttp = FILE_ATTRIBUTE_HIDDEN; //** 2010-05-22 22-08-09 Rett Pop [+]: New file attributes
//if ( 1 == argc )
{
printf("\n%s ver: %i.%i\n\n", PROGRAM_NAME, VER_MAJOR, VER_MINOR);
cout << "Make empty file.\n\nUsage: mkfe [-n <file name>] [-p <file path>] [-s <file size>]\n\t[-u <units>] [-a <attr>] [-h|/h|-?]\n\n";
cout << " -a <attr>\tOptional file attributes. Permitted: A, S, H, R.\n\t\tBy default - H(idden)\n";
cout << " -l \tGiven size (see -s) - is how much free space should be left on the storage.\n";
cout << " -n <file name>\tFile of new file.\n\t\tBy default - unique name for gived directory\n";
cout << " -p <file path>\tDestination path where file will be created.\n\t\tBy default - current directory\n";
cout << " -s <file size>\tSize of new file.\n\t\tBy default - whole empty space on <file path>\n";
cout << " -u <units>\tUnits of gived size. Permitted: B, K, M, G, % (of empty space).\n\t\tBy default - M(egabytes)\n";
cout << " -h|/? \tShow this help and exit\n";
}
//** 2010-05-20 01-18-57 Rett Pop [+]: If no params gived, ask to start
if ( 1 == argc )
{
cout << "\n It will create file which fill all free space on current drive!\nAre you sure?: (case sensitive Y/N) ";
if ( 'Y' != getchar() ){
return ERR_OK;
}
}
//-------------------------------------------------------
//** 2010-05-19 22-25-50 Rett Pop [+]: Process command line params
try
{
for ( int i=1; i<argc; i++ )
{
if ( (0 == wcscmp(argv[i] ,_T("-h")) ) ||
(0 == wcscmp( argv[i] ,_T("/?") )) ||
(0 == wcscmp( argv[i] ,_T("-?") )) )
{
return ERR_OK;
}
if ( (0 == wcscmp( argv[i] ,_T("-h") )) ){
return ERR_OK;
}
if ( (i<argc) && (0 == wcscmp( argv[i] ,_T("-n") )) ){
cpFName = argv[((++i))]; // get next and increase to next+next
}
if ( (i<argc) && (0 == wcscmp( argv[i] ,_T("-p") )) ){
cpDestPath = argv[((++i))]; // get next and increase to next
}
if ( (0 == wcscmp( argv[i] ,_T("-l") )) ){
blLeftSpace = true;
}
if ( (i<argc) && (0 == wcscmp( argv[i] ,_T("-s") )) ){
giFSize = _wtoi( argv[((++i))] ); // get next and increase to next
}
if ( (i<argc) && (0 == wcscmp( argv[i] ,_T("-u") )) )
{
_TCHAR* cUn = argv[((++i))];
if ( 0 == wcscmp( cUn, _T("B")) ) giMult = MULTIPL_B;
if ( 0 == wcscmp( cUn, _T("K")) ) giMult = MULTIPL_K;
if ( 0 == wcscmp( cUn, _T("M")) ) giMult = MULTIPL_M;
if ( 0 == wcscmp( cUn, _T("G")) ) giMult = MULTIPL_G;
if ( 0 == wcscmp( cUn, _T("%")) ) giMult = MULTIPL_P;
}
//** 2010-05-22 22-09-30 Rett Pop [+]: -a - new file attributes
if ( (i<argc) && 0 == wcscmp(argv[i], _T("-a")) )
{
_TCHAR* cAtt = argv[((++i))];
wFAttp = FILE_ATTRIBUTE_NORMAL;
if ( NULL != wcspbrk(cAtt, _T("Aa")) ) wFAttp |= FILE_ATTRIBUTE_ARCHIVE;
if ( NULL != wcspbrk(cAtt, _T("Hh")) ) wFAttp |= FILE_ATTRIBUTE_HIDDEN;
if ( NULL != wcspbrk(cAtt, _T("Rr")) ) wFAttp |= FILE_ATTRIBUTE_READONLY;
if ( NULL != wcspbrk(cAtt, _T("Ss")) ) wFAttp |= FILE_ATTRIBUTE_SYSTEM;
}
}
}
catch(...){
cerr << "Error processing command line parameters\n";
return ERR_BADRAMS;
}
//-------------------------------------------------------
//** 2010-05-19 22-39-17 Rett Pop [+]: If destination path not gived, takes current directory
if ( NULL == cpDestPath )
{
cpDestPath = new _TCHAR[_MAX_PATH];
blDelDPath = true;
if ( NULL == _wgetcwd(cpDestPath, _MAX_PATH) )
{
cerr << "Error determining currend working directory";
return ERR_PATH;
}
}
else
{ // else try to change current directory to given
if ( 0 != _wchdir( cpDestPath ) )
{
cerr << "Error changing working directory";
return ERR_PATH;
}
}
//-------------------------------------------------------
//** 2010-05-22 21-43-51 Rett Pop [+]: Check for free space on destination volume
__int64 i64FreeBytesToCaller, i64TotalBytes;
if ( 0 == GetDiskFreeSpaceEx( cpDestPath,
(PULARGE_INTEGER) &i64FreeBytesToCaller,
(PULARGE_INTEGER) &i64TotalBytes,
(PULARGE_INTEGER) &iVolFSpace) )
{
cerr << "Error determining free disk space\n";
return ERR_DISK;
}
//-------------------------------------------------------
//** 2010-05-19 22-37-51 Rett Pop [+]: Calculate target size, if given
if( giFSize > 0 )
{
if (MULTIPL_P == giMult)
{
// If multiplier = percents, then calculates percents from free volume space
giFSize = (iVolFSpace/100)*(giFSize>100?100:giFSize); // then giMult cannot be more than 100.
}
else
{
giFSize *= giMult;
}
// if user said how many space we should left, do it
if (blLeftSpace)
{
// if free space is less, than wanted, - exit
if (iVolFSpace <= giFSize)
{
cout << "There is less free space than need to leave. So, exit.\n";
return ERR_NOFREESPACE;
}
giFSize = iVolFSpace - giFSize;
}
}
else
{
giFSize = iVolFSpace;
}
//-------------------------------------------------------
//** 2010-05-22 21-46-09 Rett Pop [+]: Determine the type of target volume
//iVolType = GetDriveType(cpDestPath);
{
_TCHAR pcRoot[_MAX_DRIVE];
_wsplitpath_s(cpDestPath, pcRoot, _MAX_DRIVE, NULL, 0, NULL, 0, NULL, 0);
iVolType = GetDriveType(pcRoot);
}
//** 2010-05-22 21-50-48 Rett Pop [+]: If target volume is FixedDisk ad user wants to fill whole space, request confirmation
if ( (DRIVE_FIXED == iVolType) && (giFSize >= iVolFSpace) )
{
cout << "\nDestination disk is fixed disk. Are You sure You want fill this disk's all free space? (Y/N): ";
fflush (stdin) ;
if ( 'Y' != getchar() ) {
return ERR_OK;
}
}
cout << endl;
//** 2010-05-23 00-10-50 Rett Pop [-]: For fully automatic
//** 2010-05-22 21-56-08 Rett Pop [+]: If target - readonly system
if (DRIVE_CDROM == iVolType)
{
cout << "\nDestination disk is CD-ROM. Do You want I'll try to write on it?\n";
if ( 'Y' != getchar() )
return ERR_OK;
}
//-------------------------------------------------------
//** 2010-05-19 22-47-40 Rett Pop [+]: If file name not given, take unique temp-file name
if ( NULL == cpFName )
{
_TCHAR* cpT = _T("mkfXXXXX");
cpFName = new _TCHAR[MAX_PATH];
if ( 0 == GetTempFileName(cpDestPath, _T("mkf"), 0, cpFName ) )
{
cerr << "Error generating unique filename\n";
return ERR_FILENAME;
}
}
//** 2010-05-19 23-07-10 Rett Pop [+]: try to create file
int fh = _wopen(cpFName, _O_CREAT | _O_WRONLY );
//** 2010-05-19 23-10-03 Rett Pop [+]: If error on creating file occurs - exit
if ( -1 == fh )
{
cerr << "Error creating file " << cpFName << endl;
return ERR_FILE;
}
// if file size is more then volume size, set it equal to it :)
if ( giFSize > iVolFSpace )
{
cout << "\nTarget size is greater than available space. Fill all available space.\n";
giFSize = iVolFSpace;
}
if ( giFSize <= 0 )
{
cout << "Target size = 0. Will not create file. So, exit.";
return ERR_ZEROSIZE;
}
//-------------------------------------------------------
//** 2010-05-22 22-00-03 Rett Pop [C]: Start writing
wprintf(_T("Start to create file %s on path %s with size %lI64u bytes\nPlease, be patient. It can takes a few minutes.\n"),
cpFName, cpDestPath, giFSize);
if (blLeftSpace) {
cout << "Left for " << (iVolFSpace - giFSize) << " bytes free space\n";
}
DWORD iTicks = GetTickCount();
char pEB = EOF;
if ( -1L == _lseeki64(fh, giFSize-1, SEEK_SET) ) // left 1 byte for EOF
{
cout << "Error set file size\n";
_close (fh);
}
else
{
_write(fh, (void*) &pEB, 1);
_close (fh);
//** 2010-05-22 22-17-38 Rett Pop [+]: Set file attributes
SetFileAttributes(cpFName, wFAttp);
cout << "File succefully created. It took " << ((GetTickCount() - iTicks)/1000) << " seconds.\n";
}
//-------------------------------------------------------
// Clear memory.
if ( blDelDPath ) {
delete[] cpDestPath;
}
delete[] cpFName;
return 0;
}