I am working on a c project and I need to remove a file from within a directory. For some reason though it keeps on saying that it can’t delete because the file or directory doesn’t exist. Below is the code that I am using to remove the file.
void deleteOldestLog()
{
FILE *fp;
char path[FILE_PATH_BUF_LEN], *fileName;
fp = popen("ls -tr /home/myfolder/logs/ |head -1", "r");
if (fp == NULL)
{
printf("Failed to run command");
}
else
{
char removalPath[FILE_PATH_BUF_LEN];
while ((fileName = fgets(path, sizeof(path)-1, fp)) != NULL)
{
sprintf(removalPath, "/home/myfolder/logs/%s", fileName, sizeof(fileName)-1);
printf("Removing file: %s", removalPath);
if (remove(removalPath) != 0)
{
perror("ERROR DELETING LOG");
}
else
{
printf("Successfully deleted %s", removalPath);
}
break;
}
pclose(fp);
}
}
Even though it says that it can’t find the file because it doesn’t exist I know that this isn’t true because if I run ll followed by the path that the c program printed it returns the file that I am trying to delete.
I think it might be because fgets is putting ‘\0’ on the end of the string which is stopping the remove from working.
How can I fix this?
There’s a newline at the end of the file name read by
fgets(). Your file name doesn’t actually end with a newline.You attempt to remove the newline with:
However, to be effective, you’d need to use
strlen()instead ofsizeof(), and you’d need to modify the format string:The argument for the
*must be anintandstrlen()returns asize_t; hence the cast. (GCC will warn about that sort of thing if you turn on the warnings; use at least-Wall.)A tip for you: when in doubt, print the string. I’ll typically use a format like this. Note the angle brackets around the string:
When you see:
you know there’s a problem with a newline in the string. Without the markers, you might not notice that there’s a newline in the string causing the extra newline in the output.
Let’s look at the original
sprintf()again:The format string expects 1 argument, a string. The call provides two values, a string and a length. So, the first problem is that there is a left-over argument. This usually does no damage, but be aware of it. Presumably, the reason for passing the length minus one was to lose the last character. The formats in the
printf()family can be adorned with one or two numbers, and either or both can have a*instead of an integer value. These numbers constrain the lengths of the formatted value. When you write:you state the length of the output shall be exactly the length specified by an
intvalue passed as an argument before the string itself. Hence the revision:(which I just fixed while adding this information.)
I’ve also not added error checking to the output of
sprintf()etc. That’s not unusual; however, best coding practices do ensure that functions likesprintf()return the value you expect (which is the number of characters written to the string, excluding the trailing null'\0'.(Aside: in general, it is better to use
snprintf()thansprintf(); that can avoid buffer overflows.However, the behaviour of the
*snprintf()functions under MSVC is different from the behaviour mandated by the C Standards (C99, C11). Worse, in the case ofvsnprintf_s()and the other_sfunctions, the argument lists are different between the MSVC and the C Standard.)