Data base confusion - c

I have a strange thing in my code execution
every thing goes ok except the value of player_count. When i read the data again from file, it still = 0 although name and email are updated correctly ..!!
why player_count still equal 0 ??????
here is the code :
#define MAX_DATA 128
#define STRLEN 101
#define FILENAME "C:\\Users\\ahmed\\Desktop\\C codes\\new_game\\data_base.dat"
typedef struct
{
char name[STRLEN] ;
char email[STRLEN] ;
int score ;
int id ;
int Set ;
} player_t ;
typedef struct
{
player_t player[MAX_DATA] ;
int player_count ;
}DataBase ;
typedef struct
{
DataBase db ;
FILE *filename ;
}Connection ;
void Store_Player_Database( int score )
{
Connection *conn = Creat_Connection(FILENAME );
player_t *player = conn->db.player ;
Read_Database(conn) ;
int player_num = conn->db.player_count ;
printf("Your name : ") ;
get_str(player[player_num].name , STRLEN) ;
printf("Your e-mail : ") ;
get_str(player[player_num].email , STRLEN) ;
player[player_num].Set = 1 ;
player[player_num].score = score ;
conn->db.player_count++ ;
printf("count here = %d\n",conn->db.player_count) ;
Write_Database(conn) ;
}
Connection *Creat_Connection(const char *filename )
{
Connection *conn = calloc(1,sizeof(Connection)) ;
//check_mem(conn) ;
int i = 0;
for( i = 0 ; i< MAX_DATA ; i++)
conn->db.player[i].id = i+1 ;
/// for update or read
conn->filename = fopen(filename , "r+") ;
//check(db->filename , "File open failed !") ;
return conn ;
}
int Read_Database(Connection *conn)
{
int rc ;
if(conn)
{
if(conn->filename)
{
DataBase *db = &conn->db ;
rc=fread(db,sizeof(DataBase),1,conn->filename); // load database from file .
printf("count = %d\n" , db->player_count) ;printf("%s %s \n" , db->player[0].name , db->player[0].email);
/* if (rc != 1)
{
printf("Error load database from file\n") ;
return -1 ;
}*/
}
}
return 1 ;
}
int Write_Database(Connection *conn)
{
int rc ;
if(conn)
{
if(conn->filename)
{
rewind(conn->filename) ;
DataBase *db = &conn->db ;printf("%s %s count = %d \n" , db->player[0].name , db->player[0].email , conn->db.player_count);
rc = fwrite(db,sizeof(DataBase),1,conn->filename) ;
if (rc != 1)
{
printf("Error load database from file\n") ;
return -1 ;
}
fflush(conn->filename) ;
}
}
return 1 ;
}
/*****************************/
int main(void)
{
int score = 5 ;
/* any code here */
Store_Player_Database(score) ;
Store_Player_Database(score +1) ; // at that call i get name and mail correct but player_count still zero ??? why?!
return 0 ;
}

When i try this program in linux it runs correctly
then i find the bug finally .
In windows fread should open in binary mode like that :
conn->filename = fopen(filename , "rb+") ; // use rb+ instead of r+ to open it in binary mode

Related

C : printf printing variables in the mixed order

Here is my code,
#include <time.h>
#include <pthread.h>
#include <string.h>
#include <inttypes.h>
#include <unistd.h>
unsigned sleep(unsigned sec) ;
void get_time(char *buf) {
time_t t = time(NULL) ;
struct tm tm = *localtime(&t) ;
sprintf(buf,"%02d:%02d:%02d", tm.tm_hour, tm.tm_min, tm.tm_sec) ;
}
void *calculateSize(uint64_t size, char *buf) {
if (size < 1024ULL){
sprintf(buf, "%.1f %s", (float) size, "B") ;
return NULL ;
}
else if (size < (1024 * 1024)) {
sprintf(buf, "%.1f %s", (float) size/1024ULL, "KiB") ;
return NULL ;
}
else if (size > (1024 * 1024)) {
sprintf(buf, "%.1f %s", (float) size/(1024ULL * 1024ULL), "MiB") ;
return NULL ;
}
strcpy(buf, "0") ;
return NULL ;
}
void * run(char *interface, char * download_buf, char * upload_buf) {
unsigned long rdiff,tdiff ;
unsigned long rx_old,rx_new ;
unsigned long tx_old,tx_new ;
char buf[10] ;
char rx_file[512] ;
char tx_file[512] ;
sprintf(rx_file, "/sys/class/net/%s/statistics/rx_bytes", interface) ;
sprintf(tx_file, "/sys/class/net/%s/statistics/tx_bytes", interface) ;
FILE *rf = fopen(rx_file,"r") ;
FILE *tf = fopen(tx_file,"r") ;
if (rf != NULL && tf != NULL) {
fscanf(rf,"%lu", &rx_old) ;
fscanf(tf,"%lu", &tx_old) ;
fclose(rf) ;
fclose(tf) ;
}
else {
return NULL ;
}
sleep(1) ;
rf = fopen(rx_file,"r") ;
tf = fopen(tx_file,"r") ;
if (rf != NULL && tf != NULL) {
fscanf(rf,"%lu", &rx_new) ;
fscanf(tf,"%lu", &tx_new) ;
rdiff = rx_new - rx_old ;
tdiff = tx_new - tx_old ;
fclose(rf) ;
fclose(tf) ;
}
else {
return NULL ;
}
calculateSize(rdiff,buf) ;
strcpy(download_buf,buf) ;
calculateSize(tdiff,buf) ;
strcpy(upload_buf,buf) ;
return NULL ;
}
void *net_speed(void *thread_speed_args ) {
char* iface = *(char **)thread_speed_args ;
char carrier_file[512] ;
sprintf(carrier_file,"/sys/class/net/%s/carrier", iface) ;
printf("Reading from %s\n", carrier_file) ;
while(1) {
if( access( carrier_file, F_OK ) == 0 ) {
run(iface, ((char **)thread_speed_args)[1], ((char **)thread_speed_args)[2]) ;
}
else {
sprintf(((char **)thread_speed_args)[1],"000 B") ;
sprintf(((char **)thread_speed_args)[2],"000 B") ;
sleep(1) ;
}
}
return NULL ;
}
int main(int argc, char *argv[]) {
char time_buf[10] ; //hh:mm:ss : 8 char + 1 null terminator char
char download_buf[8],upload_buf[8] ;
char* thread_speed_args[3] = { argv[1], download_buf, upload_buf } ;
pthread_t thread_speed ;
pthread_create(&thread_speed, NULL, net_speed, thread_speed_args) ;
pthread_detach(thread_speed) ;
while(1){
get_time(time_buf) ;
printf("Down:%s Up:%s %s\n", thread_speed_args[1], thread_speed_args[2], time_buf) ;
fflush(stdout) ;
sleep(1) ;
}
}
I am using a thread to continuously monitor my wireless data transfer rate on an interface, I am also printing the time along with the transfer rate. I am just experimenting with threads, forgive me if my programming logic is bad.
I notice that when I do a speed test the output or print becomes all messed up like below
Down:0.0 B Up:0.0 B 23:49:03
Down:0.0 B Up:0.0 B 23:49:04
Down:0.0 B Up:0.0 B 23:49:05
Down:17.0 KiB9.2 KiB Up:9.2 KiB 23:49:06
Down:5.3 KiB Up:6.5 KiB 23:49:07
Down:3.4 KiB Up:4.1 KiB 23:49:08
Down:400.6 Ki20.3 KiB23:49:09 Up:20.3 KiB23:49:09 23:49:09
Down:918.6 Ki49.6 KiB23:49:10 Up:49.6 KiB23:49:10 23:49:10
Down:912.8 Ki53.5 KiB23:49:11 Up:53.5 KiB23:49:11 23:49:11
Down:959.2 Ki32.2 KiB23:49:12 Up:32.2 KiB23:49:12 23:49:12
Down:711.5 Ki33.8 KiB23:49:13 Up:33.8 KiB23:49:13 23:49:13
See the last few lines?
Could anyone tell me what is happening here? How do I correct it?
This is happening because you're accessing a common resource in multiple threads simultaneously - in this case, the STDOUT handle. You'll need to synchronize your threads when outputting the information to the console - the easiest way is using mutexes. You can read more here.
While your threads lack any kind of synchonization (which will randomly garble your output in some rare cases) this isn't even your problem.
Here is your problem:
char download_buf[8],upload_buf[8] ;
char buf[10] ;
strcpy(download_buf,buf) ;
strcpy(upload_buf,buf) ;
You are copying an up to 9 character string into a 7 char string so that overflows the buffer. And since the buffers happen to be next to each other on the stack the second strcpy will overwrite the 0 terminator of the first string. Same with the time_buf overwriting the 0 terminator of the second string.
Overall a whole lot of undefined behavior due to buffer overflows.

Make function to read Temperature from DS18B20 and show on LCD

I want to create a new function that will return me a actual temperature from DS18B20 as a float variable. I need that kind of variable to place a string on LCD.
Already I'm using function to read temperature like that:
int8_t readTemp(struct ds18b20 *d) {
struct ds18b20 *newTemp;
char tempAct[5];
while (d->next != NULL)
{
d = d->next;
int fd = open(d->devPath, O_RDONLY);
if (fd == -1)
{
perror("Couldn't open the w1 device.");
return 1;
}
char buf[256];
ssize_t numRead;
while ((numRead = read(fd, buf, 256)) > 0)
{
newTemp = malloc(sizeof(struct ds18b20));
strncpy(newTemp->tempData, strstr(buf, "t=") + 2, 5);
//float tempC = strtof(d->tempData, NULL);
sprintf(tempAct, "%s C", newTemp->tempData);
//printf("Device: %s - ", d->devID);
//printf("Temp: %.3f C ", tempC / 1000);
//printf("%.3f F\n\n", (tempC / 1000) * 9 / 5 + 32);
}
close(fd);
}
return 1;}
I have problem with sprintf from this line:
sprintf(tempAct, "%s C", newTemp->tempData);
In the main code:
int main(void) {
struct ds18b20 *rootNode;
struct ds18b20 *devNode;
struct ds18b20 *getTemp;
// Load pin configuration. Ignore error if already loaded
system("echo w1 > /sys/devices/bone_capemgr.9/slots>/dev/null");
while (1) {
rootNode = malloc(sizeof(struct ds18b20));
devNode = rootNode;
getTemp = rootNode;
int8_t devCnt = findDevices(devNode);
printf("\n Found %d devices\n\n", devCnt);
int8_t tempAct = readTemp(getTemp);
printf("\n Temp Act: %d \n\n", tempAct);
//readTemp(rootNode);
// Free linked list memory
while (rootNode) {
// Start with current value of root node
devNode = rootNode;
// Save address of next devNode to rootNode before deleting current devNode
rootNode = devNode->next;
// Free current devNode.
free(devNode);
}
free(rootNode);
}
return 0;}
I'm trying to recreate the functions from finddevices:
int8_t devCnt = findDevices(devNode);
printf("\n Found %d devices\n\n", devCnt);
int8_t tempAct = readTemp(getTemp);
printf("\n Temp Act: %d \n\n", tempAct);
But the tempData* isn't imported from readTemp fuction to main code.
The code is littered with issues that are not explicitly part of your question. Just some:
readTemp() does not return temperature. In fact it returns 1 if it fails and 1 if it succeeds. That is probably an error.
readTemp() appears to read all available temperature sensors, passed to it as a linked list of struct ds18b20 not just one. But actually skips the root node and accesses the second and subsequent without checking it is valid. If the root node contains no device (just a pointer to the first device), then you need only pass it pass rootNode->next instead.
It is not clear why it dynamically allocates a new struct ds18b20 or why it fails to later de-allocate. That is a serious memory leak.
At a guess the following is more likely to be close to what you need (without knowing anything about struct ds18b20 or what the expected output of the sensor is - just going by the evidence in the code (and commented out code) you have posted - so some bold assumptions have been made.
int readTemp( struct ds18b20 *d, // List of sensors
float* temperatures, // Pointer to array to receive temperatures
int8_t max_temperatures ) // Max number of temperatures to receive
{
struct ds18b20* sensor = d ;
int count = 0 ;
while( sensor != NULL && count < max_temperatures )
{
int fd = open( sensor->devPath, O_RDONLY ) ;
if( fd >= 0 )
{
if( read( fd, buf, sizeof(buf) ) > 0 )
{
char buf[256];
char* temp_str = strstr(buf, "t=") + 2 ;
sscanf( temp_str, "%f", &temperatures[count] ) ;
temperatures[count] /= 1000 ;
count++ ;
}
close( fd ) ;
sensor = sensor->next ;
}
else
{
perror("Couldn't open the w1 device.");
}
}
return count ;
}
Then in you can call it thus:
int8_t devCount = findDevices( rootNode ) ;
float* temperatures = malloc( devCnt * sizeof(float) ) ;
int8_t tempCount = readTemp( rootNode->next, temperatures, devCount ) ;
for( int i = 0; i < tempCount; i++ )
{
printf( "Temp Act: %f\n", temperatures[i] ) ;
}
free( temperatures ) ;
If you know there is only one device or you only need print the first, then this can be simplified:
int8_t devCount = findDevices( rootNode ) ;
if( devCount > 0 )
{
float temperature = 0f ;
int8_t tempCount = readTemp( rootNode->next, temperature, 1 ) ;
if( tempCount > 0 )
{
printf( "Temp Act: %f\n", temperature ) ;
}
}
Issues in your main() are also varied, including:
The root node is needlessly dynamically allocated
several aliases to the root node are needlessly created
The device list is repeatedly re-enumerated and the device list allocated and free'd on every iteration of a non-terminating loop. Assuming the number of sensors does not change while the code is running, this is unnecessary.
The loop never ends - even in the event of an error.
A better implementation might look something like:
int main(void)
{
// Load pin configuration. Ignore error if already loaded
system("echo w1 > /sys/devices/bone_capemgr.9/slots>/dev/null");
struct ds18b20 rootNode = { 0 } ;
int8_t devCount = findDevices( rootNode ) ;
if( devCount > 0)
{
struct ds18b20* devlist = rootNode->next ;
float* temperatures = malloc( devCount * sizeof(float) ) ;
int8_t tempCount = 0 ;
do
{
tempCount = readTemp( devList, temperatures, devCount ) ;
for( int i = 0; i < tempCount; i++ )
{
printf( "Temp Act: %f\n", temperatures[i] ) ;
}
} while (tempCount > 0 ) ;
// Free resources after a temperature read fails
free( temperatures ) ;
// Free linked list memory
while( devlist != NULL )
{
// Save address of next before deleting current
struct ds18b20* next = devlist->next ;
// Free current devNode.
free( devlist ) ;
// get next
devlist = next ;
}
}
return 0 ;
}

C MultiThread Value not printed

First, Here is an entire code.
Read the file
Input file content into structure value
Begin Multithread
$ cat sunje.conf
{
DSN:GOLDILOCKS
UID:TEST
PWD:test
COMMIT INTERVAL:1
}
$ cat sh.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sys/time.h>
//EXEC SQL INCLUDE SQLCA;
typedef struct thread
{
char *dsn;
char *uid;
char *pwd;
char mode;
int num;
int start;
int end;
int interval;
} thread;
pthread_mutex_t mutex;
void *MultiThread(void* threadInfo);
int main(int argc, char **argv)
{
char s[1024];
FILE *fp;
char conn[4][1024];
int i = 0;
int session = 0;
int record = 0;
char mode = NULL;
//int interval;
fp = fopen("sunje.conf", "r");
while(!feof(fp))
{
fgets(s, 1024, fp);
char *ptr = strchr(s, ':');
if (ptr != NULL)
{
strcpy(conn[i], ptr + 1);
conn[i][strlen(conn[i]) - 1] = '\0';
//printf("conn[%d]=\"%s\"\n", i, conn[i]);
i++;
}
}
fclose(fp);
session = atoi(argv[1]);
record = atoi(argv[2]);
mode = argv[4][0];
printf("=========================================\n");
printf("DSN = [%s]\n"
"ID = [%s]\n"
"PW = [%s]\n"
"Commit Interval = [%s]\n"
"\n"
"Total Session = %d\n"
"Total Record = %d\n"
"Mode = %c\n", conn[0], conn[1], conn[2], conn[3], session, record, mode);
printf("=========================================\n");
int init = 1;
int init_div = record / session ;
int init_mod = record % session ;
if (mode == 's')
{
init = record;
init_div = 0;
}
pthread_mutex_init(&mutex, NULL);
thread threadInfo[session];
pthread_t threadCount[session];
i = 0;
for ( i = 0 ; i < session ; i ++)
{
pthread_mutex_lock(&mutex);
if( i != ( session - 1 ) )
{
threadInfo[i].dsn = conn[0];
threadInfo[i].uid = conn[1];
threadInfo[i].pwd = conn[2];
threadInfo[i].interval = atoi(conn[3]);
threadInfo[i].mode = mode;
threadInfo[i].num = i;
threadInfo[i].start = init;
threadInfo[i].end = init + init_div - 1;
}else
{
threadInfo[i].dsn = conn[0];
threadInfo[i].uid = conn[1];
threadInfo[i].pwd = conn[2];
threadInfo[i].interval = atoi(conn[3]);
threadInfo[i].mode = mode;
threadInfo[i].num = i;
threadInfo[i].start = init;
threadInfo[i].end = init + init_div + init_mod - 1;
}
pthread_mutex_unlock(&mutex);
printf("Thread Num = [%d]\n"
"Mode = [%c]\n"
"Start = [%d]\n"
"End = [%d]\n"
"Interval = [%d]\n"
"DSN = [%s]\n\n"
,threadInfo[i].num, threadInfo[i].mode, threadInfo[i].start, threadInfo[i].end, threadInfo[i].interval, threadInfo[i].dsn);
pthread_create ( &threadCount[i], NULL, MultiThread, (void*)&threadInfo[i] );
init = init + init_div;
}
int result;
i = 0;
for ( i = 0 ; i < session ; i ++)
{
pthread_join ( threadCount[i], (void *)&result );
}
printf("Thread Success\n");
return 0;
}
void *MultiThread(void* threadInfo)
{
thread* info = (thread*)threadInfo;
// struct timeval st, et;
char mode;
int num;
int start;
int end;
int interval;
mode = info->mode;
num = info->num;
start = info->start;
end = info->end;
interval = info->interval;
printf("num[%d] dsn[%s] uid[%s] pwd[%s] mode[%c] interval[%d] start[%d] end[%d]\n", num, info->dsn, info->uid, info->pwd, mode, interval, start, end);
return NULL;
}
Now, I ask a question..
I want to print last thread's value. But only "dsn" value not printed..
I used mutex of pthread to solve this problem. But it was not.
$ ./sh 3 300 2 i
=========================================
DSN = [GOLDILOCKS]
ID = [TEST]
PW = [test]
Commit Interval = [1]
Total Session = 3
Total Record = 300
Mode = i
=========================================
Thread Num = [0]
Mode = [i]
Start = [1]
End = [100]
Interval = [1]
DSN = [GOLDILOCKS]
Thread Num = [1]
Mode = [i]
Start = [101]
End = [200]
Interval = [1]
DSN = [GOLDILOCKS]
num[0] dsn[GOLDILOCKS] uid[TEST] pwd[test] mode[i] interval[1] start[1] end[100]
Thread Num = [2]
Mode = [i]
Start = [201]
End = [300]
Interval = [1]
DSN = [GOLDILOCKS]
num[1] dsn[GOLDILOCKS] uid[TEST] pwd[test] mode[i] interval[1] start[101] end[200]
num[2] dsn[] uid[TEST] pwd[test] mode[i] interval[1] start[201] end[300]
Thread Success
Could you help me?
I can't understand why num[2]'s dsn is not show
int result is 4 bytes.
(void *)&result is 8 bytes.
If the memory structure made like [ int 4 byte result ][ conn[0][0] .. ] .. on first time,
the return will be like [ 8 byte (void **)&result ][ conn[0][4] .. ] ..
Where is conn[0][0] ~ conn[0][3] ? this location covered with NULL(\000).
This program doesn't read after NULL value.
Here is gdb result.
Breakpoint 1, main (argc=5, argv=0x7fffffffdbf8) at sh.gc:131
131 pthread_join ( threadCount[i], (void **)&result );
1: conn[0] = "\000\000\000\000GOLDILOCKS", '\000' <repeats 26 times>, "\364G\336\367\377\177\000\000\000"
(gdb) p &conn[0]
$1 = (char (*)[50]) 0x7fffffffd5c0
(gdb) p &result
$2 = (int *) 0x7fffffffd5bc
(gdb)

how to do multiple read/write HDD/USB bytes in c [duplicate]

This question already has answers here:
C++ sector aligned read
(2 answers)
SetFilePointer without FILE_FLAG_NO_BUFFERING
(2 answers)
Closed 5 years ago.
First, here are a couple links i looked at...
Read and write hard disk sector directly and efficiently
Read specific sector on hard drive using C language on windows
I'm trying to do almost the same thing. What I'm having trouble with is reading the device multiple times so I can store the read bytes from a DEVICE (USB) to writing them into a FILE.
This is what I am trying to do...
declare variables
initialize variables
SetFilePointer()
ReadFile()
output the read bytes to a file
use ReadFile() to get more bytes
output the read bytes to same file again
repeat 6 and 7 (actually just repeating 4 and 5)
This doesn't seem to be working. I would like to read x amount of bytes and store those values into a file then read more and store those values in the same file as last time. I would like it to repeat the process until it reads to the end of the device. I would like this program to work on any size of device. If I can put it in a loop then I can read and write infinite sized devices.
This is a how to read/write so I would like to do this in reverse as well. Read the file for values then write them to the device.
I'm using a 128MB USB. It contains 131858432 bytes. If any more info is needed then I will post it if I have it.
My code:
#include <windows.h>
#include <stdio.h>
int main(int argc, char ** argv)
{
BYTE sector[0x400] = {0};
DWORD bytesRead;
HANDLE device = NULL;
int numSector = 1;
int maxRead = 1;
FILE *readChar = fopen("G:\\usb_128MB_Dec2.txt", "w+");
device = CreateFile("\\\\.\\L:", // Drive to open
GENERIC_READ|GENERIC_WRITE, // Access mode
FILE_SHARE_READ|FILE_SHARE_WRITE, // Share Mode
NULL, // Security Descriptor
OPEN_EXISTING, // How to create
0, // File attributes
NULL); // Handle to template
if(device == INVALID_HANDLE_VALUE)
{
printf("CreateFile: %u\n", GetLastError());
system("pause");
return 1;
}
// set the file pointer for first time
SetFilePointer(device, numSector, NULL, FILE_BEGIN);
// Edit 1. Comment 2.
if(GetLastError() != NO_ERROR)
{
printf("GetLastError: %d\n", GetLastError());
goto end; // end: is before closing files or handles at end of main()
}
// read device for maxRead number of bytes and store the reading into a file
ReadFile(device, sector, maxRead, &bytesRead, NULL);
fprintf(readChar, "%d\n", sector[0]);
// This part of code does not act like expected
SetFilePointer(device, numSector, NULL, FILE_CURRENT);
if(!ReadFile(device, sector, maxRead, &bytesRead, NULL))
printf("err\n");
else
fprintf(readChar, "%d", sector[0]);
end: // Edit 1. Comment 2.
CloseHandle(device);
fclose(readChar);
system("pause");
return 0;
}
Screen ouput:
GetLastError: 87
File output:
Nothing is in the file.
The file should contain an 8 bit decimal value instead of nothing or a 0.
Edit 1:
87 means INVALID PARAMETER.
Your reads have to be sector aligned so you can't seek to offset 1,
but only 0, sector_size, 2sector_size, ..., nsector_size, Your reads
have also be in multiplies of sector size, and your memory buffer has
to be aligned to sector_size.
Sector size could be retrieved with GetDiskFreeSpace and aligned
memory can be obtained with VirtualAlloc.
Maybe you should check also FSCTL_LOCK_VOLUME and
FSCTL_DISMOUNT_VOLUME.
Here's the other code that works for one time reading of the device
#include <windows.h>
#include <stdio.h>
int main(int argc, char ** argv)
{
BYTE sector[0x200] = {0};
DWORD bytesRead;
HANDLE device = NULL;
int numSector = 1;
int maxRead = 0x200;
long long int i;
FILE *readChar = fopen("G:\\usb_128MB_Dec.txt", "w+");
device = CreateFile("\\\\.\\L:", // Drive to open
GENERIC_READ|GENERIC_WRITE, // Access mode
FILE_SHARE_READ|FILE_SHARE_WRITE, // Share Mode
NULL, // Security Descriptor
OPEN_EXISTING, // How to create
0, // File attributes
NULL); // Handle to template
if(device == INVALID_HANDLE_VALUE)
{
printf("CreateFile: %u\n", GetLastError());
system("pause");
return 1;
}
SetFilePointer(device, numSector, NULL, FILE_BEGIN);
if (!ReadFile(device, sector, maxRead, &bytesRead, NULL))
{
printf("ReadFile: %u\n", GetLastError());
goto end;
}
else
{
printf("Success!\n");
}
if(readChar == NULL)
{
printf("Did not open file. Exit 2.");
goto end;
}
for(i = 0; i < maxRead - 1; i++)
{
fprintf(readChar, "%d\n", sector[i]);
}
fprintf(readChar, "%d", sector[i]); // so the previous loop wont add \n to the last read wanted
end:
CloseHandle(device);
fclose(readChar);
system("pause");
return 0;
}
File contents:
235
88
...
Each byte read is stored in decimal value on a new line.
So it may be better understood what I'm trying to do, here it is in code:
// What I want to do..
// This part works
SetFilePointer(device, numSector, NULL, FILE_BEGIN);
ReadFile(device, sector, maxRead, &bytesRead, NULL);
for(i = 0; i < size_of_device - 0x200; i += 512)
{
for(j = 0; j < maxRead; j++)
{
fprintf(readChar, "%d\n", sector[j]);
}
// stops working
SetFilePointer(device, numSector, NULL, FILE_CURRENT);
ReadFile(device, sector, maxRead, &bytesRead, NULL);
}
for(j = 0; j < maxRead - 1; j++)
{
fprintf(readChar, "%d\n", sector[j]);
}
fprintf(readChar, "%d", sector[j]);
// .. end of what i want to do
Edit 2: Working on reading multiple times now.
#include <windows.h>
#include <stdio.h>
int main(int argc, char ** argv)
{
BYTE sector[0x200] = {0};
DWORD bytesRead;
HANDLE device = NULL;
//int numSector = 512; // original value was 1 not 512 but variable is not needed
int maxRead = 512;
int i, j, k = 0, l; // loop variables
FILE *readChar = fopen("G:\\wii u hdd image\\usb_128MB_Dec3.txt", "w+");
if(readChar == NULL)
{
printf("Error creating file.\n");
goto end;
}
device = CreateFile("\\\\.\\L:", // Drive to open
GENERIC_READ|GENERIC_WRITE, // Access mode
FILE_SHARE_READ|FILE_SHARE_WRITE, // Share Mode
NULL, // Security Descriptor
OPEN_EXISTING, // How to create
0, // File attributes
NULL); // Handle to template
// If device does not contain a handle value
if(device == INVALID_HANDLE_VALUE)
{
printf("Error. GetLastError: %u\n", GetLastError());
goto end;
}
for(i = 0; i < maxRead*503; i++) // maxRead * 503 = 257536
{
// If ReadFile() fails it will exit the program without adding a '\n' to the readChar file.
if(!ReadFile(device, sector, maxRead, &bytesRead, NULL))
{
printf("Error of ReadFile(). GetLastError(): %u\n", GetLastError());
goto end;
}
// If this is the first time through the loop then '\n' won't be added to the readChar file.
if(i != 0)
{
fprintf(readChar, "\n");
system("cls");
printf("%.2f%%\n", (i / 257536));
}
// Runs for 511 times. Then prints the 512th decimal value after the loop.
for(j = 0; j < maxRead - 1; j++)
{
fprintf(readChar, "%d\n", sector[j]);
}
fprintf(readChar, "%d", sector[j]);
}
end:
CloseHandle(device);
fclose(readChar);
system("pause");
return 0;
}
Edit 3:
This question has not been answered in another post.
87 means INVALID PARAMETER.
Your reads have to be sector aligned so you can't seek to offset 1, but only 0, sector_size, 2*sector_size, ..., n*sector_size, Your reads have also be in multiplies of sector size, and your memory buffer has to be aligned to sector_size.
Sector size could be retrieved with GetDiskFreeSpace and aligned memory can be obtained with VirtualAlloc.
Maybe you should check also FSCTL_LOCK_VOLUME and FSCTL_DISMOUNT_VOLUME.
Edit
Because direct reading (or writing) isn't buffered, if you want to operate on smaller sizes then sector size, you have to handle buffering yourself.
This code implements reading single bytes from arbitrary places using one sector buffering scheme. Disclaimer: Needs through testing. Beware of possible bugs.
#include <windows.h>
typedef __int64 int64;
struct MyDevice
{
HANDLE handle;
DWORD sector_size;
int64 current_sector_position;
void* sector_buffer;
};
BOOL OpenMyDevice( struct MyDevice* device, const char* name )
{
device->current_sector_position = -1;
device->handle = INVALID_HANDLE_VALUE;
device->sector_buffer = 0;
{
DWORD bytes_per_sector, unused1, unused2, unused3;
// GetDiskFreeSpace doesn't like "\\.\".
const char* name2 = name;
if ( strncmp( name, "\\\\.\\", 4 ) == 0 )
name2 = name + 4;
// For comaptibility reasons we will get logical sector size here.
// For Vista+ it would be better to use DeviceIoControl with IOCTL_STORAGE_QUERY_PROPERTY.
if ( !GetDiskFreeSpace( name2, &unused1, &bytes_per_sector, &unused2, &unused3 ) )
return FALSE;
device->sector_size = bytes_per_sector;
}
device->sector_buffer = VirtualAlloc( 0, device->sector_size, MEM_COMMIT, PAGE_READWRITE );
if ( !device->sector_buffer )
return FALSE;
device->handle = CreateFile(
name,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
0,
OPEN_EXISTING,
FILE_FLAG_NO_BUFFERING, // Can be zero, but in most cases it assumed by Windows.
0 );
if ( device->handle == INVALID_HANDLE_VALUE )
{
VirtualFree( device->sector_buffer, 0, MEM_RELEASE );
device->sector_buffer = 0;
return FALSE;
}
return TRUE;
}
// Call only when OpenDevice was successful.
void CloseMyDevice( struct MyDevice* device )
{
CloseHandle( device->handle );
device->handle = INVALID_HANDLE_VALUE;
VirtualFree( device->sector_buffer, 0, MEM_RELEASE );
device->sector_buffer = 0;
}
BOOL LoadMyDeviceSector( struct MyDevice* device, int64 byte_offset )
{
// Calculate sector position.
int64 sector_position = ( byte_offset / device->sector_size ) * device->sector_size;
if ( sector_position == device->current_sector_position )
// No need to load, it is in buffer
return TRUE;
{
LARGE_INTEGER li;
li.QuadPart = sector_position;
if ( SetFilePointerEx( device->handle, li, 0, FILE_BEGIN ) )
{
DWORD read;
if ( ReadFile( device->handle, device->sector_buffer, device->sector_size, &read, 0 ) )
{
if ( read == device->sector_size )
{
device->current_sector_position = sector_position;
return TRUE;
}
// else Hmmm. Maybe this is read beyond EOF?
}
}
}
// Cant guarantee that device->sector_buffer contains valid data.
device->current_sector_position = -1;
return FALSE;
}
BOOL LoadNextMyDeviceSector( struct MyDevice* device )
{
DWORD read;
device->current_sector_position = -1;
if ( ReadFile( device->handle, device->sector_buffer, device->sector_size, &read, 0 ) )
{
if ( read == device->sector_size )
return TRUE;
// else Hmmm. Maybe this is read beyond EOF?
}
return FALSE;
}
BOOL SetMyDevicePos( struct MyDevice* device, int64 sector_aligned_byte_offset )
{
LARGE_INTEGER li;
li.QuadPart = sector_aligned_byte_offset;
device->current_sector_position = -1;
return SetFilePointerEx( device->handle, li, 0, FILE_BEGIN );
}
int GetMyDeviceByte( struct MyDevice* device, int64 offset )
{
if ( LoadMyDeviceSector( device, offset ) )
{
// Calculate position in sector buffer.
int64 offset_in_sector = offset - ( offset / device->sector_size ) * device->sector_size;
return ((unsigned char*)( device->sector_buffer ))[ offset_in_sector ];
}
return -1;
}
BOOL GetMyDeviceBytes( struct MyDevice* device, int64 byte_offset, void* dst_buffer, int64 count )
{
char* dst = (char*) dst_buffer;
int64 sector_position = ( byte_offset / device->sector_size ) * device->sector_size;
int64 start = byte_offset - sector_position; // First loop pass can be unaligned!
while ( count > 0 )
{
if ( LoadMyDeviceSector( device, byte_offset ) )
{
int64 chunk = device->sector_size - start;
if ( chunk > count )
chunk = count;
// chunk <= sector_size so conversion to int isn't harmful.
memcpy( dst, ((char*)(device->sector_buffer)) + start, (int)chunk );
dst += chunk;
byte_offset += chunk;
count -= chunk;
start = 0; // From now loop would be always sector_size aligned.
}
else
return FALSE;
}
return TRUE;
}
int main( int argc, char* argv[] )
{
struct MyDevice device = { INVALID_HANDLE_VALUE };
if ( OpenMyDevice( &device, "\\\\.\\K:" ) )
{
// #1: Get one byte from device.
{
int byte = GetMyDeviceByte( &device, 11111 );
if ( byte >= 0 )
{
}
}
// #2: Get multiple bytes from device.
{
char buff[1000];
if ( GetMyDeviceBytes( &device, 111111, buff, 1000 ) )
{
}
}
// #3: Scan 100 sectors beginning from sector 111 for byte 155.
{
if ( SetMyDevicePos( &device, 111*device.sector_size ) )
{
int i, j;
for ( i = 0 ; i < 100 ; ++i )
{
if ( !LoadNextMyDeviceSector( &device ) )
break;
for ( j = 0 ; j < (int)device.sector_size ; ++j )
{
int byte = ((unsigned char*)( device.sector_buffer ))[ j ];
if ( byte == 155 )
{
// FOUND!
}
}
}
}
}
CloseMyDevice( &device );
}
}
GetMyDeviceByte and GetMyDeviceBytes are rather random seek oriented for small byte tranfers. If someone needs to trasfer large amounts of data in sequential order it is a lot faster to SetMyDevicePos and LoadNextMyDeviceSector like #3 in main.
I would prefer to write this code in C++.

How do I pass an array of Pointers to a structure and allocate the members

ok, heres my code. I'm trying to pass an array of pointers to a structure to a function.
I need to dynamically allocate each structure and put a pointer to that structure in the array.
When I malloc the second time thru it gets a heap error.
HELP
#define MAXSTRUCTS 50
#define MAXBUFF 100
typedef struct {
char fullName[41];
char address[41];
char cityState[41];
char zipcode[11];
} Persons;
int readData(Persons *structPtrs[]);
int main(void) {
int totalStructs;
Persons *structPtrs[MAXSTRUCTS];
totalStructs = 0;
structPtrs[0] = NULL;
totalStructs = readData(structPtrs);
}
int readData(Persons *strptr[]) {
int tStructs = 0;
int recs;
char inRecord[MAXBUFF];
Persons *tmpPtr;
tStructs = 0;
for (recs=0; recs < MAXSTRUCTS; recs++) {
if (gets(inRecord) != NULL) {
strptr[recs] = (Persons *)malloc( sizeof(Persons));
tmpPtr = strptr[recs];
strncpy(tmpPtr->fullName,inRecord,MAXBUFF);
gets(inRecord);
strncpy(tmpPtr->address,inRecord,MAXBUFF);
gets(inRecord);
strncpy(tmpPtr->cityState,inRecord,MAXBUFF);
gets(inRecord);
strncpy(tmpPtr->zipcode,inRecord,MAXBUFF);
strptr[recs] = tmpPtr;
tStructs++;
}
else {
if ( recs = 0 ) {
exit (0);
}
recs=MAXSTRUCTS;
}
}
return(tStructs);
}
You are doing everything right in regard of passing an array of pointers and allocating memory. What leading to a heap corruption is incorrect usage of strncpy function. The arrays where you are trying to copy data to are slightly smaller than MAXBUFF in all cases. To fix this, you have to specify the size of destination array instead of MAXBUFF. For example, instead of:
strncpy(tmpPtr->fullName,inRecord,MAXBUFF);
... do (assuming that buffer is already filled with \0 symbols):
strncpy(tmpPtr->fullName,inRecord, sizeof(tmpPtr->fullName) - 1);
Also, using gets function is not recommended as well as it could easily lead to buffer overruns. Try using fgets instead.
Here is your modified example that works:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAXSTRUCTS 2
#define MAXBUFF 100
typedef struct {
char fullName[41];
char address[41];
char cityState[41];
char zipcode[11];
} Persons;
int readData(Persons *structPtrs[]);
int main ()
{
int totalStructs;
int recs;
Persons *structPtrs[MAXSTRUCTS];
totalStructs = 0;
structPtrs[0] = NULL;
totalStructs = readData(structPtrs);
for(recs = 0; recs < totalStructs; ++recs) {
printf ("Record #%d - %s\n", recs + 1, structPtrs[recs]->fullName);
}
return 0;
}
int readData(Persons *strptr[])
{
int tStructs = 0;
int recs;
char inRecord[MAXBUFF];
Persons *tmpPtr;
tStructs = 0;
for (recs=0; recs < MAXSTRUCTS; ++recs) {
memset (inRecord, 0, sizeof(inRecord));
if (fgets(inRecord, sizeof (inRecord) - 1, stdin))
{
strptr[recs] = (Persons *)malloc(sizeof(Persons));
tmpPtr = strptr[recs];
memset (tmpPtr, 0, sizeof(Persons));
strncpy(tmpPtr->fullName,inRecord,sizeof(tmpPtr->fullName) - 1);
fgets(inRecord, sizeof (inRecord) - 1, stdin);
strncpy(tmpPtr->address,inRecord,sizeof(tmpPtr->address) - 1);
fgets(inRecord, sizeof (inRecord) - 1, stdin);
strncpy(tmpPtr->cityState,inRecord, sizeof(tmpPtr->cityState) - 1);
fgets(inRecord, sizeof (inRecord) - 1, stdin);
strncpy(tmpPtr->zipcode,inRecord, sizeof (tmpPtr->zipcode) - 1);
strptr[recs] = tmpPtr;
tStructs++;
} else {
if ( recs = 0 ) {
exit (0);
}
recs=MAXSTRUCTS;
}
}
return(tStructs);
}
int readDataToRecord( Persons *eachEntry[] ) {
int numEntries = 0 ;
Persons *tempPtr ;
for( int i=0 ; i < NUM_OF_RECORDS; ++i ) {
eachEntry[i] = ( Record * ) malloc( sizeof( Record ) ) ;
memset( eachEntry[i], 0, sizeof( Record ) ) ;
tempPtr = eachEntry[i] ;
fgets( tempPtr->firstName, sizeof( tempPtr->firstName ), stdin ) ;
fgets( tempPtr->secondName, sizeof( tempPtr->secondName), stdin ) ;
eachEntry[i] = tempPtr ;
++numEntries ;
}
return numEntries ;
}
This would also efficiently do the job. Once you have new record, you would any how have the memory allocated for each of its member. So you can directly fgets to that variable.
#Vlad : Please let me know if I am wrong.

Resources