Безопасно ли изменять файл на месте, если размер замены совпадает с размером оригинала? - PullRequest
0 голосов
/ 28 февраля 2020

Я хочу сделать что-то похожее на sed -i 's/abc/def/' file, но без временного файла. В моем случае совпадение и замена имеют одинаковую длину; следующий сейф:

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);

(для краткости ошибочная обработка опущена)

Кроме того, не уверен, что mmap делает это быстрее!

1 Ответ

4 голосов
/ 28 февраля 2020

Это зависит от того, что вы подразумеваете под «безопасным». В отличие от использования временного файла и atomi c rename поверх старого файла после завершения, в этой операции нет атомарности; другие процессы могли видеть файл в промежуточном, частично измененном состоянии. И, кроме того, нет никаких заказов между магазинами; они могли видеть конец замены до того, как увидят ее начало, или видеть их в любом другом возможном порядке, и, возможно, даже в несовместимых , если также используют mmap и не используют никаких барьеров памяти. Обратите внимание, что в mmap нет ничего особенного; Вы можете сделать то же самое и с write.

Если ни один из них не является «небезопасным» для вас, то операция абсолютно безопасна. В частности, он не будет усекать файл или что-то в этом роде.

...