0

I need to write a binary file to some specified directory using a C program. But, while writing I want to make sure that if the directory structure does not exist it should create one for me.

How can I achieve this?

Jay
  • 24,173
  • 25
  • 93
  • 141
Aman Deep Gautam
  • 8,091
  • 21
  • 74
  • 130
  • 3
    What have you tried? Where are you stuck? Are you familiar with `readdir(3)` and `mkdir(2)`? – sarnold Jun 21 '12 at 22:45
  • 1
    Here you can find solution: http://stackoverflow.com/questions/675039/how-can-i-create-directory-tree-in-c-linux – Adam Sznajder Jun 21 '12 at 22:45
  • 2
    As far as I know, there exists no wholly portable way to handle directories. What platform are you on? – thb Jun 21 '12 at 22:45
  • There is a C solution (provided by YT) at the question referenced by @Yob; that question is for C++, though, so it isn't quite a direct duplicate of this question. – Jonathan Leffler Jun 21 '12 at 23:51
  • Enjoy the fish! I amended my post only because I found it strange that you didn't accept my correct answer in the first place. – przemoc Jun 25 '12 at 22:21

1 Answers1

2

You have to check whether the leaf directory exists, using stat(), and iteratively create directories in a top-down manner, using mkdir(). Or you may even abandon the check and start with a directory creation - it will just fail with bunch of EEXIST errors if your directories are already there. This is just an easy way.

If you're concerned about correctness, there is a better way. You should use openat() on subsequent available components (directories) of the desired path and mkdirat() to create lacking ones. That way you can avoid possible races. In the end, you should open your file using openat() too.

Check relevant manpages to see how you should use mentioned system calls.


If the above rod was not sufficiently long enough for you, then below you can find my simple Linux-flavored fish. xopen() function allows you to open the file in a given path, creating directories along the way.

#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>

/* Look out! It modifies pathname! */
int xopen(char *pathname, int flags, mode_t mode, mode_t dirmode)
{
    int fd, errsv;
    int dirfd = AT_FDCWD;
    char *ptr = pathname;

    while (*ptr == '/')
        ptr++;
    for (;;) {
        strsep(&ptr, "/");
        if (ptr == NULL) {
            fd = openat(dirfd, pathname, flags, mode);
            break;
        }
        while (*ptr == '/')
            ptr++;
        if (*ptr == '\0') {
            errno = EISDIR;
            fd = -1;
            break;
        }
        if ((fd = mkdirat(dirfd, pathname, dirmode)) < 0 && errno != EEXIST)
            break;
        if ((fd = openat(dirfd, pathname, O_DIRECTORY)) < 0)
            break;
        if (dirfd != AT_FDCWD)
            close(dirfd);
        dirfd = fd;
        pathname = ptr;
    }
    errsv = errno;
    if (dirfd != AT_FDCWD)
        close(dirfd);
    errno = errsv;

    return fd;
}
przemoc
  • 3,759
  • 1
  • 25
  • 29