C function to copy directory in UNIX: files fail to copy - c

I'm trying to write a function in C to copy the contents of a directory to another directory. Here is what I have so far:
void *copydirectory(void *arg1, void *arg2)
{
int error;
struct dirent *direntp;
DIR *dirp_source, *dirp_destination;
char *source, *destination;
copy_t copy;
char filename[MAXNAME];
// Set directory arguments
source = arg1;
destination = arg2;
fprintf(stderr, "Source directory is %s and destination directory is %s\n", source, destination);
// Open directories
if ((dirp_source = opendir(source)) == NULL)
{
fprintf(stderr, "Failed to open %s\n", source);
return 1;
}
if ((dirp_destination = opendir(destination)) == NULL)
{
perror("Failed to open destination directory");
return 1;
}
// Read files in directory
while ((direntp = readdir(dirp_source)) != NULL)
{
copy.tid = pthread_self();
fprintf(stderr, "now at line 64\n");
// Copy source filename
if (snprintf(filename, MAXNAME, direntp->d_name) == MAXNAME)
{
fprintf(stderr, "Input filename %s is too long", direntp->d_name);
continue;
}
fprintf(stderr, "now at line 73\n");
fprintf(stderr, "%s\n", filename);
// Open file for reading
if ((copy.args[0] = open(filename, R_FLAGS)) == -1)
{
fprintf(stderr, "Failed to open source file %s: %s\n", filename, strerror(errno));
continue;
}
// Create destination filename for writing
if (snprintf(filename, MAXNAME, "%s", direntp->d_name) == MAXNAME)
{
fprintf(stderr, "Output filename %s is too long\n", direntp->d_name);
continue;
}
fprintf(stderr, "%s\n", filename);
// Open file for writing
if ((copy.args[1] = open(filename, W_FLAGS, W_PERMS)) == -1)
{
fprintf(stderr, "Failed to open destination file %s: %s\n", filename, strerror(errno));
continue;
}
if (error = pthread_create((&copy.tid), NULL, copyfilepass, copy.args))
{
fprintf(stderr, "Failed to create thread: %s\n", strerror(error));
copy.tid = pthread_self();
}
}
// Close directory
while ((closedir(dirp_source) == -1) && (errno = EINTR));
fprintf(stderr, "Successfully copied all files in directory \n");
}
Now, for testing I simply have 2 directories in the folder named dir1 and dir2. dir1 contains 3 files: file1, file2, file3.
But, when I compile and run the code, I get these messages:
./
./
Failed to open destination file .: is a directory
Failed to open source file file2: No such file or directory
Failed to open source file file3: No such file or directory
../
../
Failed to open destination file .: is a directory
Failed to open source file file1: No such file or directory
Anyone have any suggestions on what's wrong?

Failed to open destination file .: is a directory
You see this because your source directory contains links called "." and ".." to itself and its parent directory respectively. You should specifically check for and avoid these entries.
Failed to open source file file2: No such fle or directory
You see this because you're trying to open a file called "file2" in the process's current working directory, but that doesn't exist - the file you're after is in the source directory. You need to build the filename taking this into account:
// Copy source filename
if (snprintf(filename, MAXNAME, "%s/%s", source, direntp->d_name) == MAXNAME)

Related

Bad file descriptor after recursive function to open file in C

I want to do a error check in a openFile Function in C and on errno:2 I want to recursivly call again the same function.
I don't get the right answer, if I want to do fputs() after opened the file I get a Error (Bad file descriptor)
Here is my code:
void openFile(FILE **fstream, char* path, char* mode) {
*fstream = fopen(path, mode);
if(*fstream == NULL) {
printf("\nError number %2d : ",errno);
perror("Error opening file: ");
switch (errno) {
case 2:
printf("Creating file %s now...\n", path);
*fstream = fopen(path, "a+"); //Creating file in append-mode
if (fstream == NULL) {
perror("Couldn't open the file!\nError");
exit(EXIT_FAILURE);
}
fclose(*fstream); //Closing filestream
openFile(fstream, path, mode); //Recursive call of openFile() to re-open in read-mode
/* freopen(path,mode,fstream) */ //Doesn't work either
break;
default:
exit(EXIT_FAILURE);
break;
}
} else if (*fstream != NULL) {
printf("Successfully opened %s\n", path);
}
}
The call:
openFile(&fp, path,"r");
if (fputs("blabla\nblabla\n",fp) == EOF) {
perror("Unable to write file with fputs()");
}
What I'm doing wrong? I think it's at the point of the recursive call of the function, but what I have to do here? I don't get it..
Output is:
> .\a
Content of path: test.txt
Error number 2 : Error opening file: : No such file or directory
Creating file test.txt now...
Successfully opened test.txt
Unable to write file with fputs(): Bad file descriptor
PS: I am a beginner with C, I've read and youtubed a lot about pointer, but I don't get the mistake.
Thank you in advance
You opened the file with "r" yet you're attempting to write. You need "w" instead.

How to use file structure?

I am having a small problem, I have the current file structure:
And this is my code:
#include <stdio.h>
#include <stdlib.h>
const char FILE_NAME[] = "inputfile.txt";
int main()
{
FILE *in_file; /* input file */
in_file = fopen(FILE_NAME, "r");
if (in_file == NULL) {
printf("Cannot open %s\n", FILE_NAME);
exit(8);
}else{
printf("File opened %s\n", FILE_NAME);
}
fclose(in_file);
return (0);
}
And I get this error:
Cannot open inputfile.txt
But the file is right there.
Can someone help me?
(If I change the "r" to "w" I can write to the file, but I can't find the file on my SSD)
The program will look for the file in the current working directory. This is most likely the same directory as the compiled executable.
If you are using an IDE, check the project settings and check where the compiled executable is placed. Then either copy the textfile to that directory manually or edit the project so that building it copies the file automatically.
If you are working from the command line (assuming your compiler is called gcc):
cd ~/Documents/programming/c/PracticalC/chapter14
gcc -Wall ch14pexercise1.c -o prog
./prog
include
include
const char FILE_NAME[] = "inputfile.txt";
int main()
{
FILE *in_file; /* write file */
in_file = fopen(FILE_NAME, "w");
if (in_file == NULL) {
printf("Cannot open %s\n", FILE_NAME);
exit(8);
}else{
printf("File opened %s\n", FILE_NAME);
}
fclose(in_file);
/read file/
FILE *in_file; /* input file */
in_file = fopen(FILE_NAME, "r");
if (in_file == NULL) {
printf("Cannot open %s\n", FILE_NAME);
exit(8);
}else{
printf("File opened %s\n", FILE_NAME);
}
fclose(in_file);
return (0);
}
If it work cheak path

Copying files from one directory into another directory using C. Trouble with opening files in the sending directory. No such file or directory

I am brand new to System Programming and am having some trouble learning how directories and files work. The program should take two arguments(directories), if both are existing directories then just copy the files from the first argument into the second. If the second is a file, return with an error, finally if the second argument doesn't exist, then create it and copy the files over.
The problem occurs when I am trying to open each file to copy over the contents to the new created copy. I can get the list of all files in the first directory. If I remove copy the data(aka. in_fd) the program copies all the files over, they just are empty files.
So far the program checks the input, makes the directory if needed. All that is left is to copy over the files.
Any help will be appreciated. I saw this on other questions but none of the answers seemed to help. Thank you in advance for all your help.
#define BUFFERSIZE 4096
#define COPYMODE 0644
void oops(char *, char *);
int main(int ac, char *av[])
{
int in_fd, out_fd, n_chars;
char buf[BUFFERSIZE];
/* check args */
if ( ac != 3 ){
fprintf( stderr, "usage: %s source destination\n", *av);
exit(1);
}
//Directory pointers
DIR *sender_dir_ptr;
DIR *receiver_dir_ptr;
struct dirent *direntp;
//Used to test second argument for new/existing directory
struct stat info;
if(lstat(av[2],&info) != 0) {
if(errno == ENOENT) {
//doesn't exist, make directory
mkdir(av[2], 0700);
if ((receiver_dir_ptr = opendir(av[2])) == NULL )
oops("cannot open %s\n", av[2]);
} else if(errno == EACCES) {
// we don't have permission to know if
// the path/file exists.. impossible to tell
oops("Permission Denied", av[2]);
}
}
//so, it exists.
if(S_ISDIR(info.st_mode)) {
//it's a directory. Assign the directory pointer
if ((receiver_dir_ptr = opendir(av[2])) == NULL )
oops("cannot open %s\n", av[2]);
} else if(S_ISREG(info.st_mode)) {
//it's a file, display error and exit
oops("File exists but looking for a directory", av[2]);
}
if ((sender_dir_ptr = opendir(av[1])) == NULL )
oops("cannot open %s\n", av[1]);
else
{
struct stat st_buf;
//Go through sender directory and copy over all files to new directory
while (( direntp = readdir(sender_dir_ptr)) != NULL )
{
lstat(direntp->d_name, &st_buf);
if (S_ISDIR (st_buf.st_mode))
{
continue;
}
else if (S_ISREG (st_buf.st_mode))
{
printf("direntp= %s\n",direntp->d_name);
char tmp_in[strlen(av[1])];
strcpy(tmp_in, av[1]);
strcat(tmp_in, "/");
strcat(tmp_in, direntp->d_name);
if ((in_fd=open(tmp_in, O_RDONLY)) == -1 )
oops("Cannot open,", direntp->d_name);
//Create pathname to the second directory
char* filename = av[2];
char tmp[strlen(av[2])];
strcpy(tmp, av[2]);
strcat(tmp, "/");
strcat(tmp, direntp->d_name);
printf("filename: %s \n", tmp);
//Create new file
if ((out_fd=creat(tmp, COPYMODE)) == -1 )
oops( "Cannot creat", tmp);
//Write old file data into the new files
while ( (n_chars = read(in_fd , buf, BUFFERSIZE)) > 0 )
if ( write(out_fd, buf, n_chars ) != n_chars )
oops("Write error to ", av[2]);
if ( n_chars == -1 )
oops("Read error from ", av[1]);
//close files
if ( close(in_fd) == -1 || close(out_fd) == -1 )
oops("Error closing files","");
}
else{
printf("File: %s \n",direntp->d_name);
}
}
//Close directories
closedir(sender_dir_ptr);
closedir(receiver_dir_ptr);
}
return 0;
}
void oops(char *s1, char *s2)
{
fprintf(stderr,"Error: %s ", s1);
perror(s2);
exit(1);
}
'direntp->d_name' is filename only, not a complete file specification as required by open() etc. You need to strcat the name to the folder path.

C zip library for opening password protected files

I am trying to use zlib and minizip. When I build 6 projects in one soltuion which are included in archive I downloaded everything works and project will create exe files (minizip and miniunz). Here is the problem, I don't know how to use miniunz and minizip source codes in my application and google isn't helping. Can somebody, who has experience with these libs, provide step by step tutorial how to include these lib in my application?
Or if you have other libraries to work with password protected files and can provide some tutorial how to include it in project that will help too, I tried to find something but there was no tutorial how to install them to projects
Thanks
Code based on minizip unzip.c.
include stdio.h zip.h unzip.h
First, create a zip with a file inside with a password.
The zip file must be in the same directory as the executable.
Run the program from a prompt in the directory of the generated program.
This example only extracts the first file!
/*-----------start-------------- */
/*Tries to open the zip in the current directory.*/
unzFile zfile = unzOpen("teste.zip");
if(zfile==NULL)
{
printf("Error!");
return;
}
printf("OK Zip teste.zip opened...\n");
int err = unzGoToFirstFile(zfile);/*go to first file in zip*/
if (err != UNZ_OK)
{
printf("error %d with zipfile in unzGoToFirstFile\n", err);
unzClose(zfile);/*close zip*/
}
/*At this point zfile points to the first file contained in the zip*/
char filename_inzip[256] = {0};/* The file name will be returned here */
unz_file_info file_info = {0};/*strcuture with info of the first file*/
err = unzGetCurrentFileInfo(zfile, &file_info, filename_inzip, sizeof(filename_inzip), NULL, 0, NULL, 0);
if (err != UNZ_OK)
{
printf("error %d with zipfile in unzGetCurrentFileInfo\n",err);
}
else
{
int len = 8192;/*size of chunk*/
char buffer[8192]={0};/*buffer used to save uncompressed data*/
printf("name of first file is :%s\n",filename_inzip);
printf("uncompressed_size = %d\n",file_info.uncompressed_size);
/*Use your password here, the same one used to create your zip */
err = unzOpenCurrentFilePassword(zfile, "yourpassword");
if (err != UNZ_OK)
printf("error %d with zipfile in unzOpenCurrentFilePassword\n", err);
else
printf("password ok\n");
FILE *fp = fopen(filename_inzip, "wb");/*file for data binary type*/
if (fp != NULL)
{
do
{/*read the current file returned by unzGoToFirstFile to buffer in chunks of the 8192*/
err = unzReadCurrentFile(zfile, &buffer, len );
if (err < 0)
{
printf("error %d with zipfile in unzReadCurrentFile\n", err);
break;
}
if (err == 0)
break;
/*Save the chunk read to the file*/
if (fwrite(&buffer, err, 1, fp) != 1)/*if error break*/
{
printf("error %d in writing extracted file\n", errno);
err = UNZ_ERRNO;
break;
}/*else continue*/
}
while (err > 0);
/*close file*/
fclose(fp);
}
}
unzClose(zfile);

How do I find out if the file is not present or the access rights are not present if the file pointer returns NULL in C?

How do I find out if the file is not present or the access rights are not present if the file pointer returns NULL in C? I am writing code in Linux. And the file has no access, but the file is present so how do I return different status that file was not present or file has no access.
Check the value of errno after the attempt to open the file:
if (NULL == (fp = fopen("myfile.txt", "r")))
{
if (ENOENT != errno)
{
fprintf(stderr, "Failed to open file: %s\n", strerror(errno));
}
else
{
fprintf(stderr, "file does not exist\n");
}
}

Resources