C copy file with memcpy and mmap file to RAM - c

I have file1.txt
This is my file
and file2.txt
This is my second file
and I want copy file2.txt content to file1.txt using memcpy
int main( int argc, char * argv[] ){
int d;
int d2;
int p;
FILE *f1;
FILE *f2;
if(argc == 3){
f1 = fopen(argv[1], "r+");
f2 = fopen(argv[2], "r+");
d = da_open(argv[1]);
d2 = da_open2(argv[2]);
p = da_cp(f2, f1, 10);
da_map(d, 10);
da_map(d2, 10);
close(p);
//closef(d2);
}
}
I don't know why but when I run this I get file2.txt with lots of random symbols. Why? what I'm doing wrong?
EDIT:
my full code
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <string.h>
int da_open(const char *name);
int da_open2(const char *name);
void *da_map(int d, int size);
int da_cp(void *str1, const void *str2, size_t n);
int da_open(const char *name){
int dskr;
dskr = open( name, O_RDONLY, 0640 );
if( dskr == -1 ){
perror( name );
exit( 255 );
}
printf( "dskr = %d\n", dskr );
return dskr;
}
int da_open2(const char *name){
int dskr;
dskr = open( name, O_RDWR, 0640 );
if( dskr == -1 ){
perror( name );
exit( 255 );
}
printf( "dskr = %d\n", dskr );
return dskr;
}
void *da_map(int d, int size){
void *a = NULL;
a = mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, d, 0 );
if( a == MAP_FAILED ){
perror( "mmap failed" );
abort();
}
return a;
}
int da_cp(void *str1, const void *str2, size_t n){
memcpy(str1, str2, n);
}
int main( int argc, char * argv[] ){
int d;
int d2;
int p;
FILE *f1;
FILE *f2;
if(argc == 3){
f1 = fopen(argv[1], "r+");
f2 = fopen(argv[2], "r+");
d = da_open(argv[1]);
d2 = da_open2(argv[2]);
p = da_cp(f2, f1, 10);
da_map(d, 10);
da_map(d2, 10);
close(p);
//closef(d2);
}
}

d and d2 are not files, they're just file descriptors (something that stores the information about the file and its input/output states).
If you want to copy from 1 file to another, you have to read the first file first. That's the example of how you can do this:
#include <stdio.h>
#include <stdlib.h>
// Open the first text file
FILE *f = fopen("textfile1.txt", "rb");
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
fseek(f, 0, SEEK_SET);
// Read it into buffer
char *buffer = malloc(fsize + 1);
fread(string, fsize, 1, f);
fclose(f);
buffer[fsize] = 0;
// Now write the string buffer into your second text file
FILE *f2 = fopen ("textfile2", "wb");
fwrite (buffer, sizeof(char), sizeof(buffer), f2);
fclose (f2);
So, as you see, the memcpy can only perform with memory in RAM and it has nothing to do with files in hard drive (unless you read it into your RAM memory)

memcpy doesn't work over a file descriptor, you can store the content of file1 in an array of chars (using fgets or fread) and then copy to file2 (using fputs or fwrite)
Also note that you need to use fclose() instead of close() with fopen()

Related

Trying to write a buffer to a file, but keep getting segmentation faults and I can't figure out why

I have some code whose goal is to open/create a file, read in messages, and then write those messages to the opened/created file. Everything up to the writing to the file seems to work just fine. Here is my code.
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include "message-lib.h"
int usage( char name[] );
void * recv_log_msgs( void * arg );
sem_t mutex;
int log_fd;
void * recv_log_msgs( void * arg ){
sleep(1);
sem_wait(&mutex);
char buffer[1024];
int number_bytes_read;
FILE *fp = log_fd;
do{
number_bytes_read = read_msg(arg, buffer, 1024);
printf("in recv\n");
printf(buffer);
fwrite(&buffer, 1, sizeof(buffer)/sizeof(buffer[0]), fp);
}while(number_bytes_read > 0);
if(number_bytes_read == 0){
close_connection(arg);
}
sem_post(&mutex);
return NULL;
}
int usage( char name[] ){
printf( "Usage:\n" );
printf( "\t%s <log-file-name> <UDS path>\n", name );
return 1;
}
int main( int argc, char * argv[] )
{
int connection;
pthread_t tid;
if ( argc != 3 )
return usage( argv[0] );
log_fd = creat(argv[1], S_IRUSR | S_IWUSR);
if(log_fd == -1){
perror(argv[1]);
return 1;
}
int listener = permit_connections(argv[2]);
if(listener == -1){
return -1;
}
sem_init(&mutex, 0, 1);
do{
connection = accept_next_connection(listener);
if(connection == -1){
return -1;
}
pthread_create(&tid, NULL, recv_log_msgs, connection);
}while(connection != -1);
close_connection(connection);
close_listener(listener);
fclose(log_fd);
return 0;
}
permit_connections, accept_next_connection, and read_msg are all from a library that was provided to me. I'm guessing my problem is in recv_log_msgs, but I'm not sure what it would be.
Here's the root of your problem:
FILE *fp = log_fd;
log_fd is a file descriptor, fp is a FILE pointer.
The two are not interchangeable, and what you need to do is use the write(...) system call for writing to the log file, or create the log file in some other fashion to get a hold of a FILEpointer to it.
FILE *fp = fopen(argv[1], "w"), might do the trick.
EDIT: As #DarrenSmith pointed out to me in the comments, you can also use
fp = fdopen(log_fd, "w")
and keep the rest of the code as is.

how to open file within while loop that is dependant on information not yet declared?

I am attempting to open a file that will only be known once it has been created within a directory, however the FILE *infile (etc, etc..) function does not work in this scenario as "infile" has not previously been delcared. I can't work out how to declare this before the loop so that it gets the current file that is being iterated at that time.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <sys/inotify.h>
#include <openssl/sha.h>
int main (int argc, char *argv[])
{
int result;
int fd;
int wd;
unsigned char c[SHA512_DIGEST_LENGTH];
int i;
//FILE *inFile = fopen (filename, "rb"); //I'm aware this would usually
//be declared here
SHA512_CTX mdContext;
int bytes;
unsigned char data[1024];
const int event_size = sizeof(struct inotify_event);
const int buf_len = 1024 * (event_size + FILENAME_MAX);
fd = inotify_init();
if (fd < 0) {
perror("inotify_init");
}
wd = inotify_add_watch(fd, "/home/joe/Documents", IN_CREATE);
while (1) {
char buff[buf_len];
char target[FILENAME_MAX];
int no_of_events, count = 0;
no_of_events = read (fd, buff, buf_len);
while (count < no_of_events) {
struct inotify_event *event = (struct inotify_event *)&buff[count];
if (event->len) {
if (event->mask & IN_CREATE)
if(!(event->mask & IN_ISDIR)) {
printf("The file %s has been created\n", event->name);
//FILE *infile = fopen (filename, "rb"); //issue arises here
//when not commented
SHA512_Init (&mdContext);
while ((bytes = fread (data, 1, 1024, filename)) != 0)
SHA512_Update (&mdContext, data, bytes);
SHA512_Final (c,&mdContext);
for(i = 0; i < SHA512_DIGEST_LENGTH; i++) printf("%02x", c[i]);
printf (" %s\n", event->name);
fclose (filename);
return 0;
fflush(stdout);
}
}
count += event_size + event->len;
}
}
return 0;
}
I'm trying to work out the issue hence the comments and also undeclared "filename".
The name of the file that you want to open is stored in event->name. That's what you want to pass to fopen. Also, you want to pass infile to both fread and fclose.
FILE *infile = fopen (event->name, "rb"); // event->name is the filename
SHA512_Init (&mdContext);
while ((bytes = fread (data, 1, 1024, infile )) != 0) // read from infile
SHA512_Update (&mdContext, data, bytes);
SHA512_Final (c,&mdContext);
for(i = 0; i < SHA512_DIGEST_LENGTH; i++) printf("%02x", c[i]);
printf (" %s\n", event->name);
fclose (infile); // close infile

mmap and memcpy usage and Segmentation Fault (core dumped) error

I have two files and I want to copy one file content to other using memcpy. But I get this error Segmentation Fault (core dumped). My main
int main( int argc, char * argv[] ){
int d1;
int d2;
char *a;
char *b;
d1 = da_open_r(argv[1]); // open file READ ONLY
d2 = da_open_w(argv[2]); // open file to WRITE
a = (char*)da_mmap(d1); // map first file
b = (char*)da_mmap(d2); // map second file
memcpy(b, a, 10); // I think this line is bad
kp_test_munamp(a, 10 ); //
kp_test_munamp(b, 10 );
kp_test_close(d1); // close 1 file
kp_test_close(d2); // close 2 file
return 0;
}
and here are my da_mmap and kp_test_munamp
void *da_mmap(int d){
mmap(NULL, 10, PROT_READ|PROT_WRITE, MAP_SHARED, d, 0);
}
int kp_test_munamp( void *a, int size ){
int rv;
rv = munmap( a, size );
if( rv != 0 ){
puts( "munmap failed" );
abort();
}
return 1;
}
I have been trying to fix this almost two hours, but still I don't know what's wrong.
EDIT my full code
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <string.h>
int da_open_r(const char *name);
int da_open_w(const char *name);
void *da_mmap(int d);
int kp_test_munamp( void *a, int size );
int kp_test_close(int fd);
int da_open_r(const char *name){
int dskr;
dskr = open( name, O_RDWR );
if( dskr == -1 ){
perror( name );
exit( 255 );
}
printf( "dskr1 = %d\n", dskr );
return dskr;
}
int da_open_w(const char *name){
int dskr;
dskr = open( name, O_RDWR );
if( dskr == -1 ){
perror( name );
exit( 255 );
}
printf( "dskr2 = %d\n", dskr );
return dskr;
}
void *da_mmap(int d){
void *a = NULL;
a = mmap(NULL, 10, PROT_WRITE, MAP_SHARED, d, 0);
if( a == MAP_FAILED ){
perror( "mmap failed" );
abort();
}
return a;
}
int kp_test_munamp( void *a, int size ){
int rv;
rv = munmap( a, size );
if( rv == -1 ){
puts( "munmap failed" );
abort();
}
return 1;
}
int kp_test_close(int fd){
int rv;
rv = close( fd );
if( rv != 0 ) perror ( "close() failed" );
else puts( "closed" );
return rv;
}
int main( int argc, char * argv[] ){
int d1;
int d2;
char *a;
char *b;
d1 = da_open_r(argv[1]); // read only
d2 = da_open_w(argv[2]); // WRITE
a = (char*)da_mmap(d1);
b = (char*)da_mmap(d2);
memcpy(b, a, 10); // I think this line is bad
kp_test_munamp(a, 10 );
kp_test_munamp(b, 10 );
kp_test_close(d1);
kp_test_close(d2);
return 0;
}
da_mmap() does not return anything! Which leads to the values of a and b being garbage and with this most probably pointing to invalid memory, which in turn makes memcpy() fail when acting on it.
Add return statement
void * da_mmap(int d) {
return mmap(NULL, 10, PROT_READ|PROT_WRITE, MAP_SHARED, d, 0);
}
Also you should test the outcome of the mapping by doing:
{
void * pvtmp = da_mmap(d1); // map first file
if (MAP_FAILED == pvtmp)
{
perror("da_mmap() failed");
exit(1);
}
a = pvtmp;
}
The same for b.
Referring the wrapper around munmap(). Correct error testing here. However by convention success is indicated by returning 0 (failure by returning -1).

C - wrong output taking integer numbers from binary file and mmap function

I have some problem about to take integer numbers from binary file. My code is:
int main (int argc, char ** argv) {
FILE * fpi, *fpo, *fp;
int i, len;
char buf[50];
if (argc != 3) {
printf ("Syntax: %s filename_input, filename_output", argv[0]);
return (1);
}
len = 0;
if ((fpi = fopen (argv[1], "rt")) == NULL)
perror ("file_input open");
if ((fpo = fopen (argv[2], "wb")) == NULL)
perror ("file_output open %");
while(fscanf(fpi,"%d",&i) != EOF){ //Take the content of file input and put in the file binary
fwrite(&i, sizeof(int), 1, fpo); //I write each number i into file output
}
return (0);
}
Here, given a txt file with for example 5 integer numbers, it generates the corresponding binary file. Then, if I try to fread this binary file is all ok, but if I try to read this binary file with mmap function and I put the content on an array, in the output, as content of array, I have a strange character, a small square with 00 02. The code where I use mmap is:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char **argv) {
int fd;
int i, n, len;
int *vet;
struct stat stat_buf;
char *paddr;
if (argc != 2) {
printf("Syntax: %s filename", argv[0]);
return (1);
}
if ((fd = open(argv[1], O_RDWR)) == -1) {
perror("open");
}
if (fstat(fd, &stat_buf) == -1) {
perror("fstat");
}
len = stat_buf.st_size;
n = len / sizeof(int);
paddr = mmap((caddr_t) 0, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (paddr == (caddr_t) -1) {
perror("mmap");
}
close(fd);
vet = (int *) paddr;
for (i = 0; i < n; i++) {
printf("%d\n", vet[i]);
}
return (0);
}
The output that it gives me is:
Thank you in advance.

C - Read by basic I/O reads only "\n"

I have a problem at my C-lecture skill practice. My exercise is to read a text document (which is in the same directory like the program) char by char and write it reversed (so from the end to the beginning, char by char) at the Terminal (i have to work at Ubuntu).
Unfortunately it doesn't work - "read" only reads newline-chars (\n).
Can you find my mistake?
#include <sys/stat.h> //mode_t: accessing rights for the file
#include <fcntl.h> //for I/O
#include <unistd.h> //for file descriptors
#include <string.h> //for strlen
short const EXIT_FAILURE = 1;
short const EXIT_SUCCESS = 0;
char const* USAGE_CMD = "usage: write_file filename string_to_write\n";
char const* ERR_OPEN = "error in open\n";
char const* ERR_READ = "error in reading\n";
char const* ERR_CLOSE = "error in close\n";
char const* ERR_WRITE = "error in write\n";
int main(int argc, char** argv){
int fd = open(argv[1], O_RDONLY);
if(fd == -1){
write(STDERR_FILENO, ERR_OPEN, strlen(ERR_OPEN));
return EXIT_FAILURE;
}
int two_char_back = (-1)*sizeof(char); //shift-value for char
int one_back = -1; //shift-value for "no shift"
int length = lseek(fd, one_back, SEEK_END);//setting to one before oef
int i = 0; //for the loop
char buffer;
char* pbuffer = &buffer; //buffer for writing
while (i < length){
if (read(fd, pbuffer, sizeof(buffer)) == -1){ //READING
write(STDERR_FILENO, ERR_READ, strlen(ERR_READ));
return EXIT_FAILURE;
}
if(write(STDOUT_FILENO, pbuffer, sizeof(buffer)) == -1){ //WRITING
write(STDERR_FILENO, ERR_WRITE, strlen(ERR_WRITE));
return EXIT_FAILURE;
}
lseek(fd, two_char_back, SEEK_CUR); //STEPPING
i++;
}
if(close(fd) == -1){ //CLOSING
write(STDERR_FILENO, ERR_CLOSE, strlen(ERR_CLOSE));
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
This is wrong:
int two_char_back = (-1)*sizeof(char);
sizeof(char) is 1, you need -2
Haven't tried running it, but looks like two_char_back should be -2. The read advances the cursor, so -1 keeps reading the same one.
Also, just an option, you could make it more efficient by reading the whole file in then reversing it, then writing.
You have a typo in following line:
int two_char_back = (-1)*sizeof(char);
It must be:
int two_char_back = (-2)*sizeof(char);
As read() increments a cursor, you are actually reading the same character all the time e.g:
example text
^
|
After reading:
example text
^
|
After seeking:
example text
^
|
Thanks for your advices a lot!
& Thanks to my colleagues!
Now it works but I created kind of a new version, here it is:
#include <sys/stat.h> //mode_t: accessing rights for the file
#include <fcntl.h> //for I/O
#include <unistd.h> //for file descriptors
#include <string.h> //for strlen
short const EXIT_FAILURE = 1;
short const EXIT_SUCCESS = 0;
char const* USAGE_CMD = "usage: write_file filename string_to_write\n";
char const* ERR_OPEN = "error in open\n";
char const* ERR_READ = "error in reading\n";
char const* ERR_CLOSE = "error in close\n";
char const* ERR_WRITE = "error in write\n";
int main(int argc, char** argv){
int fd = open(argv[1], O_RDONLY); //OPENING
if(fd == -1){
write(STDERR_FILENO, ERR_OPEN, strlen(ERR_OPEN));
return EXIT_FAILURE;
}
int file_size = lseek(fd, 0, SEEK_END); //setting to eof
int i = file_size-1; //for the loop, runs from the end to the start
char buffer;
//the files runs from the end to the back
do{
i--;
lseek(fd, i, SEEK_SET); //STEPPING from the start
if (read(fd, &buffer, sizeof(buffer)) != sizeof(buffer)){ //READING
write(STDERR_FILENO, ERR_READ, strlen(ERR_READ));
return EXIT_FAILURE;
}
if(write(STDOUT_FILENO, &buffer, sizeof(buffer)) != sizeof(buffer)){ //WRITING
write(STDERR_FILENO, ERR_WRITE, strlen(ERR_WRITE));
return EXIT_FAILURE;
}
}while (i != 0);
buffer = '\n';
write(STDOUT_FILENO, &buffer, sizeof(buffer));//no error-det. due to fixed value
if(close(fd) == -1){ //CLOSING
write(STDERR_FILENO, ERR_CLOSE, strlen(ERR_CLOSE));
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}

Resources