How to Write System Call in C++

Abdul Mateen Feb 02, 2024
  1. System Call in C++
  2. the write System Call in C++
How to Write System Call in C++

This tutorial will discuss the method to call the write system from a program written in C++. First, we will quickly refresh system calls, specifically the write system call and its prototype.

Later, we will discuss calling the write system call from a C++ program.

System Call in C++

Every operating system provides a set of services through system calls. It is a mechanism for computer programs to request a service from the operating system.

System calls provide the following services:

  1. Process creation and management
  2. Main memory management
  3. File and File system management
  4. Device Input/Output
  5. Protection
  6. Networking

The most frequent service required by programs is input/output. Next, we are going to discuss the write system call.

The programs request the underlying operating system to write on some device through write system calls.

Before moving ahead toward the write call, getting an idea about a file descriptor is important.

File Descriptor

In Unix and Unix-based operating systems, a file descriptor is a number that uniquely identifies a file or other IO resources like a socket or pipe.

Normally, the file descriptor is a non-negative integer value. Programs access files for IO through file descriptors.

The library functions deal with IO and take file descriptor as a parameter.

The first step is to open a file by the name (path absolute/relative in case the file is not located in the program’s folder) to access a file for IO.

If the open function successfully opens a file (i.e., a file exists by the same name and the user has the required rights), it returns a file descriptor.

int fd = open("abc.txt", O_RDONLY | O_CREAT);

The open function has two parameters. The first parameter is the file name, and the second is the read mode (e.g., read-only mode, write-only, etc.).

The subsequent IO operations on file are performed through the file descriptor.

the write System Call in C++

The write system call is one of the most basic routines provided by the operating system kernel. It writes data from primary memory (a buffer) into the file (stored on some hardware device).

The write() system call writes up to count bytes from the memory buffer pointed by buf to a file referred to by the file descriptor.

It is a low-level function that is only capable of understanding bytes. The write call cannot be used to write records, like classes.

Thus, higher-level input-output functions (like printf()) are inevitable to perform complex I/O.

Let’s first see the syntax of the write system call used to write data to a file.

ssize_t write(int fd, const void *buf, size_t count);

The write function’s three parameters details are:

  1. The file descriptor fd is obtained from the call to open a file. It is an integer value. The values 0, 1, and 2 can also be given for standard input, standard output, and standard error, respectively.
  2. The pointer to a buffer buf in memory where the data is stored in primary memory.
  3. The number of bytes specified by count to be written into the file pointed to by fd from the buffer buf.

The types ssize_t and size_t are, respectively, signed and unsigned integer data types defined in stddef.h.

Return Value

The write function returns a signed value. On success, it returns the number of bytes successfully written into the file, which may sometimes be less than the specified count.

The possible reasons for total written bytes to be less than the count can be the output device memory full or the source write-buffer has less number of chars to write than the number specified in the count.

On error, the write system call returns -1, and errno is set to indicate the error encountered.

Here, we have a complete program to write in the file using the write system call.

#include <errno.h>
#include <fcntl.h>

#include <iostream>

extern int errno;

using namespace std;

int main() {
  int fd, count;
  fd = open("abc.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
  cout << "File descriptor = " << fd << '\n';
  if (fd == -1) {
    // print which type of error have in a code
    printf("Error Number % d\n", errno);
    // print program detail "Success or failure"
    perror("Program");
  }
  char buff[] = "This is a test program to check write system call.";
  count = write(fd, buff, 50);
  if (count == -1)
    cout << "Error writing in file";
  else
    cout << "Number of bytes written to the file: " << count << '\n';
  close(fd);
  return 0;
}

The first header file, fcntl.h, has a write system call. The second header file has error functions.

In the open function call, we create a new file name, abc.txt, in write mode. The file may exist before but using O_TRUNC, the previous contents will be removed, and a new empty file will be created.

The code 0644 indicates the file permissions. Next, the if condition checks if the file is successfully opened or not.

In case of failure, the error message will be displayed.

Next, we created a character array (to be used as a buffer) with a sample text. Finally, we are writing into the file.

The third parameter is 50, stating the number of characters to write from the buff array.

The count is the integer value returned from the write() API call. In case of failure, the value will be -1; therefore, we check the count and print the error message accordingly.

In case of the successful write operation, we will have a positive value of count, and the if condition will show the total bytes successfully written to the file.

write system call

The first output, value 3, shows that the file is successfully opened. In the second line, 50 shows that all 50 bytes are successfully written.

Next, we modified the open statement.

fd = open("abc.txt", O_RDONLY | O_CREAT | O_TRUNC, 0644);

Notice that we have replaced O_WRONLY with O_RDONLY, and as a result, the output is:

File descriptor = -1
Error Number  13
Program: Permission denied
Error writing in file

Our open operation failed because it’s impossible to open an existing file in reading mode by truncating the contents.

As a result of failure, you can see the file descriptor is -1. Also, the writing operation is unsuccessful.

If we close the file before the write system call, the result will be an unsuccessful operation by a write system call. In this case, the output should be something like this:

File descriptor = 3
Error writing in file

Here, the file descriptor is not -1, but the file is closed; therefore, the write system call fails.

The value returned by the write system call is -1. Therefore, an error message is printed.