OS.h 分类: C++ 2009-07-19 12:31
#ifndef ICE_PATCH2_OS_H
#define ICE_PATCH2_OS_H
#include <Ice/Config.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#ifndef ICE_PATCH2_API
# ifdef ICE_PATCH2_API_EXPORTS
# define ICE_PATCH2_API ICE_DECLSPEC_EXPORT
# else
# define ICE_PATCH2_API ICE_DECLSPEC_IMPORT
# endif
#endif
namespace OS
{
#ifdef _WIN32
typedef struct _stat structstat;
#ifdef _MSC_VER
# define O_RDONLY _O_RDONLY
# define O_BINARY _O_BINARY
# define S_ISDIR(mode) ((mode) & _S_IFDIR)
# define S_ISREG(mode) ((mode) & _S_IFREG)
#endif
#else
// linux 则定义 stat 结构 为structstat 类型, O_BINARY为0
typedef struct stat structstat;
# define O_BINARY 0
#endif
// BUGFIX: aCC errors if this is stat.
ICE_PATCH2_API int osstat( const std::string&, structstat* );
ICE_PATCH2_API int remove( const std::string& );
ICE_PATCH2_API int rename( const std::string&, const std::string& );
ICE_PATCH2_API int rmdir( const std::string& );
ICE_PATCH2_API int mkdir( const std::string&, int );
ICE_PATCH2_API FILE* fopen( const std::string&, const std::string& );
ICE_PATCH2_API int open( const std::string&, int );
ICE_PATCH2_API int getcwd( std::string& ) ;
}
#endif
#include <IceUtil/DisableWarnings.h>
#include <OS.h>
#include <IceUtil/Unicode.h>
#ifdef __BCPLUSPLUS__
# include <dir.h>
# include <io.h>
#endif
using namespace std;
using namespace OS;
#ifdef _WIN32
#else
//linux 调用stat函数将path指定的文件结构信息,保存到buf中
/*
表头文件: #include <sys/stat.h>
#include <unistd.h>
定义函数: int stat(const char *file_name, struct stat *buf);
函数说明: 通过文件名filename获取文件信息,并保存在buf所指的结构体stat中
返回值: 执行成功则返回0,失败返回-1,错误代码存于errno
错误代码:
ENOENT 参数file_name指定的文件不存在
ENOTDIR 路径中的目录存在但却非真正的目录
ELOOP 欲打开的文件有过多符号连接问题,上限为16符号连接
EFAULT 参数buf为无效指针,指向无法存在的内存空间
EACCESS 存取文件时被拒绝
ENOMEM 核心内存不足
ENAMETOOLONG 参数file_name的路径名称太长
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
int main() {
struct stat buf;
stat("/etc/hosts", &buf);
printf("/etc/hosts file size = %d\n", buf.st_size);
}
-----------------------------------------------------
struct stat {
dev_t st_dev; //文件的设备编号
ino_t st_ino; //节点
mode_t st_mode; //文件的类型和存取的权限
nlink_t st_nlink; //连到该文件的硬连接数目,刚建立的文件值为1
uid_t st_uid; //用户ID
gid_t st_gid; //组ID
dev_t st_rdev; //(设备类型)若此文件为设备文件,则为其设备编号
off_t st_size; //文件字节数(文件大小)
unsigned long st_blksize; //块大小(文件系统的I/O 缓冲区大小)
unsigned long st_blocks; //块数
time_t st_atime; //最后一次访问时间
time_t st_mtime; //最后一次修改时间
time_t st_ctime; //最后一次改变时间(指属性)
};
先前所描述的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来删除或改名。
-----------------------------------------------------
struct statfs {
long f_type; //文件系统类型
long f_bsize; //块大小
long f_blocks; //块多少
long f_bfree; //空闲的块
long f_bavail; //可用块
long f_files; //总文件节点
long f_ffree; //空闲文件节点
fsid_t f_fsid; //文件系统id
long f_namelen; //文件名的最大长度
long f_spare[6]; //spare for later
};
stat、fstat和lstat函数(UNIX)
#include<sys/types.h>
#include<sys/stat.h>
int stat(const char *restrict pathname, struct stat *restrict buf);
提供文件名字,获取文件对应属性。感觉一般是文件没有打开的时候这样操作。
int fstat(int filedes, struct stat *buf);
通过文件描述符获取文件对应的属性。文件打开后这样操作
int lstat(const char *restrict pathname, struct stat *restrict buf);
连接文件
三个函数的返回:若成功则为0,若出错则为-1
给定一个pathname,stat函数返回一个与此命名文件有关的信息结构,
fstat函数获得已在描述符filedes上打开的文件的有关信息。lstat函数类似于stat,
但是当命名的文件是一个符号连接时,lstat返回该符号连接的有关信息,
而不是由该符号连接引用的文件的信息。
第二个参数是个指针,它指向一个我们应提供的结构。这些函数填写由buf指向的结构。
该结构的实际定义可能随实现而有所不同,但其基本形式是:
struct stat{
mode_t st_mode; /*file tpye &mode (permissions)
ino_t st_ino; /*i=node number (serial number)
dev_t st_rdev; /*device number for special files
nlink_t st_nlink; /*number of links
uid_t st_uid; /*user id of owner
gid_t st_gid; /*group ID of owner
off_t st_size; /*size in bytes for regular files
time_t st_atime; /*time of last access
time_t st_mtime; /*time of last modification
time_t st_ctime; /*time of last file status change
long st_blksize; /*best I/O block size
long st_blocks; /*number of 512-byte blocks allocated
};
注意,除最后两个以外,其他各成员都为基本系统数据类型。
我们将说明此结构的每个成员以了解文件属性。
使用stat函数最多的可能是ls-l命令,用其可以获得有关一个文件的所有信息。
1 函数都是获取文件(普通文件,目录,管道,socket,字符,块()的属性。
函数原型#include <sys/stat.h>
int stat(const char *restrict pathname, struct stat *restrict buf);提供文件名字,
获取文件对应属性。
int fstat(int filedes, struct stat *buf);通过文件描述符获取文件对应的属性。
int lstat(const char *restrict pathname, struct stat *restrict buf);连接文件描述命,
获取文件属性。2 文件对应的属性struct stat {
mode_t st_mode; //文件对应的模式,文件,目录等
ino_t st_ino; //inode节点号
dev_t st_dev; //设备号码
dev_t st_rdev; //特殊设备号码
nlink_t st_nlink; //文件的连接数
uid_t st_uid; //文件所有者
gid_t st_gid; //文件所有者对应的组
off_t st_size; //普通文件,对应的文件字节数
time_t st_atime; //文件最后被访问的时间
time_t st_mtime; //文件内容最后被修改的时间
time_t st_ctime; //文件状态改变时间
blksize_t st_blksize; //文件内容对应的块大小
blkcnt_t st_blocks; //伟建内容对应的块数量
};可以通过上面提供的函数,返回一个结构体,保存着文件的信息。
*/
int
OS::osstat( const string& path, structstat* buf )
{
return ::stat( path.c_str(), buf );
}
/*
remove函数的功能是删除一个文件。它的一般格式为:
remove(const char * filename);
remove函数也是一个宏,可以删除filename(文件名)指定的文件。
如果文件已经打开,则必须将该文件关闭才能够删除。如果调用成功,
返回0,否则返回-1,并置全局变量errno为ENOENT(没有此文件或目录)
或EACCES(无此权限)。
NAME
rename - change the name or location of a file
SYNOPSIS
#include <stdio.h>
int rename(const char *oldpath, const char *newpath);
DESCRIPTION
rename() renames a file, moving it between directories if required.
Any other hard links to the file (as created using link(2)) are unaffected.
If newpath already exists it will be atomically replaced (subject
to a few conditions; see ERRORS below),
so that there is no point at which another process attempting to
access newpath will find it missing.
The rename function causes the file whose name is the string pointed to by old to be
henceforth known by the name given by the string pointed to by new. The file named
old is no longer accessible by that name.
If a file named by the string pointed to by new exists prior to the call to
the rename function, the behavior is implementation-defined.
ISO C99 p267
man 2 rename
oldpath and newpath are not on the same mounted filesystem.
(Linux permits a filesystem to be
mounted at multiple points, but rename(2) does not work
across different mount points, even if the
same filesystem is mounted on both.)
rename(更改文件名称或位置)
相关函数 link,unlink,symlink
表头文件 #include<stdio.h>
定义函数 int rename(const char * oldpath,const char * newpath);
函数说明 rename()会将参数oldpath 所指定的文件名称改为参数newpath所指的文件名称。
若newpath所指定的文件已存在,则会被删除。
返回值 执行成功则返回0,失败返回-1,错误原因存于errno
范例 设计一个DOS下的rename指令rename 旧文件名新文件名
mkdir和rmdir函数.
int mkdir(const char*pathname,mode_t mode);//创建一个空目录
int rmdir(const char *pathname); //删除一个空目录,不能删除有文件目录
读目录
对于某个目录具有访问权限的任一用户都可以读该目录,但是,为了防止文件系统
产生混乱,只有内核才能写目录.这里又有一个新头文件出现<dirent.h>
DIR* opendir(const char *pathname);//成功返回指针,出错返回NULL
struct dirent *readdir(DIR *dp);
void rewinddir(DIR *dp);
int closedir(DIR *dp);
long telldir(DIR *dp);
void seekdir(DIR *dp,long loc);
struct dirent //来自/usr/include/bits/dirent.h
{
#ifndef __USE_FILE_OFFSET64
__ino_t d_ino;
__off_t d_off;
#else
__ino64_t d_ino; //i_node节点号
__off64_t d_off;
#endif
unsigned short int d_reclen;
unsigned char d_type;
char d_name[256]; /*We must not include limits.h //目录名
}
DIR结构是内核用的,对用户不公开使用.
一、获取当前工作目录函数-getcwd
头文件:<unistd.h>
函数形式:char* getcwd(char *buffer,size_t size)
返回值:成功返回当前工作目录的字符串指针
失败返回NULL
设置errno
错误信息:
EINVAL:size参数为0或者buff不是空指针;
ERANGE:size参数小于当前工作目录的长度,需要分配更大的内存
EACCES:权限不足,没有读或者搜索文件名称的权限
二、获得系统目录最大长度-pathconf
头文件:unistd.h
函数形式:long pathconf(char *path,int name)
返回值:成功返回目录长度的极限值
失败返回-1
设置errno
//name:pathconf_exam.cxx
#include<unistd.h>
#include<iostream.h>
int main(void)
{
long cur_work_len;
char* cur_work_dir;
//获得目录最大长度
if((cur_work_len=pathconf(".",_PC_PATH_MAX))==-1)
{
perror("Could not get current working directory length!");
return 1;
}
std::cout<<"Current work length is "<<cur_work_len<<std::endl;
//根据获得的目录的最大长度,分配内存
if((cur_work_dir=(char*)malloc(cur_work_len))==NULL)
{
perror("Could not allocate memory for the directory!");
return 1;
}
//获得当前的工作目录
if (getcwd(cur_work_dir,cur_work_len)==NULL)
{
perror("Could not get current working directory!");
return 1;
}
std::cout<<"Current working directory is "<<cur_work_dir<<std::endl;
return 0;
}
程序执行结果:
guocheng@guocheng-desktop:~/test/dir_exam/pathconf$ g++ -o pathconf_exam pathconf_exam.cxx
guocheng@guocheng-desktop:~/test/dir_exam/pathconf$ ./pathconf_exam
Current work length is 4096
Current working directory is /home/guocheng/test/dir_exam/pathconf
三、更改当前工作目录-chdir和fchdir
头文件:unisd.h
函数形式:int chdir(const char* path)
int fchdir(fd)
返回值:成功0
失败-1
设置errno
说明:chdir函数的参数是指向目录的字符串指针,成功的前提是程序有所搜整个目录的权限,fchdir调用的参数是目录的文件描述符,其他与chdir相同。
按照上面的例子进行修改。
//name:chdir_exam.cxx
#include<unistd.h>
#include<iostream.h>
int main(void)
{
long cur_work_len;
char* cur_work_dir;
//获得目录最大长度
if((cur_work_len=pathconf(".",_PC_PATH_MAX))==-1)
{
perror("Could not get current working directory length!");
return 1;
}
std::cout<<"Current work length is "<<cur_work_len<<std::endl;
//根据获得的目录的最大长度,分配内存
if((cur_work_dir=(char*)malloc(cur_work_len))==NULL)
{
perror("Could not allocate memory for the directory!");
return 1;
}
//获得当前的工作目录
if (getcwd(cur_work_dir,cur_work_len)==NULL)
{
perror("Could not get current working directory!");
return 1;
}
std::cout<<"Current working directory is "<<cur_work_dir<<std::endl;
//修改当前目录至上级目录
if(chdir("..")==-1)
{
perror("Could not get current working directory!");
return 1;
}
//获得当前的工作目录
if (getcwd(cur_work_dir,cur_work_len)==NULL)
{
perror("Could not get current working directory!");
return 1;
}
std::cout<<"Current working directory is "<<cur_work_dir<<std::endl;
return 0;
}
执行结果
guocheng@guocheng-desktop:~/test/dir_exam/chdir$ ./chdir_exam
Current work length is 4096
Current working directory is /home/guocheng/test/dir_exam/chdir
Current working directory is /home/guocheng/test/dir_exam
四、创建和删除工作目录-mkdir和rmdir
头文件:sys/stat.h sys/types.h
函数形式:int mkdir(const char* pathname,mode_t mode);
返回值:成功0,失败-1,设置errno
说明:创建的目录的权限由mode、-umask和0777的与值来决定。
下面是实力,在/tmp/guocheng/的目录下创建目录yu,具体代码实现如下:
//mkdir_exam.cxx
#include <sys/stat.h>
#include <sys/types.h>
#include <iostream.h>
int main(void)
{
char* pathname="/tmp/guocheng/yu";
if(mkdir(pathname,0700)==-1)
{
perror("Could not create the direcotry!");
return 1;
}
return 0;
}
函数:int rmdir(const char* pathname);
返回值:成功0,失败-1,设置errno。
1、linux文件的实现
索引结点结构(inode)在linxu系统中实现文件的存储和相关信息的保存,每个inode中存储有文件的属性、访问权限以及文件数据块的存储位置。对linux系统而言,inode是文件系统定位文件的基本途径。
左图描述了inode的结构:图中前四项统称为文件的描述信息,其他的信息均为定位文件数据的指针。
文件描述信息主要包括:
Mode:包含有inode的描述内容和用户访问权限;
Owner Infomation:文件或目录所有者的信息,包括所属组信息;
Size:用于记录文件的大小,以字节为单位;
Timesstamps:时间戳,用于记录inode的创建时间及最后的修改时间;
定位文件数据的指针主要包括以下几种:
直接块指针:前12个,直接指向数据块
间接块指针:第13个,指向含有块指针的数据块
双重间接块指针:第14个
三重间接块指针:第15个
inode共有15个块指针的数组,前12为直接指向数据快的指针,第13个是间接数据块指针,指向含有数据块指针的数据块,14和15一次类推。
假设每个指向的数据块的大小是1024字节,每个指针是32位(4字节),下面进行计算文件容量。
直接块指针:12个X1024字节=12K;
间接块指针:1个X(1024字节/4字节)X1024字节=246K;
双重间接块指针:1个X(1024字节/4字节)X(1024字节/4字节)X1024字节=65536K
三重间接块指针:1个X(1024字节/4字节)X(1024字节/4字节)X(1024字节/4字节)1024字节=16777216K,即16G;
2、文件描述符与文件指针
在linux系统中,统一了文件和设备的操作,提供了open、read、close等函数,使用文件描述符来对文件进行操作。文件描述符是一个int类型的数值,在使用open函数操作文件时返回的。
如果某个进程使用open函数打开了一个文件,通过fork函数创建当前进程的子进程,则子进程会继承父进程的环境和上下文的大部分内容,包括已经打开的文件的描述符信息,父进程和子进程将共享相同的文件偏移量。
例程:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(void)
{
//定义字符类型名字为test的字符变量
char test;
//fd用于保存打开文件的文件描述符
int fd;
//使用open函数以只读方式打开名称为test.dat的文件
//如果打开失败则给出相关的失败信息,程序返回
if((fd=open("test.dat",O_RDONLY))==-1)
{
perror("Can not open the test.dat file!");
return 1;
}
//使用fork函数产生子进程,如果产生失败给出失败信息,程序返回
if(fork()==-1)
{
perror("Can not create the child process!");
return 1;
}
//读取test.dat文件中的一个字符,将其保存在名称为test的字符变量中
read(fd,&test,1);
//输出运行结果,函数getpid会获得进程的进程号
printf("Process ID:%ld read the chatacter :%c\n",(long)getpid(),test);
//关闭文件,注意这里实际会关闭两次
//父子进程将分别执行一次关闭动作
close(fd);
return 0;
}
程序执行结果如下:
guocheng@guocheng-desktop:~/test/fd_exam$ cat test.dat
abcdefgh
guocheng@guocheng-desktop:~/test/fd_exam$ gcc -o fd_exam fd_exam.c
guocheng@guocheng-desktop:~/test/fd_exam$ ./fd_exam
Process ID:7673 read the chatacter :a
Process ID:7672 read the chatacter :b
父进程和子进程分别读取了一个字符,父子进程共享相同的文件描述符,因此父子进程读取的字符是不相同的。
3、文件的访问权限
文件的权限在文件inode的Mode字段的0-8来描述,统称用三位八进制表示。
4、获取文件信息函数
头文件:<sys/types.h> <sys/stat.h> <unistd.h>
函数形式:int stat(const char *path,strct stat *buf);
int fstat(int filedes,struct stat *buf);
int lstat(const chat *path,strct stat *buf);
返回值:成功0,失败-1,设置errno;
参数:结构体stat说明文件信息,具体含有不做解释。
struct stat
{
dev_t st_dev ID of device containing file
ino_t st_ino file serial number
mode_t st_mode mode of file (see below)
nlink_t st_nlink number of links to the file
uid_t st_uid user ID of file
gid_t st_gid group ID of file
dev_t st_rdev device ID (if file is character or block special)
off_t st_size file size in bytes (if file is a regular file)
blksize_t st_blksize a filesystem-specific preferred I/O block size for
this object. In some filesystem types, this may
vary from file to file
blkcnt_t st_blocks number of blocks allocated for this object
time_t st_atime time of last access
time_t st_mtime time of last data modification
time_t st_ctime time of last status change
}
区别:stat和lstat的区别是当目标是符号连接时,lstat返回的是符号连接的inode信息而不是符号连接指向的文件信息,fstat和stat的区别是第一个参数不同,fstat使用文件描述符做参数。
函数例程:
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc,char* argv[1])
{
//定义类型为stat的机构体file_stat,用于保存获得的文件信息
struct stat file_stat;
//main带参数运行,程序名称是一个参数
//判断程序是否带有一个参数执行,共两个参数,如果不是给出提示
//程序结束运行
if(argc!=2)
{
printf("Usage :%s filename!\n",argv[0]);
return 1;
}
//调用stat函数,如果出现错误给出错误信息,程序退出
if(stat(argv[1],&file_stat)==-1)
{
perror("Can not get the information of the file!\n");
return 1;
}
//使用POSIX中定义的宏判断是否是常规文件
if(S_ISREG(file_stat.st_mode))
printf("%s is Regular file,Judeged by S_ISREG\n",argv[1]);
//通过st_mode与S_IFREG的位运算判断是否是目录
if(file_stat.st_mode & S_IFREG)
printf("%s is a Regular File,Judeged by bits calculate S_IFREG\n",argv[1]);
//通过S_ISDIR宏判断是否是目录
if(S_ISDIR(file_stat.st_mode))
printf("%s is a Directory,Judeged by S_ISDIR\n",argv[1]);
//通过st_mode与S_IFDIR的位运算判断是否是目录
if(file_stat.st_mode & S_IFDIR)
printf("%s is a Directory,Judeged by bits calculate S_IFDIR\n",argv[1]);
//输出file_stat中的其他文件信息
printf("Ower ID:%d,Group ID:%d\n",file_stat.st_uid,file_stat.st_gid);
printf("Permission:%o\n",file_stat.st_mode & 0x1ff);
printf("Last Access Time:%15s\n",ctime(&file_stat.st_atime));
printf("Last Modification Time:%15s\n",ctime(&file_stat.st_mtime));
printf("Last Status Change Time:%15s\n",ctime(&file_stat.st_ctime));
return 0;
}
程序运行结果:
guocheng@guocheng-desktop:~/test/stat_exam$ ls
a.out stat_exam.c stat_exam.c~ test
guocheng@guocheng-desktop:~/test/stat_exam$ ./a.out stat_exam.c
stat_exam.c is Regular file,Judeged by S_ISREG
stat_exam.c is a Regular File,Judeged by bits calculate S_IFREG
Ower ID:1000,Group ID:1000
Permission:644
Last Access Time:Sun Mar 1 00:32:05 2009
Last Modification Time:Sun Mar 1 00:30:51 2009
Last Status Change Time:Sun Mar 1 00:30:51 2009
guocheng@guocheng-desktop:~/test/stat_exam$ ./a.out test/
test/ is a Directory,Judeged by S_ISDIR
test/ is a Directory,Judeged by bits calculate S_IFDIR
Ower ID:1000,Group ID:1000
Permission:755
Last Access Time:Sun Mar 1 00:25:37 2009
Last Modification Time:Sun Mar 1 00:25:36 2009
Last Status Change Time:Sun Mar 1 00:25:36 2009
5、修改文件权限函数
头文件: <sys/stat.h> <sys/types.h>
函数形式:int chmod(const char *path,mode_t mode);
int fchmod(int filedes,mode_t mode);
返回值:成功0,失败-1,设置errno;
两个函数的区别在第一个参数,使用宏定义组合设置文件的权限。
例程:
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
int main(int argc,char* argv[])
{
if(argc!=2)
{
printf("Error!");
return 1;
}
//修改文件权限至r--r--r-x
if(chmod(argv[1],S_IRUSR | S_IRGRP | S_IROTH | S_IXOTH)<0)
{
perror("Can not modify the permission of the file !");
return 1;
}
return 0;
}
执行结果:
guocheng@guocheng-desktop:~/test/chmod_exam$ ls -al test
---------- 1 guocheng guocheng 0 2009-03-01 00:50 test
guocheng@guocheng-desktop:~/test/chmod_exam$ ./a.out test
guocheng@guocheng-desktop:~/test/chmod_exam$ ls -al test
-r--r--r-x 1 guocheng guocheng 0 2009-03-01 00:50 test
6、修改文件拥有者函数
头文件: <sys/stat.h> <sys/types.h>
函数形式:int chown(const char *path,uid_t owner,gid_t,group);
int fchown(int fd,uid_t owner,gid_t,group);
int lchown(const char *path,uid_t owner,gid_t,group);
返回值:成功0,失败-1,设置errno;
7、Umask函数
头文件: <sys/stat.h> <sys/types.h>
函数形式:mode_t umask(mode_t mask);
返回值:总是执行成功返回修改前的umask值
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
int main(void)
{
int fd1,fd2;
struct stat file_stat;
fd1=open("test",O_CREAT | O_RDWR,0777);
if(fd1<0)
{
perror("Can not create the test file!");
return 1;
}
close(fd1);
if(stat("test",&file_stat)==-1)
{
perror("Can not get the information fo the test file!");
return 1;
}
printf("Permission is %o\n",file_stat.st_mode & 0x1ff);
//修改umask值077
umask(S_IWGRP | S_IRGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH);
fd2=open("test1",O_CREAT | O_RDWR,0777);
if(fd2<0)
{
perror("Can not create the test1 file!");
return 1;
}
close(fd2);
if(stat("test1",&file_stat)==-1)
{
perror("Can not get the information fo the test1 file!");
return 1;
}
printf("Permission is %o\n",file_stat.st_mode & 0x1ff);
return 0;
}
执行结果:
guocheng@guocheng-desktop:~/test/umask_exam$ vi umask_exam.c
guocheng@guocheng-desktop:~/test/umask_exam$ gcc umask_exam.c
guocheng@guocheng-desktop:~/test/umask_exam$ ./a.out
Permission is 755
Permission is 700
#ifndef ICE_PATCH2_OS_H
#define ICE_PATCH2_OS_H
#include <Ice/Config.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#ifndef ICE_PATCH2_API
# ifdef ICE_PATCH2_API_EXPORTS
# define ICE_PATCH2_API ICE_DECLSPEC_EXPORT
# else
# define ICE_PATCH2_API ICE_DECLSPEC_IMPORT
# endif
#endif
namespace OS
{
#ifdef _WIN32
typedef struct _stat structstat;
#ifdef _MSC_VER
# define O_RDONLY _O_RDONLY
# define O_BINARY _O_BINARY
# define S_ISDIR(mode) ((mode) & _S_IFDIR)
# define S_ISREG(mode) ((mode) & _S_IFREG)
#endif
#else
// linux 则定义 stat 结构 为structstat 类型, O_BINARY为0
typedef struct stat structstat;
# define O_BINARY 0
#endif
// BUGFIX: aCC errors if this is stat.
ICE_PATCH2_API int osstat( const std::string&, structstat* );
ICE_PATCH2_API int remove( const std::string& );
ICE_PATCH2_API int rename( const std::string&, const std::string& );
ICE_PATCH2_API int rmdir( const std::string& );
ICE_PATCH2_API int mkdir( const std::string&, int );
ICE_PATCH2_API FILE* fopen( const std::string&, const std::string& );
ICE_PATCH2_API int open( const std::string&, int );
ICE_PATCH2_API int getcwd( std::string& ) ;
}
#endif
#include <IceUtil/DisableWarnings.h>
#include <OS.h>
#include <IceUtil/Unicode.h>
#ifdef __BCPLUSPLUS__
# include <dir.h>
# include <io.h>
#endif
using namespace std;
using namespace OS;
#ifdef _WIN32
#else
//linux 调用stat函数将path指定的文件结构信息,保存到buf中
/*
表头文件: #include <sys/stat.h>
#include <unistd.h>
定义函数: int stat(const char *file_name, struct stat *buf);
函数说明: 通过文件名filename获取文件信息,并保存在buf所指的结构体stat中
返回值: 执行成功则返回0,失败返回-1,错误代码存于errno
错误代码:
ENOENT 参数file_name指定的文件不存在
ENOTDIR 路径中的目录存在但却非真正的目录
ELOOP 欲打开的文件有过多符号连接问题,上限为16符号连接
EFAULT 参数buf为无效指针,指向无法存在的内存空间
EACCESS 存取文件时被拒绝
ENOMEM 核心内存不足
ENAMETOOLONG 参数file_name的路径名称太长
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
int main() {
struct stat buf;
stat("/etc/hosts", &buf);
printf("/etc/hosts file size = %d\n", buf.st_size);
}
-----------------------------------------------------
struct stat {
dev_t st_dev; //文件的设备编号
ino_t st_ino; //节点
mode_t st_mode; //文件的类型和存取的权限
nlink_t st_nlink; //连到该文件的硬连接数目,刚建立的文件值为1
uid_t st_uid; //用户ID
gid_t st_gid; //组ID
dev_t st_rdev; //(设备类型)若此文件为设备文件,则为其设备编号
off_t st_size; //文件字节数(文件大小)
unsigned long st_blksize; //块大小(文件系统的I/O 缓冲区大小)
unsigned long st_blocks; //块数
time_t st_atime; //最后一次访问时间
time_t st_mtime; //最后一次修改时间
time_t st_ctime; //最后一次改变时间(指属性)
};
先前所描述的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来删除或改名。
-----------------------------------------------------
struct statfs {
long f_type; //文件系统类型
long f_bsize; //块大小
long f_blocks; //块多少
long f_bfree; //空闲的块
long f_bavail; //可用块
long f_files; //总文件节点
long f_ffree; //空闲文件节点
fsid_t f_fsid; //文件系统id
long f_namelen; //文件名的最大长度
long f_spare[6]; //spare for later
};
stat、fstat和lstat函数(UNIX)
#include<sys/types.h>
#include<sys/stat.h>
int stat(const char *restrict pathname, struct stat *restrict buf);
提供文件名字,获取文件对应属性。感觉一般是文件没有打开的时候这样操作。
int fstat(int filedes, struct stat *buf);
通过文件描述符获取文件对应的属性。文件打开后这样操作
int lstat(const char *restrict pathname, struct stat *restrict buf);
连接文件
三个函数的返回:若成功则为0,若出错则为-1
给定一个pathname,stat函数返回一个与此命名文件有关的信息结构,
fstat函数获得已在描述符filedes上打开的文件的有关信息。lstat函数类似于stat,
但是当命名的文件是一个符号连接时,lstat返回该符号连接的有关信息,
而不是由该符号连接引用的文件的信息。
第二个参数是个指针,它指向一个我们应提供的结构。这些函数填写由buf指向的结构。
该结构的实际定义可能随实现而有所不同,但其基本形式是:
struct stat{
mode_t st_mode; /*file tpye &mode (permissions)
ino_t st_ino; /*i=node number (serial number)
dev_t st_rdev; /*device number for special files
nlink_t st_nlink; /*number of links
uid_t st_uid; /*user id of owner
gid_t st_gid; /*group ID of owner
off_t st_size; /*size in bytes for regular files
time_t st_atime; /*time of last access
time_t st_mtime; /*time of last modification
time_t st_ctime; /*time of last file status change
long st_blksize; /*best I/O block size
long st_blocks; /*number of 512-byte blocks allocated
};
注意,除最后两个以外,其他各成员都为基本系统数据类型。
我们将说明此结构的每个成员以了解文件属性。
使用stat函数最多的可能是ls-l命令,用其可以获得有关一个文件的所有信息。
1 函数都是获取文件(普通文件,目录,管道,socket,字符,块()的属性。
函数原型#include <sys/stat.h>
int stat(const char *restrict pathname, struct stat *restrict buf);提供文件名字,
获取文件对应属性。
int fstat(int filedes, struct stat *buf);通过文件描述符获取文件对应的属性。
int lstat(const char *restrict pathname, struct stat *restrict buf);连接文件描述命,
获取文件属性。2 文件对应的属性struct stat {
mode_t st_mode; //文件对应的模式,文件,目录等
ino_t st_ino; //inode节点号
dev_t st_dev; //设备号码
dev_t st_rdev; //特殊设备号码
nlink_t st_nlink; //文件的连接数
uid_t st_uid; //文件所有者
gid_t st_gid; //文件所有者对应的组
off_t st_size; //普通文件,对应的文件字节数
time_t st_atime; //文件最后被访问的时间
time_t st_mtime; //文件内容最后被修改的时间
time_t st_ctime; //文件状态改变时间
blksize_t st_blksize; //文件内容对应的块大小
blkcnt_t st_blocks; //伟建内容对应的块数量
};可以通过上面提供的函数,返回一个结构体,保存着文件的信息。
*/
int
OS::osstat( const string& path, structstat* buf )
{
return ::stat( path.c_str(), buf );
}
/*
remove函数的功能是删除一个文件。它的一般格式为:
remove(const char * filename);
remove函数也是一个宏,可以删除filename(文件名)指定的文件。
如果文件已经打开,则必须将该文件关闭才能够删除。如果调用成功,
返回0,否则返回-1,并置全局变量errno为ENOENT(没有此文件或目录)
或EACCES(无此权限)。
NAME
rename - change the name or location of a file
SYNOPSIS
#include <stdio.h>
int rename(const char *oldpath, const char *newpath);
DESCRIPTION
rename() renames a file, moving it between directories if required.
Any other hard links to the file (as created using link(2)) are unaffected.
If newpath already exists it will be atomically replaced (subject
to a few conditions; see ERRORS below),
so that there is no point at which another process attempting to
access newpath will find it missing.
The rename function causes the file whose name is the string pointed to by old to be
henceforth known by the name given by the string pointed to by new. The file named
old is no longer accessible by that name.
If a file named by the string pointed to by new exists prior to the call to
the rename function, the behavior is implementation-defined.
ISO C99 p267
man 2 rename
oldpath and newpath are not on the same mounted filesystem.
(Linux permits a filesystem to be
mounted at multiple points, but rename(2) does not work
across different mount points, even if the
same filesystem is mounted on both.)
rename(更改文件名称或位置)
相关函数 link,unlink,symlink
表头文件 #include<stdio.h>
定义函数 int rename(const char * oldpath,const char * newpath);
函数说明 rename()会将参数oldpath 所指定的文件名称改为参数newpath所指的文件名称。
若newpath所指定的文件已存在,则会被删除。
返回值 执行成功则返回0,失败返回-1,错误原因存于errno
范例 设计一个DOS下的rename指令rename 旧文件名新文件名
mkdir和rmdir函数.
int mkdir(const char*pathname,mode_t mode);//创建一个空目录
int rmdir(const char *pathname); //删除一个空目录,不能删除有文件目录
读目录
对于某个目录具有访问权限的任一用户都可以读该目录,但是,为了防止文件系统
产生混乱,只有内核才能写目录.这里又有一个新头文件出现<dirent.h>
DIR* opendir(const char *pathname);//成功返回指针,出错返回NULL
struct dirent *readdir(DIR *dp);
void rewinddir(DIR *dp);
int closedir(DIR *dp);
long telldir(DIR *dp);
void seekdir(DIR *dp,long loc);
struct dirent //来自/usr/include/bits/dirent.h
{
#ifndef __USE_FILE_OFFSET64
__ino_t d_ino;
__off_t d_off;
#else
__ino64_t d_ino; //i_node节点号
__off64_t d_off;
#endif
unsigned short int d_reclen;
unsigned char d_type;
char d_name[256]; /*We must not include limits.h //目录名
}
DIR结构是内核用的,对用户不公开使用.
一、获取当前工作目录函数-getcwd
头文件:<unistd.h>
函数形式:char* getcwd(char *buffer,size_t size)
返回值:成功返回当前工作目录的字符串指针
失败返回NULL
设置errno
错误信息:
EINVAL:size参数为0或者buff不是空指针;
ERANGE:size参数小于当前工作目录的长度,需要分配更大的内存
EACCES:权限不足,没有读或者搜索文件名称的权限
二、获得系统目录最大长度-pathconf
头文件:unistd.h
函数形式:long pathconf(char *path,int name)
返回值:成功返回目录长度的极限值
失败返回-1
设置errno
//name:pathconf_exam.cxx
#include<unistd.h>
#include<iostream.h>
int main(void)
{
long cur_work_len;
char* cur_work_dir;
//获得目录最大长度
if((cur_work_len=pathconf(".",_PC_PATH_MAX))==-1)
{
perror("Could not get current working directory length!");
return 1;
}
std::cout<<"Current work length is "<<cur_work_len<<std::endl;
//根据获得的目录的最大长度,分配内存
if((cur_work_dir=(char*)malloc(cur_work_len))==NULL)
{
perror("Could not allocate memory for the directory!");
return 1;
}
//获得当前的工作目录
if (getcwd(cur_work_dir,cur_work_len)==NULL)
{
perror("Could not get current working directory!");
return 1;
}
std::cout<<"Current working directory is "<<cur_work_dir<<std::endl;
return 0;
}
程序执行结果:
guocheng@guocheng-desktop:~/test/dir_exam/pathconf$ g++ -o pathconf_exam pathconf_exam.cxx
guocheng@guocheng-desktop:~/test/dir_exam/pathconf$ ./pathconf_exam
Current work length is 4096
Current working directory is /home/guocheng/test/dir_exam/pathconf
三、更改当前工作目录-chdir和fchdir
头文件:unisd.h
函数形式:int chdir(const char* path)
int fchdir(fd)
返回值:成功0
失败-1
设置errno
说明:chdir函数的参数是指向目录的字符串指针,成功的前提是程序有所搜整个目录的权限,fchdir调用的参数是目录的文件描述符,其他与chdir相同。
按照上面的例子进行修改。
//name:chdir_exam.cxx
#include<unistd.h>
#include<iostream.h>
int main(void)
{
long cur_work_len;
char* cur_work_dir;
//获得目录最大长度
if((cur_work_len=pathconf(".",_PC_PATH_MAX))==-1)
{
perror("Could not get current working directory length!");
return 1;
}
std::cout<<"Current work length is "<<cur_work_len<<std::endl;
//根据获得的目录的最大长度,分配内存
if((cur_work_dir=(char*)malloc(cur_work_len))==NULL)
{
perror("Could not allocate memory for the directory!");
return 1;
}
//获得当前的工作目录
if (getcwd(cur_work_dir,cur_work_len)==NULL)
{
perror("Could not get current working directory!");
return 1;
}
std::cout<<"Current working directory is "<<cur_work_dir<<std::endl;
//修改当前目录至上级目录
if(chdir("..")==-1)
{
perror("Could not get current working directory!");
return 1;
}
//获得当前的工作目录
if (getcwd(cur_work_dir,cur_work_len)==NULL)
{
perror("Could not get current working directory!");
return 1;
}
std::cout<<"Current working directory is "<<cur_work_dir<<std::endl;
return 0;
}
执行结果
guocheng@guocheng-desktop:~/test/dir_exam/chdir$ ./chdir_exam
Current work length is 4096
Current working directory is /home/guocheng/test/dir_exam/chdir
Current working directory is /home/guocheng/test/dir_exam
四、创建和删除工作目录-mkdir和rmdir
头文件:sys/stat.h sys/types.h
函数形式:int mkdir(const char* pathname,mode_t mode);
返回值:成功0,失败-1,设置errno
说明:创建的目录的权限由mode、-umask和0777的与值来决定。
下面是实力,在/tmp/guocheng/的目录下创建目录yu,具体代码实现如下:
//mkdir_exam.cxx
#include <sys/stat.h>
#include <sys/types.h>
#include <iostream.h>
int main(void)
{
char* pathname="/tmp/guocheng/yu";
if(mkdir(pathname,0700)==-1)
{
perror("Could not create the direcotry!");
return 1;
}
return 0;
}
函数:int rmdir(const char* pathname);
返回值:成功0,失败-1,设置errno。
1、linux文件的实现
索引结点结构(inode)在linxu系统中实现文件的存储和相关信息的保存,每个inode中存储有文件的属性、访问权限以及文件数据块的存储位置。对linux系统而言,inode是文件系统定位文件的基本途径。
左图描述了inode的结构:图中前四项统称为文件的描述信息,其他的信息均为定位文件数据的指针。
文件描述信息主要包括:
Mode:包含有inode的描述内容和用户访问权限;
Owner Infomation:文件或目录所有者的信息,包括所属组信息;
Size:用于记录文件的大小,以字节为单位;
Timesstamps:时间戳,用于记录inode的创建时间及最后的修改时间;
定位文件数据的指针主要包括以下几种:
直接块指针:前12个,直接指向数据块
间接块指针:第13个,指向含有块指针的数据块
双重间接块指针:第14个
三重间接块指针:第15个
inode共有15个块指针的数组,前12为直接指向数据快的指针,第13个是间接数据块指针,指向含有数据块指针的数据块,14和15一次类推。
假设每个指向的数据块的大小是1024字节,每个指针是32位(4字节),下面进行计算文件容量。
直接块指针:12个X1024字节=12K;
间接块指针:1个X(1024字节/4字节)X1024字节=246K;
双重间接块指针:1个X(1024字节/4字节)X(1024字节/4字节)X1024字节=65536K
三重间接块指针:1个X(1024字节/4字节)X(1024字节/4字节)X(1024字节/4字节)1024字节=16777216K,即16G;
2、文件描述符与文件指针
在linux系统中,统一了文件和设备的操作,提供了open、read、close等函数,使用文件描述符来对文件进行操作。文件描述符是一个int类型的数值,在使用open函数操作文件时返回的。
如果某个进程使用open函数打开了一个文件,通过fork函数创建当前进程的子进程,则子进程会继承父进程的环境和上下文的大部分内容,包括已经打开的文件的描述符信息,父进程和子进程将共享相同的文件偏移量。
例程:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(void)
{
//定义字符类型名字为test的字符变量
char test;
//fd用于保存打开文件的文件描述符
int fd;
//使用open函数以只读方式打开名称为test.dat的文件
//如果打开失败则给出相关的失败信息,程序返回
if((fd=open("test.dat",O_RDONLY))==-1)
{
perror("Can not open the test.dat file!");
return 1;
}
//使用fork函数产生子进程,如果产生失败给出失败信息,程序返回
if(fork()==-1)
{
perror("Can not create the child process!");
return 1;
}
//读取test.dat文件中的一个字符,将其保存在名称为test的字符变量中
read(fd,&test,1);
//输出运行结果,函数getpid会获得进程的进程号
printf("Process ID:%ld read the chatacter :%c\n",(long)getpid(),test);
//关闭文件,注意这里实际会关闭两次
//父子进程将分别执行一次关闭动作
close(fd);
return 0;
}
程序执行结果如下:
guocheng@guocheng-desktop:~/test/fd_exam$ cat test.dat
abcdefgh
guocheng@guocheng-desktop:~/test/fd_exam$ gcc -o fd_exam fd_exam.c
guocheng@guocheng-desktop:~/test/fd_exam$ ./fd_exam
Process ID:7673 read the chatacter :a
Process ID:7672 read the chatacter :b
父进程和子进程分别读取了一个字符,父子进程共享相同的文件描述符,因此父子进程读取的字符是不相同的。
3、文件的访问权限
文件的权限在文件inode的Mode字段的0-8来描述,统称用三位八进制表示。
4、获取文件信息函数
头文件:<sys/types.h> <sys/stat.h> <unistd.h>
函数形式:int stat(const char *path,strct stat *buf);
int fstat(int filedes,struct stat *buf);
int lstat(const chat *path,strct stat *buf);
返回值:成功0,失败-1,设置errno;
参数:结构体stat说明文件信息,具体含有不做解释。
struct stat
{
dev_t st_dev ID of device containing file
ino_t st_ino file serial number
mode_t st_mode mode of file (see below)
nlink_t st_nlink number of links to the file
uid_t st_uid user ID of file
gid_t st_gid group ID of file
dev_t st_rdev device ID (if file is character or block special)
off_t st_size file size in bytes (if file is a regular file)
blksize_t st_blksize a filesystem-specific preferred I/O block size for
this object. In some filesystem types, this may
vary from file to file
blkcnt_t st_blocks number of blocks allocated for this object
time_t st_atime time of last access
time_t st_mtime time of last data modification
time_t st_ctime time of last status change
}
区别:stat和lstat的区别是当目标是符号连接时,lstat返回的是符号连接的inode信息而不是符号连接指向的文件信息,fstat和stat的区别是第一个参数不同,fstat使用文件描述符做参数。
函数例程:
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc,char* argv[1])
{
//定义类型为stat的机构体file_stat,用于保存获得的文件信息
struct stat file_stat;
//main带参数运行,程序名称是一个参数
//判断程序是否带有一个参数执行,共两个参数,如果不是给出提示
//程序结束运行
if(argc!=2)
{
printf("Usage :%s filename!\n",argv[0]);
return 1;
}
//调用stat函数,如果出现错误给出错误信息,程序退出
if(stat(argv[1],&file_stat)==-1)
{
perror("Can not get the information of the file!\n");
return 1;
}
//使用POSIX中定义的宏判断是否是常规文件
if(S_ISREG(file_stat.st_mode))
printf("%s is Regular file,Judeged by S_ISREG\n",argv[1]);
//通过st_mode与S_IFREG的位运算判断是否是目录
if(file_stat.st_mode & S_IFREG)
printf("%s is a Regular File,Judeged by bits calculate S_IFREG\n",argv[1]);
//通过S_ISDIR宏判断是否是目录
if(S_ISDIR(file_stat.st_mode))
printf("%s is a Directory,Judeged by S_ISDIR\n",argv[1]);
//通过st_mode与S_IFDIR的位运算判断是否是目录
if(file_stat.st_mode & S_IFDIR)
printf("%s is a Directory,Judeged by bits calculate S_IFDIR\n",argv[1]);
//输出file_stat中的其他文件信息
printf("Ower ID:%d,Group ID:%d\n",file_stat.st_uid,file_stat.st_gid);
printf("Permission:%o\n",file_stat.st_mode & 0x1ff);
printf("Last Access Time:%15s\n",ctime(&file_stat.st_atime));
printf("Last Modification Time:%15s\n",ctime(&file_stat.st_mtime));
printf("Last Status Change Time:%15s\n",ctime(&file_stat.st_ctime));
return 0;
}
程序运行结果:
guocheng@guocheng-desktop:~/test/stat_exam$ ls
a.out stat_exam.c stat_exam.c~ test
guocheng@guocheng-desktop:~/test/stat_exam$ ./a.out stat_exam.c
stat_exam.c is Regular file,Judeged by S_ISREG
stat_exam.c is a Regular File,Judeged by bits calculate S_IFREG
Ower ID:1000,Group ID:1000
Permission:644
Last Access Time:Sun Mar 1 00:32:05 2009
Last Modification Time:Sun Mar 1 00:30:51 2009
Last Status Change Time:Sun Mar 1 00:30:51 2009
guocheng@guocheng-desktop:~/test/stat_exam$ ./a.out test/
test/ is a Directory,Judeged by S_ISDIR
test/ is a Directory,Judeged by bits calculate S_IFDIR
Ower ID:1000,Group ID:1000
Permission:755
Last Access Time:Sun Mar 1 00:25:37 2009
Last Modification Time:Sun Mar 1 00:25:36 2009
Last Status Change Time:Sun Mar 1 00:25:36 2009
5、修改文件权限函数
头文件: <sys/stat.h> <sys/types.h>
函数形式:int chmod(const char *path,mode_t mode);
int fchmod(int filedes,mode_t mode);
返回值:成功0,失败-1,设置errno;
两个函数的区别在第一个参数,使用宏定义组合设置文件的权限。
例程:
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
int main(int argc,char* argv[])
{
if(argc!=2)
{
printf("Error!");
return 1;
}
//修改文件权限至r--r--r-x
if(chmod(argv[1],S_IRUSR | S_IRGRP | S_IROTH | S_IXOTH)<0)
{
perror("Can not modify the permission of the file !");
return 1;
}
return 0;
}
执行结果:
guocheng@guocheng-desktop:~/test/chmod_exam$ ls -al test
---------- 1 guocheng guocheng 0 2009-03-01 00:50 test
guocheng@guocheng-desktop:~/test/chmod_exam$ ./a.out test
guocheng@guocheng-desktop:~/test/chmod_exam$ ls -al test
-r--r--r-x 1 guocheng guocheng 0 2009-03-01 00:50 test
6、修改文件拥有者函数
头文件: <sys/stat.h> <sys/types.h>
函数形式:int chown(const char *path,uid_t owner,gid_t,group);
int fchown(int fd,uid_t owner,gid_t,group);
int lchown(const char *path,uid_t owner,gid_t,group);
返回值:成功0,失败-1,设置errno;
7、Umask函数
头文件: <sys/stat.h> <sys/types.h>
函数形式:mode_t umask(mode_t mask);
返回值:总是执行成功返回修改前的umask值
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
int main(void)
{
int fd1,fd2;
struct stat file_stat;
fd1=open("test",O_CREAT | O_RDWR,0777);
if(fd1<0)
{
perror("Can not create the test file!");
return 1;
}
close(fd1);
if(stat("test",&file_stat)==-1)
{
perror("Can not get the information fo the test file!");
return 1;
}
printf("Permission is %o\n",file_stat.st_mode & 0x1ff);
//修改umask值077
umask(S_IWGRP | S_IRGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH);
fd2=open("test1",O_CREAT | O_RDWR,0777);
if(fd2<0)
{
perror("Can not create the test1 file!");
return 1;
}
close(fd2);
if(stat("test1",&file_stat)==-1)
{
perror("Can not get the information fo the test1 file!");
return 1;
}
printf("Permission is %o\n",file_stat.st_mode & 0x1ff);
return 0;
}
执行结果:
guocheng@guocheng-desktop:~/test/umask_exam$ vi umask_exam.c
guocheng@guocheng-desktop:~/test/umask_exam$ gcc umask_exam.c
guocheng@guocheng-desktop:~/test/umask_exam$ ./a.out
Permission is 755
Permission is 700
相关推荐
在编程领域,随机文件操作是处理大量数据时常用的一种技术,尤其在需要持久化存储对象或结构化数据时。在给定的场景中,我们有一个`Employee`类,包含编号、姓名、年龄和工资等数据成员。这个任务要求在当前工作目录...
文件系统是操作系统中用于组织、存储和检索文件的组件。在这个实验中,虽然没有详细展开,但我们可以假设学生需要理解文件的创建、删除、读写操作,以及目录结构的管理。文件系统模拟可能涉及文件的i-node(用于存储...
DBMS是独立于操作系统的软件,但数据库中数据的组织和存储是通过操作系统中的文件系统来实现的。 适合用文件系统和数据库系统的应用例子 适用于文件系统而不是数据库系统的应用例子包括数据的备份、软件或应用程序...
总之,这个"经典数据库学习资料"压缩包,尤其是包含的DBF文件,是学习数据库原理和技术的一个好起点。通过深入研究DBF格式,你可以更好地理解和掌握数据库的本质,为未来在更复杂的数据库系统中工作打下坚实的基础。
在DOS环境下,用户通过命令行界面进行操作,例如管理文件、设备等。DOS支持一系列内置命令,如COPY、DEL、DIR等,这些命令帮助用户执行基本的文件管理和系统维护任务。 #### 二、DOS的发展历程 自1981年首次发布...
2. **wil文件编辑**:明确了主要功能是对.WIL文件进行编辑操作。 3. **wil源码**:指出该编辑器的实现代码可供学习和使用。 4. **wil文件编辑器**:概括了整个软件的核心作用,即用于.WIL文件的编辑。 **压缩包子...
在电视不就行概括地讲风华高科大家好附件适当放宽蝴蝶飞过华东师范空间规划地方就会感到很烦,这部分描述可能是一段非相关或者错误的信息,因为其内容与西门子G120变频器或GSD文件本身没有直接关联。可能是文本输入...
‘意天文件恢复大师’是一款Windows操作系统下的文件恢复软件 【基本介绍】 数据恢复。‘意天文件恢复大师’是一款Windows操作系统下的文件恢复软件,其软件精小而功能强大。 【软件特色】 1、当您不小心删除...
标签“文件处理”和“源代码”是对内容的精炼概括,表明这个压缩包包含的代码着重于文件操作,并且可以被开发者学习和参考。 根据压缩包子文件的文件名称列表,我们可以推断出以下内容: 1. SEEK.FRM:这是一个VB...
同时,理解如何在Windows操作系统中进行文件操作,例如浏览文件夹、复制/移动文件等,也是使用此类工具的前提。对于企业或专业用户,这样的工具可以极大地提高工作效率,减少手动操作带来的错误。
【标题】"新建 WinRAR 压缩文件.rar" 提示我们这可能是一个...以上就是 WinRAR 相关的知识点,虽然给定的文件描述和标签没有提供太多具体信息,但通过 WinRAR 的功能和特性,我们可以理解如何管理和操作此类压缩文件。
9. **异常处理**:在进行文件操作时,必须处理可能出现的异常,如`FileNotFoundException`、`IOException`等,确保程序的健壮性。 10. **测试与调试**:开发者可能分享了如何测试和调试代码的建议,以确保Shape文件...
"Redhat Linux操作系统下常用服务概括介绍" Redhat Linux 操作系统是一个流行的开源操作系统,它提供了许多有用的服务来提高系统的功能和安全性。下面是 Redhat Linux 操作系统下常用服务的概括介绍: 1. aep1000/...
1. **文件系统的概念**:文件系统是操作系统用于明确存储设备(常见的是硬盘,也可能是闪存)或分区上的文件的方法和数据结构;即,在存储设备上组织文件的方法。 2. **文件系统的设计目的**: - 提供一种逻辑...
由于没有具体020文件的详细信息,以上内容都是基于一般性假设的概括。实际情况下,需要更多详细资料才能提供更具体的指导。如果你能提供更多关于020文件的背景信息,我可以提供更精确的知识点解析。
MATLAB文件操作和程序设计 MATLAB是一种高性能的技术计算语言和开发环境,广泛应用于数字信号处理、图像处理、控制系统、通信系统、电路分析等领域。下面是MATLAB文件操作和程序设计的知识点总结。 EDA技巧简介 ...
质量手册是质量管理体系的纲领性文件,它概括了本工厂质量管理体系的构成及要素。程序文件是直接支撑质量手册的主要体系文件,是对各部门运作过程及质量体系要求的具体说明。作业指导书是从程序文件中引申出来的,...
根据提供的文件信息,文件名为“施工合同权利义务概括转让协议.pdf”,说明该文档是一份关于施工合同中的权利与义务进行概括性转让的正式协议文本。标题表明协议内容涉及将特定施工合同下的权利和义务,从原合同一方...
而标签"javascript 文件保存到本地"则是对文章主题的一个简洁概括,说明这是一篇专注于在客户端使用JavaScript语言保存文件到本地硬盘的方法的分享文章。 接下来,详细解析给定的示例代码: - 第一个函数saveFile...