// MakeFile.cpp : Defines the entry point for the console application.
//
//History
// 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 1
using namespace std;
//** 2010-05-19 22-23-13 Rett Pop [+]: Global variables
__int64 giFSize = 0;
int giMult = MULTIPL_M;
_TCHAR* cpDestPath = NULL;
_TCHAR* cpFName = NULL;
int _tmain(int argc, _TCHAR* argv[])
{
UINT iVolType = DRIVE_UNKNOWN;
__int64 iVolFSpace = 0; //** 2010-05-22 21-43-19 Rett Pop [+]: Volume free space
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>] [-h|/h|-?]\n\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.\n\t\tBy default - M(egabytes)\n";
cout << " -a <attr>\tOptional file attributes. Permitted: A, S, H, R.\n\t\tBy default - H(idden)\n";
cout << " -h|/? \tShow this help and exit\n";
// return ERR_NOPARAMS;
}
//** 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;
//getchar();
}
//-------------------------------------------------------
//** 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") )) && (i<argc) ){
return ERR_OK;
}
if ( (0 == wcscmp( argv[i] ,_T("-n") )) && (i<argc) ){
cpFName = argv[((++i))]; // get next and increase to next+next
}
if ( i >= argc ) break; //
if ( (0 == wcscmp( argv[i] ,_T("-p") )) && (i<argc) ){
cpDestPath = argv[((++i))]; // get next and increase to next
}
if ( i >= argc ) break; //
if ( (0 == wcscmp( argv[i] ,_T("-s") )) && (i<argc) ){
giFSize = _wtoi( argv[((++i))] ); // get next and increase to next
}
if ( i >= argc ) break; //
if ( (0 == wcscmp( argv[i] ,_T("-u") )) && (i<argc) ){
_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;
}
//** 2010-05-22 22-09-30 Rett Pop [+]: -a - new file attributes
if ( 0 == wcscmp(argv[i], _T("-a")) && (i<argc) )
{
_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];
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 ){
giFSize *= giMult;
} 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;
}
//-------------------------------------------------------
//** 2010-05-22 22-00-03 Rett Pop [C]: Start writing
wprintf(_T("Start to create file %s on path %s with size %i bytes\n"), cpFName, cpDestPath, giFSize);
cout << "Please, be patient. It can takes a few minutes.\n";
const int iSectorSize = 4*MULTIPL_K;
DWORD iTicks = GetTickCount();
char* pEB = new char[iSectorSize];
memset(pEB, 0x0, iSectorSize);
for ( __int64 i = 0; i <= giFSize; i+=(iSectorSize) )
{
//** 2010-05-23 00-19-48 Rett Pop [+]: Writing blocks with size 4K - much faster
if ( giFSize - i > iSectorSize )
_write(fh, pEB, iSectorSize);
else
_write(fh, pEB, giFSize - i);
}
_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";
//-------------------------------------------------------
delete[] pEB;
delete[] cpFName;
return 0;
}