Size is always zero when reading DRM EDID file - c++

I tried to read the EDID of my monitor connected to LVDS1. I use ArchLinux and C++/clang. My problem is: the file size always returns 0. I don't know if this is a programming problem or something OS specific, other files return a proper file size. Is it a special file? Is the symlink directory /sys/class/drm/card0-DP-1 the problem?
file: /sys/class/drm/card0-LVDS-1/edid
code:
#include <fstream>
#include <iostream>
using namespace std;
typedef unsigned char BYTE;
long
get_file_size(FILE *f)
{
long pos_cursor, pos_end;
pos_cursor = ftell(f);
fseek(f, 0, 2);
pos_end = ftell(f);
fseek(f, pos_cursor, 0);
return pos_end;
}
int
main()
{
const char *filepath = "/sys/class/drm/card0-LVDS-1/edid";
FILE *file = NULL;
if((file = fopen(filepath, "rb")) == NULL)
{
cout << "file could not be opened" << endl;
return 1;
}
else
cout << "file opened" << endl;
long filesize = get_file_size(file);
cout << "file size: " << filesize << endl;
fclose(file);
return 0;
}
output:
file opened
file size: 0
===
as suggested by MSalters, I tried stat for the file size. Also returns 0. I assume the code is correct, so it is somehow just not possible to access the file?
I also tried the symlink target path (/sys/devices/pci0000:00/0000:00:02.0/drm/card0/card0-LVDS-1/edid), just in case that was the problem - but still 0.
code:
#include <iostream>
#include <sys/stat.h>
using namespace std;
int
main()
{
const char *filepath = "/sys/class/drm/card0-LVDS-1/edid";
struct stat results;
if (stat(filepath, &results) == 0)
cout << results.st_size << endl;
else
cout << "error" << endl;
return 0;
}
output
0
===
I tried other files in the same directory (dpms edid enabled i2c-6 modes power status subsystem uevent). They all return a filesize of 4096 except edid.

I suspect that fseek(f, 0, 2); might mean fseek(f, 0, SEEK_CUR); which obviously doesn't do anything. You'd want SEEK_END which isn't portable, but then again /sys/ isn't either. (Of course, do #include <stdio.h>)
But considering it's already Linux-specific, why not use stat ?

Related

C++ mincore return vector every byte is 1

I use mincore to judge memory by mmap open in memory or disk. but return a set vector. Why? In fact the result must be a all clear vector, but I get all set.
This is my code. Why is line 28 (cout << "find" << endl;) always skipped?
/proc/pid/smap can see RSS is 0, but mincore return total file in memory.
#include <iostream>
#include <unistd.h>
#include <sys/mman.h>
#include <bitset>
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
using namespace std;
int main()
{
char* pData1 = NULL;
int fd1 = open("test_large_file_1", O_RDWR);
if (fd1 == -1)
{
cout << "file error ..." << endl;
return -1;
}
off_t size1 = lseek(fd1, 0, SEEK_END);
if (size1 == -1)
{
cout << "lseek error ..." << endl;
return -1;
}
pData1 = (char *)mmap(NULL, size1, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd1, 0 );
if (pData1 == MAP_FAILED)
{
cout << "mmap error ..." << endl;
return -1;
}
unsigned char *pVec = new unsigned char[size1 / 1024 / 4];
if (-1 == mincore(pData1, size1, pVec))
{
cout << "mincore error ..." << endl;
return -1;
}
for (int i = 0; i < size1 / 1024/ 4; ++i)
{
if (i % 1000 == 0)
cout << (int)pVec[i] << endl;
if ((pVec[i] & 1) == 0)
{
cout << "find" << endl;
break;
}
}
close(fd1);
munmap((void *)pData1, size1);
return 0;
}
I want to get whether an address by mmap opening in memory or not, veteran has some way?/
I need help.
I get a old file(don't open long time),mincore return a normal vector(has 0 and 1), but a new file(just now open or read ...),mincore return a all set bit vector.
This phenomenon is due to page cache, that will save recently page to cache, if a program repeatly open a file, the page of file will be get in memory .

Write vector of unsigned char to binary file c++

I am reading binary file cmd.exe into unsigned chars array. Total bytes read into bytes_read are 153. I converted it to base64 string and then decode this string back (code from 2nd answer base64 decode snippet in c++) into vector<'BYTE>. Here BYTE is unsigned char.
decodedData.size() is also 153. But when I write this vector to file in binary mode to get my cmd.exe file again I get only 1 KB file. What thing I missed?
// Reading size of file
FILE * file = fopen("cmd.exe", "r+");
if (file == NULL) return 1;
fseek(file, 0, SEEK_END);
long int size = ftell(file);
fclose(file);
// Reading data to array of unsigned chars
file = fopen("cmd.exe", "r+");
unsigned char * myData = (unsigned char *)malloc(size);
int bytes_read = fread(myData, sizeof(unsigned char), size, file);
fclose(file);
std::string encodedData = base64_encode(&myData[0], bytes_read);
std::vector<BYTE> decodedData = base64_decode(encodedData);
////write data to file
ofstream outfile("cmd.exe", ios::out | ios::binary);
outfile.write((const char *)decodedData.data(), decodedData.size());
Update:
Thanks #chux for suggesting "r+" --> "rb+" Problem resolved.
You marked this as C++.
This is one C++ approach using fstream to read a binary file. To simplify for this example, I created a somewhat bigger m_buff than needed. From the comments, it sounds like your fopen("cmd.exe", "r+") was in error, so I'm only providing a C++ binary read.
Method tReader() a) opens a file in binary mode, b) reads the data into m_buff, and c) captures gCount for display.
It also demonstrates one possible use of chrono to measure duration.
#include <chrono>
// 'compressed' chrono access --------------vvvvvvv
typedef std::chrono::high_resolution_clock HRClk_t;
typedef HRClk_t::time_point Time_t;
typedef std::chrono::microseconds US_t;
using namespace std::chrono_literals; // suffixes 100ms, 2s, 30us
#include <iostream>
#include <fstream>
#include <cassert>
class T516_t
{
enum BuffConstraints : uint32_t {
Meg = (1024 * 1024),
END_BuffConstraints
};
char* m_buff;
int64_t m_gCount;
public:
T516_t()
: m_buff (nullptr)
, m_gCount (0)
{
m_buff = new char[Meg];
}
~T516_t() = default;
int exec()
{
tReader();
return(0);
}
private: // methods
void tReader()
{
std::string pfn = "/home/dmoen/.wine/drive_c/windows/system32/cmd.exe";
// open file in binary mode
std::ifstream sIn (pfn, std::ios_base::binary);
if (!sIn.is_open()) {
std::cerr << "UNREACHABLE: unable to open sIn " << pfn
<< " priviledges? media offline?";
return;
}
Time_t start_us = HRClk_t::now();
do
{
// perform read
sIn.read (m_buff, Meg);
// If the input sequence runs out of characters to extract (i.e., the
// end-of-file is reached) before n characters have been successfully
// read, buff contains all the characters read until that point, and
// both eofbit and failbit flags are set
m_gCount = sIn.gcount();
if(sIn.eof()) { break; } // exit when no more data
if(sIn.failbit ) {
std::cerr << "sIn.faileBit() set" << std::endl;
}
}while(1);
auto duration_us = std::chrono::duration_cast<US_t>(HRClk_t::now() - start_us);
sIn.close();
std::cout << "\n " << pfn
<< " " << m_gCount << " bytes"
<< " " << duration_us.count() << " us"
<< std::endl;
} // int64_t tReader()
}; // class T516_t
int main(int , char**)
{
Time_t start_us = HRClk_t::now();
int retVal = -1;
{
T516_t t516;
retVal = t516.exec();
}
auto duration_us = std::chrono::duration_cast<US_t>(HRClk_t::now() - start_us);
std::cout << " FINI " << duration_us.count() << " us" << std::endl;
return(retVal);
}
One typical output on my system looks like:
/home/dmoen/.wine/drive_c/windows/system32/cmd.exe 722260 bytes 1180 us
FINI 1417 us
Your results will vary.
Your ofstream use looks good (so did not replicate).

stringstream doesn't clean up completely?

I'm working on what will be a pretty large and complicated system and trying to make sure it's as watertight as possible right from the start. Whilst running some memory checks, I noticed something odd when using stringstreams: they don't always seem to release all the memory when they get deleted/go out of scope.
I've tried searching the internet for answers, but most are old (so possibly out of date) and/or are more concerned with refreshing the contents than releasing the memory, so I've not really been able to tell if it's a known issue or a common mistake I'm making.
I've written a simple test to show what's going on:
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
using namespace std;
float getMemUsage(int& pid)
{
if (pid < 0)
pid = getpid();
char buf[30];
snprintf(buf, 30, "/proc/%u/statm", (unsigned)pid);
FILE* pf = fopen(buf, "r");
if (pf)
{
unsigned size; // total program size
//unsigned resident;// resident set size
//unsigned share;// shared pages
//unsigned text;// text (code)
//unsigned lib;// library
//unsigned data;// data/stack
//unsigned dt;// dirty pages (unused in Linux 2.6)
fscanf(pf, "%u" /* %u %u %u %u %u"*/, &size/*, &resident, &share, &text, &lib, &data*/);
fclose(pf);
return size/1024.0;
}
else
return -1.0;
}
int main(int argc, char* argv[])
{
if (argc < 2)
cerr << "no file specified\n";
ifstream file;
file.open(argv[1]);
int pid = -1;
const float memUseAtStart = getMemUsage(pid);
{
float memUseBefore = getMemUsage(pid);
stringstream sstream;
float memUseAfter = getMemUsage(pid);
cerr << "\tMemory use change after stringstream declaration: " << memUseAfter - memUseBefore << endl;
memUseBefore = getMemUsage(pid);
filebuf* pbuf = file.rdbuf();
memUseAfter = getMemUsage(pid);
cerr << "\tMemory use change after getting file buffer: " << memUseAfter - memUseBefore << endl;
memUseBefore = getMemUsage(pid);
sstream << pbuf;
memUseAfter = getMemUsage(pid);
cerr << "\tMemory use change after copying file contents: " << memUseAfter - memUseBefore << endl;
memUseBefore = getMemUsage(pid);
sstream.clear();
sstream.str( string() );
memUseAfter = getMemUsage(pid);
cerr << "\tMemory use change after 'clearing': " << memUseAfter - memUseBefore << endl;
}
cerr << "Overall memory use change: " << getMemUsage(pid) - memUseAtStart << endl;
file.close();
return 0;
}
Which gives me the following output when called with a file larger than around 32K:
Memory use change after stringstream declaration: 0
Memory use change after getting file buffer: 0
Memory use change after copying file contents: 0.0322266
Memory use change after 'clearing': 0
Overall memory use change: 0.00195312
I'm running on Linux (SL6.6) and compiling with gcc 4.1.2 (though I've also tried clang and ICC with similar results).
Obviously, it's not a huge leak; it's just a little annoying that I can't make it completely tidy... Is there something I can/should do to release the memory manually? Or is it just something weird (with my setup and/or stringstream itself) I'll have to live with?
NB The intended use for the stringstream is to read in some file contents above and then parse them line by line; I would try using istringstream but I couldn't figure out how to set its value from the ifstream...
Thanks!

mprotect and file handles

I have this simple program where I am trying to protect a block of memory, and then read a file into that memory, releasing it when it segfaults..
first I thought there was only a problem if the file is a fifo.. but now it seems that even for a normal file it fails,
this is the code:
#include <errno.h>
#include <string.h>
#include <iostream>
#include <assert.h>
#include <malloc.h>
#include <sys/mman.h>
#include <unistd.h>
#include <map>
#include <algorithm>
#include <unistd.h>
#include <signal.h>
using namespace std;
#define BUFFER_SIZE 8000
#define handle_error(msg) \
do { cout << __LINE__ << endl ;perror(msg); exit(EXIT_FAILURE); } while (0)
volatile int fault_count = 0;
char* buffer = 0;
int size = 40960;
int my_fault_handler(void* addr, int serious) {
if (mprotect(buffer, size,
PROT_READ | PROT_WRITE) == -1)
handle_error("mprotect");
++fault_count;
cout << "Segfaulting" << endl;
return 1;
}
static void handler(int sig, siginfo_t *si, void *unused) {
my_fault_handler(si ->si_addr, sig);
}
int main (int argc, char *argv[])
{
long pagesize = sysconf(_SC_PAGESIZE);
struct sigaction sa;
sa.sa_flags = SA_SIGINFO | SA_NOCLDWAIT;
sigemptyset(&sa.sa_mask);
sa.sa_sigaction = &handler;
if (sigaction(SIGSEGV, &sa, NULL) == -1)
perror("sigaction");
cerr << "pageSize: " << pagesize << endl;
buffer = (char*)memalign(pagesize, size);
if (buffer == NULL)
handle_error("memalign");
if (mprotect(buffer, size, PROT_READ) == -1)
handle_error("mprotect");
FILE* file = fopen("test", "r");
cout << "File Open" << endl;
if (!file) {
cout << "Failed opening file " << strerror(errno) << endl;
return 0;
}
//*buffer = 0;
while(fread(buffer, pagesize*2, 1, file)) {
if (mprotect(buffer, size,
PROT_READ) == -1)
handle_error("mprotect");
}
cout << ' ' << strerror(errno) << endl;
return(0);
}
note the //*buffer = 0;, if I unmark this line the program segfaults and works correctly..
anyone has any idea?
the errno is bad address.
Thanks!
UPDATE:
It seems a similiar question was asked here:
Loading MachineCode From File Into Memory and Executing in C -- mprotect Failing
where posix_memalign was suggested, I have tried this and it didn't work.
The problem is that you're not checking for an error in the FILE handle after a short read.
What the system would tell you is that the first fread failed and didn't trigger the fault handler.
If you checked for ferror outside the loop (sloppy as an example):
while(fread(buffer, pagesize*2, 1, file)) {
if (mprotect(buffer, size,
PROT_READ) == -1)
handle_error("mprotect");
}
if (ferror(file) != 0) {
cout << "Error" << endl;
}
Why it failed is that the underlying read failed, and returned an errno of 14 (EFAULT), which is not quite what is documented to happen when read fails in this situation (it says that Buf points outside the allocated address space.)
You can only trust the signal handler to be triggered in the mprotect case when the code in question is running in the user context, most system calls will fail and return EFAULT in the case that the buffer is invalid or does not have the correct permissions.

fwrite fails on big data

Hey just try to compile an image in code and put it out as jpg again but fwrite returns 0 and img.jpg keeps empty :(
#include <stdio.h>
#include <string>
#include <iostream>
size_t count = 76830;//=length of data
const uint8_t data[] = {0xff,0xd8,0xff,0xe0,0x0,0x10,0x4a,0x46,0x49,0x46.....
0x0,0x7f,0xff,0xd9};
using namespace std;
//use this to saveToFile...
void saveToFile(const char * filename) {
FILE * file = fopen(filename, "rb");
if (file == NULL) {
std::cout << "error opening file" << std::endl;
return;
}
cout << endl << fwrite(data, sizeof(uint8_t), sizeof(data), file); //this line returns 0!!!
fclose(file);
}
int main () {
saveToFile("img.jpg");
}
fopen(filename, "rb");
This opens the file for reading, not writing. You want
fopen(filename, "wb");
// ^