6

I need to delete the last n characters from a file using C code. At fist I was trying to use '\b', but it returns a Segmentation Fault. I have seen interesting answers to similar questions here and here, but I would prefer to use mmap function to do this, if it's possible. I know it could be simpler to truncate the file by creating a temp file, and writing chars to temp until some offset of the original file. The problem is I don't seem to understand how to use mmap function to do this, can't see what parameters I need to pass to that function, specially address, length and offset. From what I've read, I should use MAP_SHARED in flags and PROT_READ|PROT_WRITE in protect.

The function definition says:

void * mmap (void *address, size_t length, int protect, int flags, int filedes, off_t offset)

Here is my main:

int main(int argc, char * argv[])
{
    FILE * InputFile;
    off_t position;
        int charsToDelete;

    if ((InputFile = fopen(argv[1],"r+")) == NULL)
    {
            printf("tdes: file not found: %s\n",argv[1]);
    }
    else
    {
                charsToDelete = 5;
        fseeko(InputFile,-charsToDelete,SEEK_END);
        position = ftello(InputFile);
        printf("Pos: %d\n",(int)position);
        int i;
        //for(i = 0;i < charsToDelete;i++)
        //{
        //  putc(InputFile,'\b');
        //}
    }
    fclose(InputFile);
    return 0;
}
Community
  • 1
  • 1
anairinac
  • 559
  • 4
  • 6
  • 18

3 Answers3

7

Why not use:

   #include <unistd.h>
   #include <sys/types.h>

   int truncate(const char *path, off_t length);
   int ftruncate(int fd, off_t length);

like for instance:

    charsToDelete = 5;
    fseeko(InputFile,-charsToDelete,SEEK_END);
    position = ftello(InputFile);
    ftruncate(fileno(InputFile), position);
xtof pernod
  • 862
  • 5
  • 7
3

Read all but n bytes from the file and write to a temporary file, close the original file, rename temporary file as original file.

Or use e.g. truncate or similar function if you have it.


Also, failure to open the file doesn't have to be that it can't be found, You should check errno on failure to see what the error is. Use e.g. strerror to get a printable string from the error code.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
2

Unfortunately, mmap does not allow you to change size of underlying file object.

Instead, I would recommend to simply truncate your file, use something like this:

truncate(filename, new_length);
mvp
  • 111,019
  • 13
  • 122
  • 148
  • I thought I could use `mmap` for that. In which cases using that function would seem a good idea? When I need to make some character shift in the file? Like when using `memmove`? – anairinac Jun 09 '13 at 19:21
  • 1
    because `mmap` maps file contents into memory (you can use pointers with known memory block size), you must remove mapping *before* you change file size by writing more data to it or by using `truncate`. If you want to manipulate file contents quickly, `mmap` is good and fast method. But if you need to change file size, change it upfront, and then use `mmap`. – mvp Jun 09 '13 at 19:25