C++ fwrite doesn't write to text file, have no idea why? - c++

I have this code that basically reads from file and creates new file and write the content from the source to the destination file. It reads the buffer and creates the file, but fwrite
doesn't write the content to the newly created file, I have no idea why.
here is the code. (I have to use only this with _sopen, its part of legacy code)
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <fcntl.h>
#include <string>
#include <share.h>
#include <sys\stat.h>
int main () {
std::string szSource = "H:\\cpp\\test1.txt";
FILE* pfFile;
int iFileId = _sopen(szSource.c_str(),_O_RDONLY, _SH_DENYNO, _S_IREAD);
if (iFileId >= 0)
pfFile = fdopen(iFileId, "r");
//read file content to buffer
char * buffer;
size_t result;
long lSize;
// obtain file size:
fseek (pfFile , 0 , SEEK_END);
lSize = ftell (pfFile);
fseek(pfFile, 0, SEEK_SET);
// buffer = (char*) malloc (sizeof(char)*lSize);
buffer = (char*) malloc (sizeof(char)*lSize);
if (buffer == NULL)
{
return false;
}
// copy the file into the buffer:
result = fread (buffer,lSize,1,pfFile);
std::string szdes = "H:\\cpp\\test_des.txt";
FILE* pDesfFile;
int iFileId2 = _sopen(szdes.c_str(),_O_CREAT,_SH_DENYNO,_S_IREAD | _S_IWRITE);
if (iFileId2 >= 0)
pDesfFile = fdopen(iFileId2, "w+");
size_t f = fwrite (buffer , 1, sizeof(buffer),pDesfFile );
printf("Error code: %d\n",ferror(pDesfFile));
fclose (pDesfFile);
return 0;
}
You can make main file and try it see if its working for you .
Thanks

Change your code to the following and then report your results:
int main () {
std::string szSource = "H:\\cpp\\test1.txt";
int iFileId = _sopen(szSource.c_str(),_O_RDONLY, _SH_DENYNO, _S_IREAD);
if (iFileId >= 0)
{
FILE* pfFile;
if ((pfFile = fdopen(iFileId, "r")) != (FILE *)NULL)
{
//read file content to buffer
char * buffer;
size_t result;
long lSize;
// obtain file size:
fseek (pfFile , 0 , SEEK_END);
lSize = ftell (pfFile);
fseek(pfFile, 0, SEEK_SET);
if ((buffer = (char*) malloc (lSize)) == NULL)
return false;
// copy the file into the buffer:
result = fread (buffer,(size_t)lSize,1,pfFile);
fclose(pfFile);
std::string szdes = "H:\\cpp\\test_des.txt";
FILE* pDesfFile;
int iFileId2 = _sopen(szdes.c_str(),_O_CREAT,_SH_DENYNO,_S_IREAD | _S_IWRITE);
if (iFileId2 >= 0)
{
if ((pDesfFile = fdopen(iFileId2, "w+")) != (FILE *)NULL)
{
size_t f = fwrite (buffer, (size_t)lSize, 1, pDesfFile);
printf ("elements written <%d>\n", f);
if (f == 0)
printf("Error code: %d\n",ferror(pDesfFile));
fclose (pDesfFile);
}
}
}
}
return 0;
}
[edit]
for other posters, to show the usage/results of fwrite - what is the output of the following?
#include <stdio.h>
int main (int argc, char **argv) {
FILE *fp = fopen ("f.kdt", "w+");
printf ("wrote %d\n", fwrite ("asdf", 4, 1, fp));
fclose (fp);
}
[/edit]

sizeof(buffer) is the size of the pointer, i.e. 4 and not the number of items in the buffer
If buffer is an array then sizeof(buffer) would potentially work as it returns the number of bytes in the array.

The third parameter to fwrite is sizeof(buffer) which is 4 bytes (a pointer). You need to pass in the number of bytes to write instead (lSize).
Update: It also looks like you're missing the flag indicating the file should be Read/Write: _O_RDWR
This is working for me...
std::string szdes = "C:\\temp\\test_des.txt";
FILE* pDesfFile;
int iFileId2;
err = _sopen_s(&iFileId2, szdes.c_str(), _O_CREAT|_O_BINARY|_O_RDWR, _SH_DENYNO, _S_IREAD | _S_IWRITE);
if (iFileId2 >= 0)
pDesfFile = _fdopen(iFileId2, "w+");
size_t f = fwrite (buffer , 1, lSize, pDesfFile );
fclose (pDesfFile);

Since I can't find info about _sopen, I can only look at man open. It reports:
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
Your call _sopen(szdes.c_str(),_O_CREAT,_SH_DENYNO,_S_IREAD | _S_IWRITE); doesn't match either one of those, you seem to have flags and 'something' and modes / what is SH_DENY?
What is the result of man _sopen?
Finally, shouldn't you close the file descriptor from _sopen after you fclose the file pointer?
Your final lines should look like this, btw :
if (iFileId2 >= 0)
{
pDesfFile = fdopen(iFileId2, "w+");
size_t f = fwrite (buffer , 1, sizeof(buffer),pDesfFile ); //<-- the f returns me 4
fclose (pDesfFile);
}
Since you currently write the file regardless of whether or not the fdopen after the O_CREAT succeeded. You also do the same thing at the top, you process the read (and the write) regardless of the success of the fdopen of the RDONLY file :(

You are using a mixture of C and C++. That is confusing.
The sizeof operator does not do what you expect it to do.

Looks like #PJL and #jschroedl found the real problem, but also in general:
Documentation for fwrite states:
fwrite returns the number of full items actually written, which may be less than count if an error occurs. Also, if an error occurs, the file-position indicator cannot be determined.
So if the return value is less than the count passed, use ferror to find out what happened.
The ferror routine (implemented both as a function and as a macro) tests for a reading or writing error on the file associated with stream. If an error has occurred, the error indicator for the stream remains set until the stream is closed or rewound, or until clearerr is called against it.

Related

How to receive a JPEG image over serial port

So I am trying to send a jpeg image (4Kb) from a raspberry pi to my Mac wirelessly using Xbee Series 1. I have an image on the raspberry pi and can read it into binary format. I've used this binary format to save it into another image file and it creates a copy of the image correctly. That tells me that I am reading it correctly. So I am trying to send that data over a serial port (to be transferred by the xbee's) to my Mac. Side note, Xbee's can only transmit I think 80 bytes of data per packet or something. I don't know how that affects what I'm doing though.
My problem is, I do not know how to read the data and properly store it into a jpeg file itself. Most of the Read() functions I have found require you to enter a length to read and I don't know how to tell how long it is since its just a serial stream coming in.
Here is my code to send the jpeg.
#include "xSerial.hpp"
#include <iostream>
#include <cstdlib>
using namespace std;
int copy_file( const char* srcfilename, const char* dstfilename );
int main(){
copy_file("tylerUseThisImage.jpeg", "copyImage.jpeg");
return 0;
}
int copy_file( const char* srcfilename, const char* dstfilename )
{
long len;
char* buf = NULL;
FILE* fp = NULL;
// Open the source file
fp = fopen( srcfilename, "rb" );
if (!fp) return 0;
// Get its length (in bytes)
if (fseek( fp, 0, SEEK_END ) != 0) // This should typically succeed
{ // (beware the 2Gb limitation, though)
fclose( fp );
return 0;
}
len = ftell( fp );
std::cout << len;
rewind( fp );
// Get a buffer big enough to hold it entirely
buf = (char*)malloc( len );
if (!buf)
{
fclose( fp );
return 0;
}
// Read the entire file into the buffer
if (!fread( buf, len, 1, fp ))
{
free( buf );
fclose( fp );
return 0;
}
fclose( fp );
// Open the destination file
fp = fopen( dstfilename, "wb" );
if (!fp)
{
free( buf );
return 0;
}
// this is where I send data in but over serial port.
//serialWrite() is just the standard write() being used
int fd;
fd = xserialOpen("/dev/ttyUSB0", 9600);
serialWrite(fd, buf, len);
//This is where the file gets copied to another file as a test
// Write the entire buffer to file
if (!fwrite( buf, len, 1, fp ))
{
free( buf );
fclose( fp );
return 0;
}
// All done -- return success
fclose( fp );
free( buf );
return 1;
}
On the receive side I know I need to open up the serial port to read and use some sort of read() but I don't know how that is done. Using a serial library it has some functions to check if serial data is available and return the number of characters available to read.
One question about the number of characters available to read, will that number grow as the serial stream comes over or will it immediately tell the entire length of the data to be read?
But finally, I know after I open the serial port, I need read the data into a buffer and then write that buffer to a file but I have not had any luck. This is what I have tried thus far.
// Loop, getting and printing characters
char temp;
bool readComplete = false;
int bytesRead = 0;
fp = fopen("copyImage11.jpeg", "rwb");
for (;;)
{
if(xserialDataAvail(fd) > 0)
{
bytesRead = serialRead(fd, buf, len);
readComplete = true;
}
if (readComplete)
{
if (!fwrite(buf, bytesRead, 1, fp))
{
free(buf);
fclose(fp);
return 0;
}
fclose(fp);
free(buf);
return 1;
}
}
I don't get errors with my code, it just doesnt create the jpeg file correctly. Maybe I'm not transmitting it right, or maybe I'm not reading/writing to file correctly. Any help would be appreciated. Thanks everyone you rock!
If you are defining your own protocol, then you need to have a method for sending the length first.
I would recommend testing your code by sending short blocks of ascii text to confirm your i/o. Once that is working you can use the ascii to set up the transfer; ie send the length, and have your receiver ready for an expected block.

_read function is returning obsolete values for file handle

The block of code here runs fine till the _read function is called, after that it changes the value of file handle variable 'fh' for no reason.
std::string& xLogFile;
std::string& xBuffer;
struct _stat& xStatBuffer)
char *buffer;
buffer = (char *)malloc(sizeof(char) * xStatBuffer.st_size);
#define _O_RDONLY 0x0000 /* open for reading only */
int fh = 0, read_bytes =0;
fh = _open(xLogFile.c_str(), _O_RDONLY); // ToDo function deprecated should be changed to fstream
if (fh ==1)
{
if (mWriteLog) IntPkgUtil::TraceLog("Error!! Couldn't open the log file");
return true;
}
read_bytes = _read(fh,&buffer,xStatBuffer.st_size);
_close(fh);
if (read_bytes <= 0)
{
if (mWriteLog) IntPkgUtil::TraceLog("Error!! Couldn't read the log file");
return true;
}
buffer[read_bytes] = '\0';
xBuffer = buffer;
This is a block of code i am using to read from a file into a buffer, but it is failing at the _read function, where the value of file handle 'fh' changes after the call to the function.
Fix the code as below, buffer and not &buffer. You are overwriting the stack.
read_bytes = _read(fh,buffer,xStatBuffer.st_size);

Wrong value of UID in stat() and wrong pr_pid in psinfo_t

My function reads process list from /proc, then read process psinfo file into proper sturcture, as well as data about this file, and prints it.
The problem is, some of the data in those structures is wrong. As usual, the moment when program partially works, is the most confusing. It reads all data correct, except for PID (pr_pid), which is always 0, and UID of a file, which is also always 0. Why? Is it possible for data to load partially correctly? That shouldn't be possible.. 0 would be possible if we were talking about PPID, but solaris documentation clearly states pr_pid is the PID.
Links which I thought would have answers, but I couldn't find one:
http://docs.oracle.com/cd/E19963-01/html/821-1473/proc-4.html
http://linux.die.net/man/3/getpwnam
http://linux.die.net/man/2/stat
code:
void printProcessInformation(char pid[]){
//find full path name to your "stat" file
//DIR *dir;
//struct dirent *ent;
//Creating string with /proc/PID
char * s = malloc(snprintf(NULL, 0, "%s%s", "/proc/", pid) + 1);
sprintf(s, "%s%s", "/proc/", pid);
//Creating string with /proc/PID/psinfo (full path)
char * fullPath = malloc(snprintf(NULL, 0, "%s%s", s, "/psinfo") + 1);
sprintf(fullPath, "%s%s", s, "/psinfo");
free(s);
//printf("%s\n",fullPath);
//Reading data from file
FILE* file = fopen(fullPath, "r");
char* buffer;
buffer = (char*) malloc(sizeof(psinfo_t));
if(file == NULL)
{
perror("Error: Couldn't open file");
return;
}
fread((void *)buffer, sizeof(psinfo_t), 1, file);
psinfo_t* pData = (psinfo_t*) buffer;
free(buffer);
buffer = (char*) malloc(sizeof(stat));
stat(file,buffer);
struct stat* fileStat=(struct stat*) buffer;
printf("File owner id:%d\n",fileStat->st_uid);
free(buffer);
fclose(file);
struct passwd* pw=getpwuid(fileStat->st_uid);
//Loading data from structures
time_t sTime=pData->pr_start.tv_sec;
int pr_pid=pData->pr_pid;
char* fname=pData->pr_fname;
char* uid=pw->pw_name;
printf("%8s %5d %16s %.24s\n", uid, pr_pid, fname, ctime(&sTime));
}
Look at this:
psinfo_t* pData = (psinfo_t*) buffer;
free(buffer);
...
int pr_pid=pData->pr_pid;
You're setting pData to the contents of buffer in the first line and then freeing it. What pData points to is now lost to you, it may in fact be reused in the next malloc. When you try to use it in the last line above you're reading who knows what. You're freeing too agressively in this case. Don't free pData, (indirectly through buffer) until you're done using it.

How to read pkcs#7 file properly

I have a file with detached pkcs#7 signature of size 267 bytes. I create it after executing
CryptSignMessage(
&SigParams,
TRUE,
1,
MessageArray,
MessageSizeArray,
pbSignedMessageBlob,
&cbSignedMessageBlob)
function and then I write content of pbSignedMessageBlob:
pbSignedMessageBlob[cbSignedMessageBlob] = '\0';
FILE *file;
file = fopen("c:\\path\\sign_pkcs7.pk7", "wb");
fwrite(pbSignedMessageBlob, sizeof(BYTE), cbSignedMessageBlob, file);
fclose(file);
Then I try to verify this signature and read this file:
BYTE *pkcsContent;
FILE *file3;
file3 = fopen("c:\\users\\timur\\desktop\\sign_pkcs7.pk7", "rb");
pkcsContent = MyReadFile(file3, cbArray);
BYTE* MyReadFile(FILE *f, DWORD &len)
{
size_t result;
BYTE *buffer;
if (f == NULL)
{
fputs ("File error", stderr);
exit (1);
}
fseek (f, 0, SEEK_END);
len = ftell (f);
rewind (f);
//buffer = (BYTE*) malloc (sizeof(char)*lSize);
buffer = new BYTE[len + 1];
if (buffer == NULL)
{
fputs ("Memory error", stderr);
exit (2);
}
result = fread (buffer, 1, len, f);
if (result != len)
{
fputs ("Reading error",stderr);
exit (3);
}
buffer[len] = '\0';
fclose (f);
return buffer;
}
But the file content I get into pkcsContent is only 37 bytes length.
I also tried to manage files using std::fstream, but result is the same. Maybe the way I'm writing file to disk is wrong?
Are you trying to compute the length of pkcsContent with strlen (this is my guess since you're null-terminating the buffer in MyReadFil)? You can't do that because PKCS#7 is binary data and it can contain 0 anywhere.

How do I extract a user stream from a WinDbg extension?

I have embedded a custom stream in a dump (i.e. passed the UserStreamParam argument to MiniDumpWriteDump function). Now, I'm trying to extract the stream from a WinDbg extension. (Note that I have verified that I can retrieve the stream using the MiniDumpReadDumpStream function).
I'm using the IDebugAdvanced2::Request method with DEBUG_REQUEST_READ_USER_MINIDUMP_STREAM request. I am able to retrieve data from standard streams. For example, the following snippet will correctly retrieve the contents of the misc info stream.
DEBUG_READ_USER_MINIDUMP_STREAM rums = {};
rums.StreamType = MiscInfoStream;
rums.Buffer = &buf;
rums.BufferSize = sizeof buf;
hr = p->Request(DEBUG_REQUEST_READ_USER_MINIDUMP_STREAM,
&rums, sizeof rums, 0, 0, 0);
However, trying to retrieve my own stream will result in an error (0x80070570, ERROR_FILE_CORRUPT) and WinDbg outputs
Dir entry 11, ??? stream has unknown stream type 6381921
Note that the same message appears as a part of the .dumpdebug output.
Stream 11: type ??? (6381921), size 00000038, RVA 00033FA9
Dir entry 11, ??? stream has unknown stream type 6381921
What is the problem? How do I retrieve contents of my user stream?
very late answer
StreamType cannot be UserDefined StreamTypes
jen-lung chiu of ms posted so in osronline windbg lists long back
do not know if the latest dbgeng has this limitation eliminated
you either retrieve it with a dbghelp function independently
(using dbghelp functions inside windbg extensions are not recommended )
or parse the stream yourself with fopen() fread() like below
userstream:\>type ..\usrstr.cpp
#include <stdio.h>
#include <engextcpp.hpp>
#include <dbghelp.h>
const ULONG MBUFFSIZE = 0x1000;
PVOID Buff = 0;
int __cdecl ReadUserStream (char *dmpfile)
{
PMINIDUMP_HEADER MiniHeader = 0;
PMINIDUMP_DIRECTORY MiniDir = 0;
PMINIDUMP_USER_STREAM userstream = 0;
size_t result = 0;
ULONG Streams =0;
ULONG i = 0;
FILE * fp = fopen(dmpfile,"rb");
if (fp)
{
result = fread(Buff, 1, sizeof(MINIDUMP_HEADER), fp );
if ( result == sizeof(MINIDUMP_HEADER) )
{
MiniHeader = (PMINIDUMP_HEADER) Buff;
Streams = MiniHeader->NumberOfStreams;
for (i = 0; i < Streams; i++ )
{
result = fread( Buff, 1, sizeof(MINIDUMP_DIRECTORY), fp );
if ( result == sizeof(MINIDUMP_DIRECTORY) )
{
MiniDir = (PMINIDUMP_DIRECTORY) Buff;
if ( MiniDir->StreamType > LastReservedStream )
{
userstream = (PMINIDUMP_USER_STREAM)Buff;
ULONG savedbuffsize = userstream->BufferSize;
ULONG savedtype = userstream->Type;
PCHAR savedbufferptr = (PCHAR)userstream->Buffer;
long pos = ftell(fp);
fseek(fp, (long)savedbufferptr,SEEK_SET);
result = fread( Buff, 1, savedbuffsize, fp );
if ( result == savedbuffsize )
{
printf(
"\n"
"Datastream Type = %.8x\n"
"Buffer Size = %.8x\n"
"Buffer = %p\n"
"Buffer content = %s\n"
"\n",
savedtype,
savedbuffsize,
savedbufferptr,
Buff
);
fseek(fp,pos,SEEK_SET);
continue;
}
else
{
printf(
"failed to read buffer contents at offset %p of
user stream %x\n",
savedbufferptr,
savedtype);
fseek(fp,pos,SEEK_SET);
continue;
}
}
}
else
{
printf("failed to fread Minidump directory exiting \n");
goto getout;
}
}
}
else
{
printf("failed to fread Minidump header exiting \n");
goto getout;
}
}
else
{
printf("failed to open dmp file exiting \n");
goto getout;
}
getout:
if (fp)
fclose(fp);
return 0;
}
int __cdecl main (int argc, char * argv[])
{
if (argc !=2)
{
printf("Usage %s %s\n",argv[0],"somedump.dmp");
return 0;
}
Buff = malloc( MBUFFSIZE );
if (Buff)
{
ReadUserStream(argv[1]);
free(Buff);
return 0;
}
else
{
printf("malloc failed exiting\n");
return 0;
}
}
output from an userdump that has userStreams in it
(oleg staradumov debuginfo.com writeuserstream.cpp )
userstream:\>usrstr.exe
Usage usrstr.exe somedump.dmp
userstream:\>usrstr.exe test.dmp
Datastream Type = 00010000
Buffer Size = 00000021
Buffer = 000010B6
Buffer content = This is the first data stream...
Datastream Type = 00010001
Buffer Size = 00000023
Buffer = 000010D7
Buffer content = and this is the second data stream
I found this topic while looking for a method to read out user stream from the dbg file.
#blabb 's answer is correct in basics and helped me a lot, but it has a two flaws:
You should use the MINIDUMP_HEADER.StreamDirectoryRva to locate the MINIDUMP_DIRECTORY list.
You should not convert the MINIDUMP_DIRECTORY entry to MINIDUMP_USER_STREAM, because that's an error (MINIDUMP_USER_STREAM is a bigger struct than MINIDUMP_DIRECTORY, so you are reading uninitialized memory there) Use the MINIDUMP_DIRECTORY to locate the needed part of the stream.
Even if not tested, it should work if you fill StreamType with a custom value (greater than LastReservedStream = 0xFFFF) instead of MiscInfoStream.