HI!
I am trying to pass whole structure from one program and read it in another using fifo.
I'm using read and write functions. I had a problem with putting my structure into this functions. When I did it and tried to send and receive I get an error (core dump) or I recived some trash. I dont know exactly, where my problem take place (in receiver or sender). How can I send/receive my structure, or what i have wrong in my code.Here is my code...Receiver
struct data
{
char* message;
int size;
vector <times> prog;
};
int if_fifo(char* name)
{
struct stat info;
int score = stat(name,&info);
if(S_ISFIFO(info.st_mode))
{
return 1;
}
else
{
return 0;
}
}
int fifo_in(char* name)
{
data msg;
int pip;
pip = open(name, O_RDONLY | O_NONBLOCK);
while(1)
{
int hr = read(pip,&msg,sizeof(msg));
if(hr != 0)
{
cout << "Message: " << msg.message << endl;
}
}
cout << "O.K." << endl;
return 0;
}
int main(int argc, char** argv) {
int c, status_in, status_out;
char* input;
char* output;
float del;
if(argc < 5)
{
cout << "Za malo podanych parametrow" << endl;
return 1;
}
else
{
while ((c = getopt(argc, argv, "iod:")) != -1)
{
switch (c)
{
case 'i':
input = argv[2];
status_in = if_fifo(input);
break;
case 'o':
output = argv[3];
status_out = if_fifo(output);
break;
case 'd':
del = atof(argv[4]);
break;
case '?':
printf("UKNOWN");
}
}
}
if(status_in == 1)
{
return fifo_in(input);
}
else
{
cout << "It isnt fifo!!" << endl;
}
return 0;
}
And sender:
struct data
{
char* message;
int size;
vector <times> prog;
}msg;
int if_fifo(char* name)
{
struct stat info;
int score = stat(name,&info);
if(S_ISFIFO(info.st_mode))
{
return 1;
}
else
{
return 0;
}
}
int fifo_out(char* name)
{
msg.message = "To jest to!!";
msg.size = sizeof(msg.message);
int pip;
pip = open(name, O_WRONLY);
if( pip == -1 )
{
perror("Error: open( ): ");
return 1;
}
write(pip,&msg,sizeof(msg));
return 0;
}
int main(int argc, char** argv) {
int c, status_out;
char* output;
if(argc < 3)
{
cout << "Za malo podanych parametrow" << endl;
return 1;
}
else
{
while ((c = getopt(argc, argv, "o:")) != -1)
{
switch (c)
{
case 'o':
output = argv[2];
status_out = if_fifo(output);
break;
case '?':
printf("UKNOWN");
}
}
}
if(status_out == 1)
{
return fifo_out(output);
}
return 0;
}
you cannot just send memory structures from one program to another. You have to do whats called 'serialization' ie convert the struct into a byte stream that represents the structure. There are many, many serialization techniques: ASN1/ Ber, XML, JSON, Google protocol buffs, roll your own.
Just so you know why this is. The field message in your struct is actually a pointer, when you send this pointer to another program it points to the same address but in the receiver prgram not the sender. That address likely doesnt exist and certainly does not contain the string you had in the sender program.
Currently I'm using this function which I've cobbled together from reading several loosely related questions all over the internet. The problem I'm having is that the first time I ran it it returned an error, but unfortunately I haven't been able to reproduce it. Now when I run it it simply returns 0 every time.
DWORD GetAddressOfString(char *input)
{
unsigned char *p = NULL;
MEMORY_BASIC_INFORMATION info;
HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, _processID);
for (p = NULL; VirtualQueryEx(process, p, &info, sizeof(info)) == sizeof(info); p += info.RegionSize)
{
if (info.State == MEM_COMMIT && (info.Type == MEM_MAPPED || info.Type == MEM_PRIVATE))
{
char *buffer = new char[info.RegionSize];
SIZE_T bytesRead;
ReadProcessMemory(process, p, &buffer, info.RegionSize, &bytesRead);
for (int i = 0; i <= (info.RegionSize - sizeof(input)); i++)
{
if (memcmp(input, &buffer[i], sizeof(input)) == 0)
{
return i;
}
}
}
}
}
Here's a quick and dirty version that searches for data in itself. If you open up Notepad++, type "SomeDataToFind", replace the pid with the correct value, and run it, it should find the data as well. It might give you something to start with and embellish to suit your needs.
Your code was searching for the wrong length, returning the wrong offset, leaking memory like a sieve, and not always returning a value which is undefined behavior.
#include <Windows.h>
#include <iostream>
#include <string>
#include <vector>
char* GetAddressOfData(DWORD pid, const char *data, size_t len)
{
HANDLE process = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, pid);
if(process)
{
SYSTEM_INFO si;
GetSystemInfo(&si);
MEMORY_BASIC_INFORMATION info;
std::vector<char> chunk;
char* p = 0;
while(p < si.lpMaximumApplicationAddress)
{
if(VirtualQueryEx(process, p, &info, sizeof(info)) == sizeof(info))
{
p = (char*)info.BaseAddress;
chunk.resize(info.RegionSize);
SIZE_T bytesRead;
if(ReadProcessMemory(process, p, &chunk[0], info.RegionSize, &bytesRead))
{
for(size_t i = 0; i < (bytesRead - len); ++i)
{
if(memcmp(data, &chunk[i], len) == 0)
{
return (char*)p + i;
}
}
}
p += info.RegionSize;
}
}
}
return 0;
}
int main()
{
const char someData[] = "SomeDataToFind";
std::cout << "Local data address: " << (void*)someData << "\n";
//Pass whatever process id you like here instead.
DWORD pid = GetCurrentProcessId();
char* ret = GetAddressOfData(pid, someData, sizeof(someData));
if(ret)
{
std::cout << "Found: " << (void*)ret << "\n";
}
else
{
std::cout << "Not found\n";
}
return 0;
}
I wanted to write a program which loads an image given by command line and afterwards does something with it. My problem now is: Whenever I execute the program it prints me the palette size of the image (which gives me a wrong output (12) for every picture in jpg format I enter), and afterwards it crashes, but I can not figure out my mistake.
What am I doing wrong?
inline bool exists(const std::string& name) {
if (FILE *file = fopen(name.c_str(), "r")) {
fclose(file);
return true;
}
else {
return false;
}
}
int main(int argc, char* argv[])
{
if (argc != 3)
{
std::cout << "Too few/too much arguments. Usage: ShrinkImage <Input-File> <Number of target colours>\n";
return 0;
}
int num_colors;
char * filepath = argv[1];
if (!exists(filepath))
{
std::cout << "File does not exist.\n";
return 0;
}
num_colors = std::stoi(argv[2], nullptr);
ULONG_PTR(m_gdiplusToken);
Gdiplus::GdiplusStartupInput gdiplusstartupinput;
Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusstartupinput, NULL);
const size_t cSize = strlen(filepath) + 1;
size_t Size = cSize - 1;
wchar_t *wc = new wchar_t[cSize];
swprintf(wc, cSize, L"%hs", filepath);
Gdiplus::Image image(wc);
std::cout << image.GetPaletteSize() << '\n';
std::cout << "Printed PaletteSize\n";
delete wc;
Gdiplus::GdiplusShutdown(m_gdiplusToken);
std::cout << "After Shutdown\n";
return 0;
}
Solution is:
Writing instead of
Gdiplus::Image image(wc);
this:
Gdiplus::Image * image = Gdiplus::Image::FromFile(wc);
delete image;
image = 0;
This solves my problem.
Is there any API in c++ for getting the size of a specified folder?
If not, how can I get the total size of a folder including all subfolders and files?
How about letting OS do it for you:
long long int getFolderSize(string path)
{
// command to be executed
std::string cmd("du -sb ");
cmd.append(path);
cmd.append(" | cut -f1 2>&1");
// execute above command and get the output
FILE *stream = popen(cmd.c_str(), "r");
if (stream) {
const int max_size = 256;
char readbuf[max_size];
if (fgets(readbuf, max_size, stream) != NULL) {
return atoll(readbuf);
}
pclose(stream);
}
// return error val
return -1;
}
Actually I don't want to use any third party library. Just want to
implement in pure c++.
If you use MSVC++ you have <filesystem> "as standard C++".
But using boost or MSVC - both are "pure C++".
If you don’t want to use boost, and only the C++ std:: library this answer is somewhat close. As you can see here, there is a Filesystem Library Proposal (Revision 4). Here you can read:
The Boost version of the library has been in widespread use for ten
years. The Dinkumware version of the library, based on N1975
(equivalent to version 2 of the Boost library), ships with Microsoft
Visual C++ 2012.
To illustrate the use, I adapted the answer of #Nayana Adassuriya , with very minor modifications (OK, he forgot to initialize one variable, and I use unsigned long long, and most important was to use: path filePath(complete (dirIte->path(), folderPath)); to restore the complete path before the call to other functions). I have tested and it work well in windows 7.
#include <iostream>
#include <string>
#include <filesystem>
using namespace std;
using namespace std::tr2::sys;
void getFoldersize(string rootFolder,unsigned long long & f_size)
{
path folderPath(rootFolder);
if (exists(folderPath))
{
directory_iterator end_itr;
for (directory_iterator dirIte(rootFolder); dirIte != end_itr; ++dirIte )
{
path filePath(complete (dirIte->path(), folderPath));
try{
if (!is_directory(dirIte->status()) )
{
f_size = f_size + file_size(filePath);
}else
{
getFoldersize(filePath,f_size);
}
}catch(exception& e){ cout << e.what() << endl; }
}
}
}
int main()
{
unsigned long long f_size=0;
getFoldersize("C:\\Silvio",f_size);
cout << f_size << endl;
system("pause");
return 0;
}
You may use boost in this way. You can try to optimize it some deeper.
#include <iostream>
#include <string>
#include <boost/filesystem.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/algorithm/string.hpp>
using namespace std;
namespace bsfs = boost::filesystem;
void getFoldersize(string rootFolder,long & file_size){
boost::replace_all(rootFolder, "\\\\", "\\");
bsfs::path folderPath(rootFolder);
if (bsfs::exists(folderPath)){
bsfs::directory_iterator end_itr;
for (bsfs::directory_iterator dirIte(rootFolder); dirIte != end_itr; ++dirIte )
{
bsfs::path filePath(dirIte->path());
try{
if (!bsfs::is_directory(dirIte->status()) )
{
file_size = file_size + bsfs::file_size(filePath);
}else{
getFoldersize(filePath.string(),file_size);
}
}catch(exception& e){
cout << e.what() << endl;
}
}
}
}
int main(){
long file_size =0;
getFoldersize("C:\\logs",file_size);
cout << file_size << endl;
system("pause");
return 0;
}
Something like this would be better to avoid adding symbolic(soft) links:
std::uintmax_t directorySize(const std::filesystem::path& directory)
{
std::uintmax_t size{ 0 };
for (const auto& entry : std::filesystem::recursive_directory_iterator(directory))
{
if (entry.is_regular_file() && !entry.is_symlink())
{
size += entry.file_size();
}
}
return size;
}
Size of files in a folder
Please have a look at this link
#include <iostream>
#include <windows.h>
#include <string>
using namespace std;
__int64 TransverseDirectory(string path)
{
WIN32_FIND_DATA data;
__int64 size = 0;
string fname = path + "\\*.*";
HANDLE h = FindFirstFile(fname.c_str(),&data);
if(h != INVALID_HANDLE_VALUE)
{
do {
if( (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
{
// make sure we skip "." and "..". Have to use strcmp here because
// some file names can start with a dot, so just testing for the
// first dot is not suffient.
if( strcmp(data.cFileName,".") != 0 &&strcmp(data.cFileName,"..") != 0)
{
// We found a sub-directory, so get the files in it too
fname = path + "\\" + data.cFileName;
// recurrsion here!
size += TransverseDirectory(fname);
}
}
else
{
LARGE_INTEGER sz;
// All we want here is the file size. Since file sizes can be larger
// than 2 gig, the size is reported as two DWORD objects. Below we
// combine them to make one 64-bit integer.
sz.LowPart = data.nFileSizeLow;
sz.HighPart = data.nFileSizeHigh;
size += sz.QuadPart;
}
}while( FindNextFile(h,&data) != 0);
FindClose(h);
}
return size;
}
int main(int argc, char* argv[])
{
__int64 size = 0;
string path;
size = TransverseDirectory("c:\\dvlp");
cout << "\n\nDirectory Size = " << size << "\n";
cin.ignore();
return 0;
}
For more detail PLease CLick Here
The file system functions are integral part of each operative system, written mostly in C and assembler, not C++, each C++ library implementation for this are in one way or another a wrapper of this functions. Taking on count the effort and if you will not use your implementation in different OS, maybe is a good idea to use this functions directly and save some overhead and time.
Best regards.
I have my types definition file with:
typedef std::wstring String;
typedef std::vector<String> StringVector;
typedef unsigned long long uint64_t;
and code is:
uint64_t CalculateDirSize(const String &path, StringVector *errVect = NULL, uint64_t size = 0)
{
WIN32_FIND_DATA data;
HANDLE sh = NULL;
sh = FindFirstFile((path + L"\\*").c_str(), &data);
if (sh == INVALID_HANDLE_VALUE )
{
//if we want, store all happened error
if (errVect != NULL)
errVect ->push_back(path);
return size;
}
do
{
// skip current and parent
if (!IsBrowsePath(data.cFileName))
{
// if found object is ...
if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)
// directory, then search it recursievly
size = CalculateDirSize(path + L"\\" + data.cFileName, NULL, size);
else
// otherwise get object size and add it to directory size
size += (uint64_t) (data.nFileSizeHigh * (MAXDWORD ) + data.nFileSizeLow);
}
} while (FindNextFile(sh, &data)); // do
FindClose(sh);
return size;
}
bool IsBrowsePath(const String& path)
{
return (path == _T(".") || path == _T(".."));
}
This uses UNICODE and returns failed dirs if you want that.
To call use:
StringVector vect;
CalculateDirSize(L"C:\\boost_1_52_0", &vect);
CalculateDirSize(L"C:\\boost_1_52_0");
But never pass size
//use FAT32
#undef UNICODE // to flag window deactive unicode
#include<Windows.h> //to use windows api
#include<iostream>
#include<iomanip>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
#pragma pack(1) //tell compiler do'nt do prag
struct BPB
{
BYTE JMP[3];
BYTE OEM[8];
WORD NumberOfBytesPerSector;
BYTE NumberOfSectorsPerCluster;
WORD NumberOfReservedSectors;
BYTE NumberOfFATs;
WORD NumberOfRootEntries16;
WORD LowNumbferOfSectors;
BYTE MediaDescriptor;
WORD NumberOfSectorsPerFAT16;
WORD NumberOfSectorsPerTrack;
WORD NumberOfHeads;
DWORD NumberOfHiddenSectors;
DWORD HighNumberOfSectors;
DWORD NumberOfSectorsPerFAT32;
WORD Flags;
WORD FATVersionNumber;
DWORD RootDirectoryClusterNumber;
WORD FSInfoSector;
WORD BackupSector;
BYTE Reserver[12];
BYTE BiosDrive;
BYTE WindowsNTFlag;
BYTE Signature;
DWORD VolumeSerial;
BYTE VolumeLabel[11];
BYTE SystemID[8];
BYTE CODE[420];
WORD BPBSignature;
};
//-----------------------------------------------------------
struct DirectoryEntry
{
BYTE Name[11];
BYTE Attributes;
BYTE Reserved;
BYTE CreationTimeTenth;
WORD CreationTime;
WORD CreationDate;
WORD LastAccessTime;
WORD HiClusterNumber;
WORD WriteTime;
WORD WriteDate;
WORD LowClusterNumber;
DWORD FileSize; //acual size of file
};
//---------------------------------------------------
void dirFunction(string s){
string path = "\\\\.\\" + s + ":";
HANDLE hFile = CreateFile(path.c_str(), GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);//open partition
BPB bootSector;//var from bootSector structure
DWORD readBytes = 0;
if (hFile == INVALID_HANDLE_VALUE)
{
cout << "Error " << GetLastError()<<endl;
return;
}
ReadFile(hFile, (BYTE*)&bootSector, sizeof(bootSector), &readBytes, 0);//read partition and load bootSector information inside our structure
LONG t = 0;
ULONG distance = bootSector.NumberOfReservedSectors +
bootSector.NumberOfFATs*bootSector.NumberOfSectorsPerFAT32;//distance from begine until Root Directory or content of partetion
distance *= bootSector.NumberOfBytesPerSector;//convert distance number to bytes value
SetFilePointer(hFile, distance, &t, FILE_BEGIN);//set pointer to root directory begine or begine of data
int clusterSize = bootSector.NumberOfBytesPerSector*bootSector.NumberOfSectorsPerCluster; //cluster size
int NumberOfEntries = clusterSize / sizeof(DirectoryEntry); //number of record inside cluster
DirectoryEntry* root = new DirectoryEntry[NumberOfEntries];//descripe the partetion
ReadFile(hFile, (BYTE*)root, clusterSize, &readBytes, 0);
DWORD clusterNumber;
for (int i = 0; i < NumberOfEntries; i++)
{
if (root[i].Name[0] == 0)//there no entery after this
break;
if (root[i].Name[0] == 0xE5)
continue;
if ((root[i].Attributes & 0xF) == 0xF)
continue;
for (int j = 0; j < 8; j++)
cout << root[i].Name[j];
if((root[i].Attributes & 0x10) != 0x10){
cout<<".";
for (int j = 8; j < 11; j++)
cout << root[i].Name[j];
}
if ((root[i].Attributes & 0x10) == 0x10){
cout << "\t<Folder>" ;
}else{
cout<<"\t<File>" ;
}
clusterNumber = root[i].HiClusterNumber << 16;
clusterNumber |= root[i].LowClusterNumber;
cout <<"\t"<<root[i].FileSize<<"bytes" << "\t" << clusterNumber<<"cluster" << endl;
}
CloseHandle(hFile);
}
//---------------------------------------------------------------
string convertLowerToUpper(string f){
string temp = "";
for (int i = 0; i < f.size(); i++){
temp += toupper(f[i]);
}
return temp;
}
//---------------------------------------------------------------
string getFileName(BYTE filename[11]){
string name = "";
for (int i = 0; i < 8; i++){
if (filename[i] != ' ')
name += filename[i];
}
return (name);
}
//------------------------------------------------------------------
int findEntryNumber(DirectoryEntry* root, int NumberOfEntries, string required){
string n;
int j = 0;
for (int i = 0; i < NumberOfEntries; i++){
if (strcmp((getFileName(root[i].Name).c_str()), convertLowerToUpper(required).c_str()) == 0){
return i;
}
}
return -1;
}
//---------------------------------------------------------------
void typeFunction(string fileName, string s){
string path = "\\\\.\\" + s + ":";
HANDLE hFile = CreateFile(path.c_str(), GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);//open partition
BPB bootSector;//var from bootSector structure
DWORD readBytes = 0;
if (hFile == INVALID_HANDLE_VALUE)
{
cout << "Error " << GetLastError()<<endl;
return;
}
ReadFile(hFile, (BYTE*)&bootSector, sizeof(bootSector), &readBytes, 0);//read partition and load bootSector information inside our structure
LONG t = 0;
ULONG distance = bootSector.NumberOfReservedSectors +
bootSector.NumberOfFATs*bootSector.NumberOfSectorsPerFAT32;//distance from begine until Root Directory or content of partetion
distance *= bootSector.NumberOfBytesPerSector;//convert distance number to bytes value
SetFilePointer(hFile, distance, &t, FILE_BEGIN);//set pointer to root directory begine or begine of data
int clusterSize = bootSector.NumberOfBytesPerSector*bootSector.NumberOfSectorsPerCluster; //cluster size
int NumberOfEntries = clusterSize / sizeof(DirectoryEntry); //number of record inside cluster
DirectoryEntry* root = new DirectoryEntry[NumberOfEntries];//descripe the partetion
ReadFile(hFile, (BYTE*)root, clusterSize, &readBytes, 0);
DWORD clusterNumber;
int index = findEntryNumber(root, NumberOfEntries, fileName);
if (index == -1){
cout << "File is not found" << endl;
return;
}
if (((root[index].Attributes & 0x10) == 0x10) ){
cout << "Is not file name" << endl;
return;
}
clusterNumber = root[index].HiClusterNumber << 16;
clusterNumber |= root[index].LowClusterNumber;
ULONG temp = (clusterNumber - 2) * clusterSize;
distance += temp;
t = 0;
SetFilePointer(hFile, distance, &t, FILE_BEGIN);
BYTE* buffer = new BYTE[clusterSize];
readBytes = 0;
ReadFile(hFile, (BYTE*)buffer, clusterSize, &readBytes, 0);
for (int i = 0; i < root[index].FileSize; i++){
cout << buffer[i];
}
cout << endl;
CloseHandle(hFile);
}
//----------------------------------------------------------------------
void delFunction(string filename, string s){
string path = "\\\\.\\" + s + ":";
HANDLE hFile = CreateFile(path.c_str(), GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);//open partition
BPB bootSector;//var from bootSector structure
DWORD readBytes = 0;
if (hFile == INVALID_HANDLE_VALUE)
{
cout << "Error " << GetLastError()<<endl;
return;
}
ReadFile(hFile, (BYTE*)&bootSector, sizeof(bootSector), &readBytes, 0);//read partition and load bootSector information inside our structure
LONG t = 0;
ULONG distance = bootSector.NumberOfReservedSectors +
bootSector.NumberOfFATs*bootSector.NumberOfSectorsPerFAT32;//distance from begine until Root Directory or content of partetion
distance *= bootSector.NumberOfBytesPerSector;//convert distance number to bytes value
SetFilePointer(hFile, distance, &t, FILE_BEGIN);//set pointer to root directory begine or begine of data
int clusterSize = bootSector.NumberOfBytesPerSector*bootSector.NumberOfSectorsPerCluster; //cluster size
int NumberOfEntries = clusterSize / sizeof(DirectoryEntry); //number of record inside cluster
DirectoryEntry* root = new DirectoryEntry[NumberOfEntries];//descripe the partetion
ReadFile(hFile, (BYTE*)root, clusterSize, &readBytes, 0);
DWORD clusterNumber;
readBytes = 0;
t = 0;
int index = findEntryNumber(root, NumberOfEntries, filename);
if (index == -1){
cout << "FIle is not found" << endl;
return;
}
if ((root[index].Attributes & 0x10) == 0x10){
cout << "Is not file name" << endl;
return;
}
//delete file
root[index].Name[0] = 0xE5;
SetFilePointer(hFile, distance, &t, FILE_BEGIN);
WriteFile(hFile, (BYTE*)root, clusterSize, &readBytes, 0);
cout<<filename<<" is deleted\n";
CloseHandle(hFile);
}
//----------------------------------------------------------------------
string removeExtention(string s){
string t = "";
for (int i = 0; i < s.size(); i++){
if (s[i] == '.')break;
t += s[i];
}
return t;
}
//-------------------------------------------------------------------
void main()
{
string swich_value;
string directory;
string file_name;
//dirFunction("G");
cout<<"plz, Enter single Partition character ------> example E or G\n\n";
cin>>directory;
string path = "\\\\.\\" + directory + ":";
cout<<"current directory is "<<path<<endl;
cout<<"Enter Options: \n1- dir \n2- type file_name.extention \n3- del file_name.extention\n\n";
again:
cin>>swich_value;
if(swich_value.at(1)!='i')
cin>>file_name;
string answer;
switch(swich_value.at(1)){
case 'i':
dirFunction(directory);
cout<<"\nare you want to do another process: y or n?";
cin>>answer;
if (answer.at(0)=='y')
goto again;
break;
case 'y':
typeFunction(removeExtention(file_name), directory);
cout<<"\nare you want to do another process: y or n?";
cin>>answer;
if (answer.at(0)=='y')
goto again;
break;
case 'e':
delFunction(removeExtention(file_name), directory);
cout<<"\nare you want to do another process: y or n?";
cin>>answer;
if (answer.at(0)=='y')
goto again;
break;
}
}
You can use "boost::filesystem"
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;
unsigned long long int get_directory_size(const fs::path& directory){
if (!fs::exists(directory)) return 0;
if (fs::is_directory(directory)){
unsigned long long int ret_size = 0;
fs::directory_iterator m_dir_itr(directory);
for (m_dir_itr = fs::begin(m_dir_itr); m_dir_itr != fs::end(m_dir_itr); ++m_dir_itr){
fs::directory_entry m_dir_entry = *m_dir_itr;
if (fs::is_regular_file(m_dir_entry.path())){
ret_size += fs::file_size(m_dir_entry.path());
}else if (fs::is_directory(m_dir_entry.path())){
ret_size += get_directory_size(m_dir_entry.path());
}
}
return ret_size;
} else if (fs::is_regular_file(directory)){
return fs::file_size(directory);
}
return 0;
}
#include <stdio.h>
int main(int /*argc*/, char** /*argv*/) {
// Assuming 'C:/Folder' be any directory then its size can be found using
auto folder_size = get_directory_size("C:/Folder");
printf("Size of 'C:/Folder' is %d\n",folder_size);
return 0;
}
With the introduction of std::filesystem, you no more have to use any system APIs or any external libraries.
#include <filesystem>
namespace n_fs = ::std::filesystem;
double archive::getFolderSize(std::string path)
{
double r = 0.0;
try{
if (!n_fs::is_directory(path))
{
r += (double)n_fs::file_size(path);
}
else
{
for(auto entry: n_fs::directory_iterator(path))
getFolderSize(entry.path().string());
}
}
catch(exception& e)
{
std::cout << e.what() << std::endl();
}
return r;
}
int main(){
double folderSize = getFolderSize("~/dev/"); //Replace with your path
std::cout << "Size of Folder: " << folderSize;
}
Try using GetFileSizeEx function. Following is some sample code for this. You need to get the size from the LARGE_INTEGER union though.
#include <iostream>
#include <windows.h>
#include <stdio.h>
#include <io.h>
using namespace std;
int main()
{
FILE *fp;
fp = fopen("C:\test.txt","r");
int fileNo = _fileno(fp);
HANDLE cLibHandle = (HANDLE)_get_osfhandle(fileNo);
long int fileSize = 0;
LARGE_INTEGER fileSizeL;
GetFileSizeEx(cLibHandle, &fileSizeL);
return 0;
}
5 years and not a simple solution with standard C++, that's why I would like to contribute my solution to this question:
uint64_t GetDirSize(const std::string &path)
{
uint64_t size = 0;
for (const auto & entry : std::experimental::filesystem::directory_iterator(path))
{
if(entry.status().type() == std::experimental::filesystem::file_type::regular)
size += std::experimental::filesystem::file_size(entry.path());
if (entry.status().type() == std::experimental::filesystem::file_type::directory)
size += GetDirSize(entry.path().generic_string());
}
return size;
}
Use it for example by calling
GetDirSize("C:\\dir_name")
if you're using Windows.
Calculating a folder size in bytes on Windows.
size_t GetFolderSizeInBytes(std::wstring path)
{
size_t result = 0;
WIN32_FIND_DATA findData;
HANDLE hFileHandle;
std::wstring sourcePath(path);
if (GetFileAttributes(sourcePath.c_str()) & FILE_ATTRIBUTE_DIRECTORY)
sourcePath.push_back(L'\\');
std::wstring fileName(sourcePath);
fileName.append(L"*");
hFileHandle = FindFirstFileEx(
fileName.data(),
FindExInfoStandard,
&findData,
FindExSearchNameMatch,
NULL,
FIND_FIRST_EX_ON_DISK_ENTRIES_ONLY);
if (hFileHandle != INVALID_HANDLE_VALUE)
{
do
{
if (!wcscmp(findData.cFileName, L".") || !wcscmp(findData.cFileName, L".."))
continue;
if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
{
// Folder
std::wstring newPath = path + L"\\" + findData.cFileName;
result += GetFolderSizeInBytes(newPath);
}
else
{
// File
unsigned long high = findData.nFileSizeHigh;
unsigned long low = findData.nFileSizeLow;
size_t size = size_t(high * (MAXWORD + 1)) + low;
result += size;
}
} while (FindNextFile(hFileHandle, &findData));
FindClose(hFileHandle);
}
return result;
}
it need a way to call function whose name is stored in a string similar to eval. Can you help?
C++ doesn't have reflection so you must hack it, i. e.:
#include <iostream>
#include <map>
#include <string>
#include <functional>
void foo() { std::cout << "foo()"; }
void boo() { std::cout << "boo()"; }
void too() { std::cout << "too()"; }
void goo() { std::cout << "goo()"; }
int main() {
std::map<std::string, std::function<void()>> functions;
functions["foo"] = foo;
functions["boo"] = boo;
functions["too"] = too;
functions["goo"] = goo;
std::string func;
std::cin >> func;
if (functions.find(func) != functions.end()) {
functions[func]();
}
return 0;
}
There are at least 2 alternatives:
The command pattern.
On windows, you can use GetProcAddress to get a callback by name, and dlopen + dlsym on *nix.
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
double eval( string expression );
int main( int argc, char *argv[] )
{
string expression = "";
for ( int i = 1; i < argc; i++ )
{
expression = expression + argv[i];
}
cout << "Expression [ " << expression << " ] = " << endl;
eval( expression );
}
double eval( string expression )
{
string program = "";
program = program + "#include <cmath>\n";
program = program + "#include <iostream>\n";
program = program + "using namespace std;\n";
program = program + "int main()\n";
program = program + "{\n";
program = program + " cout << ";
program = program + expression;
program = program + " << endl;\n";
program = program + "}";
ofstream out( "abc.cpp" );
out << program;
out.close();
system( "g++ -o abc.exe abc.cpp" );
system( "abc" );
}
You could try to adopt an existing scripting engine, expose the functions you like to this and then use this to evaluate your statements. One such enging could be the V8 engine: https://developers.google.com/v8/intro but there are many alternatives and different languages to choose from.
Here are some examples:
Boost Python
V8
LUA
AngelScript
Except using the function map in the program and hack it on the Makefile, you can access it through ELF.
I think this method is better as it did not need to write duplicate code and compile it every time on different machine.
Here is my demo C/C++ equivalent of eval(“function(arg1, arg2)”)
#include<stdio.h>
#include<stdlib.h>
#include<elf.h>
#include<libelf.h>
#include<unistd.h>
#include<fcntl.h>
#include<gelf.h>
#include<string.h>
void my_fun()
{
int a = 19;
printf("my_fun is excute, a is %d \n", a);
}
void my_fun2()
{
printf("my_fun2 is excute\n");
return;
}
void my_fun3()
{
return;
}
void excute_fun(char *program_name, char *function_name)
{
int i, count;
Elf32_Ehdr *ehdr;
GElf_Shdr shdr;
Elf *elf;
Elf_Scn *scn = NULL;
Elf_Data *data;
int flag = 0;
int fd = open(program_name, O_RDONLY);
if(fd < 0) {
perror("open\n");
exit(1);
}
if(elf_version(EV_CURRENT) == EV_NONE) {
perror("elf_version == EV_NONE");
exit(1);
}
elf = elf_begin(fd, ELF_C_READ, (Elf *) NULL);
if(!elf) {
perror("elf error\n");
exit(1);
}
/* Elf32_Off e_shoff; */
/* if ((ehdr = elf32_getehdr(elf)) != 0) { */
/* e_shoff = ehdr->e_shoff; */
/* } */
/* scn = elf_getscn(elf, 0); */
/* printf("e_shoff is %u\n", e_shoff); */
/* scn += e_shoff; */
while ((scn = elf_nextscn(elf, scn)) != NULL) {
gelf_getshdr(scn, &shdr);
if (shdr.sh_type == SHT_SYMTAB) {
/* found a symbol table. */
break;
}
}
data = elf_getdata(scn, NULL);
if(!shdr.sh_entsize)
count = 0;
else
count = shdr.sh_size / shdr.sh_entsize;
for (i = 0; i < count; ++i) {
GElf_Sym sym;
gelf_getsym(data, i, &sym);
char *sym_name = elf_strptr(elf, shdr.sh_link, sym.st_name);
if(sym_name != NULL && sym_name[0] != '_' && sym_name[0] != '\0' && sym_name[0] != ' ' && sym.st_value != 0)
{
/* printf("sym_name is %s\n", sym_name); */
/* printf("%s = %X\n", elf_strptr(elf, shdr.sh_link, sym.st_name), sym.st_value); */
if(!strcmp(sym_name, function_name)) {
void (*fun)(void) = (void*)sym.st_value;
(*fun)();
flag = 1;
}
}
}
if(!flag)
printf("can not find this function\n");
elf_end(elf);
close(fd);
}
int main(int argc, char *argv[])
{
char *input = (char*)malloc(100);
for(;;) {
printf("input function_name to excute: ");
scanf("%s", input);
excute_fun(argv[0], input);
memset(input, 0, sizeof(input));
printf("\n");
}
free(input);
return 0;
}
This implementation is based on Example of Printing the ELF Symbol Table