Linux программирование в примерах | страница 85
Смысл значений и их действие на положение в файле показаны на рис. 4.1. При условии, что файл содержит 3000 байтов и что перед каждым вызовом >lseek()
текущим является смещение 2000 байтов, новое положение после каждого вызова будет следующим.
Рис. 4.1. Смещения для >lseek()
Отрицательные смещения относительно начала файла бессмысленны; они вызывают ошибку «недействительный параметр».
Возвращаемое значение является новым положением в файле. Поэтому, чтобы получить ваше текущее местоположение в файле, используйте
>off_t curpos;
>...
>curpos = lseek(fd, (off_t)0, SEEK_CUR);
Буква >l
в >lseek()
означает >long
. >lseek()
был введен в V7 Unix, когда размеры файлов были увеличены; в V6 был простой системный вызов >seek()
. В результате большое количество старой документации (и кода) рассматривает параметр offset как имеющий тип >long
, и вместо приведения к типу >off_t
довольно часто можно видеть суффикс L в константных значениях смешений:
>curpos = lseek(fd, 0L, SEEK_CUR);
На системах с компилятором стандартного С, где >lseek()
объявлена с прототипом, такой старый код продолжает работать, поскольку компилятор автоматически преобразует 0L из >long
в >off_t
, если это различные типы.
Одной интересной и важной особенностью >lseek()
является то, что она способна устанавливать смещение за концом файла. Любые данные, которые впоследствии записываются в это место, попадают в файл, но с образованием «интервала» или «дыры» между концом предыдущих данных файла и началом новых данных. Данные в промежутке читаются, как если бы они содержали все нули.
Следующая программа демонстрирует создание дыр. Она записывает три экземпляра >struct
в начало, середину и дальний конец файла. Выбранные смешения (строки 16–18, третий элемент каждой структуры) произвольны, но достаточно большие для демонстрации особенности:
>1 /* ch04-holes.c --- Демонстрация lseek() и дыр в файлах. */
>2
>3 #include
>4 #include
>5 #include
>6 #include
>7 #include
>8 #include
>9 #include
>10
>11 struct person {
>12 char name[10]; /* имя */
>13 char id[10]; /* идентификатор */
>14 off_t pos; /* положение в файле для демонстрации */
>15 } people[] = {
>16 { "arnold", "123456789", 0 },
>17 { "miriam", "987654321", 10240 },