lseek() system call repositions the read/write file offset i.e., it changes the positions of the read/write pointer within the file. In every file any read or write operations happen at the position pointed to by the pointer. lseek() system call helps us to manage the position of this pointer within a file.
e.g., let’s suppose the content of a file F1 is “1234567890” but you want the content to be “12345hello”. You simply can’t open the file and write “hello” because if you do so then “hello” will be written in the very beginning of the file. This means you need to reposition the pointer after ‘5’ and then start writing “hello”. lseek() will help to reposition the pointer and write() will be used to write “hello”
Syntax
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
The first parameter is the file descriptor of the file, which you can get using open() system call. the second parameter specifies how much you want the pointer to move and the third parameter is the reference point of the movement i.e., beginning of file(SEEK_SET), current position(SEEK_CUR) of pointer or end of file(SEEK_END).
Examples:
- lseek(fd,5,SEEK_SET) – this moves the pointer 5 positions ahead starting from the beginning of the file
- lseek(fd,5,SEEK_CUR) – this moves the pointer 5 positions ahead from the current position in the file
- lseek(fd,-5,SEEK_CUR) – this moves the pointer 5 positions back from the current position in the file
- lseek(fd,-5,SEEK_END) -> this moves the pointer 5 positions back from the end of the file
On success, lseek() returns the position of the pointer within the file as measured in bytes from the beginning of the file. But, on failure, it returns -1.
To understand the working of lseek() system call lets first write two programs: Program1 without using lseek() and Program2 using lseek().
Pre-requisite: Create a file “seeking” and write “1234567890abcdefghijxxxxxxxxxx” into it.
Program1: Program using lseek() system call that reads 10 characters from file “seeking” and print on screen. Again read 10 characters and write on screen.
#include<unistd.h> #include<fcntl.h> #include<sys/types.h #include<sys/stat.h> #int main() { int n,f; char buff[10]; f=open("seeking",O_RDWR); read(f,buff,10); write(1,buff,10); read(f,buff,10); write(1,buff,10); }
Output
Q. What you think should be the output of this program?
Ans: it will be
1234567890abcdefghij
Because when the file opens the pointer is in the start by default. read() reads 10 characters “1234567890”. The pointer is now positioned at ‘a’ i.e., 10 positions ahead. write() then writes the characters on screen. read() again reads next 10 characters “abcdefghij” and write() writes on the screen.
Program2: Program using lseek() system call that reads 10 characters from file “seeking” and print on screen. Skip next 5 characters and again read 10 characters and write on screen.
#include<unistd.h> #include<fcntl.h> #include<sys/types.h #include<sys/stat.h> int main() { int n,f; char buff[10]; f=open("seeking",O_RDWR); read(f,buff,10); write(1,buff,10); lseek(f,5,SEEK_CUR);//skips 5 characters from the current position read(f,buff,10); write(1,buff,10); }
Output
This time the output will be the first 10 characters “1234567890” followed by “fghijxxxxx”. The inbetween 5 characters are skipped because we used lseek to reposition the pointer 5 characters ahead from the current (SEEK_CUR) position.
Here’s another program to understand the working better
Program3: Write a program to print 10 characters starting from the 10th character from a file “seeking”.
//Let the contents of the file F1 be “1234567890abcdefghijxxxxxxxx”. This means we want the output to be “abcdefghij”.
//Note: the first character ‘1’ is at 0th position
#include<unistd.h> #include<fcntl.h> #include<sys/types.h #include<sys/stat.h> #include<stdio.h> int main() { int n,f,f1; char buff[10]; f=open("seeking",O_RDWR); f1=lseek(f,10,SEEK_SET); printf("Pointer is at %d position\n",f1); read(f,buff,10); write(1,buff,10); }
How it works?
lseek is used to position the cursor at 10th position from the starting, hence the use of SEEK_SET. f1 saves the current position of the pointer which is printed. Then the next 10 characters are read using read() and printed on screen using write().
Output
Video Link
Practice Questions on lseek() system call
Q1. Write a program to print characters starting from 15th character till the 20th character of file F1.txt into file F4.txt.
Q2. Write a program to print the last 5 characters of a file.
Q3. Write a program to read a number(n) from the user. Print the first n characters from the file F1.txt.
Q4. Write a program to print the second half of a file.
Q5. Write program(s) to show the use of SEEK_SET, SEEK_CUR and SEEK_END. (solution)
Viva Questions on lseek() system call
Q1. How can you find the size of the file using lseek() system call?
Q2. Can lseek() be used to read and write also?
Relevant Programs
read()/write() system call
open() system call
fork() system call
Answer to Q1:
Position the pointer at the end using SEEK_END. lseek() will return the position of last character which will give the size of the file
Wow that was unusual. I just wrote an very long comment but after I clicked submit my comment didn’t appear.
Grrrr… well I’m not writing all that over again. Regardless, just wanted to say fantastic blog!