Rupam098
Rupam098

Reputation: 33

Please explain What's wrong with this C code?

What I am trying is to get all the file present in a directory and then add a .enc extension to this file. Example- Let File.txt is present then I will perform some encryption related task and after that the new file name would be File.txt.enc

Here is my code:

#include <dirent.h>
#include <stdio.h>
#include <string.h>

int main(void)
{
    DIR *d;
    struct dirent *dir;
    char *name;
    int val;
    d = opendir(".");
    if (d)
    {
        while ((dir = readdir(d)) != NULL)
        {
            name=dir->d_name;
            printf("File Found:%s\n",name);
            strcat(name,".enc");
            val=rename(dir->d_name,name);
            if(val==0)
                    printf("Encrypted File:%s\n",name);
            else
                    perror("Error: ");
        }
        closedir(d);
    }
    return(0);
}

But I am getting a output like this......

File Found:write_pgm_img.c
Error: : No such file or directory
File Found:realloc.c
Error: : No such file or directory
File Found:getusage.txt
Error: : No such file or directory
File Found:directory.c
Error: : No such file or directory

As you can see "No such file or directory" error. But I can't understand why?? Please explain.Thanks in advance.

Upvotes: 0

Views: 377

Answers (4)

Gerhardh
Gerhardh

Reputation: 12404

You are messing up pointers and memory content:

            name=dir->d_name;
            printf("File Found:%s\n",name);
            strcat(name,".enc");
            val=rename(dir->d_name,name);

After the first line, name and dir->d_name point to the same memory address. This means you try to add a suffix to the memory where dir->d_name is located. You cannot expect that memory to be large enough to hold your suffix. (But in this case this does not cause the problem as your file names seem to be short enough)

Also your update will affect both name and dir->d_name in the same way which makes renaming pointless because you try to rename getusage.txt.enc to getusage.txt.enc

A possible solution could be:

        char name[sizeof(dir->d_name)+4];
        while ((dir = readdir(d)) != NULL)
        {
            strcpy(name, dir->d_name);
            printf("File Found:%s\n",name);
            strcat(name,".enc");
            val=rename(dir->d_name,name);

Upvotes: 5

Since name may not have a larger size, strcat(name,".enc"); will may write past that size and causes UB. As others point out, this does not cause the ENOENT error you get (assuming you use linux).

To fix that you have to create a new, large enough buffer and copy the new name to it. This would also fix the error you get because this way you do not overwrite the old name.

Upvotes: 0

Kevin Boone
Kevin Boone

Reputation: 4307

I think perhaps you're assuming that name=dir->d_name creates some new piece of data called name. It's an easy enough mistake to make, because in many programming languages that's exactly what would happen. In C though, you've just set a pointer called name to refer to the existing data called d_name.

If you want to append something to d_name, you probably need to copy it to a char * that references a piece of storage large enough to hold it, and the suffix, and the terminating null, and then copy the suffix onto the end of that new storage. Something like:

char *new_name = malloc (strlen (dir->d_name) + strlen (suffix) + 1);
strcpy (new_name, dir->d_name);
strcat (new_name, suffix);
...
free (new_name);

Probably there are many other ways to achieve the same thing. The fundamental point is that assigning pointer types in C does not allocate or duplicate storage.

Upvotes: 1

shafeeq
shafeeq

Reputation: 1589

Your name & dir->d_name have the same address. Hence strcat(name,".enc"); will update both name & dir->d_name and the source will have the prefix '.enc'

Upvotes: 1

Related Questions