文件目录操作函数

文件及目录函数(37)
chdir, chmod, chown, chroot
fchdir, fchmod, fchown, ftruncate
lchown, truncate,
get_current_dir_name, getcwd, getwd
opendir, closedir, readir, scandir, seekdir, rewinddir, telldir
(mkdir, rmdir)
fstat, lstat, stat
ftw, nftw
link, readlink, symlink, unlink
access, alphasort, realpath, remove, rename, umask
utime, utimes
 
access:  判断是否有存取文件的权限
头文件: unistd.h
函数定义: int access(const char *pathname, int mode);
说明: access()会检查是否可以读/写某一已存在的文件. 参数 mode 有几种情况组合, R_OK,
W_OK, X_OK 和 F_OK. R_OK, W_OK 与 X_OK 用来检查文件是否具有读取, 写入和执行的权
限. F_OK则是用来判断该文件是否存在. 由于 access()只作权限的核查, 并不理会文件形态或
文件内容, 因此, 如果一目录表示为"可写入", 表示可以在该目录中建立新文件等操作, 而非意
味此目录可以被当做文件处理. 若所有欲查核的权限都通过了检查则返回 0 值, 表示成功, 只要
有一权限被禁止则返回-1.
错误代码:   
    EACCESS      参数 pathname 所指定的文件不符合所要求测试的权限
    EROFS        欲测试写入权限的文件存在于只读文件系统内
    EFAULT       参数 pathname 指针超出可存取内存空间
    EINVAL       参数 mode 不正确
    ENAMETOOLONG 参数 pathname 太长
    ENOTDIR      参数 pathname 为一目录
    ENOMEM       核心内存不足
    ELOOP        参数 pathname 有过多符号连接问题
    EIO           I/O 存取错误
附加说明: 使用access()作用户认证方面的判断要特别小心, 例如在access()后再做open()的空
文件可能会造成系统安全上的问题. 应用举例:
#include <stdio.h>
#include <unistd.h>
int main(void)
{
if(access("/etc/passwd", R_OK) == 0)
{
    printf("/etc/passwd can be read\n");
}
return 0;
}
运行结果:
/etc/passwd can be read
alphasort:  依字母顺序排序目录结构
头文件: dirent.h
定义函数: int alphasort(const struct dirent **a, const struct dirent **b);
说明: alphasort()为 scandir()最后调用的函数, 详细说明请参考 scandir().
应用举例:   
/* 读取/目录下的目录结构, 并依字母顺寻排列  */
#include <stdio.h>
#include <dirent.h>
int main(void)
{
struct dirent **namelist;
int i, total;
total = scandir("/", &namelist, 0, alphasort);
if(total < 0)
    perror("scandir");
else
{
    for(i = 0; i < total; i++)
    {
     printf("%s\n", namelist[i]->d_name);
    }
    printf("total = %d\n", total);
}
return 0;
}
运行结果:
.
..
.autofsck
bin boot
...
total = 24
chdir:  改变当前的工作目录
头文件: unistd.h
函数定义: int chdir(const char *path);
说明: chdir()用来将当前的工作目录该变成为参数 path 所指的目录. 若成功返回 0, 失败返回-1,
errno为错误代码.
chmod:  改变文件的权限
头文件: sys/types.h sys/stat.h
函数定义: int chmod(const char *path, mode_t mode);
说明: chmod()会依参数 mode 权限来更改参数 path 指定文件的权限. 参数 mode 有下列数种组
合:
    S_ISUID            04000   文件的(set user-id on execution)位
    S_ISGID            02000   文件的(set group-id on execution)位
    S_ISVTX            01000   文件的 sticky位
    S_IRUSR(S_IREAD) 00400   文件所有者具可读取权限
    S_IWUSR(S_IWRITE) 00200   文件所有者具可写入权限
    S_IXUSR(S_IEXEC) 00100   文件所有者具可执行权限
    S_IRGRP            00040   用户组具可读取权限
    S_IWGRP            00020   用户组具可写入权限
    S_IXGRP            00010   用户组具可执行权限
    S_IROTH            00004   其他用户具可读取权限
    S_IWOTH            00002   其他用户具可写入权限
    S_IXOTH            00001   其他用户具可执行权限
只有该文件的所有者或有效用户识别码为 0, 才可以修改该文件权限. 基于系统安全, 如果欲将
数据写入一执行文件, 而该执行文件具有 S_ISUID 或 S_ISGID 权限, 则这两个位会被清除. 如
果一目录具有 S_ISUID 位权限, 表示在此目录下只有该文件的所有者或 root 可以删除该文件.
若权限改变成功返回 0, 失败返回-1, 错误原因存于 erron.
错误代码:
    EPERM    进程的有效用户识别码与欲修改权限的文件拥有者不同, 而且也不具 root 权限.   
    EACCESS 参数 path 所指定的文件无法存取
    EROFS    欲写入权限的文件存在于只读文件系统内
    EFAULT   参数 path 指针超出可存取内存空间
    EINVAL   参数 mode 不正确
    ENAMETOOLONG 参数 path 太长
    ENOENT   指定的文件不存在
    ENOTDIR 参数 path 路径并非一目录
    ENOMEM   核心内存不足
    ELOOP    参数 path 有过多符号连接问题
    EIO       I/O 存取错误 chown:  改变文件的所有者
头文件: sys/types.h unistd.h
函数定义: int chown(const char *path, uid_t owner, gid_t group);
说明: chown()会将参数 path 指定文件的所有者变更为参数 owner 代表的用户, 而将该文件的组
变更为参数 group 组. 如果参数 owner 或 group 为-1, 对应的所有者或组不会有所改变. root 与
文件所有者皆可改变文件组, 但所有者必须是参数group组的成员. 当root用chown()改变文件
所有者或组时, 该文件若具有 S_ISUID 或 S_ISGID 权限, 则会清除此权限位, 此外如果具有
S_ISGID权限但不具S_IXGRP位, 则该文件会被强制锁定, 文件模式会保留. 成功则返回0, 失
败返回-1, 错误原因存于 errno. 错误代码同 chmod().
chroot:  改变根目录
头文件: unistd.h
函数定义: int chroot(const char *path);
说明: chroot()用来改变根目录为参数 path 所指定的目录. 只有超级用户才允许改变根目录, 子
进程将继承新的根目录. 调用成功则返回 0, 失败则返-1, 错误代码存于 errno.
错误代码:   
    EPERM    权限不足, 无法改变根目录
    EFAULT   参数 path 指针超出可存取内存空间
    ENAMETOOLONG 参数 path 太长
    ENOTDIR 路径中的目录存在但却非真正的目录
    EACCESS 存取目录时被拒绝
    ENOMEM   核心内存不足
    ELOOP    参数 path 有过多符号连接问题
    EIO       I/O 存取错误
应用举例:
#include <stdio.h>
#include <unistd.h>
int main(void)
{
/* 将根目录改为/tmp ,并将工作目录切换至/tmp */
chroot("/tmp");
chdir("/");
return 0;
}
closedir:  关闭目录
头文件: sys/types.h dirent.h
函数定义: int closedir(DIR *dir);
说明: closedir()关闭参数dir所指的目录流. 关闭成功则返回0, 失败返回-1, 错误原因存于errno
中. EBADF 参数 dir 为无效的目录流. fchdir:  改变当前的工作目录
头文件: unistd.h
函数定义: int fchdir(int fd);
说明: fchdir()用来将当前的工作目录改变成以参数 fd 所指的文件描述词. 执行成功则返回 0, 失
败返回-1, errno 为错误代码.
fchmod:  改变文件的权限
头文件: sys/types.h sys/stat.h
函数定义: int fdmod(int fildes, mode_t mode);
说明: fchmod()会依参数mode权限来更改参数fildes所指文件的权限. 参数fildes为已打开文件
的文件描述词. 参数mode请参考chmod(). 权限改变成功则返回0, 失败返回-1, 错误原因存于
errno.   
错误代码:   
    EBADF 参数 fildes 为无效的文件描述词
    EPERM 进程的有效用户识别码与欲修改权限的文件所有者不同, 而且也不具 root 权限
    EROFS 欲写入权限的文件存在于只读文件系统内
    EIO     I/O 存取错误
fchown:  改变文件的所有者
头文件: sys/types.h unistd.h
函数定义: int fchown(int fd, uid_t owner, gid_t group);
说明: fchown()会将参数fd指定文件的所有者变更为参数owner代表的用户, 而将该文件的组变
更为参数group组. 如果参数owner或group为-1, 对映的所有者或组有所改变. 参数fd为已打
开的文件描述词. 当 root 用 fchown()改变文件所有者或组时, 该文件若具 S_ISUID 或 S_ISGID
权限, 则会清除此权限位. 成功则返回 0, 失败则返回-1, 错误原因存于 errno.
错误代码:   
    EBADF   参数 fd 文件描述词为无效的或该文件已关闭
    EPERM   进程的有效用户识别码与欲修改权限的文件所有者不同, 而且也不具 root 权限, 或
是参数 owner, group 不正确
    EROFS   欲写入的文件存在于只读文件系统内
    ENOENT 指定的文件不存在
    EIO      I/O 存取错误
fstat:  由文件描述词取得文件状态
头文件: sys/stat.h unistd.h
函数定义: int fstat(int fildes, struct stat *buf);
说明: fstat()用来将参数fildes所指的文件状态, 复制到参数buf所指的结构中(struct stat). fstat()
与 stat()作用完全相同, 不同处在于传入的参数为已打开的文件描述词. 详细内容请参考 stat().
执行成功则返回 0, 失败返回-1, 错误代码存于 errno. ftruncate:  改变文件大小
头文件: unistd.h
函数定义: int ftruncate(int fd, off_t length);
说明: ftruncate()会将参数fd指定的文件大小改为参数length指定的大小. 参数fd为已打开的文
件描述词, 而且必须是以写入模式打开的文件. 如果原来的文件大小比参数length 大, 则超过的
部分会被删去. 执行成功则返回 0, 失败返回-1, 错误原因存于 errno.
错误代码:   
    EBADF    参数 fd 文件描述词为无效的或该文件已关闭
    EINVAL 参数 fd 为一 socket 并非文件, 或是该文件并非以写入模式打开
ftw:  遍历目录树
头文件: ftw.h
函数定义: int ftw(const char *dir, int (*fn)(const char *file, const struct stat *sb, int flag), int
depth);
说明: ftw()会从参数 dir 指定的目录开始, 往下一层层地递归式遍历子目录. 每进入一个目录, 便
会调用参数*fn 定义的函数来处理. ftw()会传三个参数给 fn(), 第一个参数*file 指向当时所在的目
录路径, 第二个参数是*sb, 为stat结构指针(该结构的定义请参考stat()), 第三个参数为旗标, 有
下面几种可能值:
    FTW_F    一般文件
    FTW_D    目录
    FTW_DNR 不可读取的目录. 此目录以下将不被遍历
    FTW_SL   符号连接
    FTW_NS   无法取得 stat 结构数据, 有可能是权限问题
最后一个参数depth代表ftw()在进行遍历目录时可同时打开的文件数. ftw()在遍历时每一层目录
至少需要一个文件描述词, 如果遍历时用完了 depth所给予的限制数目, 整个遍历将因不断地关
闭文件和打开文件操作而显得缓慢. 如果要结束 ftw()的遍历, fn()只需返回一非零值即可, 此值
同时也会是 ftw()的返回值, 否则 ftw()会试着走完所有的目录, 然后返回 0. 遍历中断则返回 fn()
函数的返回值, 全部遍历完则返回 0. 如有错误发生则返回-1.
附加说明: 由于 ftw()会动态配置内存使用, 请使用正常方式(fn 函数返回非 0 值)来中断遍历, 不
要在 fn 函数中使用 longjmp().
应用举例:
/* 列出/etc/X11 目录下的子目录  */
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <ftw.h>
int fn(const char *file, const struct stat* sb, int flag)
{
if(flag == FTW_D)
{
    printf("%s -- directory\n", file);
}
return 0; }
int main(void)
{
ftw("/etc/X11", fn, 500);
return 0;
}
运行结果:
/etc/X11 -- directory
/etc/X11/xinit -- directory
/etc/X11/xinit/xinitrc.d -- directory
/etc/X11/xinit/Xclients.d -- directory
/etc/X11/xinit/xinput.d -- directory
/etc/X11/xdm -- directory
/etc/X11/applnk -- directory
/etc/X11/twm -- directory
get_current_dir_name:  取得当前的工作目录
头文件: unistd.h
函数定义: char *get_current_dir_name(void);
说明: 此函数会返回一字符串指针, 指向目前的工作目录绝对路径字符串. 执行成功返回字符串
指针, 失败返回 NULL, 错误代码存于 errno.
getcwd:  取得当前的工作目录
头文件: unistd.h
函数定义: char *getcwd(char *buf, size_t size);
说明: getcwd()会将当前的工作目录绝对路径复制到参数 buf 所指的内存空间, 参数 size 为 buf
的空间大小. 在调用此函数时, buf 所指的内存空间要足够大, 若工作目录绝对路径的字符串长
度超过参数size大小, 则回值NULL, errno的值则为ERANGE. 倘若参数buf为NULL, getcwd()
会依参数 size 的大小自动配置内存(使用 malloc()), 如果参数 size 也为 0, 则 getcwd()会依工作
目录绝对路径的字符串程度来决定所配置的内存大小, 进程可以在使用完此字符串后利用 free()
来释放此空间. 执行成功则将结果复制到参数 buf 所指的内存空间, 或是返回自动配置的字符串
指针. 失败返回 NULL, 错误代码存于 errno.
getwd:  取得当前的工作目录
头文件: unistd.h
函数定义: char *getwd(char *buf);
说明: getwd()会将当前的工作目录绝对路径复制到参数 buf 所指的内存空间, 然后将此路径字符
串指针返回. 执行成功则将结果复制到参数 buf 所指的内存空间, 失败返回 NULL, 错误代码存
于 errno.
应用举例:
#include <stdio.h>
#include <unistd.h>
int main(void)
{ char *ptr1, *ptr2;
char buf[80];
ptr1 = get_current_dir_name();
printf("%s\n", ptr1);
getcwd(buf, sizeof(buf));
printf("%s\n", buf);
ptr2 = getcwd(NULL, 0);
printf("%s\n", ptr2);
free(ptr2);
getwd(buf);
printf("%s\n", buf);
return 0;
}
运行结果:
/root/c-function
/root/c-function
/root/c-function
/root/c-function
lchown:  改变文件的所有者
头文件: sys/types.h unistd.h
函数定义: int lchown(const char *path, uid_t ownwer, gid_t group);
说明: lchown()会将参数path指定文件的所有者变更为参数owner代表的用户, 而将该文件的组
变更为参数 group 组. 如果参数 owner 或 group 为-1, 对应的所有者活组不会有所改变. 当 root
用lchown()改变文件所有者或组时, 该文件若具S_ISUID或S_ISGID权限, 则会清除此权限位.
lchown()与 chown 不同之处在于, 如果参数 path 指定的文件为一符号连接(symbolic link),
lchown()是改变连接本身的所有者或组, chown()则是改变连接所指向的文件所有者或组. 成功
则返回 0, 失败返回-1, 错误原因在于 errno.
错误代码:
    EPERM     进程的有效用户识别码与欲修改权限的文件拥有者不同, 而且也不具 root 权限,
或是参数 owner/group 不正确
    EACCESS   参数 path 所指定的文件无法存取
    EROFS     欲写入的文件存在于只读文件系统内
    EFAULT    参数 path 指针超出可存取内存空间
    ENAMETOOLONG 参数 path 太长
    ENOENT    参数 path 指定的文件不存在
    ENOTDIR   参数 path 路径并非一目录
    ENOMEM    核心内存不足
    ELOOP     参数 path 有过多符号连接问题
    EIO        I/O 存取错误
 
 link:  建立文件硬连接
头文件: unistd.h
函数定义: int link(const char *oldpath, const char *newpath);
说明: link()以参数 newpath 指定的名称来建立一个新的连接(硬连接)到参数 oldpath 所指定的已
存在文件. 如果参数 newpath 指定的名称为一已存在的文件则不会建立连接. 成功则返回 0, 失
败返回-1, 错误原因存于 errno.
错误代码:
    EXDEV   参数 oldpath 与 newpath 不是建立在同一文件系统
    EPERM   参数 oldpath 与 newpath 所指的文件系统不支持硬连接
    EROFS   文件存在于只读文件系统内
    EFAULT 参数 oldpath 或 newpath 指针超出可存取内存空间
    ENAMETOLLONG   参数 oldpath 或 newpath 太长
    ENOMEM 核心内存不足
    EEXIST 参数 newpath 所指的文件名已存在
    EMLINK 参数 oldpath 所指的文件已达最大连接数目
    ELOOP   参数 pathname 有过多符号连接问题
    ENOSPC 文件系统的剩余空间不足
    EIO      I/O 存取错误
附加说明: link()所建立的硬连接无法跨越不同文件系统, 如果需要请改用 symlink().
lstat:  由文件描述词取得文件状态
头文件: sys/stat.h unistd.h
函数定义: int lstat(const char *file_name, struct stat *buf);
说明: lstat()与stat()作用完全相同, 都是取得参数file_name所指的文件状态, 其差别在于, 当文
件为符号连接时, lstat()会返回该link本身的状态. 详细内容请参考stat(). 执行成功则返回0, 失
败返回-1, 错误代码存于 errno.
nftw:  遍历目录树
头文件: ftw.h
函数定义: int nftw(const char *dir, int (*fn)(const char *file, const struct stat *sb, int flag, struct
FTW *s), depth, int flags);
说明: nftw()与 ftw()很像, 都是从参数 dir 指定的目录开始, 往下一层层地递归式遍历子目录. 每
进入一个目录, 便会调用参数*fn 定义的函数来处理. nftw()会传四个参数给 fn(), 第一个参数*file
指向当时所在的目录路径, 第二个参数是*sb, 为 stat 结构指针(结构定义请参考 stat()), 第三个
参数为旗标, 有以下几种可能:
    FTW_F    一般文件
    FTW_D    目录
    FTW_DNR 不可读取的目录. 此目录以下将不被遍历
    FTW_SL   符号连接
    FTW_NS   无法取得 stat 结构数据, 有可能是权限问题
    FTW_DP   目录, 而且其子目录都已被遍历过了.
    FTW_SLN 符号连接, 但连接不存在文件 fn()的第四个参数是 FTW 结构, 定义如下:
struct FTW{
int base;
int level;
}
level 代表遍历当时的深度, nftw()第三个参数 depth 代表 nftw()在进行遍历目录时可同时打开的
文件数. ftw()在遍历时每一层目录至少需要一个文件描述词, 如果遍历时用完了 depth 所给予的
限制数目, 整个遍历将因不断地关闭文件和打开文件操作而显得缓慢. nftw()最后一个参数 flags
用来指定遍历时的动作, 可以指定下列的操作或用 OR 组合:
    FTW_CHDIR   在读目录之前用 chdir()移到此目录
    FTW_DEPTH   执行深度优先搜索. 在遍历此目录前先将所有子目录遍历完
    FTW_MOUNT   遍历时不要跨越到其他文件系统
    FTW_PHYS    不要遍历符号连接的目录. 预设会遍历符号连接目录
如果要结束 ftw()的遍历, fn()只需返回一非零值即可, 此值同时也会是 ftw()的返回值, 否则 ftw()
会试着走完所有的目录, 然后返回 0. 遍历中断则返回 fn()函数的返回值, 全部遍历完则返回 0.
如有错误发生则返回-1.
附加说明: 由于 ftw()会动态配置内存使用, 请使用正常方式(fn 函数返回非 0 值)来中断遍历, 不
要在 fn 函数中使用 longjmp().
opendir:  打开目录
头文件: sys/types.h dirent.h
函数定义: DIR *opendir(const char *name);
说明: opendir()用来打开参数 name 指定的目录, 并返回 DIR*形态的目录流, 和 open()类似, 接
下来对目录的读取和搜索都要使用此返回值. 成功则返回 DIR*型态的目录流, 打开失败则返回
NULL.
错误代码:
    EACCESS 权限不足
    EMFILE   已达到进程可同时打开的文件数上限
    ENFILE   已达到系统可同时打开的文件数上限
    ENOTDIR 参数 name 非真正的目录
    ENOENT   参数 name 指定的目录不存在, 或是参数 name 为一空字符串
    ENOMEM   核心内存不足
readdir:  读取目录
头文件: sys/types.h dirent.h
定义函数: struct dirent *readdir(DIR *dir);
说明: readdir()返回参数 dir 目录流的下个目录进入点. 结构 dirent 定义如下:
struct dirent{
ino_t d_ino;
ff_t d_off;
signed short int d_reclen;
unsigned char d_type;
char d_name[256]; };
d_ino    此目录进入点的 inode
d_off    目录文件开头至此目录进入点的位移
d_reclen _name 的长度, 不包含 NULL 字符
d_type    d_name 所指的文件类型
d_name   文件名
成功则返回下个目录进入点, 有错误发生或读取到目录文件尾则返回 NULL. EBADF 参数 dir 为
无效的目录流.
应用举例:
/* 读取/etc/rc.d 目录文件结构, 然后显示目录下的文件  */
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
int main(void)
{
DIR *dir;
struct dirent *ptr;
int i;
dir = opendir("/etc/rc.d");
while((ptr = readdir(dir)) != NULL)
{
    printf("d_name: %s\n", ptr->d_name);
}
return 0;
}
运行结果:
d_name: rc1.d
d_name: rc3.d
d_name: rc
d_name: rc2.d
d_name: rc0.d
d_name: rc.sysinit
d_name: ..
d_name: rc6.d
d_name: rc4.d
d_name: init.d
d_name: rc.local
d_name: rc5.d
d_name: .
readlink:  取得符号连接所指的文件
头文件: unistd.h
函数定义: int readlink(const char *path, char *buf, size_t bufsize); 说明: readlink()会将参数path的符号连接内容存到参数buf所指的内存空间, 返回的内容不是以
NULL 作字符串结尾, 但会将字符串的字符数返回. 若参数 bufsiz小于符号连接的内容长度, 过
长的内容会被截断. 执行成功则传符号连接所指的文件路径字符串, 失败则返回-1, 错误代码存
于 errno.
错误代码:   
    EACCESS 取文件时被拒绝, 权限不够
    EINVAL   参数 bufsiz 为负数
    EIO       I/O 存取错误
    ELOOP    欲打开的文件有过多符号连接问题
    ENAMETOOLONG 参数 path 的路径名称太长
    ENOENT   参数 path 所指定的文件不存在
    ENOMEM   核心内存不足
    ENOTDIR 参数 path 路径中的目录存在但却非真正的目录
realpath:  将相对目录路径转换成绝对路径
头文件: limits.h stdlib.h
函数定义: char *realpath(const char *path, char *resolved_path);
说明: realpath()用来将参数 path 所指的相对路径转换成绝对路径存于参数 resolved_path 所指
的字符串数组中. 如果转换成功则返回指向 resolved_path 的指针. 失败返回 NULL, 错误代码
存于 errno.
remove:  删除文件或目录
头文件: stdio.h
函数定义: int remove(const char *pathname);
说明: remove()会删除参数 pathname 指定的文件. 如果参数 pathname 为一文件, 则调用
unlink()处理, 若参数 pathname 为一目录, 则调用 rmdir()来处理. 请参考 unlink()与 rmdir(). 成
功则返回 0, 失败则返回-1, 错误原因存于 errno.
错误代码:   
    EROFS    欲写入的文件存在于只读文件系统内
    EFAULT   参数 pathname 指针超出可存取内存空间
    ENAMETOOLONG   参数 pathname 太长
    ENOMEM   核心内存不足
    ELOOP    参数 pathname 有过多符号连接问题
    EIO       I/O 存取错误.
rename:  更改文件名或位置
头文件: stdio.h
函数定义: int rename(const char *oldpath, const char *newpath);
说明: rename()会将参数 oldpath 所指定的文件名称改为参数 newpath 所指的文件名称. 若
newpath 所指定的文件已存在, 则会被删除. 执行成功则返回 0, 失败返回-1, 错误原因存于
errno. rewinddir:  将读取目录的位置设为开头位置
头文件: sys/types.h dirent.h
函数定义: void rewinddir(DIR *dir);
说明: rewinddir()用来设置参数 dir 目录流目前的读取位置为原来开头的读取位置. EBADF 表示
dir 为无效的目录流.
scandir:  读取特定的目录数据
头文件: dirent.h
函数定义: int scandir(const char *dir, struct dirent ***namelist, int (*select)(const struct dirent *),
int (*compar)(const struct dirent**, const struct dirent**));
说明: scandir()会扫描参数dir指定的目录文件, 经由参数select指定的函数来挑选目录结构至参
数namelist数组中, 最后在调用参数compar指定的函数来排序namelist数组中的目录数据. 每
次从目录文件中读取一个目录结构后便将此结构传给参数 select 所指的函数, select 函数若不想
要将此目录机构复制到 namelist 数组就返回 0, 若 select 为空指针则代表选择所有的目录结构.
scandir()会调用 qsort()来排序数据, 参数compar则为 qsort()的参数, 若是要排列目录名称字母
则可使用alphasort(). 结构dirent定义请参考readdir(). 成功则返回复制到namelist数组中的数
据结构数目, 有错误发生则返回-1. ENOMEM 表示核心内存不足.
应用举例:
/* 读取/目录下文件名长度大于 5 的目录结构  */
#include <stdio.h>
#include <string.h>
#include <dirent.h>
int select(const struct dirent *dir)
{
if(strlen(dir->d_name) > 5)
    return 1;
else
    return 0;
}
int main(void)
{
struct dirent **namelist;
int i, total;
total = scandir("/", &namelist, select, 0);
if(total < 0)
    perror("scandir");
else
{
    for(i = 0; i < total; i++)
    {
     printf("%s\n", namelist[i]->d_name);
     printf("total = %d\n", total);   
    } }
return 0;
}
运行结果:
selinux
total = 3
.autofsck
total = 3
lost+found
total = 3
seekdir:  设置下回读取目录的位置
头文件: dirent.h
函数定义: void seekdir(DIR *dir, off_t offset);
说明: seekdir()用来设置参数dir目录流目前的读取位置, 在调用readdir()时便从此新位置开始读
取. 参数 offset 代表距离目录文件开头的偏移量. EBADF 表示参数 dir 为无效路径.
stat:  取得文件状态
头文件: sys/stat.h unistd.h
函数定义: int stat(const char *file_name, struct stat *buf);
说明: stat()用来将参数file_name所指的文件状态, 复制到参数buf所指的结构中. 下面是struct
stat 内各参数的说明:
struct stat
{
dev_t    st_dev;       /* device */
ino_t    st_ino;       /* inode */
mode_t st_mode;      /* protection */
nlink_t    st_nlink; /* number of hard links */
uid_t     st_uid;      /* user ID of owner */
gid_t     st_gid;      /* group ID of owner */
dev_t     st_rdev;     /* device type */
off_t      st_size;    /* total size, in bytes */
unsigned long st_blksize; /* blocksize for filesystem I/O */
unsigned long st_blocks; /* number of blocks allocated */
time_t    st_atime;    /* time of lastaccess */
time_t    st_mtime;    /* time of last modification */
time_t    st_ctime;    /* time of last change */
};
st_dev    文件的设备编号
st_ino    文件的 i-node
st_mode   文件的类型和存取的权限
st_nlink 连到该文件的硬连接数目, 刚建立的文件值为 1
st_uid    文件所有者的用户识别码 st_gid    文件所有者的组识别码
st_rdev   若此文件为装置设备文件, 则为其设备编号
st_size   文件大小, 以字节计算
st_blksize 文件系统的 I/O 缓冲区大小
st_blcoks 占用文件区块的个数, 每一区块大小为 512 个字节
st_atime 文件最近一次被存取或被执行的时间, 一般只有在用 mknod, utime, read, write 与
tructate 时改变
st_mtime 文件最后一次被修改的时间, 一般只有在用 mknod, utime 和 write 时才会改变
st_ctime i-node 最近一次被更改的时间, 此参数会在文件所有者, 组, 权限被更改时更新
先前所描述的 st_mode 则定义了下列数种情况:
    S_IFMT     0170000 文件类型的位遮罩
    S_IFSOCK 0140000 scoket
    S_IFLNK    0120000 符号连接
    S_IFREG    0100000 一般文件
    S_IFBLK    0060000 区块装置
    S_IFDIR    0040000 目录
    S_IFCHR    0020000 字符装置
    S_IFIFO    0010000 先进先出
    S_ISUID      04000 文件的(set user-id on execution)位
    S_ISGID      02000 文件的(set group-id on execution)位
    S_ISVTX      01000 文件的 sticky位
    S_IRUSR(S_IREAD)    00400 文件所有者具可读取权限
    S_IWUSR(S_IWRITE) 00200 文件所有者具可写入权限
    S_IXUSR(S_IEXEC)    00100 文件所有者具可执行权限
    S_IRGRP      00040 用户组具可读取权限
    S_IWGRP      00020 用户组具可写入权限
    S_IXGRP      00010 用户组具可执行权限
    S_IROTH      00004 其他用户具可读取权限
    S_IWOTH      00002 其他用户具可写入权限
    S_IXOTH      00001 其他用户具可执行权限
上述的文件类型在 POSIX 中定义了检查这些类型的宏定义:
    S_ISLNK (st_mode) 判断是否为符号连接
    S_ISREG    (st_mode) 是否为一般文件
    S_ISDIR     (st_mode)是否为目录
    S_ISCHR    (st_mode)是否为字符装置文件
    S_ISBLK     (s3e)   是否为先进先出
    S_ISSOCK (st_mode) 是否为 socket
若一目录具有 sticky位(S_ISVTX), 则表示在此目录下的文件只能被该文件所有者, 此目录所有
者或 root 来删除或改名. 执行成功则返回 0, 失败返回-1, 错误代码存于 errno.
错误代码:   
    ENOENT   参数 file_name 指定的文件不存在
    ENOTDIR 路径中的目录存在但却非真正的目录
    ELOOP    欲打开的文件有过多符号连接问题, 上限为 16 符号连接
    EFAULT   参数 buf 为无效指针, 指向无法存在的内存空间     EACCESS 存取文件时被拒绝
    ENOMEM   核心内存不足
    ENAMETOOLONG 参数 file_name 的路径名称太长
应用举例:
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
int main(void)
{
struct stat buf;
stat("/etc/passwd", &buf);
printf("etc/passwd file size = %d\n", buf.st_size);
return 0;
}
运行结果:
etc/passwd file size = 2529
symlink:  建立文件符号连接
头文件: unistd.h
函数定义: int symlink(const char *oldpath, const char *newpath);
说明: symlink()以参数 newpath 指定的名称来建立一个新的连接(符号连接)到参数 oldpath 所指
定的已存在文件. 参数oldpath指定的文件不一定要存在, 如果参数newpath指定的名称为一已
存在的文件则不会建立连接. 成功则返回 0, 失败返回-1, 错误原因存于 errno.
错误代码:
    EPERM   参数 oldpath 与 newpath 所指的文件系统不支持符号连接
    EROFS   欲测试写入权限的文件存在于只读文件系统内
    EFAULT 参数 oldpath 或 newpath 指针超出可存取内存空间
    ENAMETOOLONG 参数 oldpath 或 newpath 太长
    ENOMEM 核心内存不足
    EEXIST 参数 newpath 所指的文件名已存在
    EMLINK 参数 oldpath 所指的文件已达到最大连接数目
    ELOOP   参数 pathname 有过多符号连接问题
    ENOSPC 文件系统的剩余空间不足
    EIO      I/O 存取错误
telldir:  取得目录流的读取位置
头文件: dirent.h
函数定义: off_t telldir(DIR *dir);
说明: telldir()返回参数dir目录流目前的读取位置. 此返回值代表距离目录文件开头的偏移量, 有
错误发生时返回-1. EBADF 表示参数 dir 为无效的目录流. truncate:  改变文件大小
头文件: unistd.h
函数定义: int truncate(const char *path, off_t length);
说明: truncate()会将参数 path 指定的文件大小改为参数 length指定的大小. 如果原来的文件大
小比参数 length大, 则超过的部分会被删去. 执行成功则返回 0, 失败返回-1, 错误原因存于
errno.   
错误代码:   
    EACCESS   参数 path 所指定的文件无法存取。
    EROFS     欲写入的文件存在于只读文件系统内
    EFAULT    参数 path 指针超出可存取内存空间
    EINVAL    参数 path 包含不合法字符
    ENAMETOOLONG 参数 path 太长
    ENOTDIR   参数 path 路径并非一目录
    EISDIR    参数 path 指向一目录
    ETXTBUSY 参数 path 所指的文件为共享程序, 而且正被执行中
    ELOOP     参数 path’有过多符号连接问题
    EIO        I/O 存取错误
umask:  设置建立新文件时的权限遮罩
头文件: sys/types.h sys/stat.h
函数定义: mode_t umask(mode_t mask);
说明: umask()会将系统 umask 值设成参数mask&0777 后的值, 然后将先前的 umask 值返回.
在使用 open()建立新文件时, 该参数 mode 并非真正建立文件的权限, 而是(mode&~umask)的
权限值. 例如, 在建立文件时指定文件权限为0666, 通常umask值默认为022, 则该文件的真正
权限则为 0666&~022=0644, 也就是 rw-r--r--. 此调用不会有错误值返回, 返回值为原先系统
的 umask 值.
unlink:  删除文件
头文件: unistd.h
函数定义: int unlink(const char *pathname);
说明: unlink()会删除参数 pathname 指定的文件. 如果该文件名为最后连接点, 但有其他进程打
开了此文件, 则在所有关于此文件的文件描述词皆关闭后才会删除. 如果参数 pathname 为一符
号连接, 则此连接会被删除. 成功则返回 0, 失败返回-1, 错误原因存于 errno.
错误代码:   
    EROFS   文件存在于只读文件系统内
    EFAULT 参数 pathname 指针超出可存取内存空间
    ENAMETOOLONG 参数 pathname 太长
    ENOMEM 核心内存不足
    ELOOP   参数 pathname 有过多符号连接问题
    EIO      I/O 存取错误 utime:  修改文件的存取时间和更改时间
头文件: sys/types.h utime.h
函数定义: int utime(const char *filename, struct utimebuf *buf);
说明: utime()用来修改参数 filename 文件所属的 inode 存取时间. 结构 utimbuf 定义如下:
struct utimbuf{
time_t actime;
time_t modtime;
};
如果参数buf为空指针(NULL), 则该文件的存取时间和更改时间全部会设为目前时间. 执行成功
则返回 0, 失败返回-1, 错误代码存于 errno.
错误代码:   
    EACCESS 存取文件时被拒绝, 权限不足
    ENOENT   指定的文件不存在
utimes:  修改文件的存取时间和更改时间
头文件: sys/types.h utime.h
函数定义: int utimes(char *filename, struct timeval *tvp);
说明: utimes()用来修改参数filename文件所属的inode存取时间和修改时间, 结构timeval定义
如下:
struct timeval{
long tv_sec;
long tv_usec; /* 微妙  */
};
参数 tvp 指向两个 timeval 结构空间, 和 utime()使用的 utimebuf 结构比较, tvp.tc_sec 则为
utimbuf.actime, tvp.tv_sec 为 utimbuf.modtime. 执行成功则返回 0. 失败返回-1, 错误代码存于
errno.   
错误代码:   
    EACCESS 存取文件时被拒绝, 权限不足
    ENOENT   指定的文件不存在
 

你可能感兴趣的:(文件目录操作函数)