how to determine USN_RECORD version for usn journal? - ntfs-mft

I want to learn the principle of everything, and use usn logs to monitor the addition and deletion of system files.
I wrote a piece of code under windows11, VS2019, Platform Toolset= (v142).
But I found that record->Reason (USN_RECORD) always returns 0; also, if I delete a file, I monitor that it is a garbled file name with $. For example, if I delete the file "ABC.TXT", I monitor and detect that a file name like "$1a2f5.txt" is returned. After I googled, I found that it is because USN_RECORD has multiple versions, V2, V3, V4, but I don't know how to detect the version number.
Here is the code:
#ifndef VC_EXTRALEAN
#define VC_EXTRALEAN // 从 Windows 头中排除极少使用的资料
#endif
#include <Windows.h>
#include <stdio.h>
#include <string>
#include <iostream>
#include "usn_test.h"
//#define BUFFER_SIZE (1024 * 1024)
constexpr auto BUFFER_SIZE = sizeof(USN) + 0x100000;
HANDLE drive;
USN maxusn;
DWORDLONG gUsnJournalID;
void delete_usn()
{
DELETE_USN_JOURNAL_DATA dujd;
dujd.UsnJournalID = gUsnJournalID;
dujd.DeleteFlags = USN_DELETE_FLAG_DELETE;
DWORD br;
if (DeviceIoControl(drive,
FSCTL_DELETE_USN_JOURNAL,
&dujd,
sizeof(dujd),
nullptr,
0,
&br,
nullptr)
)
{
CloseHandle(drive);
return;
}
CloseHandle(drive);
return;
}
template<typename _T_USN_RECORD>
void check_record(_T_USN_RECORD* record)
{
WCHAR szName[MAX_PATH];
CopyMemory(szName,
((PBYTE)record) + record->FileNameOffset,
record->FileNameLength);
szName[record->FileNameLength / sizeof(WCHAR)] = 0;
std::wcout << szName << L",Reason:" << record->Reason << std::endl;
}
template<>
void check_record(USN_RECORD_V4* record)
{
WCHAR szName[MAX_PATH];
CopyMemory(szName,
((PBYTE)record) + record->Extents->Offset,
record->Extents->Length);
// Let's zero-terminate it
szName[record->Extents->Length / sizeof(WCHAR)] = 0;
std::wcout << szName << L",Reason:" << record->Reason << std::endl;
}
bool create_usn()
{
CREATE_USN_JOURNAL_DATA cujd{};
cujd.MaximumSize = 0; // 0表示使用默认值
cujd.AllocationDelta = 0; // 0表示使用默认值
DWORD br;
if (
DeviceIoControl(drive, // handle to volume
FSCTL_CREATE_USN_JOURNAL, // dwIoControlCode
&cujd, // input buffer
sizeof(cujd), // size of input buffer
nullptr, // lpOutBuffer
0, // nOutBufferSize
&br, // number of bytes returned
nullptr) // OVERLAPPED structure
)
{
return true;
}
auto&& info = "create usn error. Error code: " + std::to_string(GetLastError());
fprintf(stderr, "fileSearcherUSN: %s\n", info.c_str());
return false;
}
template<typename _T_USN_RECORD>
void read_record(DWORDLONG& nextid, void* buffer, _T_USN_RECORD*& record, _T_USN_RECORD*& recordend, const DWORD& bytecount)
{
nextid = *((DWORDLONG*)buffer);
// printf("Next ID: %lu\n", nextid);
record = (_T_USN_RECORD*)((USN*)buffer + 1);
recordend = (_T_USN_RECORD*)(((BYTE*)buffer) + bytecount);
while (record < recordend)
{
check_record(record);
record = (_T_USN_RECORD*)(((BYTE*)record) + record->RecordLength);
}
}
template<>
void read_record(DWORDLONG& nextid, void* buffer, USN_RECORD_V4*& record, USN_RECORD_V4*& recordend, const DWORD& bytecount)
{
nextid = *((DWORDLONG*)buffer);
// printf("Next ID: %lu\n", nextid);
record = (USN_RECORD_V4*)((USN*)buffer + 1);
recordend = (USN_RECORD_V4*)(((BYTE*)buffer) + bytecount);
while (record < recordend)
{
//check_record(record);
record = (USN_RECORD_V4*)(((BYTE*)record) + record->Header.RecordLength);
}
}
int main(int argc, char** argv)
{
//typedef USN_JOURNAL_DATA_V2 USN_JOURNAL_DATA;
#define FILE_END 38
//typedef MFT_ENUM_DATA MFT_ENUM_DATA_V1;
MFT_ENUM_DATA mft_enum_data;
DWORD bytecount = 1;
void* buffer;
USN_RECORD_V3* recordV3;
USN_RECORD_V3* recordendV3;
USN_RECORD_V4* recordV4;
USN_RECORD_V4* recordendV4;
USN_JOURNAL_DATA* journal;
DWORDLONG nextid{};
buffer = new BYTE[BUFFER_SIZE];
if (buffer == NULL)
{
printf("VirtualAlloc: %u\n", GetLastError());
return 0;
}
printf("Opening volume.\n");
drive = CreateFile(L"\\\\?\\h:", GENERIC_READ, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_FLAG_NO_BUFFERING, NULL);
if (drive == INVALID_HANDLE_VALUE)
{
printf("CreateFile: %u\n", GetLastError());
return 0;
}
if (!create_usn())
{
return -1;
}
printf("Calling FSCTL_QUERY_USN_JOURNAL\n");
if (!DeviceIoControl(drive, FSCTL_QUERY_USN_JOURNAL, NULL, 0, buffer, BUFFER_SIZE, &bytecount, NULL))
{
printf("FSCTL_QUERY_USN_JOURNAL: %u\n", GetLastError());
return 0;
}
// delete_usn();
journal = (USN_JOURNAL_DATA*)buffer;
gUsnJournalID = journal->UsnJournalID;
printf("UsnJournalID: %lu\n", journal->UsnJournalID);
printf("FirstUsn: %lu\n", journal->FirstUsn);
printf("NextUsn: %lu\n", journal->NextUsn);
maxusn = journal->MaxUsn;
mft_enum_data.StartFileReferenceNumber = 0;
mft_enum_data.LowUsn = 0;
mft_enum_data.HighUsn = maxusn;
mft_enum_data.MaxMajorVersion = journal->MaxSupportedMajorVersion;
mft_enum_data.MinMajorVersion = journal->MinSupportedMajorVersion;
for (;;)
{
// printf("=================================================================\n");
// printf("Calling FSCTL_ENUM_USN_DATA\n");
if (!DeviceIoControl(drive, FSCTL_ENUM_USN_DATA, &mft_enum_data, sizeof(mft_enum_data), buffer, BUFFER_SIZE, &bytecount, NULL))
{
auto bRet = GetLastError();
if (bRet != 38)
{
delete_usn();
break;
}
if (bRet == 38)//file to end
{
// break;
Sleep(1000);//wait for new file change
auto oldNextUsn = journal->NextUsn;
if (!DeviceIoControl(drive, FSCTL_QUERY_USN_JOURNAL, NULL, 0, buffer, BUFFER_SIZE, &bytecount, NULL))
{
printf("FSCTL_QUERY_USN_JOURNAL: %u\n", GetLastError());
return 0;
}
journal = (USN_JOURNAL_DATA*)buffer;
if (journal->NextUsn > oldNextUsn)//new file have changed
{
mft_enum_data.StartFileReferenceNumber = 0;
mft_enum_data.LowUsn = oldNextUsn;
mft_enum_data.HighUsn = journal->MaxUsn;
mft_enum_data.MaxMajorVersion = journal->MaxSupportedMajorVersion;
mft_enum_data.MinMajorVersion = journal->MinSupportedMajorVersion;
}
continue;
}
}
// printf("Bytes returned: %u\n", bytecount);
if(mft_enum_data.MinMajorVersion == 4)//it's wrong if i determine version by mft_enum_data.MaxMajorVersion
read_record(nextid, buffer, recordV4, recordendV4, bytecount);
else
read_record(nextid, buffer, recordV3, recordendV3, bytecount);
mft_enum_data.StartFileReferenceNumber = nextid;
}
delete[] buffer;
delete_usn();
}
I have spent 2 weeks for this.google and write a test.day and day.

Related

Simple webserver unable to refetch web page. Page includes html and large css file like stat.st_size=22926

I have created a simple webserver, but I am unable to re-fetch the page twice. In server code my intention was to fetch as many times as the user prefers. I am fetching the page in Firefox browser. I am not saying there is anything wrong with the browser, but there may be problems with my code. So can anyone please tell me what could be the reason that my server is unable to render the page and css again. Is there any mistake in the response header? Why is browser unable to fetch the page?
This is the code:
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
//aaa
#define PORT 5000
#define BUF_SIZE 20000
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
int min(int a, int b)
{
return a>b?b:a;
}
int process(int size,char buffer[size],char status)
{
int i=0;
int line_len=0;
char *line=malloc(sizeof(char) *150);
while(i<size)
{
if(strncmp((void *)&buffer[i],"style9.css",strlen("style9.css"))==0)
return 3;
if(strncmp((void *)&buffer[i],"GET / HTTP/1.1",14)==0)
{
while(buffer[i]!='\n')
{
line[line_len]=buffer[i];
line_len++;
i++;
}
//line[line_len]='\0';
//printf("%s\n",line);
memset(line,0,line_len);
line_len=0;
return 2;
}
i++;
line_len++;
}
return 2;
}
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count)
{
off_t orig;
if (offset != NULL) {
/* Save current file offset and set offset to value in '*offset' */
orig = lseek(in_fd, 0, SEEK_CUR);
if (orig == -1)
return -1;
if (lseek(in_fd, *offset, SEEK_SET) == -1)
return -1;
}
size_t totSent = 0;
while (count > 0) {
size_t toRead = min(BUF_SIZE, count);
char buf[BUF_SIZE];
ssize_t numRead = read(in_fd, buf, toRead);
if (numRead == -1)
return -1;
if (numRead == 0)
break; /* EOF */
ssize_t numSent = write(out_fd, buf, numRead);
if (numSent == -1)
return -1;
if (numSent == 0) /* Should never happen */
printf("fatal: should never happen");
//fatal("sendfile: write() transferred 0 bytes");
count -= numSent;
totSent += numSent;
}
if (offset != NULL) {
/* Return updated file offset in '*offset', and reset the file offset
to the value it had when we were called. */
*offset = lseek(in_fd, 0, SEEK_CUR);
if (*offset == -1)
return -1;
if (lseek(in_fd, orig, SEEK_SET) == -1)
return -1;
}
return totSent;
}
int main(int argc, char const *argv[])
{
int server_fd, new_socket, valread;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[1000] = {0};
int get_return321;
//GET /css/style.css HTTP/1.1
char *hello = "HTTP/1.1 200 Okay\r\nContent-Type: text/html; charset=ISO-8859-4 \r\n\r\n";
//"HTTP/1.1 200 OK\\r\\n" \
"Content-Length: 55\r\n\n Content-Type: application/json\r\n '{\"name\":\"fawad\"}'";
//struct stat sb;
char *hello1 = "HTTP/1.1 200 Okay\r\nContent-Type: text/css\r\n\r\n";
struct stat sb_html;
struct stat sb_css;
int fd_in_html=open("/home/fawad/Desktop/C-work/html9.html",O_RDONLY);
const char* filename_html="/home/fawad/Desktop/C-work/html9.html";
int fd_in_css=open("/home/fawad/Desktop/C-work/css/style9.css",O_RDONLY);
const char* filename_css="/home/fawad/Desktop/C-work/css/style9.css";
if (stat(filename_html, &sb_html) == -1)
{
printf("%d\n",errno);
//exit(EXIT_FAILURE);
}
if (stat(filename_css, &sb_css) == -1)
{
printf("%d\n",errno);
//exit(EXIT_FAILURE);
}
printf("%lu\n",sb_css.st_size);
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
{
perror("socket failed");
//exit(EXIT_FAILURE);
}
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,&opt, sizeof(opt)))
{
perror("setsockopt");
//exit(EXIT_FAILURE);
}
/*if( setsockopt(server_fd, SOL_SOCKET, SO_SNDBUF, &sb.st_size, sizeof(sb.st_size)))
{
printf("sockopt\n");
}*/
/*int state = 1;
if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &state, sizeof(state)))
{
printf("sockopt\n");
}*/
int state = 1;
if(setsockopt(server_fd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state)))
{
printf("TCP CORK\n");
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( PORT );
if (bind(server_fd, (struct sockaddr *)&address,sizeof(address))<0)
{
perror("bind failed");
//exit(EXIT_FAILURE);
}
if (listen(server_fd, 3) < 0)
{
perror("listen");
//exit(EXIT_FAILURE);
}
while(1)
{
printf("in loop\n");
if ((new_socket = accept(server_fd, (struct sockaddr *)&address,
(socklen_t*)&addrlen))<0)
{
// exit(EXIT_FAILURE);
}
printf("request came\n");
valread = read( new_socket , buffer, (1000));
//printf("%s\n",buffer );
printf("_________________________________\n");
get_return321=process(900,buffer,'r');
buffer[499]='\0';
printf("\n");
printf("\n");
if(get_return321==2)
{
send(new_socket , hello , strlen(hello) , 0 );
//send(new_socket , buffer_html , sb_html.st_size , 0 );
sendfile(new_socket,fd_in_html,0,sb_html.st_size);
printf("html sent\n");
}
if(get_return321==3)
{
send(new_socket , hello1 , sb_css.st_size , 0 );
sendfile(new_socket,fd_in_css,0,sb_css.st_size);
printf("3 reached\n");
}
close(new_socket);
state = 0;
setsockopt(server_fd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state));
//close(new_socket);
state = 1;
setsockopt(server_fd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state));
}
//close(fd_in);
close(fd_in_html);
}
This is the output of running the program and sending a few requests from browser
user#fawad:Desktop/C-work# ./a.out
22926
in loop
request came
_________________________________
html sent
in loop
request came
_________________________________
3 reached
in loop
request came
_________________________________
html sent
in loop
request came
_________________________________
html sent
in loop
Killed
I have fixed it. I was not closing file descriptors so my current positions always stayed at the end of files in re-fetch attempts from firefox. Now working this is the full working code
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
//aaa
#define PORT 80
#define BUF_SIZE 20000
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
int min(int a, int b)
{
return a>b?b:a;
}
int process(int size,char buffer[size],char status)
{
int i=0;
int line_len=0;
char *line=malloc(sizeof(char) *150);
while(i<size)
{
if(strncmp((void *)&buffer[i],"style9.css",strlen("style9.css"))==0)
return 3;
if(strncmp((void *)&buffer[i],"GET / HTTP/1.1",14)==0)
{
while(buffer[i]!='\n')
{
line[line_len]=buffer[i];
line_len++;
i++;
}
//line[line_len]='\0';
//printf("%s\n",line);
memset(line,0,line_len);
line_len=0;
return 2;
}
i++;
line_len++;
}
return 2;
}
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count)
{
off_t orig;
if (offset != NULL) {
/* Save current file offset and set offset to value in '*offset' */
orig = lseek(in_fd, 0, SEEK_CUR);
if (orig == -1)
return -1;
if (lseek(in_fd, *offset, SEEK_SET) == -1)
return -1;
}
size_t totSent = 0;
while (count > 0) {
size_t toRead = min(BUF_SIZE, count);
char buf[BUF_SIZE];
ssize_t numRead = read(in_fd, buf, toRead);
if (numRead == -1)
return -1;
if (numRead == 0)
break; /* EOF */
ssize_t numSent = write(out_fd, buf, numRead);
if (numSent == -1)
return -1;
if (numSent == 0) /* Should never happen */
printf("fatal: should never happen");
//fatal("sendfile: write() transferred 0 bytes");
count -= numSent;
totSent += numSent;
}
if (offset != NULL) {
/* Return updated file offset in '*offset', and reset the file offset
to the value it had when we were called. */
*offset = lseek(in_fd, 0, SEEK_CUR);
if (*offset == -1)
return -1;
if (lseek(in_fd, orig, SEEK_SET) == -1)
return -1;
}
return totSent;
}
int main(int argc, char const *argv[])
{
int server_fd, new_socket, valread;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[1000] = {0};
int get_return321;
//GET /css/style.css HTTP/1.1
char *hello = "HTTP/1.1 200 Okay\r\nContent-Type: text/html; charset=ISO-8859-4 \r\n\r\n";
//"HTTP/1.1 200 OK\\r\\n" \
"Content-Length: 55\r\n\n Content-Type: application/json\r\n '{\"name\":\"fawad\"}'";
//struct stat sb;
char *hello1 = "HTTP/1.1 200 Okay\r\nContent-Type: text/css\r\n\r\n";
struct stat sb_html;
struct stat sb_css;
int fd_in_html;//=open("/home/fawad/Desktop/C-work/html9.html",O_RDONLY);
const char* filename_html="/home/fawad/Desktop/C-work/html9.html";
int fd_in_css;//=open("/home/fawad/Desktop/C-work/css/style9.css",O_RDONLY);
const char* filename_css="/home/fawad/Desktop/C-work/css/style9.css";
//printf("%lu\n",sb_css.st_size);
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
{
perror("socket failed");
//exit(EXIT_FAILURE);
}
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,&opt, sizeof(opt)))
{
perror("setsockopt");
//exit(EXIT_FAILURE);
}
/*if( setsockopt(server_fd, SOL_SOCKET, SO_SNDBUF, &sb.st_size, sizeof(sb.st_size)))
{
printf("sockopt\n");
}*/
/*int state = 1;
if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &state, sizeof(state)))
{
printf("sockopt\n");
}*/
int state = 1;
if(setsockopt(server_fd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state)))
{
printf("TCP CORK\n");
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( PORT );
if (bind(server_fd, (struct sockaddr *)&address,sizeof(address))<0)
{
perror("bind failed");
//exit(EXIT_FAILURE);
}
if (listen(server_fd, 3) < 0)
{
perror("listen");
//exit(EXIT_FAILURE);
}
while(1)
{
printf("in loop\n");
if ((new_socket = accept(server_fd, (struct sockaddr *)&address,
(socklen_t*)&addrlen))<0)
{
// exit(EXIT_FAILURE);
}
printf("request came\n");
valread = read( new_socket , buffer, (1000));
//printf("%s\n",buffer );
printf("_________________________________\n");
get_return321=process(900,buffer,'r');
buffer[499]='\0';
printf("\n");
printf("\n");
if(get_return321==2)
{
send(new_socket , hello , strlen(hello) , 0 );
//send(new_socket , buffer_html , sb_html.st_size , 0 );
fd_in_html=open("/home/fawad/Desktop/C-work/html9.html",O_RDONLY);
if (stat(filename_html, &sb_html) == -1)
{
printf("%d\n",errno);
//exit(EXIT_FAILURE);
}
sendfile(new_socket,fd_in_html,0,sb_html.st_size);
close(fd_in_html);
printf("html sent\n");
}
if(get_return321==3)
{
send(new_socket , hello1 , sb_css.st_size , 0 );
fd_in_css=open("/home/fawad/Desktop/C-work/css/style9.css",O_RDONLY);
if (stat(filename_css, &sb_css) == -1)
{
printf("%d\n",errno);
//exit(EXIT_FAILURE);
}
sendfile(new_socket,fd_in_css,0,sb_css.st_size);
printf("3 reached\n");
close(fd_in_css);
}
close(new_socket);
state = 0;
setsockopt(server_fd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state));
//close(new_socket);
state = 1;
setsockopt(server_fd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state));
}
//close(fd_in);
close(fd_in_html);
}

StoreProhibitedCause Exception with linked list on ESP8266

I have implemented a linked list class as follows for storage of sensor data readings.
(Note the total code is ~4000 lines so I can't provide it all, hopefully this gives an idea of what's done).
struct DataItem {
String _dataType;
float _dataArray[dataArraySize_const];
float _calibratedData = -1.0;
float _rawData = -1.0;
DataItem *_next;
uint8_t _dataArraySize = dataArraySize_const;
float *_calibrationParameters;
uint8_t _numCalibrationParameters;
};
class DataContainer {
public:
DataContainer() {
_head = NULL;
_tail = NULL;
};
DataItem* addDataItem(String dataTypeIn, float calibrationParameters[10], uint8_t numberOfCalibrationParameters) {
DataItem *temp = new DataItem;
temp->_dataType = dataTypeIn;
temp->_calibratedData = -1.0;
temp->_rawData = -1.0;
for (uint8_t i = 0; i < dataArraySize_const; i++) { temp->_dataArray[i] = 0; } //Setting all the data array to 0
temp->_calibrationParameters = calibrationParameters;
temp->_numCalibrationParameters = numberOfCalibrationParameters;
temp->_next = NULL;
if(_head == NULL) {
_head = temp;
_tail = temp;
temp = NULL;
}
else {
_tail->_next = temp;
_tail = temp;
}
return temp;
};
uint8_t setDataValue(String dataType, float value, uint8_t arrayIndex) {
DataItem *temp = new DataItem;
temp = _head;
Serial.println("Addresses: ");
while(temp != NULL) {
Serial.print("temp address: 0x");
Serial.println((unsigned long)temp, HEX);
Serial.print("head address: 0x");
Serial.println((unsigned long)_head, HEX);
Serial.print("temp add address: 0x");
Serial.println((unsigned long)&temp, HEX);
if (temp->_dataType == dataType) { break; }
else if (temp == NULL) { return 1; }
temp = temp->_next;
}
temp->_dataArray[arrayIndex] = value;
float sum = 0.0;
for (uint8_t i = 0; i < dataArraySize_const; i++) {
sum += temp->_dataArray[i];
}
temp->_rawData = sum/dataArraySize_const;
Serial.println("Pre calibration");
this->calibrate(temp);
Serial.println("Finished calibration");
return 0;
};
void calibrate(DataItem *temp) {
temp->_calibratedData = temp->_calibrationParameters[0];
for (uint8_t i = 1; i <= temp->_numCalibrationParameters; i++) {
temp->_calibratedData += temp->_calibrationParameters[i] * pow(temp->_rawData, i);
}
}
uint8_t setCalibrationParameters(String dataType, float calibrationParameters[10]) {
DataItem *temp = new DataItem;
temp = _head;
while(temp != NULL) {
if (temp->_dataType == dataType) { break; }
else if (temp == NULL) { return 1; }
temp = temp->_next;
}
temp->_calibrationParameters = calibrationParameters;
return 0;
};
private:
DataItem *_head, *_tail;
};
uint8_t numUsedCalibrationParameters = 10;
float calibrationParam[numUsedCalibrationParameters] = {0,1,0,0,0,0,0,0,0,0};
uint8_t dataArrayPosition = 0;
uint8_t dataArraySize = 10;
void setup(void) {
Serial.begin(115200);
Serial.setDebugOutput(false);
delay(20);
Serial.println("\n\nbegin");
pinMode(A0, INPUT);
dataContainer.addDataItem("ADC",calibrationParam,numUsedCalibrationParameters);
void loop(void) {
dataContainer.setDataValue("ADC", analogRead(A0), dataArrayPosition);
if (dataArrayPosition < dataArraySize) { ++dataArrayPosition; }
else { dataArrayPosition = 0; }
delay(100);
}
After around 31000 loops (just under 2^15 which is suspicious to me), I get a StoreProhibitedCause Exception. If I comment out dataContainer.setDataValue("ADC", analogRead(A0), dataArrayPosition);, I no longer get the exception. I suspect it's some way that I have implemented the linked list and it has a memory issue but I have tried printing out the addresses of everything and it doesn't look like anything is running away.
Exception:
Exception (29):
epc1=0x4000df64 epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000
>>>stack>>>
ctx: sys
sp: 3fffec10 end: 3fffffb0 offset: 01a0
3fffedb0: 4024576b 3fff0b08 00000002 40245700
.....
===================== SOLVED =====================
DataItem *temp = new DataItem; should be DataItem *temp; for setDataValue() and setCalibrationParameters().
Otherwise it keeps on creating new structs for every addition.
DataItem *temp = new DataItem; should be DataItem *temp; for setDataValue() and setCalibrationParameters().
Otherwise it keeps on creating new structs for every addition.
(I can't mark it solved without having an answer).

ffmpeg RTSP stream decoding memory leak

I need to decode rtsp stream from Ip camera using ffmpeg, below is the code for decoder
ffmpeg_decoder.h
class ffmpeg_decoder
{
public:
ffmpeg_decoder();
int initial(QString & url);
int h264Decodec();
void close_stream();
virtual ~ffmpeg_decoder();
AVPicture picture;
int width;
int height;
QMutex mutex;
QImage imageDecoded;
private:
AVFormatContext *pFormatCtx;
AVCodecContext *pCodecCtx;
AVFrame *pFrame;
AVPacket packet;
SwsContext * pSwsCtx;
int videoStream;
QString rtspURL;
};
ffmpeg_decoder.cpp
ffmpeg_decoder::ffmpeg_decoder()
{
pCodecCtx = NULL;
videoStream=-1;
}
ffmpeg_decoder::~ffmpeg_decoder()
{
sws_freeContext(pSwsCtx);
}
int ffmpeg_decoder::initial(QString & url)
{
int err;
rtspURL=url;
AVCodec *pCodec;
av_register_all();
avformat_network_init();
pFormatCtx = avformat_alloc_context();
pFrame = av_frame_alloc();
err = avformat_open_input(&pFormatCtx, rtspURL.toStdString().c_str(), NULL,
NULL);
if (err < 0)
{
printf("Can not open this file");
return -1;
}
if (avformat_find_stream_info(pFormatCtx,NULL) < 0)
{
printf("Unable to get stream info");
return -1;
}
int i = 0;
videoStream = -1;
for (i = 0; i < pFormatCtx->nb_streams; i++)
{
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
videoStream = i;
break;
}
}
if (videoStream == -1)
{
printf("Unable to find video stream");
return -1;
}
pCodecCtx = pFormatCtx->streams[videoStream]->codec;
width=pCodecCtx->width;
height=pCodecCtx->height;
avpicture_alloc(&picture,PIX_FMT_RGB24,pCodecCtx->width,pCodecCtx->height);
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
pSwsCtx = sws_getContext(width, height, PIX_FMT_YUV420P, width,
height, PIX_FMT_RGB24,
SWS_BICUBIC, 0, 0, 0);
if (pCodec == NULL)
{
printf("Unsupported codec");
return -1;
}
printf("video size : width=%d height=%d \n", pCodecCtx->width,
pCodecCtx->height);
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
{
printf("Unable to open codec");
return -1;
}
printf("initial successfully");
return 0;
}
int ffmpeg_decoder::h264Decodec()
{
int frameFinished=0;
// while (av_read_frame(pFormatCtx, &packet) >= 0)
if(av_read_frame(pFormatCtx, &packet) >= 0)
{
if(packet.stream_index==videoStream)
{
avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
if (frameFinished)
{
printf("***************ffmpeg decodec*******************\n");
mutex.lock();
int rs = sws_scale(pSwsCtx, (const uint8_t* const *) pFrame->data,
pFrame->linesize, 0,
height, picture.data, picture.linesize);
imageDecoded = QImage();
imageDecoded= QImage(this->picture.data[0],this->width,this->height,QImage::Format_RGB888);
//imageDecoded = imageDecoded.copy();
mutex.unlock();
if (rs == -1)
{
printf("__________Can open to change to des imag_____________e\n");
return -1;
}
}
}
}
av_free_packet(&packet);
av_frame_unref(pFrame);
av_packet_unref(&packet);
avpicture_free(&picture);
return 1;
}
void ffmpeg_decoder::close_stream(){
/*if (pFrame)
av_free(&pFrame);*/
if (pCodecCtx)
avcodec_close(pCodecCtx);
if (pSwsCtx)
sws_freeContext(pSwsCtx);
avpicture_free(&picture);
if (pFormatCtx)
avformat_close_input(&pFormatCtx);
}
Below is the main thread which do the decoding.
I am using Qt for creating thread and do decoding
ffmpeg_decoder * ffmpeg = new ffmpeg_decoder();;
if(ffmpeg->initial(rtspURL)==0){
while (1) {
ffmpeg->h264Decodec();
//get frame and do processing right now it disabled, and still see the memory leak.
.......
if(stopFlg.load()==1)
break;
}
//close stream if break
ffmpeg->close_stream();
}
else {
ffmpeg->close_stream();
}
When I run 36 thread with different URL I can see the memory usage of the program increase over time.
I have used valgrind to detect the leak, and here is the relevant part of the log
This is the first memory leak location
=14402== by 0x692017F: av_malloc (in /usr/lib/x86_64-linux-gnu/libavutil-ffmpeg.so.54.31.100)
==14402== by 0x692048D: av_mallocz (in /usr/lib/x86_64-linux-gnu/libavutil-ffmpeg.so.54.31.100)
==14402== by 0x691915E: av_frame_alloc (in /usr/lib/x86_64-linux-gnu/libavutil-ffmpeg.so.54.31.100)
==14402== by 0x419663: ffmpeg_decoder::initial(QString&) (ffmpeg_decoder.cpp:24)
==14402== by 0x41ABEC: RTSP_Player_Object::run() (rtsp_player_object.cpp:15)
Another
==14402== 2,176 bytes in 16 blocks are indirectly lost in loss record 23,113 of 23,379
==14402== at 0x4C2E0EF: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14402== by 0x7780A4E: QImageData::create(unsigned char*, int, int, int, QImage::Format, bool, void (*)(void*), void*) (in /home/vapplica/Qt5.11.1/5.11.1/gcc_64/lib/libQt5Gui.so.5.11.1)
==14402== by 0x7780C30: QImage::QImage(unsigned char*, int, int, QImage::Format, void (*)(void*), void*) (in /home/vapplica/Qt5.11.1/5.11.1/gcc_64/lib/libQt5Gui.so.5.11.1)
==14402== by 0x419B21: ffmpeg_decoder::h264Decodec() (ffmpeg_decoder.cpp:96)
I have check the documentation and sample on ffmpeg site, and I think I am releasing the allocated memory, but still I can see the memory leak when I run the program.

Downloading Image to a specific folder using gp_filesystem_get_file()

Trying my hands on libgphoto2 library examples and while going through simple-capture.c file. Can i download foo.jpg captured image to a specified folder on my computer?
As far as i understood, in capture_to_file() camera_file_path.folder is the folder in which the file can be found on the camera. So open() should specify the host(computer) location. But nothing worked, i get following error:
You need to specify a folder starting with /store_xxxxxxxxx/
Am i missing something here? Any help would be appreciated, thanks!
I got this working.
Written small application for multiple cameras. Including main() for about question.
int main(int argc, char **argv)
{
CameraList *list;
Camera **cams;
int retval, count, i;
GPContext *context;
FILE *f;
char *data;
unsigned long size;
const char *name, *value;
/*
* Create context
*/
context = sample_create_context();
/*
* Setup Images DB directory.
*/
char* home = getenv("HOME");
if (home == NULL)
{
printf("Error: Unable to fetch home env! \n");
exit(1);
}
char* path = "/Desktop/mw/";
size_t len = strlen(home) + strlen(path) + 1;
char* imgdb = malloc(len);
if (imgdb == NULL)
{
printf("Error: Unable to malloc(). \n");
exit(1);
}
strcpy(imgdb, home);
strcat(imgdb, path);
directory_exists_or_create(imgdb);
/*
* Logs
*/
gp_log_add_func(GP_LOG_ERROR, errordumper, NULL);
/*
* Detect all the cameras that can be autodetected
*/
retval = gp_list_new(&list);
if (retval < GP_OK)
{
printf("Unable to create camera list.\n");
return 1;
}
count = sample_autodetect(list, context);
if (count < GP_OK)
{
printf("No cameras detected.\n");
return 1;
}
/*
* Now open all the cameras we autodetected for usage.
*/
printf("Number of cameras: %d\n", count);
cams = calloc(sizeof(Camera*), count);
for (i = 0; i < count; i++)
{
gp_list_get_name(list, i, &name);
gp_list_get_value(list, i, &value);
retval = sample_open_camera(&cams[i], name, value, context);
if (retval < GP_OK)
{
fprintf(stderr, "Camera %s on port %s failed to open\n", name, value);
}
}
if (argc > 0)
{
while ((++argv)[0])
{
if (argv[0][0] == '-')
{
switch (argv[0][1])
{
case 'h':
case 'H':
{
/* Now call a simple function in each of those cameras. */
for (i = 0; i < count; i++)
{
CameraText text;
char *owner;
retval = gp_camera_get_summary (cams[i], &text, context);
if (retval < GP_OK)
{
fprintf (stderr, "Failed to get summary.\n");
continue;
}
gp_list_get_name (list, i, &name);
gp_list_get_value (list, i, &value);
printf("%-30s %-16s\n", name, value);
printf("Summary:\n%s\n", text.text);
/* Query a simple string configuration variable. */
retval = get_config_value_string (cams[i], "owner", &owner, context);
if (retval >= GP_OK)
{
printf("Owner: %s\n", owner);
free (owner);
}
else
{
printf("Owner: No owner found.\n");
}
}
}
/* Graceful exit from the program */
goto exit_;;
default:
printf("Unknown option -%c\n\n", argv[0][1]);
break;
}
}
}
}
/* When I set GP_LOG_DEBUG instead of GP_LOG_ERROR above, I noticed that the
* init function seems to traverse the entire filesystem on the camera. This
* is partly why it takes so long.
* (Marcus: the ptp2 driver does this by default currently.)
*/
printf("Cameras init. Takes about 10 seconds each.\n");
for (i = 0; i < count; i++)
{
retval = gp_camera_init(cams[i], context);
if (retval != GP_OK)
{
printf(" Camera [%d] init failed with retval %d\n", i, retval);
exit (1);
}
}
printf(" ----------------\n");
printf(" Sampler is ready \n");
printf(" ----------------\n");
printf("Usage : \n");
printf(" ESC - Exit the program\n");
printf(" i/I - Insert new product barcode manually\n");
#if defined(BARCODE_ENABLED)
printf(" b/B - Insert new product barcode using barcode-scanner\n");
#endif
char get_key;
char exit_key = 0;
char bcr_buf[128] = {0};
int hemispheres_counts = 0;
int rotar_steps = 0;
do
{
get_key = getchar();
switch (get_key)
{
// Gracefull Exit
case _ESC_:
exit_key = 1;
break;
// Manual insert mode
case 'i':
case 'I':
printf("ACTION: Type in the name.\n");
scanf("%128s", bcr_buf);
process:
press_enter();
printf("ACTION: Shall we start? press return key.\n");
press_enter();
hemispheres_counts = 0;
rotar_steps = 0;
char product_filename[256] = {0};
strcpy(product_filename, imgdb);
strcat(product_filename, bcr_buf);
if (directory_exists_or_create(product_filename))
{
printf("\n\n!!! ATTENTION: The product already exists !!!\n\n");
printf("\nEnter options:\n");
printf(" ESC - Exit the program\n");
printf(" i/I - Insert new product barcode manually\n");
#if defined(BARCODE_ENABLED)
printf(" b/B - Insert new product barcode using barcode-scanner\n");
#endif
break;
}
while (hemispheres_counts < MAX_HEMISPHERES)
{
while (rotar_steps < MAX_ROTAR_STEPS)
{
for (i = 0; i < count; i++)
{
capture_to_memory(cams[i], context, (const char**)&data, &size);
char fname[64] = {0};
char mk_filename[256] = {0};
strcpy(mk_filename, product_filename);
snprintf(fname, sizeof(fname), "/%d-%d-%d.jpg", i, hemispheres_counts, rotar_steps);
strcat(mk_filename, fname);
printf("file name %s\n", mk_filename);
f = fopen(mk_filename, "wb");
if (f)
{
retval = fwrite (data, size, 1, f);
if (retval != size)
{
printf(" fwrite size %ld, written %d\n", size, retval);
}
fclose(f);
}
else
{
printf(" fopen *.jpg failed. %s\n", strerror(errno));
}
usleep(500*1000);
}
rotar_steps++;
}
rotar_steps = 0;
hemispheres_counts++;
if (hemispheres_counts < MAX_HEMISPHERES)
{
printf("Flip the product and hit 'RETURN' key\n");
press_enter(); // This expect some input from user, thats it.
printf("Started capturing other hemisphere!\n");
} else {
printf("Sampling Done for barcode: %s\n", bcr_buf);
printf(" -------------------------------------\n");
printf("\nEnter options:\n");
printf(" ESC - Exit the program\n");
printf(" i/I - Insert new product barcode manually\n");
#if defined(BARCODE_ENABLED)
printf(" b/B - Insert new product barcode using barcode-scanner\n");
#endif
break;
}
}
break;
}
} while (exit_key != 1);
exit_:
/*
* Release all the resources.
*/
printf("\nReleasing all the resources ... \n");
for (i = 0; i < count; i++)
{
gp_camera_exit(cams[i], context);
}
if (cams) {
free(cams);
}
free(imgdb);
#if defined(BARCODE_ENABLED)
close_bcr();
#endif
printf("Done.\n");
return 0;
}

Modbus rtu set serial mode Error

I get an error when I use modbus_rtu_set_serial_mode. The error is thrown by ioctl saying bad file descriptor. After googling I found out that a dozen of people had problems with this, but sadly no solutions. If you have even the slightest clue what's going on, please at least set me in the right direction. I'm working in Ubuntu 14.04.1 LTS
#define MODBUS_RTU_RS232 0
#define MODBUS_RESPONSE_TIMEOUT_SEC 10
#define MODBUS_RESPONSE_TIMEOUT_USEC 0
//...
std::string mode = "RTU";
std::string port = "/dev/ttyO3";
std::string commInterface = "RS232";
int baudrate = 19200;
char parity = 'N';
int dataBit = 8;
int stopBit = 1;
int slaveAddress = 10;
modbus_t *mb;
//...
}
//function calling the modbus_rtu_set_serial_mode
//...
if(mode = "RTU"){
mb = modbus_new_rtu(port, baudrate, parity, dataBit, stopBit);
if(mb == NULL)
{
return false;
}
}
if(commInterface == "RS232"){
if(modbus_rtu_set_serial_mode(mb, MODBUS_RTU_RS232) < 0){
std::cout << "modbus_rtu_set_serial_mode failed, errMsg: "
<< modbus_strerror(errno); //Here it prints "Bad File Descriptor"
modbus_close(mb);
modbus_free(mb);
return false;
}
}
struct timeval old_response_timeout;
modbus_get_response_timeout(mb, &old_response_timeout);
struct timeval response_timeout;
response_timeout.tv_sec = MODBUS_RESPONSE_TIMEOUT_SEC;
response_timeout.tv_usec = MODBUS_RESPONSE_TIMEOUT_USEC;
modbus_set_response_timeout(mb, &response_timeout);
modbus_set_slave(mb, slaveAddress);
int connectSlave = modbus_connect(mb);
if (connectSlave < 0)
{
std::cout << "Slave error";
modbus_close(mb);
modbus_free(mb);
return false;
}
//...
modbus-rtu.c file
int modbus_rtu_set_serial_mode(modbus_t *ctx, int mode)
{
if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) {
#if HAVE_DECL_TIOCSRS485
modbus_rtu_t *ctx_rtu = ctx->backend_data;
struct serial_rs485 rs485conf;
memset(&rs485conf, 0x0, sizeof(struct serial_rs485));
if (mode == MODBUS_RTU_RS485) {
rs485conf.flags = SER_RS485_ENABLED;
if (ioctl(ctx->s, TIOCSRS485, &rs485conf) < 0) {
return -1;
}
ctx_rtu->serial_mode |= MODBUS_RTU_RS485;
return 0;
} else if (mode == MODBUS_RTU_RS232) {
if (ioctl(ctx->s, TIOCSRS485, &rs485conf) < 0) {
return -1;
}
/*int status;
status |= TIOCM_RTS;
if (ioctl(ctx->s, TIOCMSET, &status) < 0) {
return -1;
}*/
ctx_rtu->serial_mode = MODBUS_RTU_RS232;
return 0;
}
#else
if (ctx->debug) {
fprintf(stderr, "This function isn't supported on your platform\n");
}
errno = ENOTSUP;
return -1;
#endif
}
/* Wrong backend and invalid mode specified */
errno = EINVAL;
return -1;
}

Resources