How to read the disk usage (du) in a C variable - c++

I would like to do the following in a "c" program.
I need to get the disk usage of the following directory and should be able to read it in a variable.
du -sb /home/mann | awk '{print$1}'
I would like to do the above in C program and copy the output in a variable. I need to do this for this directory alone not for the "/" or "/home".

Pipe the output of your command to a file on the disk. Run your command using system
Read the file using standard C functions
Update your variable
Another option is to use popen/pclose to launch your command. This will return a file descriptor from which you can read.
Yet another option is to hunt your system for any library function that provides the information you desire

Related

Will File I/O In Current Working Directory Ever Fail?

On my home Linux laptop, I like to write wrapper programs and GUI helpers for things I use frequently. However, I don't like Bash scripting very much, so I do a lot of stuff in C++. However, a lot of times, this requires me to use the system() function from the cstdlib.
This system() command is awesome, but I wanted a way to call system() and receive the stdout/stderror. The system() command only returns the return code from the command. So, in a Bash script, one can do:
myVar=$(ls -a | grep 'search string')
echo $myVar
and myVar will output whatever the stdout was for the command. So I began writing a wrapper class that will add a pipe-to-file to the end of the command, open the file, read all of the piped stdout, and return it as either one long string or as a vector of strings. The intricacies of the class are not really relevant here (I don't think anyway), but the above example would be done like this:
SystemCommand systemCommand;
systemCommand.setCommand("ls -a | grep \'search string\' ");
systemCommand.execute();
std::cout << systemCommand.outputAsString() << std::endl;
Behind the scenes, when systemCommand.execute() is called, the class ensures that the command will properly pipe all stdout/stderr to a randomly generated filename, in the current working directory. So for example, the above command would end up being
"ls -a | grep 'search string' >> 1452-24566.txt 2>&1".
The class then goes attempts to open and read from that file, using ifstream:
std::ifstream readFromFile;
readFromFile.open(_outputFilename);
if (readFromFile.is_open()) {
//Read all contents of file into class member vector
...
readFromFile.close();
//Remove temporary file
...
} else {
//Handle read failure
}
So here is my main question will std::ifstream ever fail to open a recently created file in the current working directory? If so, what would be a way to make it more robust (specifically on Linux)?
A side/secondary question: Is there a very simplified way to achieve what I'm trying to achieve without using file pipes? Perhaps some stuff available in unistd.h? Thanks for your time.
So here is my main question will std::ifstream ever fail to open a recently created file in the current working directory?
Yes.
Mount a USB thumb drive (or some other removable media)
cd to the mount
Execute your program. While it's executing, remove the drive.
Watch the IO error happen.
There's a ton of other reasons too. Filesystem corruption, hitting the file descriptor limit, etc.
If so, what would be a way to make it more robust (specifically on Linux)?
Make temporary files in /tmp, whose entire purpose is for temporary files. Or don't create a file at all, and use pipes for communication instead (Like what popen does, like harmic suggested). Even so, there are no guarantees; try to gracefully handle errors.

Recovering Files on Windows and C

Well this time I'm trying to write a program in C which recover deleted files from a disk, it could be an external disk, I have an idea than i had used before on linux, it is to open the disk as a kind of file and scaning the Headers and file footers of everything within the disk, the point is I'm not sure if there's allow on windows to open a disk as an File, basiclly I have the logic how to develope this program, but I'm not sure how to implement it on windows, anybody can give me a hand with this?.
The code I used on linux to open a disk as a file was:
Edit: That was a sample of what I was using guys, it's just to give you an idea of what I was doing, the correct syntax I used was the next:
direccion = ui->linea->text().toLatin1().constData();
f = fopen(direccion,"rb");
I used QT creator on linux, and direccion variable was a TextField value which contained the file path of the disk through a button function that open a QFileDialog...
could I use it in windows as well?
Thank you before hand..
"The code I used on linux to open a disk as a file was:"
File *f = fopen("E:\", "rb");
I seriously doubt you ever got this code working on any linux system (or windows either).
You'll need to escape the backslash path delimiter, if it's presented in any string literal:
FILE* f = fopen("E:\\", "rb");
// ^
Also all that filesystem path style you are presenting to access a particular disk, is about accessing a windows file path/disk.
No linux file system has notion about drive characters, and the file path delimiter value used is '/', not '\\'.
To recover deleted files, you can't use fopen or fstream::open because the file was deleted. Check the return value from the function or test the stream state.
The way to recover deleted files is:
Get the Master File Table as raw data.
Search for the record containing a string similar to the deleted
filename.
Change the entry in the Master File Table to "undeleted".
Write the Master File Table back to the drive.
The above usually requires platform specific API, which is different on Linux and Windows platforms.

Accessing text data files from a static library function

How to I enable a static library to pull in data available in ascii data files?
I am trying to add a model to a simulation as a library which contains functions that read data from data files. I am able to compile and run the functions from a main program outside the actual full simulation, but once I put the functions as a library on the host for the simulation the data no longer gets read.
As the path to the data is changing depending on the user, I cannot provide an absolute data path to the ascii data files. Is there a way to use objcopy to make the data files into object code in the library or how can I best access the data from my static library?
There are several solutions to open a file that has an unknown location at compile time. Prompt the user for the name of the file, including directory. Use an environment variable to designate the directory containing the file ... Fortran 2003 has an intrinsic to obtain the value of an environment variable. Obtain the information from a command line argument ... again Fortran 2003 has an intrinsic for this purpose. With all of these, construct the filename as a string variable and provide that variable to the FILE keyword of the OPEN statement.
I don't know why you inclouded the Fortran tag, but in Fortran you:
tell the code to open a file you want using a character string
to read from it
and to close it
There is no difference between a main program or a library.
If you have a function like, say:
void read_data_from_files() { ... }
You'll need to change it in the DLL to be more like:
DataObject read_data_from_file(const char* file_path) { ... }
And then call it appropriately.
You'll need to design DataObject.

Bash input/output in C++

I'm writing program in C++ (for XAMPP communication) and I want to execute command which I have in strings (I know that this is simply system("command")) but I want to get the output from bash to C++ to string. I've founded several threads about this, but no which solved Bash -> C++.
You can call the FILE *popen(const char *command, const char *mode) function. Then, you can read the file it returns to get the output of your call.
It's like using a pipe to redirect the output of the command you used to a file in the hard drive and then read the file, but you don't get to create a file in the hard drive.
The documentation of the popen() is here.
You need to call the popen function, and read the output from the FILE it returns.
You can try Standard Output Redirection to redirect the standard output to a file stream
and then use it to read to a string.
Dup()

launch app, capture stdout and stderr in c++

How do I launch an app and capture the output via stdout and maybe stderr?
I am writing an automated build system and I need to capture the output to analyze. I'd like to update the svn repo and grab the revision number so I can move the files in autobuild/revNumber/ if successful. I also would like to build using make and upload the compile text to my server for everyone to see the warnings and errors on a failed build.
I can't find the system() function, but I found the CreateProcess() function on MSDN. I am able to launch what I need but I have no idea how to capture the stderr and stdout. I notice the process launches separately unless I set a breakpoint and keep my app exiting which it then will keep all the text in my app console window. I would also want to wait until all processes are finished and then scan the data it produced to do any additional operations I need. How do I do any of this?
In real shells (meaning, not sea shells - I mean, not in C Shell or its derivatives), then:
program arg1 arg2 >/tmp/log.file 2>&1
This runs program with the given arguments, and redirects the stdout to /tmp/log.file; the notation (hieroglyph) '2>&1' at the end sends stderr (file descriptor 2) to the same place that stdout (file descriptor 1) is going. Note that the sequence of operations is important; if you reverse them, then standard error will go to where standard output was going, and then standard output (but not standard error) will be redirected to the file.
The choice of file name shown is abysmal for numerous reasons - you should allow the user to choose the directory, and probably should include the process ID or time stamp in the file name.
LOG=${TMPDIR:-/tmp}/log.$$.$(date +%Y%m%d-%H%M%S)
program arg1 arg2 >$LOG 2>&1
In C++, you can use the system() function (inherited from C) to run processes. If you need to know the file name in the C++ program (plausible), then generate the name in the program (strftime() is your friend) and create the command string with that file name.
(Strictly, you also need getenv() to get $TMPDIR, and the POSIX function getpid() to get the process ID, and then you can simulate the two-line shell script (though the PID used would be of the C++ program, not the launched shell).
You could instead use the POSIX popen() function; you'd have to include the '2>&1' notation in the command string that you create to send the standard error of the command to the same place as standard output goes, but you would not need a temporary file:
FILE *pp = popen("program arg1 arg2 2>&1", "r");
You can then read off the file stream. I'm not sure whether there's a clean way to map a C file stream into a C++ istream; there probably is.
You need to fill up the STARTUP_INFO structure, which has hStdInput, hStdOutput and hStdError. Remember to inherit handles when you CreateProcess.
/* Assume you open a file handle or pipe called myoutput */
STARTUP_INFO si_startinfo;
ZeroMemory(&si_startinfo, sizeof(STARTUP_INFO));
si_startinfo.cb = sizeof(STARTUP_INFO);
si_startinfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
si_startinfo.hStdOutput = myoutput;
si_startinfo.hStdError = myoutput;
si_startifno.dwFlags != STARTF_USEHANDLES;
PROCESS_INFORMATION pi_procinfo;
ZeroMemory(&pi_procinfo, sizeof(PROCESS_INFORMATION);
CreateProcess(NULL, cmdline, NULL, NULL, true, 0, NULL, pathname, &si_startinfo, &pi_procinfo);
I have not shown the error handling aspects, which you will need to do. The 5th argument is set to true to inherit the handles. Others have explained how to create pipes so I won't repeat it here.
Microsoft's CRTs and the MSDN library do include the system function and the _popen function.