Unable to read file contents into buffer using read() - c++

Following is a sample code compiled using GNU compiler (g++ command) on an Ubuntu OS 16.04:
#include<iostream>
#include<unistd.h>
#include<fcntl.h>
#include <errno.h>
int main()
{ char* pBuffer;
char* storedfilepath = "/home/rtpl/Desktop/ts.mp4";
std::cout<<"\n Opening file at "<<storedfilepath<<"\n";
int NumBytesToRead = 1000 ;
int filedes = open(storedfilepath,O_RDONLY);
std::cout<<"\n value of error is "<<errno<<"\n";
std::cout<<"\n value of filedes is "<<filedes;
if (filedes==0)
std::cout<<"\n File cannot be opened";
else
{
std::cout<<"\n File opened successfully";
std::cout<<"\n Now reading file\n";
}
//if(
int ret = read(filedes,pBuffer,NumBytesToRead);
std::cout<<"\n value of error is "<<errno<<"\n";
if(ret!= -1)
std::cout<<"\n File read successfully";
else
std::cout<<"\n File contents cannot be read";
std::cout<<"\nEnd.\n";
close(filedes);
return 0;
}
When compiled; I get this message:
rtpl#rtpl-desktop:~/Desktop$ g++ -g checkts.cpp
checkts.cpp: In function ‘int main()’:
checkts.cpp:8:27: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
char* storedfilepath = "/home/rtpl/Desktop/ts.mp4";
Upon execution:
rtpl#rtpl-desktop:~/Desktop$ ./a.out
Opening file at /home/rtpl/Desktop/ts.mp4
value of error is 0
value of filedes is 3
File opened successfully
Now reading file
value of error is 14
File contents cannot be read
End.
Entire gdb debug can be found here.
Question : Why won't the file contents be read when the file is legit and the compiler throws no error?

Assuming you're running Linux, an errno value of 14 is EFAULT, or "bad address".
Given the code
char* pBuffer;
.
.
.
int ret = read(filedes,pBuffer,NumBytesToRead);
pBuffer is not initialized or otherwise set, so the value in pBuffer is indeterminate and it certainly doesn't point to a valid address.
You need to actually provide a buffer where read() can place the data read:
char buffer[ 1024 ]
.
.
.
ssize_t ret = read(filedes,buffer,NumBytesToRead);
would work, as long as NumBytesToRead does not exceed the number of bytes in buffer. Note also that ret is now the proper ssize_t instead of int.

Related

Assertion failed DirectX 11

I'm working on a DirectX 11 project and keep getting this error:
It says that error occurs in model.cpp file which my teacher sent me. Line 400: assert(file);
void CModel::LoadMaterial( const char *FileName, MODEL_MATERIAL **MaterialArray, unsigned int *MaterialNum )
{
char dir[MAX_PATH];
strcpy(dir, FileName);
PathRemoveFileSpec(dir);
char str[256];
FILE *file;
file = fopen( FileName, "rt" );
assert(file);
MODEL_MATERIAL *materialArray;
unsigned int materialNum = 0;
Or maybe I should send the whole model.cpp file to see why there is that Runtime Error?
Ensure that the FileName file exists. The assert is being thrown because the file object is null (0) as the call to fopen failed.

Redirect ffmpeg console output to a string or a file in C++

I'm trying to use ffmpeg to do some operations for me. It's really simple for now. I want to omit the ffmpeg output in my console, either redirecting them to strings or a .txt file that I can control. I'm on Windows 10.
I have tried _popen (with and "r" and "w") and system("ffmpeg command > output.txt")', with no success.
#include <iostream>
#include <stdio.h>
using namespace std;
#define BUFSIZE 256
int main()
{
/* 1.
x = system("ffmpeg -i video.mp4 -i audio.mp4 -c copy output.mp4 > output.txt");
*/
/* 2.
FILE* p;
p = _popen("ffmpeg -i video.mp4 -i audio.mp4 -c copy output.mp4", "w");
_pclose(p);
*/
/* 3.
char cmd[200] = { "ffmpeg -i video.mp4 -i audio.mp4 -c copy output.mp4" };
char buf[BUFSIZE];
FILE* fp;
if ((fp = _popen(cmd, "r")) == NULL) {
printf("Error opening pipe!\n");
return -1;
}
while (fgets(buf, BUFSIZE, fp) != NULL) {
// Do whatever you want here...
// printf("OUTPUT: %s", buf);
}
if (_pclose(fp)) {
printf("Command not found or exited with error status\n");
return -1;
}
*/
return 0;
}
Further in the development, I would like to know when the ffmpeg process finished (maybe I can monitor the ffmpeg return value?) or to display only the last line if the some error occurred.
I have made it to work.
In the solution 1, I added " 2>&1" to the end of the string.
Found it here: ffmpeg command line write output to a text file
output-to-a-text-file
Thanks!

Exec fails due to Bad Address

I have a serious problem with exec.I've tried both options with list(execl) and array(execv) but the problem remains.I'll give the function in which i try to make the call.
#include <unistd.h>
#include <sys/types.h>
void MyFunc(string aparams[],char* infile,char* outfile,int k,int points){
int mcount=3;
char* offset= new char[5];
sprintf(offset,"%d",k);
char* pntr=new char[5];
sprintf(pntr,"%d",points);
char* *wparams=new char*[mcount];
for (int i = 0; i < mcount; i++) {
wparams[i] = new char[aparams[i].length() + 1];
strcpy(wparams[i], aparams[i].c_str());
}
char *cwd;
cwd=(char*)malloc(255);
getcwd(cwd,255);
strcat(cwd,"/");
strcat(cwd,wparams[0]);
cout << cwd << endl;
execl(cwd,wparams[0],"-i",infile,"-o",outfile,"-f",offset,"-n",pntr,"-a",wparams[1],wparams[2],wparams[3],(char*) NULL);
cout << "exec failed" << endl;
perror("The problem in exec is:");
exit(3);
}
aparams[0] contains a string with the name of an executable file,let's say "test".I compiled -> g++ test.cpp -o test -> so I got this executable.
The other positions of aparams contain some arguments for the test program.
So,test never runs(when I run it from command line it's ok) and perror shows the message "The problem in exec is: Bad Address."
I've also tried to cast all arguments(const char*) but nothing changed.
Is it a problem with arguments? Or it's a matter of the executable?
mcount is 3, so wparams points to an array with three elements - wparams[0], wparams[1] and wparams[2].
Then you access wparams[3] which is invalid and contains garbage.
Don't try to access array elements that don't exist.
Your problem is in this line:
execl(cwd,
wparams[0],
"-i", infile, "-o", outfile, "-f", offset, "-n", pntr,
"-a", wparams[1], wparams[2], wparams[3], (char*) NULL);
You're trying to send wparams[3], which doesn't exists! It's the 4th element of wparam array and you explicitly defined it as array[3] in the initialization of your variable mcount.

Geting the file size of a system application on windows in C++

I am trying to get the file size of a system application on windows. To test this i have created a test application that tries to get the file size of smss.exe in C:\Windows\System32\smss.exe but it fails with error: ERROR_FILE_NOT_FOUND. The file does actually exist (i have checked). I've also tried different methods for getting the file size, with: FindFirstFile, CreateFile and GetFileSizeEx. But all return the same error. I would also like to read the file contents.
What am i doing wrong?
The code:
// Test.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <iostream>
__int64 getFileSize(LPWSTR filePath)
{
WIN32_FILE_ATTRIBUTE_DATA fad;
if (!GetFileAttributesEx(filePath, GetFileExInfoStandard, &fad))
{
_tprintf(TEXT("\n CAnt get file size for file %s error %d"), filePath, GetLastError());
return 0;
}
LARGE_INTEGER size;
size.HighPart = fad.nFileSizeHigh;
size.LowPart = fad.nFileSizeLow;
return size.QuadPart;
}
int _tmain(int argc, _TCHAR* argv[])
{
_tprintf(TEXT("File size %d "), getFileSize(L"C:\\Windows\\System32\\smss.exe"));
}
As your application is 32-bit, the system redirects your path to go to SysWOW64 instead, where there is no smss.exe. While you have discovered that Wow64DisableWow64FsRedirection disables this redirection, also consider that having a 64-bit program would also do the trick.
Getting the size of a file is already answered here (can't yet add a comment to your question, so I need to write it as an answer):
How can I get a file's size in C++?
std::ifstream::pos_type filesize(const char* filename)
{
std::ifstream in(filename, std::ifstream::in | std::ifstream::binary);
in.seekg(0, std::ifstream::end);
return in.tellg();
}

ifstream creates file if it doesn't exist

I'm having some trouble writing a Linux console app which reads apache logs.
I need to handle bash script arguments, the last one being a path to the log file.
My problem is that if the file doesn't exist, I would like to throw an exception.
But when I try to open the file in read-only mode, instead of failing it creates the file !
Here's the code :
// logreader.h
#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
#include <stdexcept>
class LogReader
{
public:
LogReader(int, const char **);
virtual ~LogReader();
// ...
private:
std::ifstream log_;
};
// logreader.cpp
#include <logreader.h>
LogReader::LogReader(int argc, const char ** argv):
log_()
{
log_.exceptions(std::ifstream::failbit | std::ifstream::badbit);
for (int i = 1; i < argc; ++i)
{
std::string arg(argv[i]);
if (i == argc - 1)
{
try
{
log_.open(arg.c_str(), std::ifstream::in);
}
catch (std::ifstream::failure)
{
throw std::runtime_error("The file " + arg + " wasn't opened");
}
}
}
}
LogReader::~LogReader()
{
}
// main.cpp
#include <logreader.h>
int main(int argc, const char ** argv)
{
LogReader(argc, argv);
return 0;
}
Script call:
jmcomets $ ./test -g -l
jmcomets $ ls -l
-rw-rw-r-- 1 jmcomets jmcomets 0 Nov 14 22:41 -l
Since you are opening an std::ifstream it is necessary to add std::ios_base::in (or any other spelling of the std::ios_base::openmode) according to 27.9.1.9 [ifstream.members] paragraph 4: The flag is automatically added by the call to open(). Note that an std::ofstream or an std::fstream would automatically add std::ios_base::out (27.9.1.13 [ofstream.members] paragrpah 3) or std::ios_base::in | std::ios_base::out (27.9.1.17 [fstream.members] paragraph 3), both of which resulting in a new file being created if it doesn't exist (and there are write permissions, etc.).
If the code you posted creates a new file, the implementation of the standard C++ library is wrong: when only the flag std::ios_base::in is specified, the file is open "as if" using the open mode "r" with fopen() (27.9.1.4 [filebuf.members] paragraph 5). fopen() in turn doesn't create a new file when it gets an open mode of "r" (7.21.5.3 paragraph 3).
You can set the failbit in the exceptions flag for the ifstream:
std::ifstream log;
log.exceptions ( std::ifstream::failbit );
try {
log.open ("test.txt");
}
catch (std::ifstream::failure e) {
std::cout << "Exception opening/reading file\n";
}
Source
I've tested, and ifstream will throw a failure exception if the file cannot be opened, e.g. file not found, no read permissions. It will open read-only.
You need to specify ifstream::in as a second parameter as:
log.open(arg.c_str(), ifstream::in)
You can also do:
std::ifstream log(arg.c_str(), ifstream::in);
and skip the call to open()
Edit with something Linux compatible;
Try opening with fopen before writing. If the file DNE the FILE pointer will be null.
FILE * file;
file = fopen ("myfile.txt","r");
if (file == NULL)
//throw if fopen didn't already.
else
//do stuff with my file