引言:
在Linux中,目录也是文件,我们在使用linux系统时,一般使用mkdir命令创建新的目录,跟命令相对应的也有创建目录、删除目录的函数。
(一)
用mkdir函数创建目录,用rmdir函数删除目录。注意:当我们在创建普通文件时,一般指定文件的mode为读、写权限,但对于目录,我们至少要设置1个执行权限,以允许访问该目录中的文件名。用rmdir函数删除一个空目录。函数原型如下:
#include <sys/stat.h>
#include <sys/types.h>
int mkdir(const char *pathname, mode_t mode); // 若成功返回0, 若出错返回-1
#include <unistd.h>
int rmdir(const char *pathname); // 若成功返回0,若出错返回-1
if(mkdir("makefile", S_IRUSR | S_IWUSR | S_IXUSR) == -1){
printf("mkdir failed.\n");
exit(0);
}
if(rmdir("makefile") == -1){
printf("remoce dir failed.\n");
}
(二)
对某个目录具有访问权限的任一用户都可读该目录,但是,为了防止文件系统产生混乱,只有内核才能写目录。一个目录的写权限位和执行权限位决定了再该目录中能否创建新文件以及删除文件,他们并不代表能否写目录本身。
对于普通文件来讲,要想读写一个文件,必须先用open函数得到文件描述符;类似的对于目录来讲,也必须先用opendir函数得到目录的DIR结构,之后,利用该结构作为readdir等函数的参数来对目录进行其他操作。
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name); //返回值:若成功则返回指针,若出错则返回NULL
struct dirent *readdir(DIR *dirp); //返回值:若成功则返回指针,若在目录结尾或出错则返回NULL
void rewinddir(DIR *dirp); //重设读取目录的位置为开头位置
int closedir(DIR *dirp); //返回值:若成功返回0,若出错返回-1
long telldir(DIR *dp); //返回值:与dp关联的目录中的当前位置
void seekdir(DIR *dp, long loc); //设置下回读取目录的位置
以上目录操作函数中使用的两个结构体dirent和DIR结构体。
struct dirent
{
long d_ino; /* inode number 索引节点号 */
off_t d_off; /* offset to this dirent 在目录文件中的偏移 */
unsigned short d_reclen; /* length of this d_name 文件名长 */
unsigned char d_type; /* the type of d_name 文件类型 */
char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最长255字符 */
}
struct __dirstream
{
void *__fd; /* `struct hurd_fd' pointer for descriptor. */
char *__data; /* Directory block. */
int __entry_data; /* Entry number `__data' corresponds to. */
char *__ptr; /* Current pointer into the block. */
int __entry_ptr; /* Entry number `__ptr' corresponds to. */
size_t __allocation; /* Space allocated for the block. */
size_t __size; /* Total valid data in the block. */
__libc_lock_define (, __lock) /* Mutex lock for this structure. */
};
typedef struct __dirstream DIR;
(三)
示例程序:该程序是APUE上的程序
#include "apue.h"
#include "error.h"
#include <dirent.h>
#include <limits.h>
#ifdef PATH_MAX
static int pathmax = PATH_MAX;
#else
static int pathmax = 0;
#endif
#define SUSV3 200112L
static long posix_version = 0;
#define PATH_MAX_GUESS 1024
/*function type that is called for each filename*/
typedef int Myfunc(const char *, const struct stat *, int);
static Myfunc myfunc;
static int myftw(char *, Myfunc *);
static int dopath(Myfunc *);
static long nreg, ndir, nblk, nchr, nfifo, nslink, nsock, ntot;
char *path_alloc(int *sizep)
{
char *ptr;
int size;
if(posix_version == 0)
posix_version = sysconf(_SC_VERSION);
if(pathmax == 0){
errno = 0;
if((pathmax = pathconf("/", _PC_PATH_MAX)) < 0){
if(errno == 0)
pathmax = PATH_MAX_GUESS;
else
err_sys("pathconf error for _PC_PATH_MAX");
}else{
pathmax++;
}
}
if(posix_version < SUSV3)
size = pathmax + 1;
else
size = pathmax;
if((ptr = malloc(size)) == NULL)
err_sys("malloc error for pathname");
if(sizep != NULL)
*sizep = size;
return (ptr);
}
int
main(int argc, char *argv[])
{
int ret;
if(argc != 2)
err_sys("usage: a.out <pathname>");
ret = myftw(argv[1], myfunc); /*does it all*/
ntot = nreg + ndir + nblk + nchr + nfifo + nslink + nsock;
if(ntot = 0)
ntot = 1; /*avoid divide by 0; print 0 for all counts*/
printf("regular files = %7ld, %5.2f %%\n", nreg,
nreg * 100.0 / ntot);
printf("regular files = %7ld, %5.2f %%\n", ndir,
ndir * 100.0 / ntot);
printf("regular files = %7ld, %5.2f %%\n", nblk,
nblk * 100.0 / ntot);
printf("regular files = %7ld, %5.2f %%\n", nchr,
nchr * 100.0 / ntot);
printf("regular files = %7ld, %5.2f %%\n", nfifo,
nfifo * 100.0 / ntot);
printf("regular files = %7ld, %5.2f %%\n", nslink,
nslink * 100.0 / ntot);
printf("regular files = %7ld, %5.2f %%\n", nsock,
nsock * 100.0 / ntot);
exit(ret);
}
/*
* Descend through the hierarchy, starting at "pathname".
* The caller's func() is called for every file.
*/
#define FTW_F 1 /*file other than directory*/
#define FTW_D 2 /*directory*/
#define FTW_DNR 3 /*directory that can't be read*/
#define FTW_NS 4 /*file that we can't stat*/
static char *fullpath; /*contains full pathname for every file*/
static int
myftw(char *pathname, Myfunc *func)
{
int len;
fullpath = path_alloc(&len); /*malloc's for PATH_MAX + 1 bytes*/
strncpy(fullpath, pathname, len); /*protect against*/
fullpath[len - 1] = 0; /*buffer ovwerun*/
return(dopath(func));
}
/*
* Descend through the hierarchy, starting at "fullpath"
* If "fullpath" is anything other than a directory, we lsata() it,
* call func(), and return. For a directory, we call ourself
* recursively for each name in the directory.
*/
static int /*we return whatever func() returns*/
dopath(Myfunc * func)
{
struct stat statbuf;
struct dirent *dirp;
DIR *dp;
int ret;
char *ptr;
if(lstat(fullpath, &statbuf) < 0) /*stat error*/
return(func(fullpath, &statbuf, FTW_NS));
if(S_ISDIR(statbuf.st_mode) == 0) /*not a directory*/
return(func(fullpath, &statbuf, FTW_F));
/*
* It's a directory. First call func() for the directory.
* then process each filename in the directory.
*/
if((ret = func(fullpath, &statbuf, FTW_D)) != 0)
return(ret);
ptr = fullpath + strlen(fullpath); /*point to end of fullpath*/
*ptr++ = '/';
*ptr = 0;
if((dp = opendir(fullpath)) == NULL) /*can't read directory*/
return(func(fullpath, &statbuf, FTW_DNR));
while((dirp = readdir(dp)) != NULL){
if(strcmp(dirp->d_name, ".") == 0 ||
strcmp(dirp->d_name, "..") == 0)
continue; /*ignore dot and dot-dot*/
strcpy(ptr, dirp->d_name); /*apend name after slash*/
if((ret = dopath(func)) != 0) /*recursive*/
break; /*time ro leave*/
}
ptr[-1] = 0; /*erase everything from slash onwards*/
if(closedir(dp) < 0)
err_ret("can't close directory %s", fullpath);
return(ret);
}
static int
myfunc(const char *pathname, const struct stat *statptr, int type)
{
switch(type){
case FTW_F:
switch(statptr->st_mode & S_IFMT){
case S_IFREG: nreg++; break;
case S_IFBLK: nblk++; break;
case S_IFCHR: nchr++; break;
case S_IFIFO: nfifo++; break;
case S_IFLNK: nslink++; break;
case S_IFSOCK: nsock++; break;
case S_IFDIR:
err_dump("for S_IFDIR for %s", pathname);
/*directories should have type = FTW_D*/
}
break;
case FTW_D:
ndir++;
break;
case FTW_DNR:
err_ret("can't read directory %s", pathname);
case FTW_NS:
err_ret("stat error for %s", pathname);
break;
default:
err_dump("unknown type %d for pathname %s", type, pathname);
}
return 0;
}
运行测试:
编译程序:gcc myftw.c
执行测试:./a.out /work
测试显示:
can't read directory /work//lost+found/:Permission denied
stat error for /work//lost+found/:Permission denied
regular files = 91064, inf %
regular files = 6831, inf %
regular files = 0, nan %
regular files = 2, inf %
regular files = 0, nan %
regular files = 704, inf %
regular files = 0, nan %