Hi ALL
How to create directory recursively in UNIX using system call mkdir?
surprisingly i dint find any way in api to make it work like "mkdir -
p".
Pls tell me is there any system call to do this?
Is thre any best already existing code to do this?
Note: I canot use system cmd.
|
|
0
|
|
|
|
Reply
|
doublemaster007 (85)
|
1/4/2010 8:15:47 AM |
|
Muhammed a �crit :
> How to create directory recursively in UNIX using system call mkdir?
Nope, not in POSIX.
> Pls tell me is there any system call to do this?
The mkdir function returns ENOENT in situations where the parent
directory does not exist:
<http://www.opengroup.org/onlinepubs/000095399/functions/mkdir.html>
In such situation, you could recursively try to create the upper structure.
> Is thre any best already existing code to do this?
Very simple and to be improved sample:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
static char *strndup(const char *s, size_t n) {
char *const s2 = malloc(n + 1);
s2[0] = '\0';
strncat(s2, s, n);
return s2;
}
static int mkdirs(const char *path, mode_t mode) {
#define IS_SEP(C) ( ( C ) == '/')
int ret = mkdir(path, mode);
/* A component of the path prefix specified by path does not name
an existing directory ? */
if (ret != 0 && errno == ENOENT) {
size_t i, last = 0;
for(i = 0 ; path[i] != '\0' ; i++) {
if (IS_SEP(path[i])) {
last = i;
}
}
if (last != 0) {
char *const parent = strndup(path, last);
ret = mkdirs(parent, mode);
free(parent);
if (ret == 0) {
ret = mkdir(path, mode);
}
}
}
return ret;
#undef IS_SEP
}
|
|
0
|
|
|
|
Reply
|
Xavier
|
1/4/2010 8:57:26 AM
|
|
Muhammed <doublemaster007@gmail.com> writes:
>Hi ALL
>How to create directory recursively in UNIX using system call mkdir?
>surprisingly i dint find any way in api to make it work like "mkdir -
>p".
>Pls tell me is there any system call to do this?
>Is thre any best already existing code to do this?
Some systems have mkdirp(3);
NAME
mkdirp, rmdirp - create or remove directories in a path
SYNOPSIS
cc [ flag ... ] file ... -lgen [ library ... ]
#include <libgen.h>
int mkdirp(const char *path, mode_t mode);
int rmdirp(char *dir, char *dir1);
Casper
--
Expressed in this posting are my opinions. They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.
|
|
0
|
|
|
|
Reply
|
Casper
|
1/4/2010 9:42:32 AM
|
|
Casper H.S. Dik a �crit :
> Some systems have mkdirp(3);
HPUX (dead) and SunOS (humm.. not yet dead :p), but unfortunately not
POSIX/Linux/BSD/Windows.
The function has never been standardized AFAICS ; maybe because of
unspecified (or hard to specify) behaviour regarding existing subpathes
(ie. if an intermediate path exist as symbolic link, shall the given
directory be created or shall the function fail ?)
|
|
0
|
|
|
|
Reply
|
Xavier
|
1/4/2010 10:21:02 AM
|
|
Xavier Roche <xroche@free.fr.NOSPAM.invalid> writes:
>Casper H.S. Dik a �crit :
>> Some systems have mkdirp(3);
>HPUX (dead) and SunOS (humm.. not yet dead :p), but unfortunately not
>POSIX/Linux/BSD/Windows.
>The function has never been standardized AFAICS ; maybe because of
>unspecified (or hard to specify) behaviour regarding existing subpathes
>(ie. if an intermediate path exist as symbolic link, shall the given
>directory be created or shall the function fail ?)
I would assume such a function behaves like "mkdir -p"; the function
appears to live in libgen and so it's probably from Sys V.
The Solaris source can be found in:
http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libgen/common/
Casper
--
Expressed in this posting are my opinions. They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.
|
|
0
|
|
|
|
Reply
|
Casper
|
1/4/2010 10:36:56 AM
|
|
Xavier Roche <xroche@free.fr.NOSPAM.invalid> writes:
> Casper H.S. Dik a �crit :
>> Some systems have mkdirp(3);
>
> HPUX (dead) and SunOS (humm.. not yet dead :p), but unfortunately not
> POSIX/Linux/BSD/Windows.
HP-UX is a supported product of a living company with a 'roadmap'
which points eight years into the future and the next 'major minor
release currently being 'in development'. Sun is basically bankrupt
and on the brink of being acquired by Oracle, and the future of
everything which presently exists under the 'Sun umbrella' is open to
speculation. Taking this into account, your asssessment seems somewhat
.... strange ... except if one is willing to make a few of the usual
assumption, namely, that 'dead' (to a Windows user) means "won't ever
run on my PC" and 'not dead yet' "while I haven't really found the
time to actually do so, I still contemplate to install it in order to
play around with it someday".
A loosely related question would be: What is the precise reason that
the very existience of non-x86-CPUs is so awfully frightening to some
PC people that they have this apparently irresistible desire to
constantly shout "Dead! Dead! Dead!" as some weird mantra in the hope
that this might motivate reality to fall in lines with their wishes?
My guess would be 'they believe to know how to program x86-CPUs using
machine language and feel terribly homesick in absence of
mov DWORD PTR [esp+0x4],ebx ...
|
|
0
|
|
|
|
Reply
|
Rainer
|
1/4/2010 12:42:13 PM
|
|
Rainer Weikusat a �crit :
> HP-UX is a supported product of a living company with a 'roadmap'
> which points eight years into the future and the next 'major minor
> release currently being 'in development'.
Yes, great. But I was referring to the market share, actually :)
> My guess would be 'they believe to know how to program x86-CPUs
You seem to mix two concepts - Operating System != Architecture.
> mov DWORD PTR [esp+0x4],ebx ...
I prefer move.l 4(sp),a0 ; even if assembly is a bit far now.
(A bit off-topic here though)
|
|
0
|
|
|
|
Reply
|
Xavier
|
1/4/2010 12:51:17 PM
|
|
Xavier Roche <xroche@free.fr.NOSPAM.invalid> writes:
> Rainer Weikusat a �crit :
>> HP-UX is a supported product of a living company with a 'roadmap'
>> which points eight years into the future and the next 'major minor
>> release currently being 'in development'.
>
> Yes, great. But I was referring to the market share, actually :)
Statistically (according to your statistic), I don't exist and neither
do you nor anyone else, as Douglas Adams has already proven more than
twenty years ago. Does that maybe ring a bell somewhere?
|
|
0
|
|
|
|
Reply
|
Rainer
|
1/5/2010 11:14:01 AM
|
|
On Mon, 04 Jan 2010 09:57:26 +0100, Xavier Roche wrote:
> Muhammed a écrit :
>> How to create directory recursively in UNIX using system call mkdir?
>
> Nope, not in POSIX.
>
>> Pls tell me is there any system call to do this?
>
> The mkdir function returns ENOENT in situations where the parent
> directory does not exist:
> <http://www.opengroup.org/onlinepubs/000095399/functions/mkdir.html>
>
> In such situation, you could recursively try to create the upper
> structure.
>
>> Is thre any best already existing code to do this?
>
> Very simple and to be improved sample:
>
I have a non-recursive one:
/* This function does about the same as "mkdir -p"
** It assumes *name to be a pathname/filename.
** all the nodes in the pathname-part are created
** (if they don't exist yet)
** duplicate slashes are ignored.
** NOTE: the part _after_ the last slash is not created;
** to indicate an empty directory add a trailing slash
** to the argument, (and omit the filename part).
** So, "/path/to/file.txt" , "/path/to/" and "//path//to/" all should give the same result.
** Function fails on first unrecoverable) error.
** returns :
** (return >= 0) := number of nodes that were created
** (return < 0) := -errno
*/
static int mkdir_p(const char * pathname, int mode)
{
int err = 0;
size_t len;
int rc = 0;
int cnt = 0;
char *slash;
char buff[MAX_FILENAME_SIZE];
struct stat statbuff;
len = strlen(pathname);
if (len >= sizeof buff) return -EINVAL;
memcpy(buff,pathname,len);
buff[len] = 0;
for(slash = buff; (slash = strchr(slash+1, '/' )); ) {
/* this is to catch double / in paths */
if (slash[-1] == '/') continue;
*slash = 0 ;
rc = stat(buff, &statbuff);
if (!rc) err = EEXIST; /* this is used to skip existing prefix */
else {
rc = mkdir(buff, mode);
err = (rc) ? errno: 0;
}
switch(err) {
case 0:
cnt++;
Logit("Mkdir_p[%d](\"%s\", %04o) := Ok", cnt, buff, mode );
case EEXIST:
break;
case ENOTDIR:
case EACCES:
default:
Logit("Mkdir_p(\"%s\", %04o) := [rc=%d] Err= %d (%s)"
, buff, mode, rc, err, strerror(err) );
goto quit;
}
*slash = '/' ;
}
quit:
return (err) ? -err : cnt;
}
HTH,
AvK
|
|
0
|
|
|
|
Reply
|
Moi
|
1/6/2010 10:55:21 AM
|
|
On 06/01/10 10:55, Moi wrote:
> On Mon, 04 Jan 2010 09:57:26 +0100, Xavier Roche wrote:
>
>> Muhammed a écrit :
>>> How to create directory recursively in UNIX using system call mkdir?
>>
>> Nope, not in POSIX.
>>
>>> Pls tell me is there any system call to do this?
>>
>> The mkdir function returns ENOENT in situations where the parent
>> directory does not exist:
>> <http://www.opengroup.org/onlinepubs/000095399/functions/mkdir.html>
>>
>> In such situation, you could recursively try to create the upper
>> structure.
>>
>>> Is thre any best already existing code to do this?
>>
>> Very simple and to be improved sample:
>>
>
> I have a non-recursive one:
>
> /* This function does about the same as "mkdir -p"
> ** It assumes *name to be a pathname/filename.
> ** all the nodes in the pathname-part are created
> ** (if they don't exist yet)
> ** duplicate slashes are ignored.
> ** NOTE: the part _after_ the last slash is not created;
> ** to indicate an empty directory add a trailing slash
> ** to the argument, (and omit the filename part).
> ** So, "/path/to/file.txt" , "/path/to/" and "//path//to/" all should give the same result.
> ** Function fails on first unrecoverable) error.
> ** returns :
> ** (return>= 0) := number of nodes that were created
> ** (return< 0) := -errno
> */
> static int mkdir_p(const char * pathname, int mode)
> {
> int err = 0;
> size_t len;
> int rc = 0;
> int cnt = 0;
> char *slash;
> char buff[MAX_FILENAME_SIZE];
> struct stat statbuff;
>
> len = strlen(pathname);
> if (len>= sizeof buff) return -EINVAL;
> memcpy(buff,pathname,len);
> buff[len] = 0;
>
> for(slash = buff; (slash = strchr(slash+1, '/' )); ) {
> /* this is to catch double / in paths */
> if (slash[-1] == '/') continue;
> *slash = 0 ;
> rc = stat(buff,&statbuff);
> if (!rc) err = EEXIST; /* this is used to skip existing prefix */
> else {
> rc = mkdir(buff, mode);
> err = (rc) ? errno: 0;
> }
> switch(err) {
> case 0:
> cnt++;
> Logit("Mkdir_p[%d](\"%s\", %04o) := Ok", cnt, buff, mode );
> case EEXIST:
> break;
> case ENOTDIR:
> case EACCES:
> default:
> Logit("Mkdir_p(\"%s\", %04o) := [rc=%d] Err= %d (%s)"
> , buff, mode, rc, err, strerror(err) );
> goto quit;
> }
> *slash = '/' ;
> }
> quit:
> return (err) ? -err : cnt;
> }
There is one issue with the standard (GNU and Solaris) mkdir -p. When
several threads/processes try to simultaneously create the same folder
with non-existing parents (e.g., mkdir -p a/b/c/d and a does not exists)
they sometimes end up creating them in parallel, so that mkdir()
eventually returns EEXIST after stat() said it did not exist, which
causes the function to fail. The above functions exhibit the same behaviour.
This issue can be resolved by not failing when mkdir() returns EEXIST.
--
Max
|
|
0
|
|
|
|
Reply
|
Maxim
|
1/10/2010 6:04:00 PM
|
|
|
9 Replies
2024 Views
(page loaded in 0.083 seconds)
|