Похоже, что вы либо заново открываете файл с помощью O_APPEND
, либо открыли его для чтения / записи и не пытались начать сначала, прежде чем переписать его. (Таким образом, после прочтения всего файла позиция дескриптора файла является концом файла, поэтому вновь записанные данные будут там.)
Системный вызов lseek(2)
- это то, что вам нужно для перемещения позиции файла. lseek(fd, 0, SEEK_SET)
перематывает в начало . (Аргументы идут в EDI, RSI, EDX, как обычно для соглашения системных вызовов x86-64 System V. Интерфейс ядра соответствует интерфейсу libc.)
Поскольку данные, которые вы будете записывать, имеют одинаковую длину, вам не нужно ftruncate(fd, len)
файл, прежде чем начать перезапись. Вы перепишете все байты до конца.
И кстати, вам не нужно write
каждый символ отдельно; вы можете создать небольшой буфер, содержащий все байты ASCII для номера, и сделать один системный вызов write
; намного эффективнее и фактически требует меньше кода: Печать целого числа в виде строки с синтаксисом AT & T, с системными вызовами Linux вместо printf . Мой ответ там также показывает, что вы можете #include <asm/unistd.h>
и использовать код как
mov $__NR_write, %eax # SYS_write, from unistd_64.h
вместо использования числовых литералов для номеров системных вызовов, если вы используете файл .S
, чтобы gcc запускал его через препроцессор.
К сожалению, большинство заголовков, таких как <unistd.h>
(не asm/unistd.h
), также имеют объявления C, поэтому вы не можете так просто получить макросы для констант, таких как SEEK_SET
или O_RDWR
, которые позволили бы вам сделать mov $SEEK_SET, %edx
или mov $O_WRONLY|O_CREAT|O_TRUNC, %esi
.
Отмена ссылки на файл не повлияет на содержимое уже открытого файла; чтобы получить эффект, подобный тому, что вы изображаете в вопросе, вы можете закрыть / снова открыть файл. (В Unix удаление записи каталога для файла не влияет на программы, в которых он уже открыт. Это будет освобожден с диска, как только последняя запись в каталоге и дескриптор файла для него исчезли.)
Таким образом, вы откроете его для чтения, прочитаете все данные, а затем (после проверки на наличие ошибок, когда вы уверены, что у вас есть действительные данные для записи), open(infile, O_CREAT|O_TRUNC|O_WRONLY, 0666)
и запишите данные. Вы не использовали O_APPEND
, поэтому позиция нового FD только для записи будет находиться в начале файла. И размер файла будет усечен до 0. Точно так же, как echo foo > filename
в оболочке.
(Он по-прежнему будет иметь тот же номер инода и будет «тем же файлом» с другим содержимым, если только вы не откроете его unlink(infile)
для повторного создания нового файла с таким именем. В этом случае O_CREAT
действительно необходимо . При повторном открытии существующего файла для записи + усечения O_CREAT
не требуется, если файл уже существует.)
Ключевым моментом здесь является проверка ошибок чтения, прежде чем делать что-либо разрушительное , а не просто прочитать, уничтожить оригинал и продолжить. Таким образом, файл все еще находится на диске во время сортировки.