I am using C to work on a program that manages structs in a binary file.
I am having issues with my deleteData()function.
The method gets file name from user, validates file name, asks for record id to be deleted, then it copies the records except the one to be deleted from a file it is reading to a temp file.
The function should then close files, delete old file, and rename new file by the old file's name.
Everything appears to work except I can't open the new renamed file. I have checked the outcome in every step and it all appears to be ok.
Furthermore, when I look in my folder, I can see the renamed file and from it's byte size I can tell that a record has indeed been deleted.
But I can't open the file.
Please see my code below. I am working on a MAC, I have saved the folder that includes the code on my desktop. I am new to programming so any feedback or advise would be greatly appreciated.
void
deleteData()
{
char studentID[10];
char fileName5[30];
char tmpFile[] = "tmp.bin";
FILE *file;
FILE *tmpf;
int erFlag = 0;
int foFlag = 0;
int t;
struct Record tmp;
do {
printf(" Enter file in which record is located:\n");
scanf("%30s", fileName5);
if (!valSuf(fileName5))
printf("Error wih file name.\n");
} while (!valSuf(fileName5));
file = fopen(fileName5, "rb");
if (file == NULL)
printf("Error opening file.");
if (fread(&t, sizeof(int), 1, file) != 1)
printf("error reading total");
tmpf = fopen(tmpFile, "wb");
if (tmpf == NULL)
printf("Error opening temp file.");
if (fwrite(&t, sizeof(int), 1, tmpf) != 1)
printf("Error writing total.");
printf("Enter student ID you want to delete:");
scanf("%30s", studentID);
scanf("%*[^\n]");
while (fread(&tmp, sizeof(Record), 1, file) != 0) {
printf("%s\n", tmp.studentId);
if (strcmp(tmp.studentId, studentID) != 0) {
fwrite(&tmp, sizeof(Record), 1, tmpf);
printf("written to file: %s\n", tmp.studentId);
}
else {
foFlag = 1;
}
}
if (foFlag == 1) {
printf("Record not found.\n");
fclose(tmpf);
fclose(file);
remove(tmpFile);
}
else {
printf("in final stage.\n");
printf("closing file:%d\n", fclose(file));
printf("closing tmp: %d\n", fclose(tmpf));
printf("removing old file:%d\n", remove(fileName5));
printf("renaming file: %d\n", rename(tmpFile, fileName5));
}
}
Some issues ...
scanf("%30s", studentID);but you have [only]char studentID[10];foFlagto 1 if you match [and delete] a record. But,if (foFlag == 1)should beif (foFlag == 0).removebefore doingrename. Note thatrenameis designed to atomicallyunlinkthe old file and replace it with the new file. That is, observers [other processes] will see either the old contents or the new ones, but, never a partial or missing file.You say that the resultant file has the shorter length but is unreadable. I don't see how that could be [from this code] unless you have an unusual
umaskvalue:umaskcommand to see the value. It should normally report22. If not, doumask 22to set.ls -lto see what permissions are on the file.UPDATE:
The
rw-r--r--.is normal. That is what we'd expect with aumaskvalue of22. That is, when doing anfopen(file,"wb");the resultant file will allow read access to all and write access to the owner--what we want.So, the file should be readable. Even if the ownership was messed up (e.g. unlikely, but if file is owned by root but you are user "me"), it should still allow read access because the file is "world/other" readable.
How are you testing for readability after creating the file? You could just do:
fopenand thenfclose.I've refactored your program to be more diagnostic in nature. All/most returns are checked.
I made it create a file, delete some records, and show the file contents:
Here is the program output:
Note that the count remains 3 because
deleteRecdoes not adjust it down if it finds a record to delete [exercise left for reader ;-)]If the file is unreadable, then the final
showfilewill error out.