Copy block device with multiple Threads - c

I am trying to figure out what am i doing wrong when trying to compare and copy device block with pthreads in parallel. it looks like i am getting out of SYNC and the compare phase is not working properly. any help will be appreciated
#ifndef __dbg_h__
#define __dbg_h__
#define _LARGEFILE64_SOURCE
#define _GNU_SOURCE
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/fs.h>
#include <pthread.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdint.h>
#ifdef NDEBUG
#define debug(M, ...)
#else
#define debug(M, ...) fprintf(stderr, "DEBUG %s %s %s:%d: " M "\n", __DATE__, __TIME__, __FILE__, __LINE__, ##__VA_ARGS__)
#endif
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
#define log_err(M, ...) fprintf(stderr, "[ERROR] %s %s (%s:%d: errno: %s) " M "\n", __DATE__, __TIME__, __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
#define log_warn(M, ...) fprintf(stderr, "[WARN] %s %s (%s:%d: errno: %s) " M "\n", __DATE__, __TIME__, __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
#define log_info(M, ...) fprintf(stderr, "[INFO] %s %s (%s:%d) " M "\n", __DATE__, __TIME__, __FILE__, __LINE__, ##__VA_ARGS__)
#endif
#define blksize 8192
void *compare_devices(void *arguments);
struct arg_struct {
char device_name_a[1024];
char device_name_b[1024];
off_t start_offset;
off_t end_offset;
int thread_number;
int sub_total;
};
int main(int argc, char **argv)
{
int fd;
long numblocks=0;
int i;
int err;
long total_different_size=0;
int number_of_threads=16;
struct arg_struct compare_devices_args[number_of_threads];
fd = open(argv[1], O_RDONLY);
ioctl(fd, BLKGETSIZE, &numblocks);
close(fd);
log_info("Number of blocks: %lu, this makes %.3f GB\n",
numblocks,
(double)numblocks * 512.0 / (1024 * 1024 * 1024));
//read_whole_device(argv[1]);
long number_of_bytes_per_thread;
number_of_bytes_per_thread=numblocks*512/(long)number_of_threads;
pthread_t tid[number_of_threads];
for (i=0; i<number_of_threads; i++) {
strcpy(compare_devices_args[i].device_name_a, argv[1]);
strcpy(compare_devices_args[i].device_name_b, argv[2]);
compare_devices_args[i].start_offset=(long)(i*number_of_bytes_per_thread);
compare_devices_args[i].end_offset=(long)((i+1)*number_of_bytes_per_thread-1);
compare_devices_args[i].thread_number=i+1;
err = pthread_create(&(tid[i]), NULL, &compare_devices,(void*)&compare_devices_args[i]);
if (err != 0) {
printf("\ncan't create thread :[%s]", strerror(err));
return -1;
}
}
for (i=0; i<number_of_threads; i++) {
pthread_join(tid[i], NULL);
total_different_size+=(long)compare_devices_args[i].sub_total;
}
printf ("Total of Different size between devices - %ld\n",total_different_size);
};
int read_n_bytes_from(int fd, off_t pos, char *buf, int n)
{
if (lseek(fd, pos, SEEK_SET) >= 0)
return read(fd, buf, n);
else
return -1;
}
void read_whole_device(char* device_name)
{
int fd;
char buf[1024*1024];
size_t size;
int counter=0;
log_info("reading device %s\n",device_name);
fd = open(device_name, O_RDONLY|O_NONBLOCK);
//ssize_t size = read(fd, &buf, 1024);
lseek(fd, 0, SEEK_SET);
while ( (size=read(fd, buf, 1024*1024)) > 0 ) {
printf("Read buffer %d - %d\n", size, counter);
counter++;
}
close(fd);
}
void write_block_to_device(int fd,off_t pos,char* buf, int n)
{
if (lseek(fd, pos, SEEK_SET) >= 0) {
//write
}
}
void compare_buffer(char* buf_first,char* buf_second,int length, int blk_size, int* result)
{
int i;
char buf_cpy[blk_size];
for (i=0; i<=(length/blk_size);i++)
{
if ( memcmp(buf_first+(blk_size*i), buf_second+(blk_size*i), blk_size) != 0) {
//printf ("Block %d is different\n",i);
result[i]=1;
}
else {
result[i]=0;
}
}
}
void *compare_devices(void *arguments)
{
struct arg_struct *args = arguments;
int fd_first,fd_second;
char buf_first[1024*1024];
char buf_second[1024*104];
int size_first,size_second;
int counter=0;
int result[128];
int memcmp_result;
int i;
off_t pos,pos_first,pos_second;
int total_number_of_different_blocks,difference_in_mb;
long number_of_mb_to_scan=0;
total_number_of_different_blocks=0;
log_info("Thread %d - compare devices %s,%s - start %ld end %ld\n",args->thread_number,args->device_name_a,args->device_name_b,args->start_offset,args->end_offset);
fd_first = open(args->device_name_a, O_RDONLY);
fd_second = open(args->device_name_b, O_RDONLY);
log_info("Thread %d - %d %d\n",args->thread_number,fd_first,fd_second);
log_info("Thread %d - before lseek - %ld %ld\n",args->thread_number,lseek(fd_first, 0, SEEK_CUR),lseek(fd_second, 0, SEEK_CUR));
lseek(fd_first, (off_t)args->start_offset, SEEK_SET);
lseek(fd_second, (off_t)args->start_offset, SEEK_SET);
log_info("Thread %d - after lseek - %ld %ld\n",args->thread_number,lseek(fd_first, 0, SEEK_CUR),lseek(fd_second, 0, SEEK_CUR));
log_info("Thread %d - start %ld , %ld\n",args->thread_number,lseek(fd_first, 0, SEEK_CUR),lseek(fd_second, 0, SEEK_CUR));
number_of_mb_to_scan=(args->end_offset-args->start_offset)/1024/1024;
log_info("Thread %d - Number of MB to scan %ld - start offset %ld\n",args->thread_number,number_of_mb_to_scan,lseek(fd_second, 0, SEEK_CUR));
memset(buf_first, 0, sizeof(buf_first));
memset(buf_second, 0, sizeof(buf_second));
while ( (size_first=read(fd_first, buf_first, 1024*1024)) > 0 ) {
size_second=read(fd_second,buf_second, 1024*1024);
pos_first=lseek(fd_first, 0, SEEK_CUR);
pos_second=lseek(fd_second, 0, SEEK_CUR);
log_info("Thread %d - fd (%d,%d) pos_first %lld, pos_second %lld (%d - %d) - read %d,%d\n",args->thread_number,fd_first,fd_second,(unsigned long long)pos_first-1024*1024,(unsigned long long)pos_second-1024*1024,sizeof(off_t),sizeof(pos),size_first,size_second);
//log_info("Thread %s - Hash Buf A - %ld Hash Buf B - %ld",args->thread_number,adler32(buf_first,size_first),adler32(buf_second,size_second));
if ( (memcmp_result=memcmp(buf_first, buf_second, sizeof(buf_second))) != 0 ) {
log_info("Thread %d - Found 1MB chunck which is different at pos %lld - %d (%d)\n",args->thread_number,(unsigned long long)pos_first-1024*1024, memcmp_result,sizeof(buf_first));
compare_buffer(buf_first,buf_second,1024*1024,blksize,result);
for (i=0; i<=128; i++) {
if ( result[i] == 1 ) {
//printf ("%d,",result[i]);
total_number_of_different_blocks++;
}
}
}
if ( pos_first > args->end_offset ) {
break;
}
memset(buf_first, 0, sizeof(buf_first));
memset(buf_second, 0, sizeof(buf_second));
counter++;
}
log_info("Thread %d - Number of MB to scan %ld - end offset %ld\n",args->thread_number,number_of_mb_to_scan,lseek(fd_first, 0, SEEK_CUR));
log_info("Thread %d - Completed - Scanning %d of 1MB chuncks\n",args->thread_number,counter);
log_info("Thread %d - Diffence of size between %s to %s starting at %ld and ending at %ld- %d different blocks of 8k - %dMB\n",args->thread_number,args->device_name_a,args->device_name_b,args->start_offset,args->end_offset,total_number_of_different_blocks,total_number_of_different_blocks*8192/1024/1024);
args->sub_total=total_number_of_different_blocks/8/1024;
close(fd_first);
close(fd_second);
pthread_exit(arguments);
}
Updated version:
#ifndef __dbg_h__
#define __dbg_h__
#define _LARGEFILE64_SOURCE
#define _GNU_SOURCE
#define _FILE_OFFSET_BITS 64
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/fs.h>
#include <pthread.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdint.h>
#include <getopt.h>
#include <openssl/sha.h>
#include <sched.h>
#ifdef NDEBUG
#define debug(M, ...)
#else
#define debug(M, ...) fprintf(stderr, "DEBUG %s %s %s:%d: " M "\n", __DATE__, __TIME__, __FILE__, __LINE__, ##__VA_ARGS__)
#endif
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
#define log_err(M, ...) fprintf(stderr, "[ERROR] %s %s (%s:%d: errno: %s) " M "\n", __DATE__, __TIME__, __FILE__, __LINE__, clean_er
rno(), ##__VA_ARGS__)
#define log_warn(M, ...) fprintf(stderr, "[WARN] %s %s (%s:%d: errno: %s) " M "\n", __DATE__, __TIME__, __FILE__, __LINE__, clean_er
rno(), ##__VA_ARGS__)
#define log_info(M, ...) fprintf(stderr, "[INFO] %s %s (%s:%d) " M "\n", __DATE__, __TIME__, __FILE__, __LINE__, ##__VA_ARGS__)
#endif
#ifndef _TRY_THROW_CATCH_H_
#define _TRY_THROW_CATCH_H_
#include <setjmp.h>
#define TRY do { jmp_buf ex_buf__; switch( setjmp(ex_buf__) ) { case 0: while(1) {
#define CATCH(x) break; case x:
#define FINALLY break; } default: {
#define ETRY break; } } }while(0)
#define THROW(x) longjmp(ex_buf__, x)
#endif /*!_TRY_THROW_CATCH_H_*/
unsigned long long chunck_size=1024*1024;
int blksize=16384;
int cb=0;
void *compare_devices(void *arguments);
struct arg_struct {
char device_name_a[1024];
char device_name_b[1024];
off64_t start_offset;
off64_t end_offset;
int thread_number;
int sub_total;
};
int main(int argc, char **argv)
{
int fd,s_is_set=0,d_is_set=0,copy_blocks=0,num_cpus;
int opt;
char *source_device,*dest_device,*blksize_string,*number_of_threads_string;
long numblocks_src=0,numblocks_dst=0;
int i;
int err,policy;
long total_different_size=0;
int number_of_threads=16;
int newprio, set_thread_priority=0;
pthread_attr_t tattr;
struct sched_param param;
while ((opt = getopt(argc, argv, "s:d:b:p:t:c")) != -1) {
switch (opt) {
case 's':
source_device = optarg;
log_info("source device is %s\n",source_device);
s_is_set=1;
if( access( source_device, F_OK ) != -1 ) {
log_info("source device is accessible\n");
}
else {
log_err("cannot access source device\n");
return -1;
}
break;
case 'd':
dest_device = optarg;
log_info("dest device is %s\n",dest_device);
d_is_set=1;
if( access( dest_device, F_OK ) != -1 ) {
log_info("dest device is accessible\n");
}
else {
log_err("cannot access dest device\n");
return -1;
}
break;
case 'b':
blksize = atoi(optarg);
if (blksize%4096 != 0) {
log_err("Block Size is not multiple of 4k\n");
return -1;
}
else
log_info("block size is %d\n",blksize);
break;
case 't':
number_of_threads = atoi(optarg);
num_cpus = sysconf( _SC_NPROCESSORS_ONLN );
if ( number_of_threads%2 != 0 ) {
log_err("Number of threads are not multiple of 2\n");
return -1;
}
else
log_info("number of threads is %d - number of cores %d\n",number_of_threads,num_cpus);
if ( number_of_threads > num_cpus ) {
number_of_threads=num_cpus;
}
break;
case 'c':
copy_blocks=1;
cb=1;
break;
case 'p':
if ( optarg != NULL ) {
newprio=atoi(optarg);
set_thread_priority=1;
}
break;
case ':':
log_info("%s: option '-%c' requires an argument\n",argv[0], optopt);
break;
case '?':
default:
log_info("%s: option '-%c' is invalid: ignored\n",argv[0], optopt);
break;
}
}
if ( s_is_set != 1 || d_is_set !=1 ) {
log_err("Source device and Destination device must be specified\n");
return -1;
}
struct arg_struct compare_devices_args[number_of_threads];
fd = open(source_device, O_RDONLY);
ioctl(fd, BLKGETSIZE, &numblocks_src);
close(fd);
log_info("Number of blocks in source device: %lu, this makes %.3f GB\n", numblocks_src, (double)numblocks_src * 512.0 / (1024 * 102
4 * 1024));
fd = open(dest_device, O_RDONLY);
ioctl(fd, BLKGETSIZE, &numblocks_dst);
close(fd);
log_info("Number of blocks in destination is device: %lu, this makes %.3f GB\n", numblocks_dst, (double)numblocks_dst * 512.0 / (10
24 * 1024 * 1024));
if ( numblocks_src > numblocks_dst ) {
log_info("Number of blocks in source device is larger then number of blocks in destination device");
return -1;
}
long number_of_bytes_per_thread;
number_of_bytes_per_thread=numblocks_src*512/(long)number_of_threads;
pthread_t tid[number_of_threads];
for (i=0; i<number_of_threads; i++) {
strcpy(compare_devices_args[i].device_name_a, source_device);
strcpy(compare_devices_args[i].device_name_b, dest_device);
compare_devices_args[i].start_offset=(long)(i*number_of_bytes_per_thread);
compare_devices_args[i].end_offset=(long)((i+1)*number_of_bytes_per_thread-1);
compare_devices_args[i].thread_number=i+1;
if ( set_thread_priority == 1 ) {
err = pthread_attr_init (&tattr);
policy = SCHED_RR;
err = pthread_attr_setschedpolicy(&tattr, policy);
if (err != 0) {
log_err("\nThread %d - Unable to set scheduler policy attributes :[%s]", i+1, strerror(err));
}
err = pthread_attr_getschedparam (&tattr, &param);
if (err != 0) {
log_err("\nThread %d - Unable to get scheduler priority attributes :[%s]", i+1, strerror(err));
}
log_info("\nThread %d - Old thread priority is %d",i+1,param.sched_priority);
param.sched_priority = newprio;
log_info("\nThread %d - Setting pthread priority to %d",i+1,newprio);
err = pthread_attr_setschedparam (&tattr, &param);
if (err != 0) {
log_err("\nThread %d - Unable to set scheduler attributes :[%s]", i+1, strerror(err));
}
err = pthread_create(&(tid[i]), &tattr, &compare_devices,(void*)&compare_devices_args[i]);
}
else
{
err = pthread_create(&(tid[i]), NULL, &compare_devices,(void*)&compare_devices_args[i]);
}
if (err != 0) {
log_err("\nThread %d - can't create thread :[%s]", i+1, strerror(err));
return -1;
}
}
for (i=0; i<number_of_threads; i++) {
pthread_join(tid[i], NULL);
total_different_size+=(long)compare_devices_args[i].sub_total;
}
log_info ("Total of Different size between devices - %ld\n",total_different_size);
};
void compare_buffer(char* buf_first,char* buf_second,int length, int blk_size, int* result)
{
int i;
char buf_cpy[blk_size];
for (i=0; i<=(length/blk_size);i++)
{
if ( memcmp(buf_first+(blk_size*i), buf_second+(blk_size*i), blk_size) != 0) {
result[i]=1;
}
else {
result[i]=0;
}
}
}
void *compare_devices(void *arguments)
{
struct arg_struct *args = arguments;
int fd_first,fd_second;
char buf_first[chunck_size];
char buf_second[chunck_size];
int size_first,size_second;
unsigned int counter=0;
int result[chunck_size/blksize];
int memcmp_result;
unsigned long long i;
off64_t pos,pos_first,pos_second;
unsigned long long total_number_of_different_blocks,difference_in_mb;
long number_of_mb_to_scan=0;
total_number_of_different_blocks=0;
log_info("Thread %d - compare devices %s,%s - start %llu end %llu\n",args->thread_number,args->device_name_a,args->device_nam
e_b,args->start_offset,args->end_offset);
fd_first = open(args->device_name_a, O_RDONLY);
if ( cb == 0 ) {
fd_second = open(args->device_name_b, O_RDONLY);
}
else
fd_second = open(args->device_name_b, O_RDWR);
lseek64(fd_first, (off64_t)args->start_offset, SEEK_SET);
lseek64(fd_second, (off64_t)args->start_offset, SEEK_SET);
number_of_mb_to_scan=(args->end_offset-args->start_offset)/chunck_size;
debug("Thread %d - Number of MB to scan %ld - start offset %ld\n",args->thread_number,number_of_mb_to_scan,lseek64(fd_second,
0, SEEK_CUR));
memset(buf_first, 0, sizeof(buf_first));
memset(buf_second, 0, sizeof(buf_second));
while ( (size_first=read(fd_first, buf_first, chunck_size)) > 0 && counter <= number_of_mb_to_scan ) {
size_second=read(fd_second,buf_second, chunck_size);
pos_first=lseek64(fd_first, 0, SEEK_CUR);
pos_second=lseek64(fd_second, 0, SEEK_CUR);
if ( (memcmp_result=memcmp(buf_first, buf_second, sizeof(buf_second))) != 0 ) {
debug("Thread %d - Found 1MB chunck which is different at pos %llu - %d (%d)\n",args->thread_number,(unsigned
long long)pos_first-chunck_size, memcmp_result,sizeof(buf_first));
compare_buffer(buf_first,buf_second,chunck_size,blksize,result);
for (i=0; i<=chunck_size/blksize; i++) {
if ( result[i] == 1 ) {
if ( cb == 1 ) {
debug("Thread %d - chunck %d - copying block %d - location of block in device file %llu",
args->thread_number, counter+1, i, args->start_offset+(unsigned long long)(chunck_size*counter)+(unsigned long long)(i*blksize));
lseek64(fd_first,args->start_offset+(off64_t)(chunck_size*counter)+(off64_t)(i*blksize),S
EEK_SET);
lseek64(fd_second,args->start_offset+(off64_t)(chunck_size*counter)+(off64_t)(i*blksize),
SEEK_SET);
size_first=read(fd_first, buf_first, blksize);
size_second=write(fd_second,buf_first,size_first);
if ( size_second != blksize ) {
log_err("Thread %d - Houston we have a problem in copying block number %llu",args->th
read_number, (unsigned long long)args->start_offset+(unsigned long long)(chunck_size*counter)+(unsigned long long)(i*blksize));
}
}
total_number_of_different_blocks++;
}
}
}
if ( cb == 1) {
lseek64(fd_second,(off64_t)args->start_offset+(off64_t)(chunck_size*(counter+1)),SEEK_SET);
lseek64(fd_first,(off64_t)args->start_offset+(off64_t)(chunck_size*(counter+1)),SEEK_SET);
}
if ( pos_first > args->end_offset ) {
break;
}
memset(buf_first, 0, sizeof(buf_first));
memset(buf_second, 0, sizeof(buf_second));
debug("Thread %d - chunck %d out of %d done - %llu %llu", args->thread_number, counter+1, number_of_mb_to_scan,pos_fi
rst,args->end_offset);
counter++;
}
log_info("Thread %d - Number of MB to scan %ld - end offset %llu\n",args->thread_number,number_of_mb_to_scan,lseek64(fd_first
, 0, SEEK_CUR));
log_info("Thread %d - Completed - Scanning %d of 1MB chuncks\n",args->thread_number,counter);
log_info("Thread %d - Difference of size between %s to %s starting at %llu and ending at %llu- %d different blocks of %d - %d
MB\n",args->thread_number,args->device_name_a,args->device_name_b,args->start_offset,args->end_offset,total_number_of_different_block
s,blksize,total_number_of_different_blocks*blksize/chunck_size);
args->sub_total=total_number_of_different_blocks*blksize/1024;
close(fd_first);
close(fd_second);
pthread_exit(arguments);
}

#ifndef __dbg_h__
#define __dbg_h__
#define _LARGEFILE64_SOURCE
#define _GNU_SOURCE
#define _FILE_OFFSET_BITS 64
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/fs.h>
#include <pthread.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdint.h>
#include <getopt.h>
#include <openssl/sha.h>
#include <sched.h>
#ifdef NDEBUG
#define debug(M, ...)
#else
#define debug(M, ...) fprintf(stderr, "DEBUG %s %s %s:%d: " M "\n", __DATE__, __TIME__, __FILE__, __LINE__, ##__VA_ARGS__)
#endif
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
#define log_err(M, ...) fprintf(stderr, "[ERROR] %s %s (%s:%d: errno: %s) " M "\n", __DATE__, __TIME__, __FILE__, __LINE__, clean_er
rno(), ##__VA_ARGS__)
#define log_warn(M, ...) fprintf(stderr, "[WARN] %s %s (%s:%d: errno: %s) " M "\n", __DATE__, __TIME__, __FILE__, __LINE__, clean_er
rno(), ##__VA_ARGS__)
#define log_info(M, ...) fprintf(stderr, "[INFO] %s %s (%s:%d) " M "\n", __DATE__, __TIME__, __FILE__, __LINE__, ##__VA_ARGS__)
#endif
#ifndef _TRY_THROW_CATCH_H_
#define _TRY_THROW_CATCH_H_
#include <setjmp.h>
#define TRY do { jmp_buf ex_buf__; switch( setjmp(ex_buf__) ) { case 0: while(1) {
#define CATCH(x) break; case x:
#define FINALLY break; } default: {
#define ETRY break; } } }while(0)
#define THROW(x) longjmp(ex_buf__, x)
#endif /*!_TRY_THROW_CATCH_H_*/
unsigned long long chunck_size=1024*1024;
int blksize=16384;
int cb=0;
void *compare_devices(void *arguments);
struct arg_struct {
char device_name_a[1024];
char device_name_b[1024];
off64_t start_offset;
off64_t end_offset;
int thread_number;
int sub_total;
};
int main(int argc, char **argv)
{
int fd,s_is_set=0,d_is_set=0,copy_blocks=0,num_cpus;
int opt;
char *source_device,*dest_device,*blksize_string,*number_of_threads_string;
long numblocks_src=0,numblocks_dst=0;
int i;
int err,policy;
long total_different_size=0;
int number_of_threads=16;
int newprio, set_thread_priority=0;
pthread_attr_t tattr;
struct sched_param param;
while ((opt = getopt(argc, argv, "s:d:b:p:t:c")) != -1) {
switch (opt) {
case 's':
source_device = optarg;
log_info("source device is %s\n",source_device);
s_is_set=1;
if( access( source_device, F_OK ) != -1 ) {
log_info("source device is accessible\n");
}
else {
log_err("cannot access source device\n");
return -1;
}
break;
case 'd':
dest_device = optarg;
log_info("dest device is %s\n",dest_device);
d_is_set=1;
if( access( dest_device, F_OK ) != -1 ) {
log_info("dest device is accessible\n");
}
else {
log_err("cannot access dest device\n");
return -1;
}
break;
case 'b':
blksize = atoi(optarg);
if (blksize%4096 != 0) {
log_err("Block Size is not multiple of 4k\n");
return -1;
}
else
log_info("block size is %d\n",blksize);
break;
case 't':
number_of_threads = atoi(optarg);
num_cpus = sysconf( _SC_NPROCESSORS_ONLN );
if ( number_of_threads%2 != 0 ) {
log_err("Number of threads are not multiple of 2\n");
return -1;
}
else
log_info("number of threads is %d - number of cores %d\n",number_of_threads,num_cpus);
if ( number_of_threads > num_cpus ) {
number_of_threads=num_cpus;
}
break;
case 'c':
copy_blocks=1;
cb=1;
break;
case 'p':
if ( optarg != NULL ) {
newprio=atoi(optarg);
set_thread_priority=1;
}
break;
case ':':
log_info("%s: option '-%c' requires an argument\n",argv[0], optopt);
break;
case '?':
default:
log_info("%s: option '-%c' is invalid: ignored\n",argv[0], optopt);
break;
}
}
if ( s_is_set != 1 || d_is_set !=1 ) {
log_err("Source device and Destination device must be specified\n");
return -1;
}
struct arg_struct compare_devices_args[number_of_threads];
fd = open(source_device, O_RDONLY);
ioctl(fd, BLKGETSIZE, &numblocks_src);
close(fd);
log_info("Number of blocks in source device: %lu, this makes %.3f GB\n", numblocks_src, (double)numblocks_src * 512.0 / (1024 * 102
4 * 1024));
fd = open(dest_device, O_RDONLY);
ioctl(fd, BLKGETSIZE, &numblocks_dst);
close(fd);
log_info("Number of blocks in destination is device: %lu, this makes %.3f GB\n", numblocks_dst, (double)numblocks_dst * 512.0 / (10
24 * 1024 * 1024));
if ( numblocks_src > numblocks_dst ) {
log_info("Number of blocks in source device is larger then number of blocks in destination device");
return -1;
}
long number_of_bytes_per_thread;
number_of_bytes_per_thread=numblocks_src*512/(long)number_of_threads;
pthread_t tid[number_of_threads];
for (i=0; i<number_of_threads; i++) {
strcpy(compare_devices_args[i].device_name_a, source_device);
strcpy(compare_devices_args[i].device_name_b, dest_device);
compare_devices_args[i].start_offset=(long)(i*number_of_bytes_per_thread);
compare_devices_args[i].end_offset=(long)((i+1)*number_of_bytes_per_thread-1);
compare_devices_args[i].thread_number=i+1;
if ( set_thread_priority == 1 ) {
err = pthread_attr_init (&tattr);
policy = SCHED_RR;
err = pthread_attr_setschedpolicy(&tattr, policy);
if (err != 0) {
log_err("\nThread %d - Unable to set scheduler policy attributes :[%s]", i+1, strerror(err));
}
err = pthread_attr_getschedparam (&tattr, &param);
if (err != 0) {
log_err("\nThread %d - Unable to get scheduler priority attributes :[%s]", i+1, strerror(err));
}
log_info("\nThread %d - Old thread priority is %d",i+1,param.sched_priority);
param.sched_priority = newprio;
log_info("\nThread %d - Setting pthread priority to %d",i+1,newprio);
err = pthread_attr_setschedparam (&tattr, &param);
if (err != 0) {
log_err("\nThread %d - Unable to set scheduler attributes :[%s]", i+1, strerror(err));
}
err = pthread_create(&(tid[i]), &tattr, &compare_devices,(void*)&compare_devices_args[i]);
}
else
{
err = pthread_create(&(tid[i]), NULL, &compare_devices,(void*)&compare_devices_args[i]);
}
if (err != 0) {
log_err("\nThread %d - can't create thread :[%s]", i+1, strerror(err));
return -1;
}
}
for (i=0; i<number_of_threads; i++) {
pthread_join(tid[i], NULL);
total_different_size+=(long)compare_devices_args[i].sub_total;
}
log_info ("Total of Different size between devices - %ld\n",total_different_size);
};
void compare_buffer(char* buf_first,char* buf_second,int length, int blk_size, int* result)
{
int i;
char buf_cpy[blk_size];
for (i=0; i<=(length/blk_size);i++)
{
if ( memcmp(buf_first+(blk_size*i), buf_second+(blk_size*i), blk_size) != 0) {
result[i]=1;
}
else {
result[i]=0;
}
}
}
void *compare_devices(void *arguments)
{
struct arg_struct *args = arguments;
int fd_first,fd_second;
char buf_first[chunck_size];
char buf_second[chunck_size];
int size_first,size_second;
unsigned int counter=0;
int result[chunck_size/blksize];
int memcmp_result;
unsigned long long i;
off64_t pos,pos_first,pos_second;
unsigned long long total_number_of_different_blocks,difference_in_mb;
long number_of_mb_to_scan=0;
total_number_of_different_blocks=0;
log_info("Thread %d - compare devices %s,%s - start %llu end %llu\n",args->thread_number,args->device_name_a,args->device_nam
e_b,args->start_offset,args->end_offset);
fd_first = open(args->device_name_a, O_RDONLY);
if ( cb == 0 ) {
fd_second = open(args->device_name_b, O_RDONLY);
}
else
fd_second = open(args->device_name_b, O_RDWR);
lseek64(fd_first, (off64_t)args->start_offset, SEEK_SET);
lseek64(fd_second, (off64_t)args->start_offset, SEEK_SET);
number_of_mb_to_scan=(args->end_offset-args->start_offset)/chunck_size;
debug("Thread %d - Number of MB to scan %ld - start offset %ld\n",args->thread_number,number_of_mb_to_scan,lseek64(fd_second,
0, SEEK_CUR));
memset(buf_first, 0, sizeof(buf_first));
memset(buf_second, 0, sizeof(buf_second));
while ( (size_first=read(fd_first, buf_first, chunck_size)) > 0 && counter <= number_of_mb_to_scan ) {
size_second=read(fd_second,buf_second, chunck_size);
pos_first=lseek64(fd_first, 0, SEEK_CUR);
pos_second=lseek64(fd_second, 0, SEEK_CUR);
if ( (memcmp_result=memcmp(buf_first, buf_second, sizeof(buf_second))) != 0 ) {
debug("Thread %d - Found 1MB chunck which is different at pos %llu - %d (%d)\n",args->thread_number,(unsigned
long long)pos_first-chunck_size, memcmp_result,sizeof(buf_first));
compare_buffer(buf_first,buf_second,chunck_size,blksize,result);
for (i=0; i<=chunck_size/blksize; i++) {
if ( result[i] == 1 ) {
if ( cb == 1 ) {
debug("Thread %d - chunck %d - copying block %d - location of block in device file %llu",
args->thread_number, counter+1, i, args->start_offset+(unsigned long long)(chunck_size*counter)+(unsigned long long)(i*blksize));
lseek64(fd_first,args->start_offset+(off64_t)(chunck_size*counter)+(off64_t)(i*blksize),S
EEK_SET);
lseek64(fd_second,args->start_offset+(off64_t)(chunck_size*counter)+(off64_t)(i*blksize),
SEEK_SET);
size_first=read(fd_first, buf_first, blksize);
size_second=write(fd_second,buf_first,size_first);
if ( size_second != blksize ) {
log_err("Thread %d - Houston we have a problem in copying block number %llu",args->th
read_number, (unsigned long long)args->start_offset+(unsigned long long)(chunck_size*counter)+(unsigned long long)(i*blksize));
}
}
total_number_of_different_blocks++;
}
}
}
if ( cb == 1) {
lseek64(fd_second,(off64_t)args->start_offset+(off64_t)(chunck_size*(counter+1)),SEEK_SET);
lseek64(fd_first,(off64_t)args->start_offset+(off64_t)(chunck_size*(counter+1)),SEEK_SET);
}
if ( pos_first > args->end_offset ) {
break;
}
memset(buf_first, 0, sizeof(buf_first));
memset(buf_second, 0, sizeof(buf_second));
debug("Thread %d - chunck %d out of %d done - %llu %llu", args->thread_number, counter+1, number_of_mb_to_scan,pos_fi
rst,args->end_offset);
counter++;
}
log_info("Thread %d - Number of MB to scan %ld - end offset %llu\n",args->thread_number,number_of_mb_to_scan,lseek64(fd_first
, 0, SEEK_CUR));
log_info("Thread %d - Completed - Scanning %d of 1MB chuncks\n",args->thread_number,counter);
log_info("Thread %d - Difference of size between %s to %s starting at %llu and ending at %llu- %d different blocks of %d - %d
MB\n",args->thread_number,args->device_name_a,args->device_name_b,args->start_offset,args->end_offset,total_number_of_different_block
s,blksize,total_number_of_different_blocks*blksize/chunck_size);
args->sub_total=total_number_of_different_blocks*blksize/1024;
close(fd_first);
close(fd_second);
pthread_exit(arguments);
}

Related

C language : gethostbyaddr() return : Operation not permitted

Currently i'm trying to make a ping-like program and it work pretty good but i've a probleme on the DNS_lookup()
Here is my function :
char *DNS_reverse_lookup(struct sockaddr_in *host_addr)
{
if (host_addr == NULL)
{
printf("host_addr is empty.\n");
return NULL;
}
struct hostent *host_info = NULL;
host_info = gethostbyaddr(&host_addr->sin_addr.s_addr, sizeof(*host_addr), host_addr->sin_family);
if (host_info == NULL)
{
printf("%s:%d : gethostbyaddr() failed : %s\n", __FILE__, __LINE__, strerror(h_errno));
return NULL;
}
return host_info->h_name;
}
Here the gethostbyaddr() return Operation not permitted for some domain for exemple for google.com but for my ovh server it return the expected result and i don't know why
someone can explain ?
Here's all of my code :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/time.h>
#include <time.h>
#include <netinet/ip_icmp.h>
#include <signal.h>
#include <ifaddrs.h>
#include "globaldata/gd.h"
#include "netsocket/netsocket.h"
// packet size
#define PING_PKT_S 64
// Automatic port number
#define PORT_NB 0
#define PING_SLEEP_RATE 1000000
// Give the timeout delay for receiving packets
// In seconds
#define RECV_TIMEOUT 2
struct icmp_pkt {
struct icmphdr header;
char msg[PING_PKT_S - sizeof(struct icmphdr)];
};
void sigintHandler(int sig_num);
unsigned short checksum(void *b, int len);
struct sockaddr_in *DNS_lookup(char *host_domain_name);
char *DNS_reverse_lookup(struct sockaddr_in *host_addr);
void send_ping(Socket_t *socket, char *ping_ip, char *host_domain_name);
GlobalData gd;
int main(int argc, char *argv[])
{
/* Declaration */
// information about the host
struct sockaddr_in *host_addr = NULL;
socklen_t host_addr_len = sizeof(*host_addr);
Socket_t *socket = NULL;
char *host_domain_name;
int opt_value = 0, i = 0;
FILE *socket_file = NULL;
int arg_port = 0;
int port = 0;
struct ifaddrs *ifaces;
struct ifaddrs *tmp = NULL;
/* Allocation */
socket = SOCKET_New();
/* Initialisation */
// Correct syntax
if (argc < 2)
{
printf("\nFormat %s <address>\n", argv[0]);
goto FatalError;
}
for (i = 0 ; argv[i] != 0 ; i++)
{
if (strcmp(argv[i], "-p") == 0)
{
arg_port = i;
}
}
if (arg_port)
{
port = atoi(argv[arg_port+1]);
printf("port = %d\n", port);
}
// loop while the ping is performed
gd.ping_loop = 1;
// Open socket
if (SOCKET_OpenSocket(socket, AF_INET, SOCK_RAW, IPPROTO_ICMP) == NULL)
{
printf("SOCKET_OpenSocket() failed.\n");
goto FatalError;
}
opt_value = 1;
if (setsockopt(socket->sockfd, SOL_SOCKET, SO_REUSEADDR, &opt_value, sizeof(opt_value)) == -1)
{
printf("setsockopt() failed : %s\n", strerror(errno));
}
if (SOCKET_SetAddr(socket, inet_addr(argv[1]), AF_INET, port, 5) == NULL)
{
printf("SOCKET_SetAddr() failed?\n");
goto FatalError;
}
// Get host domain name (if there is)
host_domain_name = DNS_reverse_lookup(&socket->addr);
if (host_domain_name == NULL)
{
printf("DNS_reverse_lookup() failed.\n");
host_domain_name = 0;
// goto FatalError;
}
printf("host domain name = %s (%s)\n", host_domain_name, argv[1]);
// printf("\nsockaddr :\nIP = %x\nPort = %d\nFamily = %d\n", socket->addr.sin_addr.s_addr, socket->addr.sin_port, socket->addr.sin_family);
// if (SOCKET_BindToSocket(socket) == NULL)
// {
// printf("SOCKET_BindToSocket() failed.\n");
// goto FatalError;
// }
// handle interrupt signal
signal(SIGINT, sigintHandler);
send_ping(socket, argv[1], host_domain_name);
/* Leave */
if (socket != NULL)
{
if (socket->sockfd > 0)
{
shutdown(socket->sockfd, SHUT_RDWR);
close(socket->sockfd);
printf("\nsocket closed.\n");
}
socket = SOCKET_Free(socket);
}
printf("Terminated : Without Error.\n");
return EXIT_SUCCESS;
FatalError:
if (socket != NULL)
{
if (socket->sockfd > 0)
{
shutdown(socket->sockfd, SHUT_RDWR);
close(socket->sockfd);
printf("\nsocket closed.\n");
}
socket = SOCKET_Free(socket);
}
printf("Terminated : Fatal Error.\n");
return EXIT_FAILURE;
}
void sigintHandler(int sig_num)
{
gd.ping_loop = 0;
}
unsigned short checksum(void *b, int len)
{
unsigned short *buf = b;
unsigned int sum = 0;
unsigned short result;
for (sum = 0 ; len > 1 ; len -= 2)
{
sum += *buf++;
}
if (len == 1)
{
sum += *(unsigned char *)buf;
}
sum = (sum >> 16) + (sum & 0xFFFF);
sum += (sum >> 16);
result = ~sum;
return result;
}
// Return struct sockaddr_in *ptr on success or 0 on error
struct sockaddr_in *DNS_lookup(char *host_domain_name)
{
printf("\nResolving DNS...\n");
// store host info in struct hostent
struct hostent *host_info = NULL;
static struct sockaddr_in host_addr;
memset(&host_addr, 0, sizeof(host_addr));
if ((host_info = gethostbyname(host_domain_name)) == NULL)
{
printf("%s:%d : gethostbyname() failed %s\n", __FILE__, __LINE__, strerror(h_errno));
return NULL;
}
host_addr.sin_addr.s_addr = inet_addr(host_info->h_addr_list[0]);
host_addr.sin_family = host_info->h_addrtype;
host_addr.sin_port = htons(PORT_NB);
printf("Resolved.\n\n");
return &host_addr;
}
// Return char *host_domain_name on success or 0 on error
char *DNS_reverse_lookup(struct sockaddr_in *host_addr)
{
if (host_addr == NULL)
{
printf("host_addr is empty.\n");
return NULL;
}
struct hostent *host_info = NULL;
host_info = gethostbyaddr(&host_addr->sin_addr.s_addr, sizeof(*host_addr), host_addr->sin_family);
if (host_info == NULL)
{
printf("%s:%d : gethostbyaddr() failed : %s\n", __FILE__, __LINE__, strerror(h_errno));
return NULL;
}
return host_info->h_name;
}
void send_ping(Socket_t *socket, char *ping_ip, char *host_domain_name)
{
if (socket == NULL)
{
printf("%s:%d : Bad socket.\n", __FILE__, __LINE__);
return;
}
if (socket->sockfd <= 0)
{
printf("%s:%d : Bad socket file descriptor.\n", __FILE__, __LINE__);
}
int ttl_value, msg_count, i, addr_len, flag, msg_received_count;
struct icmp_pkt packet;
struct sockaddr_in r_addr;
long double rtt_msec, total_msec;
struct timespec time_start, time_end, tfs, tfe;
struct timeval tv_out;
tv_out.tv_sec = RECV_TIMEOUT;
tv_out.tv_usec = 0;
ttl_value = 64;
msg_count = 0;
i = 0;
addr_len = 0;
flag = 1;
msg_received_count = 0;
rtt_msec = total_msec = 0.0;
// time start
clock_gettime(CLOCK_MONOTONIC, &tfs);
// SOL = Set Option Level
// SO = Set Option
// Set time to live value
if (setsockopt(socket->sockfd, SOL_IP, IP_TTL, &ttl_value, sizeof(ttl_value)) == -1)
{
printf("%s:%d : setsockopt() failed : %s\n", __FILE__, __LINE__, strerror(errno));
return;
}
printf("Socket set to TTL : %d\n", ttl_value);
// Set timeout of receiving setting
if (setsockopt(socket->sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv_out, sizeof(tv_out)) == -1)
{
printf("%s:%d : setsockopt() failed : %s\n", __FILE__, __LINE__, strerror(errno));
return;
}
printf("Ping to %s (%s).\n", host_domain_name, ping_ip);
while (gd.ping_loop)
{
// flag is whether packet was sent or not
flag = 1;
// filling packet
memset(&packet, 0, sizeof(packet));
packet.header.type = ICMP_ECHO;
packet.header.un.echo.id = getpid();
for (i = 0 ; i < sizeof(packet.msg) ; i++)
{
packet.msg[i] = '\0';
}
char message[] = "Anything";
strncpy(packet.msg, message, strlen(message));
packet.header.un.echo.sequence = msg_count++;
packet.header.checksum = checksum(&packet, sizeof(packet));
usleep(PING_SLEEP_RATE);
// send packet
clock_gettime(CLOCK_MONOTONIC, &time_start);
// if (write(socket->sockfd, &packet, sizeof(packet)) == -1)
// {
// printf("%s:%d : write() failed : %s\n", __FILE__, __LINE__, strerror(errno));
// flag = 0;
// }
if (sendto(socket->sockfd, &packet, sizeof(packet), 0, (struct sockaddr *)&socket->addr, socket->addr_len) == -1)
{
printf("%s:%d : sento() failed : %s\n", __FILE__, __LINE__, strerror(errno));
return;
}
// receiving packet
// printf("reading packet...\n");
// if (read(socket->sockfd, &packet, sizeof(packet)) == -1 && msg_count > 1)
// {
// printf("%s:%d : read() failed : %s\n", __FILE__, __LINE__, strerror(errno));
// flag = 0;
// }
if (recvfrom(socket->sockfd, &packet, sizeof(packet), 0, (struct sockaddr *)&socket->addr, &socket->addr_len) == -1)
{
printf("%s:%d : recvfrom() failed : %s\n", __FILE__, __LINE__, strerror(errno));
return;
}
else
{
clock_gettime(CLOCK_MONOTONIC, &time_end);
double time_elapsed = ((double)time_end.tv_nsec - (double)time_start.tv_nsec) / 1000000.0;
printf("time elapsed = %.4f\n", time_elapsed);
rtt_msec = (double)(time_end.tv_sec - time_start.tv_sec) * 1000.0 + time_elapsed;
// case packet wasn't sent or received
if (!flag)
{
printf("%s:%d : ERROR : Packet received with ICMP type %d code %d\n", __FILE__, __LINE__, packet.header.type, packet.header.code);
}else{
printf("%d bytes from %d (h: %s) (%s) msg_seq=%d ttl=%d rtt = %Lf ms.\n", PING_PKT_S, socket->addr.sin_family, host_domain_name, ping_ip, msg_count, ttl_value, rtt_msec);
msg_received_count++;
}
}
}
clock_gettime(CLOCK_MONOTONIC, &tfe);
double time_elapsed = ((double)(tfe.tv_nsec - tfs.tv_nsec)) / 1000000.0;
total_msec = (tfe.tv_sec - tfs.tv_sec) * 1000 + time_elapsed;
printf("\n===%s ping statistics===\n", ping_ip);
printf("\n%d packets sent, %d packets received, %f percent packet loss. Total time: %Lf ms.\n\n", msg_count, msg_received_count, (double)((msg_count - msg_received_count)/msg_count) * 100.0, total_msec);
}
terminal exec :
kali#kali:~/Code/Network/Ping$ sudo ./pingto 151.101.65.69
main.c:232 : gethostbyaddr() failed : Operation not permitted
DNS_reverse_lookup() failed.
host domain name = (null) (151.101.65.69)
Socket set to TTL : 64
Ping to (null) (151.101.65.69).
time elapsed = 8.1787
64 bytes from 2 (h: (null)) (151.101.65.69) msg_seq=1 ttl=64 rtt = 8.178748 ms.
time elapsed = 7.9054
64 bytes from 2 (h: (null)) (151.101.65.69) msg_seq=2 ttl=64 rtt = 7.905438 ms.
time elapsed = 8.2425
64 bytes from 2 (h: (null)) (151.101.65.69) msg_seq=3 ttl=64 rtt = 8.242489 ms.
^Ctime elapsed = 7.9805
64 bytes from 2 (h: (null)) (151.101.65.69) msg_seq=4 ttl=64 rtt = 7.980547 ms.
===151.101.65.69 ping statistics===
4 packets sent, 4 packets received, 0.000000 percent packet loss. Total time: 3494.951433 ms.
socket closed.
Terminated : Without Error.
You're not decoding the error code properly.
The values of h_errno do not correspond to the values that errno correspond to, so you can't use strerror to get the error text.
There is a function called hstrerror that does the same as strerror but for error codes returned by gethostbyname and other related functions.
The error codes listed in the man page are as follows:
HOST_NOT_FOUND
The specified host is unknown.
NO_ADDRESS or NO_DATA
The requested name is valid but does not have an IP address.
NO_RECOVERY
A nonrecoverable name server error occurred.
TRY_AGAIN
A temporary error occurred on an authoritative name server. Try
again later.
The "operation not permitted" code is EPERM, which on my system is 1. That code corresponds on my system to HOST_NOT_FOUND, so assuming your error codes are the same that's the actual error you're seeing.

system V message queue vs. posix message queue test

I have tested two scenarios:
system V message queue: sending 1,000,000 message "hello" with msgsend() and getting them from another process with msgget()
posix message queue: sending 1,000,000 message "hello" with mq_send() and getting them from another process with mq_receive()
then in both scenarios, I've calculated CPU processing time for sending messages into queue.
system V mq CPU push time: 0.8(sec)
posix mq CPU push time: 1.4(sec) (!)
code for system V:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <time.h>
#define EXPERIMENT_COUNT 100
clock_t start, end;
double cpu_time_useda_avg = 0;
double cpu_time_used;
struct mesg_buffer {
long mesg_type;
char mesg_text[100];
} message;
int run_sending_app()
{
key_t key;
int msgid;
// ftok to generate unique key
key = ftok("/var/tmp/progfile", 65);
// msgget creates a message queue
// and returns identifier
msgid = msgget(key, 0666 | IPC_CREAT);
message.mesg_type = 1;
// printf("Write Data : ");
// fgets(message.mesg_text, sizeof(message.mesg_text), stdin);
strcpy(message.mesg_text, "hello");
int e,i;
for( e = 0; e < EXPERIMENT_COUNT; e++ )
{
start = clock();
for(i = 0; i != 1000000; i++)
msgsnd(msgid, &message, sizeof(message), 0);
end = clock();
cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
printf("cpu_time_used = %f\n", cpu_time_used);
cpu_time_useda_avg += cpu_time_used;
}
printf("cpu_time_useda_avg = %f\n", cpu_time_useda_avg/EXPERIMENT_COUNT);
// // display the message
// printf("Data send is : %s \n", message.mesg_text);
return 0;
}
int run_receiving_app()
{
key_t key;
int msgid;
// ftok to generate unique key
key = ftok("/var/tmp/progfile", 65);
// msgget creates a message queue
// and returns identifier
msgid = msgget(key, 0666 | IPC_CREAT);
while(1)
{
// msgrcv to receive message
msgrcv(msgid, &message, sizeof(message), 0, 0);
// // display the message
// printf("Data Received is : %s \n",
// message.mesg_text);
}
// to destroy the message queue
msgctl(msgid, IPC_RMID, NULL);
return 0;
}
int main(int argc, char const *argv[])
{
if( argc > 1 )
if( !strcasecmp(argv[1], "cli") )
run_sending_app();
else if( !strcasecmp(argv[1], "serv") )
run_receiving_app();
return 0;
}
code for Posix:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <mqueue.h>
#include <time.h>
#define EXPERIMENT_COUNT 100
clock_t start, end;
double cpu_time_useda_avg = 0;
double cpu_time_used;
#define QUEUE_NAME "/test_queue"
#define MAX_SIZE 1024
#define MSG_STOP "exit"
#define CHECK(x) \
do { \
if (!(x)) { \
fprintf(stderr, "%s:%d: ", __func__, __LINE__); \
perror(#x); \
exit(-1); \
} \
} while (0) \
int mq_run_server()
{
mqd_t mq;
struct mq_attr attr;
char buffer[MAX_SIZE + 1];
int must_stop = 0;
/* initialize the queue attributes */
attr.mq_flags = 0;
attr.mq_maxmsg = 1000000;
attr.mq_msgsize = MAX_SIZE;
attr.mq_curmsgs = 0;
/* create the message queue */
// mq_unlink(QUEUE_NAME); exit(0);
mq = mq_open(QUEUE_NAME, O_CREAT | O_RDONLY, 0644, &attr);
CHECK((mqd_t)-1 != mq);
do {
ssize_t bytes_read;
/* receive the message */
bytes_read = mq_receive(mq, buffer, MAX_SIZE, NULL);
CHECK(bytes_read >= 0);
buffer[bytes_read] = '\0';
if (! strncmp(buffer, MSG_STOP, strlen(MSG_STOP)))
{
must_stop = 1;
}
else
{
// printf("Received: %s\n", buffer);
}
} while (!must_stop);
/* cleanup */
CHECK((mqd_t)-1 != mq_close(mq));
CHECK((mqd_t)-1 != mq_unlink(QUEUE_NAME));
return 0;
}
int mq_run_client()
{
mqd_t mq;
char buffer[MAX_SIZE];
/* open the mail queue */
mq = mq_open(QUEUE_NAME, O_WRONLY);
CHECK((mqd_t)-1 != mq);
strcpy(buffer, "hello");
int e,i;
for( e = 0; e < EXPERIMENT_COUNT; e++ )
{
start = clock();
for(i = 0; i != 1000000; i++)
mq_send(mq, buffer, MAX_SIZE, 0);
end = clock();
cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
printf("cpu_time_used = %f\n", cpu_time_used);
cpu_time_useda_avg += cpu_time_used;
}
printf("cpu_time_useda_avg = %f\n", cpu_time_useda_avg/EXPERIMENT_COUNT);
// printf("Send to server (enter \"exit\" to stop it):\n");
//
// do {
// printf("> ");
// fflush(stdout);
// memset(buffer, 0, MAX_SIZE);
// fgets(buffer, MAX_SIZE, stdin);
// /* send the message */
// CHECK(0 <= mq_send(mq, buffer, MAX_SIZE, 0));
// } while (strncmp(buffer, MSG_STOP, strlen(MSG_STOP)));
/* cleanup */
CHECK((mqd_t)-1 != mq_close(mq));
return 0;
}
int main(int argc, char const *argv[])
{
if( argc > 1 )
if( !strcasecmp(argv[1], "serv") )
mq_run_server();
else if( !strcasecmp(argv[1], "cli") )
mq_run_client();
return 0;
}
In both cases if I run ./a.out serv, server side runs and if I run ./a.out cli, client side runs.
My Question
Why Posix MQ performance is so low in comparing with System V MQ, while the http://man7.org/linux/man-pages/man7/mq_overview.7.html says that Posix MQ is very similar to system V MQ?!
Try changing:
mq_send(mq, buffer, MAX_SIZE, 0);
to
mq_send(mq, buffer, 104, 0);
or
#define MAX_SIZE 104
So that you are comparing the same data bulk.

select() and read() times out on serial port read yet previous write() succeeds?

After three weeks I can't get past this problem.
I have the code below running on Ubuntu 18.04.3 which sends a string successfully to another device.
When the remote device receives the string ... it sends another back ... but the code below (even with 1 sec set) times out on select().
When I comment out the select() and just do the read() ... fails to see any data as well?
It was working three weeks ago ... but recent code changes broke it ... and I cannot see why.
How could a write() on a file descriptor go out the serial port ok ... but a select() and read() using the same file descriptor get nothing back.
I have a third device (a PC with putty) so I can see everything on the wire.
All three are on an RS-485 bus.
Any other issues with the code would be greatly appreciated!
Thanks!
// main.c
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <term.h>
#include <signal.h>
#include <sys/time.h>
#include "SER.h"
static
struct sigaction mySigActTerm;
volatile
int terminate = 0;
void terminateHandler(int signum, siginfo_t *info, void *ptr)
{
//------------------------------------------------------------
// set a flag here and get out.
terminate = 1;
}
int main()
{
int rtn;
pthread_t serialThdID;
SER* mySER;
//------------------------------------------------------------
// setup terminate signal
memset(&mySigActTerm, 0, sizeof(mySigActTerm));
mySigActTerm.sa_sigaction = terminateHandler;
mySigActTerm.sa_flags = SA_SIGINFO;
sigaction(SIGTERM, &mySigActTerm, NULL);
//------------------------------------------------------------
// initialize the serial port.
mySER = SERinit("/dev/ttyUSB0", 2);
if (mySER == NULL)
{
fprintf(stderr, "main() - SERinit() returned NULL");
exit(EXIT_FAILURE);
}
//------------------------------------------------------------
// start the serial thread.
rtn = pthread_create(&serialThdID, NULL, serialThread, mySER);
if(rtn == 0)
fprintf(stderr, "starting serial thread.\n");
else
{
fprintf(stderr, "main() - pthread_create() returned %d\n%s\n", rtn, strerror(errno));
free(mySER);
exit(EXIT_FAILURE);
}
//------------------------------------------------------------
// wait till serialThread() indicates it is running.
while (mySER->ThreadStatus != threadRuning)
{
fprintf(stderr, "waiting for thread running status.\n");
sleep(1);
}
//------------------------------------------------------------
// main loop here.
while (terminate == 0)
{
// do stuff here.
}
//------------------------------------------------------------
// tell the serial thread to stop.
mySER->ThreadCtrl = threadCtrlKill;
//------------------------------------------------------------
// verify serial thread is dead!
while (mySER->ThreadStatus != threadStopped)
{
}
//------------------------------------------------------------
// clean up.
SERclose(mySER);
free(mySER);
}
serialThread.c
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <sys/time.h>
#include <term.h>
#include <inttypes.h>
#include "SER.h"
void* serialThread(void* arg)
{
char* rtn;
SER* mySER = arg;
mySER->tid = pthread_self();
mySER->ThreadStatus = threadRuning;
// thread Loop!
while(mySER->ThreadCtrl != threadCtrlKill)
{
rtn = SERwrapperFunc(mySER);
// code to print the response here
printf("%.*s\n", 8, rtn);
sleep(30);
}
mySER->ThreadStatus = threadStopped;
pthread_exit(NULL);
}
SERmaster.c
#define responseSize 4584
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <termios.h>
//#include <linux/serial.h>
//#include <aio.h>
#include <sys/time.h>
#include "SER.h"
// array used to get termios BAUD.
const
int BAUDarray[9] = { 0, // not used.
B4800, // 208
B9600, // 104
B19200, // 52
B38400, // 26
B57600, // 17.363636
B115200, // 8.727272
B230400, // 4.363636
B460800 // 2.181818
};
// delay (in uS) per character transmitted.
// 1 start, Even parity, 7bits, 1 stop.
// bit time (times 10 bits)
// Plus one bit time between characters.
const
int BAUDdelay[9] = { 0, // not used.
2288,
1144,
572,
286,
191,
96,
48,
24
};
static
char response[4584];
static
unsigned
int respIndex;
static
struct termios newtio, oldtio;
extern
volatile
int terminate;
static
int sendRecieve(SER* mySER, const char* msgBuffer, int msgCnt, int sendFlag, int receiveFlag)
{
int rtn;
char myChar;
fd_set myfds;
struct
timeval tm_out;
if (sendFlag == true)
{
while (1)
{
rtn = write(mySER->sfd, msgBuffer, msgCnt);
if (rtn == -1)
{
if (errno == EINTR)
{
fprintf(stderr, "sendRecieve() - write() EINTR !\n");
if (terminate == 1)
break; // deal with SIGTERM !
continue; // if not SIGTERM then retry.
}
else
{
fprintf(stderr, "sendRecieve() - write()\n%s\n", strerror(errno));
return EXIT_FAILURE;
}
}
else
{
if (rtn == msgCnt)
break;
else
{
fprintf(stderr, "sendRecieve() - write() returned less than msgCnt !\n");
return EXIT_FAILURE;
}
}
}
}
if (receiveFlag == true)
{
respIndex = 0;
while (1)
{
tm_out.tv_sec = 1;
tm_out.tv_usec = mySER->BAUDmult * msgCnt;
FD_ZERO(&myfds);
FD_SET(mySER->sfd, &myfds);
rtn = select(mySER->sfd + 1, &myfds, NULL, NULL, &tm_out);
if (rtn == 0)
{
fprintf(stderr, "sendRecieve() - select() timeout!\n");
return EXIT_FAILURE;
}
if (rtn == -1)
{
if (errno == EINTR)
{
fprintf(stderr, "sendRecieve() - select() EINTR !\n");
if (terminate == 1)
break;
continue;
}
else
{
fprintf(stderr, "sendRecieve() - select()\n%s\n", strerror(errno));
return EXIT_FAILURE;
}
}
while (1)
{
rtn = read(mySER->sfd, &myChar, 1);
if (rtn == -1)
{
if (errno == EINTR)
{
fprintf(stderr, "sendRecieve() - read() EINTR !\n");
if (terminate == 1)
break;
continue;
}
else
{
fprintf(stderr, "sendRecieve() - read()\n%s\n", strerror(errno));
return EXIT_FAILURE;
}
}
else
break;
response[respIndex] = myChar;
if (respIndex < responseSize - 1)
respIndex++;
else
break;
if (myChar == '\n')
return EXIT_SUCCESS;
}
}
fprintf(stderr, "sendRecieve() - select/read while loop Dumped (response frame too big)!!\n");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
char* SERwrapperFunc(SER* mySER)
{
char myCharArray[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' };
int myCharArrayCountToSend = sizeof(myCharArray);
sendRecieve(mySER, myCharArray, myCharArrayCountToSend, true, true);
return response;
}
void serPrint()
{
printf("NCCS = %d OLD: NEW:\n", NCCS);
printf("c_iflag - %08x %08x\n", oldtio.c_iflag, newtio.c_iflag);
printf("c_oflag - %08x %08x\n", oldtio.c_oflag, newtio.c_oflag);
printf("c_cflag - %08x %08x\n", oldtio.c_cflag, newtio.c_cflag);
printf("c_lflag - %08x %08x\n", oldtio.c_lflag, newtio.c_lflag);
printf("c_line - %08x %08x\n", oldtio.c_line, newtio.c_line);
printf("c_ispeed - %08x %08x\n", oldtio.c_ispeed, newtio.c_ispeed);
printf("c_ospeed - %08x %08x\n", oldtio.c_ospeed, newtio.c_ospeed);
printf("\n");
printf("VINTR - %02x %02x\n", oldtio.c_cc[VINTR], newtio.c_cc[VINTR]);
printf("VQUIT - %02x %02x\n", oldtio.c_cc[VQUIT], newtio.c_cc[VQUIT]);
printf("VERASE - %02x %02x\n", oldtio.c_cc[VERASE], newtio.c_cc[VERASE]);
printf("VKILL - %02x %02x\n", oldtio.c_cc[VKILL], newtio.c_cc[VKILL]);
printf("VEOF - %02x %02x\n", oldtio.c_cc[VEOF], newtio.c_cc[VEOF]);
printf("VTIME - %02x %02x\n", oldtio.c_cc[VTIME], newtio.c_cc[VTIME]);
printf("VMIN - %02x %02x\n", oldtio.c_cc[VMIN], newtio.c_cc[VMIN]);
printf("VSWTC - %02x %02x\n", oldtio.c_cc[VSWTC], newtio.c_cc[VSWTC]);
printf("VSTART - %02x %02x\n", oldtio.c_cc[VSTART], newtio.c_cc[VSTART]);
printf("VSTOP - %02x %02x\n", oldtio.c_cc[VSTOP], newtio.c_cc[VSTOP]);
printf("VSUSP - %02x %02x\n", oldtio.c_cc[VSUSP], newtio.c_cc[VSUSP]);
printf("VEOL - %02x %02x\n", oldtio.c_cc[VEOL], newtio.c_cc[VEOL]);
printf("VREPRINT - %02x %02x\n", oldtio.c_cc[VREPRINT], newtio.c_cc[VREPRINT]);
printf("VDISCARD - %02x %02x\n", oldtio.c_cc[VDISCARD], newtio.c_cc[VDISCARD]);
printf("VWERASE - %02x %02x\n", oldtio.c_cc[VWERASE], newtio.c_cc[VWERASE]);
printf("VLNEXT - %02x %02x\n", oldtio.c_cc[VLNEXT], newtio.c_cc[VLNEXT]);
printf("VEOL2 - %02x %02x\n", oldtio.c_cc[VEOL2], newtio.c_cc[VEOL2]);
printf("\n");
printf("\n");
}
SER* SERinit(const char* strPort, int myBAUD)
{
SER* mySER;
//------------------------------------------------------------
// create the global SER struct instance.
if ((mySER = malloc(sizeof(SER))) == NULL)
{
fprintf(stderr, "SERinit() - mySER malloc()\n%s\n", strerror(errno));
return NULL;
}
memset(mySER, 0, sizeof(SER));
//------------------------------------------------------------
// setup the BAUD.
mySER->BAUDindex = myBAUD;
mySER->BAUDvalue = BAUDarray[myBAUD];
mySER->BAUDmult = BAUDdelay[myBAUD];
//------------------------------------------------------------
// open the serial port.
mySER->sfd = open(strPort, O_RDWR | O_NOCTTY);
if (mySER->sfd < 0)
{
fprintf(stderr, "SERInit() - open()\n%s\n", strerror(errno));
free(mySER);
return NULL;
}
//------------------------------------------------------------
// save old port settings for when we exit.
tcgetattr(mySER->sfd, &oldtio);
//------------------------------------------------------------
// prepare the newtio struct with current settings.
newtio = oldtio;
//------------------------------------------------------------
// set BAUD
if (cfsetspeed(&newtio, B9600) != 0)//mySER->BAUDvalue
{
fprintf(stderr, "SERInit() - cfsetspeed()\n%s\n", strerror(errno));
free(mySER);
return NULL;
}
//------------------------------------------------------------
// set for non-canonical (raw).
cfmakeraw(&newtio);
newtio.c_cflag |= (CLOCAL | CREAD);
newtio.c_cflag &= ~(CRTSCTS | CSTOB)
// read() blocks until one char or until 100 mS timeout.
newtio.c_cc[VTIME] = 1;
newtio.c_cc[VMIN] = 1;
// flush the toilet.
tcflush(mySER->sfd, TCIFLUSH);
// write new port settings.
tcsetattr(mySER->sfd, TCSANOW, &newtio);
serPrint();
return mySER;
}
void SERclose(SER* mySER)
{
// restore old port settings.
tcsetattr(mySER->sfd, TCSANOW, &oldtio);
close(mySER->sfd);
}
SER.h
#ifndef SER_H_
#define SER_H_
#define threadInit 0x00
#define threadStarting 0x01
#define threadRuning 0x02
#define threadFailed 0x03
#define threadStopped 0x0f
#define threadCtrlRestart 0xFE
#define threadCtrlKill 0xFF
#include <stdint.h>
#include <pthread.h>
typedef struct SER
{
int BAUDindex; // the BAUD rate.
int BAUDmult; // uS per character ... plus one bite time between characters.
// used as a multiplier used to calculate sleep times after write().
// (bit time x 10 bits) 71E.
int BAUDvalue; // array used to set termios BAUD and get BAUDmult.
// 4800 = 1 2080 uS
// 9600 = 2 1040
// 19,200 = 3 520
// 38,400 = 4 260
// 76,800 = 5 130
// 115,200 = 6 65
// 230,400 = 7 32.5
// 460,800 = 8 16.25
pthread_t tid; // Stores thread ID.
uint8_t ThreadStatus; // written only by thread.
uint8_t ThreadCtrl; // written only by main.
int sfd; // serial port file descriptor.
}SER;
char* SERwrapperFunc(SER* mySER);
SER* SERinit(const char* strPort, int myBAUD);
void SERclose(SER* mySER);
void* serialThread(void* arg);
#endif /* SER_H_ */
Thanks to sawdust, I found the issue, and corrected some others!
The original SERmaster.c was select()'ing and read()'ing and discarding with a final select() which of course timed out due to no additional serial data when the message ended.
I had assumed select() only fired once and timed out.
Corrected SERmaster.c
#define responseSize 4584
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <termios.h>
//#include <linux/serial.h>
//#include <aio.h>
#include <sys/time.h>
#include "SER.h"
// array used to get termios BAUD.
const
int BAUDarray[9] = { 0, // not used.
B4800, // 208
B9600, // 104
B19200, // 52
B38400, // 26
B57600, // 17.363636
B115200, // 8.727272
B230400, // 4.363636
B460800 // 2.181818
};
// delay (in uS) per character transmitted.
// 1 start, Even parity, 7bits, 1 stop.
// bit time (times 10 bits)
// Plus one bit time between characters.
const
int BAUDdelay[9] = { 0, // not used.
2288,
1144,
572,
286,
191,
96,
48,
24
};
static
char response[4584];
static
unsigned
int respIndex;
static
struct termios newtio, oldtio;
extern
volatile
int terminate;
static
int sendRecieve(SER* mySER, const char* msgBuffer, int msgCnt, int sendFlag, int receiveFlag)
{
int rtn;
char myChar;
fd_set myfds;
struct
timeval tm_out;
if (sendFlag == true)
{
while (1)
{
rtn = write(mySER->sfd, msgBuffer, msgCnt);
if (rtn == -1)
{
if (errno == EINTR)
{
fprintf(stderr, "sendRecieve() - write() EINTR !\n");
if (terminate == 1)
break; // deal with SIGTERM !
continue; // if not SIGTERM then retry.
}
else
{
fprintf(stderr, "sendRecieve() - write()\n%s\n", strerror(errno));
return EXIT_FAILURE;
}
}
else
{
if (rtn == msgCnt)
break;
else
{
fprintf(stderr, "sendRecieve() - write() returned less than msgCnt !\n");
return EXIT_FAILURE;
}
}
}
}
if (receiveFlag == true)
{
for (int i = 0; i < responseSize; i++)
response[i] = '\0';
respIndex = 0;
// set our first select() time out for (x + 2) char times where x is what we sent via write().
tm_out.tv_sec = 0;
tm_out.tv_usec = mySER->BAUDmult * (msgCnt + 2);
while (1)
{
FD_ZERO(&myfds);
FD_SET(mySER->sfd, &myfds);
rtn = select(mySER->sfd + 1, &myfds, NULL, NULL, &tm_out);
if (rtn == 0)
{
fprintf(stderr, "sendRecieve() - select() timeout!\n");
return EXIT_FAILURE;
}
if (rtn == -1)
{
if (errno == EINTR)
{
if (terminate == 1)
{
fprintf(stderr, "sendRecieve() - select() EINTR, terminating!\n");
return EXIT_FAILURE;
}
fprintf(stderr, "sendRecieve() - select() EINTR, restarting, tm_out.tv_usec = %d, remaining = %ld\n", mySER->BAUDmult * msgCnt, tm_out.tv_usec);
continue;
}
else
{
fprintf(stderr, "sendRecieve() - select()\n%s\n", strerror(errno));
return EXIT_FAILURE;
}
}
// select() indicates ready for reading !!
while (1)
{
rtn = read(mySER->sfd, &myChar, 1);
if (rtn == -1)
{
if (errno == EINTR)
{
fprintf(stderr, "sendRecieve() - read() EINTR !\n");
if (terminate == 1)
return EXIT_FAILURE;
continue;
}
else
{
fprintf(stderr, "sendRecieve() - read()\n%s\n", strerror(errno));
return EXIT_FAILURE;
}
}
if (rtn == 0)
{
fprintf(stderr, "sendRecieve() - read() returned 0 yet select() reported ready for reading ??? should never see this !\n");
return EXIT_FAILURE;
}
// break from read while() loop to process the char.
break;
}// end read() while loop
// save the new char.
response[respIndex] = myChar;
// point to the nest storage location.
respIndex++;
if (myChar == '\n')
return EXIT_SUCCESS;
// are we pointing beyond max buffer size?
if (respIndex == responseSize)
{
fprintf(stderr, "sendRecieve() - exceeded response buffer size ... before message termination char!!\n");
return EXIT_FAILURE;
}
// set our next select() time out for 2 char times based on baud rate.
tm_out.tv_sec = 0;
tm_out.tv_usec = mySER->BAUDmult * 2;
}//end select() while loop
fprintf(stderr, "sendRecieve() - select/read outer while loop Dumped, should not see this ever !!\n");
return EXIT_FAILURE;
}// end if (receiveFlag == true)
return EXIT_SUCCESS;
}
char* SERwrapperFunc(SER* mySER)
{
char myCharArray[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' };
int myCharArrayCountToSend = sizeof(myCharArray);
sendRecieve(mySER, myCharArray, myCharArrayCountToSend, true, true);
return response;
}
void serPrint()
{
printf("NCCS = %d OLD: NEW:\n", NCCS);
printf("c_iflag - %08x %08x\n", oldtio.c_iflag, newtio.c_iflag);
printf("c_oflag - %08x %08x\n", oldtio.c_oflag, newtio.c_oflag);
printf("c_cflag - %08x %08x\n", oldtio.c_cflag, newtio.c_cflag);
printf("c_lflag - %08x %08x\n", oldtio.c_lflag, newtio.c_lflag);
printf("c_line - %08x %08x\n", oldtio.c_line, newtio.c_line);
printf("c_ispeed - %08x %08x\n", oldtio.c_ispeed, newtio.c_ispeed);
printf("c_ospeed - %08x %08x\n", oldtio.c_ospeed, newtio.c_ospeed);
printf("\n");
printf("VINTR - %02x %02x\n", oldtio.c_cc[VINTR], newtio.c_cc[VINTR]);
printf("VQUIT - %02x %02x\n", oldtio.c_cc[VQUIT], newtio.c_cc[VQUIT]);
printf("VERASE - %02x %02x\n", oldtio.c_cc[VERASE], newtio.c_cc[VERASE]);
printf("VKILL - %02x %02x\n", oldtio.c_cc[VKILL], newtio.c_cc[VKILL]);
printf("VEOF - %02x %02x\n", oldtio.c_cc[VEOF], newtio.c_cc[VEOF]);
printf("VTIME - %02x %02x\n", oldtio.c_cc[VTIME], newtio.c_cc[VTIME]);
printf("VMIN - %02x %02x\n", oldtio.c_cc[VMIN], newtio.c_cc[VMIN]);
printf("VSWTC - %02x %02x\n", oldtio.c_cc[VSWTC], newtio.c_cc[VSWTC]);
printf("VSTART - %02x %02x\n", oldtio.c_cc[VSTART], newtio.c_cc[VSTART]);
printf("VSTOP - %02x %02x\n", oldtio.c_cc[VSTOP], newtio.c_cc[VSTOP]);
printf("VSUSP - %02x %02x\n", oldtio.c_cc[VSUSP], newtio.c_cc[VSUSP]);
printf("VEOL - %02x %02x\n", oldtio.c_cc[VEOL], newtio.c_cc[VEOL]);
printf("VREPRINT - %02x %02x\n", oldtio.c_cc[VREPRINT], newtio.c_cc[VREPRINT]);
printf("VDISCARD - %02x %02x\n", oldtio.c_cc[VDISCARD], newtio.c_cc[VDISCARD]);
printf("VWERASE - %02x %02x\n", oldtio.c_cc[VWERASE], newtio.c_cc[VWERASE]);
printf("VLNEXT - %02x %02x\n", oldtio.c_cc[VLNEXT], newtio.c_cc[VLNEXT]);
printf("VEOL2 - %02x %02x\n", oldtio.c_cc[VEOL2], newtio.c_cc[VEOL2]);
printf("\n");
printf("\n");
}
SER* SERinit(const char* strPort, int myBAUD)
{
SER* mySER;
//------------------------------------------------------------
// create the global SER struct instance.
if ((mySER = malloc(sizeof(SER))) == NULL)
{
fprintf(stderr, "SERinit() - mySER malloc()\n%s\n", strerror(errno));
return NULL;
}
memset(mySER, 0, sizeof(SER));
//------------------------------------------------------------
// setup the BAUD.
mySER->BAUDindex = myBAUD;
mySER->BAUDvalue = BAUDarray[myBAUD];
mySER->BAUDmult = BAUDdelay[myBAUD];
//------------------------------------------------------------
// open the serial port.
mySER->sfd = open(strPort, O_RDWR | O_NOCTTY);
if (mySER->sfd < 0)
{
fprintf(stderr, "SERInit() - open()\n%s\n", strerror(errno));
free(mySER);
return NULL;
}
//------------------------------------------------------------
// save old port settings for when we exit.
tcgetattr(mySER->sfd, &oldtio);
//------------------------------------------------------------
// prepare the newtio struct with current settings.
newtio = oldtio;
//------------------------------------------------------------
// set BAUD
if (cfsetspeed(&newtio, B9600) != 0)//mySER->BAUDvalue
{
fprintf(stderr, "SERInit() - cfsetspeed()\n%s\n", strerror(errno));
free(mySER);
return NULL;
}
//------------------------------------------------------------
// set for non-canonical (raw).
cfmakeraw(&newtio);
newtio.c_cflag |= (CLOCAL | CREAD);
newtio.c_cflag &= ~(CRTSCTS | CSTOPB);
// read() blocks until one char or until 100 mS timeout.
newtio.c_cc[VTIME] = 1;
newtio.c_cc[VMIN] = 1;
// flush the toilet.
tcflush(mySER->sfd, TCIFLUSH);
// write new port settings.
tcsetattr(mySER->sfd, TCSANOW, &newtio);
serPrint();
return mySER;
}
void SERclose(SER* mySER)
{
// restore old port settings.
tcsetattr(mySER->sfd, TCSANOW, &oldtio);
close(mySER->sfd);
}

Code executes correctly only if prints are present (C) [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
I'm setting up a prototype for a DAQ system for Zynq FPGAs. I receive data from a server through ethernet, write it to a FIFO using the DMA and viceversa using two different pthreads. However, threads work correctly only if printf are executed. I expect there is a memory leak or some lines leading to a undefined behaviour, but I can't spot it.
Placing output to stderr has the same result. Changing addresses does nothing different.
Sorry for the shameful code, but I tried replacing almost every line by now to spot the problem.
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/mman.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sys/stat.h>
#include <stdint.h>
#include <errno.h>
#include <time.h>
#define PORT 8080
#define SA struct sockaddr
#define MM2S_CONTROL_REGISTER 0x00
#define MM2S_STATUS_REGISTER 0x04
#define MM2S_START_ADDRESS 0x18
#define MM2S_LENGTH 0x28
#define S2MM_CONTROL_REGISTER 0x30
#define S2MM_STATUS_REGISTER 0x34
#define S2MM_DESTINATION_ADDRESS 0x48
#define S2MM_LENGTH 0x58
#define VIRT_ADDR 0x40400000
#define FIFO_ADDR 0x0c000000
#define SEND_ADDR 0x0a000000
#define RECV_ADDR 0x0b000000
#define TIMEOUT 10
#define MAX_TRANSF 12274
unsigned int dma_set(unsigned int *dma_virtual_address, int offset, unsigned int value);
unsigned int dma_get(unsigned int *dma_virtual_address, int offset);
int dma_mm2s_sync(unsigned int *dma_virtual_address);
int dma_s2mm_sync(unsigned int *dma_virtual_address);
unsigned int dma_s2mm_status(unsigned int *dma_virtual_address);
unsigned int dma_mm2s_status(unsigned int *dma_virtual_address);
void memdump(void *virtual_address, int byte_count);
void print_status(unsigned int status);
unsigned long int elements = 0;
clock_t start_time;
typedef struct arg_struct {
unsigned int *virtual_address;
unsigned int *virtual_buffer;
unsigned int *head;
unsigned int *tail;
unsigned int buffsize;
unsigned int fifosize;
unsigned int sockfd;
pthread_mutex_t *lock;
char verbose;
} arguments;
unsigned int dma_set(unsigned int *dma_virtual_address, int offset, unsigned int value) {
dma_virtual_address[offset >> 2] = value;
}
unsigned int dma_get(unsigned int *dma_virtual_address, int offset) {
return dma_virtual_address[offset >> 2];
}
int dma_mm2s_sync(unsigned int *dma_virtual_address) {
unsigned int mm2s_status = dma_get(dma_virtual_address, MM2S_STATUS_REGISTER);
while (!(mm2s_status & 1 << 12) || !(mm2s_status & 1 << 1)) {
dma_s2mm_status(dma_virtual_address);
dma_mm2s_status(dma_virtual_address);
mm2s_status = dma_get(dma_virtual_address, MM2S_STATUS_REGISTER);
}
}
int dma_s2mm_sync(unsigned int *dma_virtual_address) {
unsigned int s2mm_status = dma_get(dma_virtual_address, S2MM_STATUS_REGISTER);
while (!(s2mm_status & 1 << 12) || !(s2mm_status & 1 << 1)) {
dma_s2mm_status(dma_virtual_address);
dma_mm2s_status(dma_virtual_address);
s2mm_status = dma_get(dma_virtual_address, S2MM_STATUS_REGISTER);
}
}
unsigned int dma_s2mm_status(unsigned int *dma_virtual_address) {
return dma_get(dma_virtual_address, S2MM_STATUS_REGISTER);
}
unsigned int dma_mm2s_status(unsigned int *dma_virtual_address) {
return dma_get(dma_virtual_address, MM2S_STATUS_REGISTER);
}
void print_mm2s_status(unsigned int status) {
fprintf(stderr, "[*] Stream to memory-mapped status (0x%08x#0x%02x):", status, S2MM_STATUS_REGISTER);
print_status(status);
}
void print_s2mm_status(unsigned int status) {
fprintf(stderr, "[*] Memory-mapped to stream status (0x%08x#0x%02x):", status, MM2S_STATUS_REGISTER);
print_status(status);
}
void print_status(unsigned int status) {
if (status & 0x00000001) fprintf(stderr, " halted");
else fprintf(stderr, " running");
if (status & 0x00000002) fprintf(stderr, " idle");
if (status & 0x00000008) fprintf(stderr, " SGIncld");
if (status & 0x00000010) fprintf(stderr, " DMAIntErr");
if (status & 0x00000020) fprintf(stderr, " DMASlvErr");
if (status & 0x00000040) fprintf(stderr, " DMADecErr");
if (status & 0x00000100) fprintf(stderr, " SGIntErr");
if (status & 0x00000200) fprintf(stderr, " SGSlvErr");
if (status & 0x00000400) fprintf(stderr, " SGDecErr");
if (status & 0x00001000) fprintf(stderr, " IOC_Irq");
if (status & 0x00002000) fprintf(stderr, " Dly_Irq");
if (status & 0x00004000) fprintf(stderr, " Err_Irq");
fprintf(stderr, "\n");
}
void memdump(void *virtual_address, int byte_count) {
char * p = virtual_address;
int offset;
for (offset = 0; offset < byte_count; offset++) {
fprintf(stderr, "%02x", p[offset]);
if (offset % 4 == 3) {
fprintf(stderr, " ");
}
}
}
void DMATransfer(unsigned int *virtual_address, long unsigned int src, long unsigned int dest, unsigned int length, char verbose) {
unsigned int s2mm_status = 0;
unsigned int mm2s_status = 0;
dma_set(virtual_address, S2MM_CONTROL_REGISTER, 4);
dma_set(virtual_address, MM2S_CONTROL_REGISTER, 4);
if (verbose > 0) {
print_s2mm_status(dma_s2mm_status(virtual_address));
print_mm2s_status(dma_mm2s_status(virtual_address));
}
dma_set(virtual_address, S2MM_CONTROL_REGISTER, 0);
dma_set(virtual_address, MM2S_CONTROL_REGISTER, 0);
if (verbose > 0) {
print_s2mm_status(dma_s2mm_status(virtual_address));
print_mm2s_status(dma_mm2s_status(virtual_address));
}
dma_set(virtual_address, S2MM_DESTINATION_ADDRESS, dest);
dma_set(virtual_address, MM2S_START_ADDRESS, src);
if (verbose > 0) {
print_s2mm_status(dma_s2mm_status(virtual_address));
print_mm2s_status(dma_mm2s_status(virtual_address));
}
dma_set(virtual_address, S2MM_CONTROL_REGISTER, 0xf001);
dma_set(virtual_address, MM2S_CONTROL_REGISTER, 0xf001);
if (verbose > 0) {
print_s2mm_status(dma_s2mm_status(virtual_address));
print_mm2s_status(dma_mm2s_status(virtual_address));
}
dma_set(virtual_address, S2MM_LENGTH, length);
dma_set(virtual_address, MM2S_LENGTH, length);
if (verbose > 0) {
print_s2mm_status(dma_s2mm_status(virtual_address));
print_mm2s_status(dma_mm2s_status(virtual_address));
}
dma_mm2s_sync(virtual_address);
dma_s2mm_status(virtual_address);
if (verbose > 0) {
print_s2mm_status(dma_s2mm_status(virtual_address));
print_mm2s_status(dma_mm2s_status(virtual_address));
}
}
int GetCPULoad() {
int FileHandler;
char FileBuffer[1024];
float load;
FileHandler = open("/proc/loadavg", O_RDONLY);
if(FileHandler < 0) {
return -1;
}
read(FileHandler, FileBuffer, sizeof(FileBuffer) - 1);
sscanf(FileBuffer, "%f", &load);
close(FileHandler);
return (int)(load * 100);
}
void *sender(void *params) {
arguments *args = params;
if (args->head == NULL) {
fprintf(stderr, "[-] Head pointer not valid\n");
exit(0);
}
if (args->tail == NULL) {
fprintf(stderr, "[-] Tail pointer not valid\n");
exit(0);
}
if (args->virtual_address == NULL) {
fprintf(stderr, "[-] AXI DMA register pointer not valid\n");
exit(0);
}
if (args->virtual_buffer == NULL) {
fprintf(stderr, "[-] Send buffer pointer not valid\n");
exit(0);
}
unsigned long int units_sent = 0;
unsigned int myhead = 0;
unsigned int mytail = 0;
for (;;) {
pthread_mutex_lock(args->lock);
myhead = *(args->head);
mytail = *(args->tail);
pthread_mutex_unlock(args->lock);
fprintf(stderr, "[*] Send Head: %d Tail: %d\n", myhead, mytail);
if (myhead != mytail) {
int remaining = args->buffsize;
int sent = 0;
int src = FIFO_ADDR + mytail * args->buffsize;
if (args->verbose > 2) {
fprintf(stderr, "[*] Sender: DMA is transferring data from 0x%x to 0x%x\n", src, SEND_ADDR);
}
unsigned int length = args->buffsize;
unsigned int verb = args->verbose > 2 ? 1 : 0;
pthread_mutex_lock(args->lock);
while (remaining > 0) {
length = remaining < MAX_TRANSF ? remaining : remaining % MAX_TRANSF;
DMATransfer(args->virtual_address, src + sent, SEND_ADDR, length, verb);
remaining -= args->buffsize;
sent += remaining;
}
pthread_mutex_unlock(args->lock);
elements--;
units_sent++;
if (args->verbose > 2) {
fprintf(stderr, "[*] %f elements in FIFO: %lu\n", ((double)(clock() - start_time)) / CLOCKS_PER_SEC, elements);
fprintf(stderr, "[*] %f DMA tranfer to buffer: %d\n", ((double)(clock() - start_time)) / CLOCKS_PER_SEC, units_sent);
}
remaining = args->buffsize;
sent = 0;
int result = 0;
pthread_mutex_lock(args->lock);
while (remaining > 0) {
result = send(args->sockfd, args->virtual_buffer + sent, remaining, 0);
if (result > 0) {
remaining -= result;
sent += remaining;
} else if (result < 0) {
fprintf(stderr, "[-] Error retrieving configuration from the server\n");
exit(0);
}
}
*(args->tail) = (mytail + 1) % (args->fifosize + 1);
pthread_mutex_unlock(args->lock);
//memset(args->virtual_buffer, 0, args->buffsize);
if (args->verbose > 2) {
fprintf(stderr, "[*] %f Unit sent: %d\n", ((double)(clock() - start_time)) / CLOCKS_PER_SEC, units_sent);
}
if (args->verbose > 0) {
fprintf(stderr, "[*] Packet retrieved");
}
if (args->verbose > 1) {
fprintf(stderr, " content: ");
memdump(args->virtual_buffer, args->buffsize);
}
if (args->verbose > 0) {
fprintf(stderr, "\n");
}
if (args->verbose > 2) {
fprintf(stderr, "[*] %f CPU Usage: %d\n", ((double)(clock() - start_time)) / CLOCKS_PER_SEC, GetCPULoad());
}
}
printf("0000000000000000000000000\n");
}
}
void *receiver(void *params) {
arguments *args = params;
if (args->head == NULL) {
fprintf(stderr, "[-] Head pointer not valid\n");
exit(0);
}
if (args->tail == NULL) {
fprintf(stderr, "[-] Tail pointer not valid\n");
exit(0);
}
if (args->virtual_address == NULL) {
fprintf(stderr, "[-] AXI DMA register pointer not valid\n");
exit(0);
}
if (args->virtual_buffer == NULL) {
fprintf(stderr, "[-] Recv buffer pointer not valid\n");
exit(0);
}
unsigned long int units_received = 0;
unsigned int myhead = 0;
unsigned int mytail = 0;
for (;;) {
pthread_mutex_lock(args->lock);
myhead = *(args->head);
mytail = *(args->tail);
pthread_mutex_unlock(args->lock);
fprintf(stderr, "[*] Recv Head: %d Tail: %d\n", myhead, mytail);
if (mytail != myhead + 1) {
int remaining = args->buffsize;
int received = 0;
int result = 0;
pthread_mutex_lock(args->lock);
while (remaining > 0) {
result = recv(args->sockfd, args->virtual_buffer + received, remaining, 0);
fprintf(stderr, "[*] Recv result: %d\n", result);
if (result > 0) {
remaining -= result;
received += result;
} else if (result == 0) {
fprintf(stderr, "[-] Remote side closed his end of the connection before all data was received\n");
exit(0);
} else if (result < 0) {
fprintf(stderr, "[-] Error retrieving configuration from the server\n");
exit(0);
}
}
printf("++++++++++++++++++++++++++++\n");
pthread_mutex_unlock(args->lock);
units_received++;
if (args->verbose > 2) {
fprintf(stderr, "[*] %f Unit recv: %d\n", ((double)(clock() - start_time)) / CLOCKS_PER_SEC, units_received);
}
remaining = args->buffsize;
received = 0;
int dest = FIFO_ADDR + myhead * args->buffsize;
if (args->verbose > 2) {
fprintf(stderr, "[*] Receiver: DMA is transferring data from 0x%x to 0x%x\n", RECV_ADDR, dest);
}
unsigned int length = args->buffsize;
unsigned int verb = args->verbose > 2 ? 1 : 0;
pthread_mutex_lock(args->lock);
while (remaining > 0) {
printf("############################\n");
length = remaining < MAX_TRANSF ? remaining : remaining % MAX_TRANSF;
DMATransfer(args->virtual_address, RECV_ADDR, dest + received, length, verb);
remaining -= args->buffsize;
received += args->buffsize;
}
printf("*************************\n");
*(args->head) = (myhead + 1) % (args->fifosize + 1);
pthread_mutex_unlock(args->lock);
//memset(args->virtual_buffer, 0, args->buffsize);
elements++;
if (args->verbose > 2) {
fprintf(stderr, "[*] %f elements in FIFO: %lu\n", ((double)(clock() - start_time)) / CLOCKS_PER_SEC, elements);
fprintf(stderr, "[*] %f DMA tranfer to DDR: %d\n", ((double)(clock() - start_time)) / CLOCKS_PER_SEC, units_received);
}
if (args->verbose > 0) {
fprintf(stderr, "[*] Packet received");
}
if (args->verbose > 1) {
fprintf(stderr, " content: ");
memdump(args->virtual_buffer, args->buffsize);
}
if (args->verbose > 0) {
fprintf(stderr, "\n");
}
if (args->verbose > 2) {
fprintf(stderr, "[*] %f CPU Usage: %d\n", ((double)(clock() - start_time)) / CLOCKS_PER_SEC, GetCPULoad());
}
}
printf("77777777777777777777777777777\n");
}
}
int isValidIpAddress(char *ipAddress) {
struct sockaddr_in sa;
int result = inet_pton(AF_INET, ipAddress, &(sa.sin_addr));
if (result != 0) {
return 0;
} else {
return 1;
}
}
int main(int argc, char *argv[]) {
if (argc < 3 || argc > 5) {
fprintf(stderr, "\nUsage: DAQTest [IP address] [fifo size]\nExample: DAQTest 192.168.1.81 64\n\n");
fprintf(stderr, "Optional flags: -v Verbose (print operations)\n");
fprintf(stderr, " -vv Very verbose (also print data content)\n");
fprintf(stderr, " -vvv Extremely verbose (also print DMA info)\n\n");
exit(0);
}
if (isValidIpAddress(argv[1]) == 1) {
fprintf(stderr, "[-] Invalid ip address\n");
exit(0);
}
int fifosize = atoi(argv[2]);
if (fifosize < 0 || fifosize > 8192) {
fprintf(stderr, "[-] Invalid fifo size\n");
exit(0);
}
char verbose = 0;
if (argc == 4) {
if (strcmp(argv[3], "-v") == 0) {
verbose = 1;
} else if (strcmp(argv[3], "-vv") == 0) {
verbose = 2;
} else if (strcmp(argv[3], "-vvv") == 0) {
verbose = 3;
} else {
fprintf(stderr, "[-] Unwanted parameter\n");
exit(0);
}
}
struct sockaddr_in servaddr, cli;
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == sockfd) {
fprintf(stderr, "[-] Socket creation failed\n");
exit(0);
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr(argv[1]);
servaddr.sin_port = htons(PORT);
/*
struct timeval tv;
tv.tv_sec = TIMEOUT;
tv.tv_usec = 0;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
*/
if (connect(sockfd, (SA * ) & servaddr, sizeof(servaddr)) != 0) {
fprintf(stderr, "[-] Connection failed\n");
exit(0);
}
fprintf(stderr, "[+] Connected to the server\n");
int buffsize = 0;
char* recv_buffer = (char*)&buffsize;
int remaining = sizeof(int);
int received = 0;
int result = 0;
while (remaining > 0) {
result = recv(sockfd, recv_buffer + received, remaining, 0);
if (result > 0) {
remaining -= result;
received += result;
} else if (result == 0) {
fprintf(stderr, "[-] Remote side closed his end of the connection before all data was received\n");
exit(0);
} else if (result < 0) {
fprintf(stderr, "[-] Error retrieving configuration from the server\n");
exit(0);
}
}
//fprintf(stderr, "[*] Page size: %ld\n", sysconf(_SC_PAGE_SIZE));
int dh = open("/dev/mem", O_RDWR | O_SYNC);
unsigned int *virtual_address = mmap(NULL, 65535, PROT_READ | PROT_WRITE, MAP_SHARED, dh, VIRT_ADDR);
unsigned int *virtual_sendbuff = mmap(NULL, buffsize, PROT_READ | PROT_WRITE, MAP_SHARED, dh, SEND_ADDR);
unsigned int *virtual_recvbuff = mmap(NULL, buffsize, PROT_READ | PROT_WRITE, MAP_SHARED, dh, RECV_ADDR);
unsigned int *virtual_fifo = mmap(NULL, (fifosize + 1) * buffsize, PROT_READ | PROT_WRITE, MAP_SHARED, dh, FIFO_ADDR);
if (virtual_address == MAP_FAILED) {
fprintf(stderr, "[-] AXI DMA registers mmap failed\n");
}
if (virtual_sendbuff == MAP_FAILED) {
fprintf(stderr, "[-] Send buffer mmap failed\n");
}
if (virtual_sendbuff == MAP_FAILED) {
fprintf(stderr, "[-] Send buffer mmap failed\n");
}
if (virtual_recvbuff == MAP_FAILED) {
fprintf(stderr, "[-] Receiver buffer mmap failed\n");
}
if (virtual_fifo == MAP_FAILED) {
fprintf(stderr, "[-] Fifo mmap failed\n");
}
memset(virtual_address, 0, buffsize);
memset(virtual_sendbuff, 0, buffsize);
memset(virtual_recvbuff, 0, buffsize);
memset(virtual_fifo, 0, buffsize);
int head = 0, tail = 0;
pthread_t sendth, recvth;
pthread_mutex_t lock;
pthread_mutex_init(&lock, NULL);
arguments send_args;
send_args.virtual_address = virtual_address;
send_args.virtual_buffer = virtual_sendbuff;
send_args.head = &head;
send_args.tail = &tail;
send_args.buffsize = buffsize;
send_args.fifosize = fifosize;
send_args.sockfd = sockfd;
send_args.lock = &lock;
send_args.verbose = verbose;
arguments recv_args;
recv_args.virtual_address = virtual_address;
recv_args.virtual_buffer = virtual_recvbuff;
recv_args.head = &head;
recv_args.tail = &tail;
recv_args.buffsize = buffsize;
recv_args.fifosize = fifosize;
recv_args.sockfd = sockfd;
recv_args.lock = &lock;
recv_args.verbose = verbose;
start_time = clock();
if (pthread_create(&sendth, NULL, sender, &send_args)) {
fprintf(stderr, "[-] Error creating sender thread\n");
exit(0);
}
if (pthread_create(&recvth, NULL, receiver, &recv_args)) {
fprintf(stderr, "[-] Error creating receiver thread\n");
exit(0);
}
if (pthread_join(sendth, NULL)) {
fprintf(stderr, "[-] Error joining sender thread\n");
exit(0);
}
if (pthread_join(recvth, NULL)) {
fprintf(stderr, "[-] Error joining receiver thread\n");
exit(0);
}
pthread_mutex_destroy(&lock);
close(sockfd);
fprintf(stderr, "[+] Exit\n");
return 0;
}
Try replacing the print statements with delays.
As you're doing networking, you're speed constrained by your network connection. If you do not take this into considerations, your transfer buffers may overflow. The print statements add a certain delay, which might prevent this. Replacing them with actual delays would check for this.
A better solution - if this were indeed the problem - would then be to check for buffer availability before writing.

Linux C problem with file link(device,socket) /dev/fd/ need avoid links transition

I need a program that should count files,find the biggest of them and total summ of files in directory and subdirectories(for subdirectory separately )
and what a problem: my programm always try go by links,but i don't need that!
i try to find link and socket files, but something don't work
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#include <malloc.h>
struct stat st;
struct dirent * d;
off_t sz[10000];
FILE *fp;
char PROG_NAME[100];
char FILE_NAME[100];
char * nm[10000],* maxn;
int rec1(char * rp);
int main (int argc, char *argv[])
{
/*//it's for terminal
//how much arguments
if (argc < 3)
{
printf("Too few arguments\n");
return 1;
};
if (argc> 3)
{
printf("Too many arguments\n");
return 1;
};
FILE * fp; //filepath
if ((fp=fopen(argv[2],"w"))==NULL)
{
fprintf(stderr,"%s fopen: %s %s\n",argv[0],argv[2],strerror(errno));
return 1;
};
if (fclose(fp)==-1)
{
fprintf(stderr,"%s fclose: %s %s\n",argv[0],argv[2],strerror(errno));
return 1;
};
strcpy(PROG_NAME,argv[0]);
strcpy(FILE_NAME,argv[2]);*/
strcpy(PROG_NAME,"Prog1");
strcpy(FILE_NAME,"out.txt");
char a[100]="/dev/"; //directory where we start
if ((fp=fopen(FILE_NAME,"w"))==NULL)
{
fprintf(stderr,"%s fopen: %s %s\n",PROG_NAME,FILE_NAME,strerror(errno));
return 1;
};
rec1(a);
if (fclose(fp)==-1)
{
fprintf(stderr,"%s fclose: %s %s\n",PROG_NAME,FILE_NAME,strerror(errno));
return 1;
};
exit(EXIT_SUCCESS);
}
int rec1(char * rp)
{
int i=0;
off_t sb=0,ts=0;//
char nb[1000], s[1000];
DIR * dp;//dirpath
strcpy(nb,"");//занулим nb
if ((dp=opendir(rp)) == NULL)
{
fprintf(stderr,"%s opendir: %s %s \n",PROG_NAME,rp,strerror(errno));
return 1;
};
while ((d=readdir(dp))!=NULL)
{
if (strcmp(d->d_name,".")!= 0 && strcmp(d->d_name,"..")!= 0)
{
strcpy(s,realpath(rp,NULL));
if (s[strlen(s)-1] != '/')
{
strcat(s,"/");
};
strcat(s,d->d_name);
stat(s,&st);//вызывает stat
if (stat(s,&st) != 0)
{
printf(" %s :error stat file: %s \n",PROG_NAME, s);
}
else
{
if (!S_ISDIR(st.st_mode))
{
if (st.st_size>sb)
{
strcpy(nb,d->d_name);
sb=st.st_size;
};
i++;
ts+=st.st_size;
}
else//!!!!!!!!!!!!!!!!!!!!!!!!!!!!
{
if (S_ISDIR(st.st_mode)&&(!(S_ISLNK(st.st_mode)))&&(!S_ISSOCK(st.st_mode))
&&(!S_ISFIFO(st.st_mode))&&(!S_ISCHR(st.st_mode))&&(!S_ISBLK(st.st_mode)))
{
rec1(s);
};
};
};
};
};
printf("%s %ld %ld %s \n",rp,i,ts,nb);
fprintf(fp,"%s %ld %ld %s \n",rp,i,ts,nb);
if (closedir(dp)==-1)
{
printf("%s closedir: %s %s \n",PROG_NAME,rp,strerror(errno));
return 1;
};
}
`
When script finds link-file of pre-directory it cycles.
Tried to avoid links transitions but failed.
try to define /dev/fd/4.../dev/fd/23 files but always error "no such files or directory"
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
struct stat sb;
if (argc != 2) {
fprintf(stderr, "Usage: %s <pathname>\n", argv[0]);
exit(EXIT_FAILURE);
}
if (stat(argv[1], &sb) == -1) {
perror("stat");
exit(EXIT_FAILURE);
}
printf("File type: ");
switch (sb.st_mode & S_IFMT) {
case S_IFBLK: printf("block device\n"); break;
case S_IFCHR: printf("character device\n"); break;
case S_IFDIR: printf("directory\n"); break;
case S_IFIFO: printf("FIFO/pipe\n"); break;
case S_IFLNK: printf("symlink\n"); break;
case S_IFREG: printf("regular file\n"); break;
case S_IFSOCK: printf("socket\n"); break;
default: printf("unknown?\n"); break;
}
printf("I-node number: %ld\n", (long) sb.st_ino);
printf("Mode: %lo (octal)\n",
(unsigned long) sb.st_mode);
printf("Link count: %ld\n", (long) sb.st_nlink);
printf("Ownership: UID=%ld GID=%ld\n",
(long) sb.st_uid, (long) sb.st_gid);
printf("Preferred I/O block size: %ld bytes\n",
(long) sb.st_blksize);
printf("File size: %lld bytes\n",
(long long) sb.st_size);
printf("Blocks allocated: %lld\n",
(long long) sb.st_blocks);
printf("Last status change: %s", ctime(&sb.st_ctime));
printf("Last file access: %s", ctime(&sb.st_atime));
printf("Last file modification: %s", ctime(&sb.st_mtime));
exit(EXIT_SUCCESS);
}
please help me
You are using stat() when you should be using lstat(). From the lstat() manual page:
lstat() is identical to stat(), except that if path is a symbolic link, then the link itself is stat-ed, not the file that it refers to.
And my $0.02: don't reinvent wheels
$ time sudo du --exclude /sys -xslLc /*
3 /bbs
10028 /bin
166960 /boot
0 /bulk
288 /dev
246068 /etc
100521273 /home
4 /home2
11588 /initrd.img
11612 /initrd.img.old
1789892 /lib
16 /lost+found
12 /media
12 /mnt
3 /net
747204 /opt
7245712 /proc
1035364 /root
38312 /sbin
4 /selinux
4 /srv
4 /tanq
37432 /tmp
14636048 /usr
1476612 /var
4328 /vmlinuz
4196 /vmlinuz.old
127982979 total
real 0m53.157s
user 0m20.773s
sys 0m21.137s

Resources