linux中创建目录树,如何在C++/Linux中创建目录树?
Jonathan Lef..
58
這是一個可以用C++編譯器編譯的C函數.
/*
@(#)File: $RCSfile: mkpath.c,v $
@(#)Version: $Revision: 1.13 $
@(#)Last changed: $Date: 2012/07/15 00:40:37 $
@(#)Purpose: Create all directories in path
@(#)Author: J Leffler
@(#)Copyright: (C) JLSS 1990-91,1997-98,2001,2005,2008,2012
*/
/*TABSTOP=4*/
#include "jlss.h"
#include "emalloc.h"
#include
#ifdef HAVE_UNISTD_H
#include
#endif /* HAVE_UNISTD_H */
#include
#include "sysstat.h" /* Fix up for Windows - inc mode_t */
typedef struct stat Stat;
#ifndef lint
/* Prevent over-aggressive optimizers from eliminating ID string */
const char jlss_id_mkpath_c[] = "@(#)$Id: mkpath.c,v 1.13 2012/07/15 00:40:37 jleffler Exp $";
#endif /* lint */
static int do_mkdir(const char *path, mode_t mode)
{
Stat st;
int status = 0;
if (stat(path, &st) != 0)
{
/* Directory does not exist. EEXIST for race condition */
if (mkdir(path, mode) != 0 && errno != EEXIST)
status = -1;
}
else if (!S_ISDIR(st.st_mode))
{
errno = ENOTDIR;
status = -1;
}
return(status);
}
/**
** mkpath - ensure all directories in path exist
** Algorithm takes the pessimistic view and works top-down to ensure
** each directory in path exists, rather than optimistically creating
** the last element and working backwards.
*/
int mkpath(const char *path, mode_t mode)
{
char *pp;
char *sp;
int status;
char *copypath = STRDUP(path);
status = 0;
pp = copypath;
while (status == 0 && (sp = strchr(pp, '/')) != 0)
{
if (sp != pp)
{
/* Neither root nor double slash in path */
*sp = '\0';
status = do_mkdir(copypath, mode);
*sp = '/';
}
pp = sp + 1;
}
if (status == 0)
status = do_mkdir(path, mode);
FREE(copypath);
return (status);
}
#ifdef TEST
#include
/*
** Stress test with parallel running of mkpath() function.
** Before the EEXIST test, code would fail.
** With the EEXIST test, code does not fail.
**
** Test shell script
** PREFIX=mkpath.$$
** NAME=./$PREFIX/sa/32/ad/13/23/13/12/13/sd/ds/ww/qq/ss/dd/zz/xx/dd/rr/ff/ff/ss/ss/ss/ss/ss/ss/ss/ss
** : ${MKPATH:=mkpath}
** ./$MKPATH $NAME &
** [...repeat a dozen times or so...]
** ./$MKPATH $NAME &
** wait
** rm -fr ./$PREFIX/
*/
int main(int argc, char **argv)
{
int i;
for (i = 1; i < argc; i++)
{
for (int j = 0; j < 20; j++)
{
if (fork() == 0)
{
int rc = mkpath(argv[i], 0777);
if (rc != 0)
fprintf(stderr, "%d: failed to create (%d: %s): %s\n",
(int)getpid(), errno, strerror(errno), argv[i]);
exit(rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
}
int status;
int fail = 0;
while (wait(&status) != -1)
{
if (WEXITSTATUS(status) != 0)
fail = 1;
}
if (fail == 0)
printf("created: %s\n", argv[i]);
}
return(0);
}
#endif /* TEST */
這些宏是STRDUP()and FREE()的錯誤檢查版本,strdup()并free()在emalloc.h(并在emalloc.c和中實現estrdup.c)聲明.該"sysstat.h"用的破碎版本頭交易,并且可以被替換為現代Unix系統上(但在1990年出現了許多問題后).并"jlss.h"宣布mkpath().
v1.12(上一個)和v1.13(上面)之間的變化是EEXISTin 的測試do_mkdir().Switch指出這是必要的- 謝謝你,Switch.測試代碼已經升級并在MacBook Pro(2.3GHz Intel Core i7,運行Mac OS X 10.7.4)上重現了問題,并建議在修訂版中修復問題(但測試只能顯示錯誤的存在) ,從不他們缺席).
(特此允許您將此代碼用于任何歸屬目的.)
這個代碼中有一個微妙的競爭條件,我實際上已經擊中了.它只發生在多個程序同時啟動并生成相同的文件夾路徑時.修復是添加`if(errno!= EEXIST){status = -1; 當mkdir失敗時. (7認同)
它肯定比系統更快.系統涉及很多開銷.基本上,進程必須分叉,然后必須至少加載兩個二進制文件(一個可能已經在緩存中),其中另一個是另一個的另一個分支,... (2認同)
@Switch:謝謝.這是在`mkdir()`之前使用`stat()`的麻煩; 這是TOCTOU(檢查時間,使用時間)問題.我嘗試使用在后臺運行13個進程的shell腳本來創建相同的29個元素的路徑,并且無法點擊它.然后我把測試程序分成20次,讓每個孩子嘗試,然后設法擊中了這個bug.固定代碼將具有`if(mkdir(path,mode)!= 0 && errno!= EEXIST)status = -1;`.這沒有顯示錯誤. (2認同)
@DavidMerinos:它們是頭文件(jlss.h,emalloc.h),而不是庫。但是,該代碼在GitHub上的[SOQ](https://github.com/jleffler/soq)(堆棧溢出問題)存儲庫中可用,分別為文件`jlss.h`,`emalloc.c`和`emalloc.h。在[src / libsoq](https://github.com/jleffler/soq/tree/master/src/libsoq)子目錄中。您還需要`posixver.h`,以及其他一些(`debug.h`,`stderr.c`,`stderr.h-我想就是這樣,但是您所需要的都應該在該目錄中) 。 (2認同)
總結
以上是生活随笔為你收集整理的linux中创建目录树,如何在C++/Linux中创建目录树?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: fts.exe是什么进程 有什么作用 f
- 下一篇: linux强行卸载qt,Linux下卸载