Writing File Data in the Raw

Along with open() as a raw file access function comes raw functions to read and write data. Last week’s Lesson covered the read() function. This week covers its twin sibling, write().

As with many companion functions in the C library, write() uses pretty much the same arguments as the read() function:

ssize_t write(int fildes, const void *buf, size_t nbyte);

The fildes argument is a file descriptor integer returned from an open() function, one that opens a file for writing. The buf argument is a buffer containing the data to be written, with nbyte the size of the data chunk. The buf argument is const void; const implies the buffer shouldn’t change as data is written and void allows you to typecast any data chunk for writing.

The value returned is the actual number of bytes written, which should match nbyte. When the value returned is -1, an error has occurred and the global variable errno is set.

When the open() function opens a file for writing, the O_WRONLY oflag constant is used. To create the file, you logically OR this flag with the O_CREAT defined constant, as shown in the following code:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{
    char filename[] = "file_output.txt";
    char text[] = "What a lovely little file\n";
    int fdes,r;

    /* open the file for writing and creating */
    fdes = open(filename,O_WRONLY|O_CREAT);
    if( fdes==-1 )
    {
        fprintf(stderr,"Unable to create %s\n",filename);
        return(1);
    }

    /* write the buffer */
    r = write( fdes, text, sizeof(text)-1 );
    if( r != sizeof(text)-1 )
    {
        fprintf(stderr,"Some kind of file writing error\n");
    }
    /* confirm success */
    printf("Data written to %s\n",filename);

    /* close 'er up */
    close(fdes);

    return(0);
}

Line 12 creates the file file_output.txt for writing:

fdes = open(filename,O_WRONLY|O_CREAT);

At Line 20, the string text is written to the open file:

r = write( fdes, text, sizeof(text)-1 );

Immediately after, an if test confirms that variable r is equal to the size of the string written. If not, a file-writing or creation error occurred. Otherwise, the file is closed at Line 29.

Here’s a sample run:

$ clang -Wall 0404.c
$ ./a.out
Data written to file_output.txt
$ cat file_output.txt 
What a lovely little file

If you compile this code in a Mac terminal window, you may see a permission denied error when you attempt to view the file. For some reason, under MacOS 10.15.x, security settings fly off the wall and lock down the new file. (Actually, click here to read the real reason why no permissions are set.) You can regain access by issuing the command chmod +rw file_output.txt. I have no idea why OS X is stubborn in this manner, and I have no further documentation on the topic.

Next week I cover an interesting function that crosses between the open() and fopen() functions.

2 thoughts on “Writing File Data in the Raw

  1. Here’s a solution to override the “permission denied” error on the Mac, which I’ve also learned can appear with some Linux distros as well:

    fdes = open(filename, O_WRONLY | O_CREAT, S_IRWXU );

    The S_IRWXU argument creates the file with rwx permissions for the owner. I’ll be adding another Lesson later this month to clarify the third option and its defined constants.

    I appreciate Jacco for passing along this fix. I wish more documentation was available for that third argument.

Leave a Reply