Howto: C Programming with Temporary Files in Linux

by Himanshu Arora on June 29, 2012

Sometimes while designing a software, you might have a requirement to hold some data (for reprocessing at later stage) for some duration. Some software do it within the memory in which they are running while others may create a temporary file for this purpose.

Creating temporary files to hold data is a popular practice among the software developers. There exist several system calls that are used for creating temporary files. Now one would think that why would we require system calls to create temporary files. Well the major reason behind this is to have unique temporary file names. Suppose there is a program that creates a temporary file while running and suppose multiple instances of same program are running simultaneously. If the uniqueness of temporary files is not kept in mind then multiple instances of same program may try to create temporary files with same name leading to conflict.

Now one may argue that uniqueness can be maintained by checking whether a file with same name exists or not. Agreed!!!! But this would result in a bulky code being added to the software logic to perform this operation successfully. So, its nice if the system provides some calls that can do this stuff for your software.

There are many system calls available to manipulate temporary files :

  •  mkstemp()
  •  tmpfile()
  •  tempnam()
  •  tmpnam()
  •  unlink()

While mkstemp, tmpfile, tempnam and tmpnam functions are used for creating a temporary file, the unlink function is used for removing a created temporary file. Here in this article, we will focus on the mkstemp() and unlink() system calls.

The mkstemp() and unlink() system calls

The signature of mkstemp() looks like :

#include <stdlib.h>
int mkstemp(char *template);

This system calls creates and opens the temporary file and returns the open file descriptor for it. The argument ‘template’ is used to generate the temporary file name. Since ‘template’ literally acts like a template name so the last six characters of the buffer passed as ‘template’ must contain “XXXXXX” as these characters are replaced by the system call to make the temporary file name unique.

The signature of unlink() looks like :

#include <unistd.h>
int unlink(const char *pathname);

unlink() deletes a name from the file system. If that name was the last link to a file and no processes have the file open the file is deleted and the space it was using is made available for reuse. If the name was the last link to a file but any processes still have the file open the file will remain in existence until the last file descriptor referring to it is closed. If the name referred to a symbolic link the link is removed. If the name referred to a socket, fifo or device the name for it is removed but processes which have the object open may continue to use it.

Also, to understand how to manipulate a directory within C program, refer to C Programming with Directories.

An Example

Lets have a look at an example where we use the mkstemp() and unlink() calls to demonstrate their usage for manipulating temporary files.

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<errno.h>

int main(void)
{
    // buffer to hold the temporary file name
    char nameBuff[32];
    // buffer to hold data to be written/read to/from temporary file
    char buffer[24];
    int filedes = -1,count=0;

    // memset the buffers to 0
    memset(nameBuff,0,sizeof(nameBuff));
    memset(buffer,0,sizeof(buffer));

    // Copy the relevant information in the buffers
    strncpy(nameBuff,"/tmp/myTmpFile-XXXXXX",21);
    strncpy(buffer,"Hello World",11);

    errno = 0;
    // Create the temporary file, this function will replace the 'X's
    filedes = mkstemp(nameBuff);

    // Call unlink so that whenever the file is closed or the program exits
    // the temporary file is deleted
    unlink(nameBuff);

    if(filedes<1)
    {
        printf("\n Creation of temp file failed with error [%s]\n",strerror(errno));
        return 1;
    }
    else
    {
        printf("\n Temporary file [%s] created\n", nameBuff);
    }

    errno = 0;
    // Write some data to the temporary file
    if(-1 == write(filedes,buffer,sizeof(buffer)))
    {
        printf("\n write failed with error [%s]\n",strerror(errno));
        return 1;
    }

    printf("\n Data written to temporary file is [%s]\n",buffer);

    // reset the buffer as it will be used in read operation now
    memset(buffer,0,sizeof(buffer));

    errno = 0;
    // rewind the stream pointer to the start of temporary file
    if(-1 == lseek(filedes,0,SEEK_SET))
    {
        printf("\n lseek failed with error [%s]\n",strerror(errno));
        return 1;
    }

    errno=0;
    // read the data from temporary file
    if( (count =read(filedes,buffer,11)) < 11 )
    {
        printf("\n read failed with error [%s]\n",strerror(errno));
        return 1;
    }

    // Show whatever is read
    printf("\n Data read back from temporary file is [%s]\n",buffer);

    return 0;
}

In the example above :

  • Created and open temporary file using the mkstemp() function.
  •  This function updates the Xs in the name we used with some characters that make the overall name unique.
  •  Just after the creation, the function unlink() was called.
  •  Calling unlink() does not delete the file immediately but waits for the file to get closed or the process to exit.
  •  Through the write function some data is written to the temporary file
  •  Through the read function the data is read back.
  •  The above two operations show that the temporary file can be used as any other normal file to perform file operations.
  •  As soon as the process exits, the file is deleted by unlink().

The output of the above program is :

# ./tempfile 

 Temporary file [/tmp/myTmpFile-wH5sLq] created

 Data written to temporary file is [Hello World]

 Data read back from temporary file is [Hello World]

So we see that the Xs that we used in temporary file name template were actually replaced by the some random characters (wH5sLq in this case) making the temporary file name unique.


Linux Sysadmin Course Linux provides several powerful administrative tools and utilities which will help you to manage your systems effectively. If you don’t know what these tools are and how to use them, you could be spending lot of time trying to perform even the basic administrative tasks. The focus of this course is to help you understand system administration tools, which will help you to become an effective Linux system administrator.
Get the Linux Sysadmin Course Now!

If you enjoyed this article, you might also like..

  1. 50 Linux Sysadmin Tutorials
  2. 50 Most Frequently Used Linux Commands (With Examples)
  3. Top 25 Best Linux Performance Monitoring and Debugging Tools
  4. Mommy, I found it! – 15 Practical Linux Find Command Examples
  5. Linux 101 Hacks 2nd Edition eBook Linux 101 Hacks Book

Bash 101 Hacks Book Sed and Awk 101 Hacks Book Nagios Core 3 Book Vim 101 Hacks Book

{ 6 comments… read them below or add one }

1 Jalal Hajigholamali June 29, 2012 at 8:25 am

Hi,

Thanks a lot for very nice article

2 tariq June 29, 2012 at 9:32 am

Hi,
I have a confusion between using “bash scripting” and using “C programming in Linux”

Can you explain when to use which?

Thanks

3 Tony June 29, 2012 at 10:43 pm

Thanks very much, really good article!

4 Alex June 30, 2012 at 11:58 am

mkstemp, tmpfile, tempnam and tmpnam are not system calls. They are implemented inside libc.

unlink is a system call however user space programs should call remove() instead.

Alex.

5 Jay July 1, 2012 at 7:43 am

Hi, thanks for a wonderful article.
Is there any particular reason why you use memset+strncpy, instead of strcpy ?
I saw a similar thing in your previous tutorial on “C Programming with Directories”. Kindly help, if there is something deeper that I missing. :)

Thanks

6 Ardi July 27, 2012 at 1:15 am

What a different of all functions?

Leave a Comment

Previous post:

Next post: