I want to do something similar to sed -i 's/abc/def/' file
but without temp file. In my case match and replacement are of same length; is the following safe:
fd = open(file, O_RDWR);
fstat(fd, &sbuf);
mm = mmap(0, sbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
i = 0;
while (i < sbuf.st_size) {
memcpy(tmpbuf, mm + i, BUFSIZ); // read from mem to tmpbuf (BUFSIZ at a time)
if ((p = strstr(tmpbuf, needle))) { // match found
memcpy(mm + i + (p - tmpbuf), replace, strlen(replace)); // strlen(replace) == strlen(needle)
}
i += BUFSIZ;
}
munmap(mm, sbuf.st_size);
fsync(fd);
close(fd);
(err handling omitted for brevity)
Also, not sure if mmap
is making this any faster!
It depends on what you mean by "safe". Unlike use of a temp file and atomic rename
over top of the old file after finishing, there is no atomicity to this operation; other processes could see the file in an intermediate, partially-modified state. And moreover there is not any ordering between the stores; they could see the end of the replacement before they see the beginning of it, or see them in any other conceivable order, and possibly even in inconsistent ones if also using mmap
and not using any memory barriers. Note that there's really nothing special about mmap
; you could do the same thing with write
too.
If none of these constitute "unsafety" for you, then the operation is totally safe. In particular it won't truncate the file or anything like that.