How to define multiple streams from UARTs to be used in fprintf - arm

I'm working with ARM (SAM4), it has two UARTs, I need to setup streams so that I could use fprintf to print on both.
Already tried fwopen without luck:
FILE * debug;
debug_writefn(void *cookie, const char *buf, int n);
void comm_init(void) {
debug = fwopen(NULL, &debug_writefn);
if (debug == NULL) {
printf("Error");
}
fprintf(debug, "Test");
}
However, the debug_writefn is newer called.
I'm using the arm-none-eabi-* toolchain (I guess it uses newlib), ASF and FreeRTOS.

You only need re-implement newlib's _write() or write_r() syscall to handle the stdout the stream file handle in any way you require, e.g.:
enum
{
STDIN_HANDLE,
STDOUT_HANDLE,
STDERR_HANDLE
} ;
long _write( int fd, const void *buf, size_t cnt )
{
int ret = EOF ;
if( fd == STDOUT_HANDLE || fd == STDERR_HANDLE )
{
for( int i = 0; i < cnt; i++ )
{
serialPutc( UART1, buf[i] ) ;
serialPutc( UART2, buf[i] ) ;
}
ret = i ;
}
return ret ;
}

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.

Use variable in other layer file

I have an assignment that do FAT12 system. Follow the requirement, I need 2 functions to read sector and multi sector. Those functions in HAL layer. I just tested in app (main) layer below:
In HAL.c:
#define SIZE_OF_SECTOR 512
static FILE* s_pimage = NULL;
void kmc_open_img_file()
{
s_pimage = fopen("floppy.img", "rb");
if(NULL == s_pimage)
{
printf("Can not open file!");
}
}
int32_t kmc_read_sector(uint32_t index, uint8_t *buff)
{
uint32_t offset = 0;
int32_t num_of_bytes = 0;
offset = SIZE_OF_SECTOR * index;
fseek(s_pimage, SIZE_OF_SECTOR * index, SEEK_SET);
num_of_bytes = (int32_t)fread(buff, 1, SIZE_OF_SECTOR, s_pimage);
if (num_of_bytes == 0) printf("Fail");
return num_of_bytes;
}
and in main: (added header file)
int main()
{
kmc_open_img_file();
uint8_t *buff = NULL ;
int32_t a = kmc_read_sector(0, buff);
printf("%d", a);
kmc_close_img_file();
return 0;
}
Result :Fail and 0 byte.
Can anyone help me solve it without extern variable? (this is requirement too)

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++.

C version of OpenSSL EVP_BytesToKey method

I'm looking for C implementation of the OpenSSL EVP_BytesToKey function.
This is pseudo-code explanation of the EVP_BytesToKey method (in /doc/ssleay.txt of the OpenSSL source):
/* M[] is an array of message digests
* MD() is the message digest function */
M[0]=MD(data . salt);
for (i=1; i<count; i++) M[0]=MD(M[0]);
i=1
while (data still needed for key and iv)
{
M[i]=MD(M[i-1] . data . salt);
for (i=1; i<count; i++) M[i]=MD(M[i]);
i++;
}
If the salt is NULL, it is not used.
The digests are concatenated together.
M = M[0] . M[1] . M[2] .......
this is my code(MD() is sha512. And i need the key is 32 bytes and the iv is 16 bytes):
int main()
{
unsigned long long out[8];
unsigned char key[9] = {0x4b,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c};
int len, i;
len = sizeof(key);
sha512(out, key, len);
unsigned char a[sizeof(out)];
for (i = 0; i < count; i++)
{
long2char(out, a); // unsigned long long to unsigned char;
sha512(out, a, sizeof(out));
}
return 0;
}
After count times sha512(), the out is 64 bytes, so I think I don't need the rest of that pseudo-code. But the result is not correct, I don't know what went wrong.
I wish you can help me to figure it out. thanks!
I'm looking for C implementation of the OpenSSL EVP_BytesToKey function...
Perhaps you should just use the one OpenSSL provides? You know, the one called EVP_BytesToKey in evp_key.c (shown below).
OpenSSL 1.1.0c changed the digest algorithm used in some internal components. Formerly, MD5 was used, and 1.1.0 switched to SHA256. Be careful the change is not affecting you in both EVP_BytesToKey and commands like openssl enc
int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md,
const unsigned char *salt, const unsigned char *data,
int datal, int count, unsigned char *key,
unsigned char *iv)
{
EVP_MD_CTX *c;
unsigned char md_buf[EVP_MAX_MD_SIZE];
int niv, nkey, addmd = 0;
unsigned int mds = 0, i;
int rv = 0;
nkey = EVP_CIPHER_key_length(type);
niv = EVP_CIPHER_iv_length(type);
OPENSSL_assert(nkey <= EVP_MAX_KEY_LENGTH);
OPENSSL_assert(niv <= EVP_MAX_IV_LENGTH);
if (data == NULL)
return nkey;
c = EVP_MD_CTX_new();
if (c == NULL)
goto err;
for (;;) {
if (!EVP_DigestInit_ex(c, md, NULL))
goto err;
if (addmd++)
if (!EVP_DigestUpdate(c, &(md_buf[0]), mds))
goto err;
if (!EVP_DigestUpdate(c, data, datal))
goto err;
if (salt != NULL)
if (!EVP_DigestUpdate(c, salt, PKCS5_SALT_LEN))
goto err;
if (!EVP_DigestFinal_ex(c, &(md_buf[0]), &mds))
goto err;
for (i = 1; i < (unsigned int)count; i++) {
if (!EVP_DigestInit_ex(c, md, NULL))
goto err;
if (!EVP_DigestUpdate(c, &(md_buf[0]), mds))
goto err;
if (!EVP_DigestFinal_ex(c, &(md_buf[0]), &mds))
goto err;
}
i = 0;
if (nkey) {
for (;;) {
if (nkey == 0)
break;
if (i == mds)
break;
if (key != NULL)
*(key++) = md_buf[i];
nkey--;
i++;
}
}
if (niv && (i != mds)) {
for (;;) {
if (niv == 0)
break;
if (i == mds)
break;
if (iv != NULL)
*(iv++) = md_buf[i];
niv--;
i++;
}
}
if ((nkey == 0) && (niv == 0))
break;
}
rv = EVP_CIPHER_key_length(type);
err:
EVP_MD_CTX_free(c);
OPENSSL_cleanse(md_buf, sizeof(md_buf));
return rv;
}

Producer/consumer with bounded buffer

Could someone check my code and tell me if I am on the right track.. It seems like I am a bit lost.. if you see my errors, please let me know them..
What I am trying to do is to solve bounded buffer using my own semaphores as well as GCD.
Thanks in advance..
sema.c
void procure( Semaphore *semaphore ) {
pthread_mutex_lock(semaphore->mutex1);
while(semaphore->value <= 0)
pthread_cond_wait(&semaphore->condition, semaphore->mutex1);
semaphore->value--;
pthread_mutex_unlock(semaphore->mutex1);
}
void vacate( Semaphore *semaphore ) {
pthread_mutex_lock(semaphore->mutex1);
semaphore->value++;
pthread_cond_signal(&semaphore->condition);
pthread_mutex_unlock(semaphore->mutex1);
}
void init ( Semaphore *semaphore ){
semaphore->value = 1;
pthread_mutex_t myMutex;
semaphore->mutex1 = &myMutex;
pthread_mutex_init( semaphore->mutex1, NULL);
}
void destroy ( Semaphore *semaphore ) {
pthread_mutex_destroy(semaphore->mutex1);
}
and main.c
struct variables {
Semaphore *sem;
};
struct variables vars;
void constructer (int *buffer, int *in, int *out) {
init(vars.sem);
}
void deconstructer () {
destroy(vars.sem);
}
int rand_num_gen() {
uint_fast16_t buffer;
int file;
int *rand;
file = open("/dev/random", O_RDONLY);
while( 1 ) {
read(file, &buffer, sizeof(buffer));
printf("16 bit number: %hu\n", buffer );
*rand = (int) buffer;
close(file);
break;
}
return *rand;
}
void put_buffer( int* buffer, int* in, int* out ) {
buffer[*in] = rand_num_gen(); // produce
procure(vars.sem); // wait here
*in = (*in + 1) % BUF_SIZE;
vacate(vars.sem);
}
void get_buffer( int* buffer, int* in, int* out ) {
int value;
procure(vars.sem);
value = buffer[*out];
vacate(vars.sem);
*out = (*out + 1) % BUF_SIZE;
}
int main (void) {
int *in, *out, *buffer;
constructer(buffer, in, out);
dispatch_queue_t producer, consumer;
producer = dispatch_queue_create("put_buffer", NULL);
consumer = dispatch_queue_create("get_buffer", NULL);
dispatch_async(producer,
^{
int i;
do
{
put_buffer( buffer, in, out );
dispatch_async(consumer,
^{
get_buffer( buffer, in, out );
if (i == RUN_LENGTH) exit(EXIT_SUCCESS);
});
}
while (i < RUN_LENGTH);
});
dispatch_main();
deconstructer();
exit (0);
}
Your code has a bug. In the init function you assign the address of a local variable to semaphore->mutex1, and when the function returns this address will be invalid. Later you still use this address, so this leads to undefined behavior.
You must either allocate the memory for the mutex directly in the semaphore (without a pointer) or allocate the memory via malloc.
Update:
Your program has so many bugs that you should definitely pick an easier topic to learn the basic concepts about memory management, how to allocate, use and reference a buffer, do proper error handling, etc. Here is a slightly edited version of your code. It still won't work, but probably has some ideas that you should follow.
#include <limits.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
void procure(Semaphore *semaphore) {
pthread_mutex_lock(semaphore->mutex1);
while (semaphore->value <= 0)
pthread_cond_wait(&semaphore->condition, semaphore->mutex1);
semaphore->value--;
pthread_mutex_unlock(semaphore->mutex1);
}
void vacate(Semaphore *semaphore) {
pthread_mutex_lock(semaphore->mutex1);
semaphore->value++;
pthread_cond_signal(&semaphore->condition);
pthread_mutex_unlock(semaphore->mutex1);
}
struct variables {
mutex_t sem_mutex;
Semaphore sem;
};
struct variables vars;
void constructor(int *buffer, int *in, int *out) {
vars.sem.value = 1;
vars.sem.mutex1 = &vars.sem_mutex;
pthread_mutex_init(vars.sem.mutex1, NULL);
}
void deconstructor() {
pthread_mutex_destroy(&semaphore->mutex1);
}
int rand_num_gen() {
const char *randomfile = "/dev/random";
unsigned char buffer[2]; // Changed: always treat files as byte sequences.
FILE *f = fopen(randomfile, "rb");
// Changed: using stdio instead of raw POSIX file access,
// since the API is much simpler; you don't have to care
// about interrupting signals or partial reads.
if (f == NULL) { // Added: error handling
fprintf(stderr, "E: cannot open %s\n", randomfile);
exit(EXIT_FAILURE);
}
if (fread(buffer, 1, 2, f) != 2) { // Added: error handling
fprintf(stderr, "E: cannot read from %s\n", randomfile);
exit(EXIT_FAILURE);
}
fclose(f);
int number = (buffer[0] << CHAR_BIT) | buffer[1];
// Changed: be independent of the endianness of the system.
// This doesn't matter for random number generators but is
// still an important coding style.
printf("DEBUG: random number: %x\n", (unsigned int) number);
return number;
}
void put_buffer( int* buffer, int* in, int* out ) {
buffer[*in] = rand_num_gen(); // produce
procure(&vars.sem); // wait here
*in = (*in + 1) % BUF_SIZE;
vacate(&vars.sem);
}
void get_buffer( int* buffer, int* in, int* out ) {
int value;
procure(&vars.sem);
value = buffer[*out];
vacate(&vars.sem);
*out = (*out + 1) % BUF_SIZE;
}
int main (void) {
int inindex = 0, outindex = 0;
int buffer[BUF_SIZE];
constructor(buffer, &inindex, &outindex);
// Changed: provided an actual buffer and actual variables
// for the indices into the buffer.
dispatch_queue_t producer, consumer;
producer = dispatch_queue_create("put_buffer", NULL);
consumer = dispatch_queue_create("get_buffer", NULL);
dispatch_async(producer, ^{
int i;
do {
put_buffer(buffer, &inindex, &outindex);
dispatch_async(consumer, ^{
get_buffer(buffer, &inindex, &outindex);
if (i == RUN_LENGTH) exit(EXIT_SUCCESS);
});
} while (i < RUN_LENGTH);
});
dispatch_main();
deconstructor();
exit (0);
}
As I said, I didn't catch all the bugs.

Resources