今天在 mac 上测试下载服务端的一个图片文件,发现之前能成功创建本地文件的代码,突然出现
拒绝访问的错误,此时文件打开的代码如下:
int fd = open("./test.jpg", O_RDWR|O_APPEND|O_CREAT);
int errnum = errno;
if(fd < 0) {
LOG(ERROR) << "file ./test.jpg open failed, errno is: " << errnum << ", details: "<< strerror(errnum);
}
错误内容如下:
file ./test.jpg open failed, errno is: 13, details: Permission denied;
然后我找出 open 的文档查看,在提到 open 的参数 mode 时,有这句话:
The mode argument must be supplied if O_CREAT or O_TMPFILE is
specified in flags; if it is not supplied, some arbitrary
bytes from the stack will be applied as the file mode.
也就是说如果 flags 中指定了 O_CREAT,则 mode 这个参数不可以省去,否则 open 会从栈中读取未知的值来使用;
从而导致了上述代码这样的现象,可以改成如下的方式打开目标文件:
wfd_ = open("./test.jpg", O_RDWR|O_APPEND|O_CREAT, S_IRWXU|S_IRWXG);
详细梳理下 open 这个接口的使用细节,open 函数原型如下:
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
如果 pathname 指定的文件不存在,且 flags 指定了 O_CREAT,则 open 会创建该文件,并返回文件的描述符,如果打开失败,则会返回 -1;
如果 flags 没有指定 O_CREAT 或者 O_TMPFILE , 那么 mode 将被忽略;如果前者指定了,则必须指定 mode 的值;
The mode argument specifies the file mode bits to be
applied when a new file is created. If neither O_CREAT
nor O_TMPFILE is specified in flags, then mode is ignored
(and can thus be specified as 0, or simply omitted). The
mode argument must be supplied if O_CREAT or O_TMPFILE is
specified in flags; if it is not supplied, some arbitrary
bytes from the stack will be applied as the file mode.
flags 必须指定下面三个访问模式之一:O_RDONLY, O_WRONLY, or O_RDWR;
对应只读、只写、可读写;
可选的文件创建标签如下:O_CLOEXEC, O_CREAT, O_DIRECTORY, O_EXCL, O_NOCTTY, O_NOFOLLOW, O_TMPFILE, and O_TRUNC, O_APPEND, O_ASYNC,
O_DIRECT, O_DSYNC, O_LARGEFILE, O_NOATIME (since Linux 2.6.8), O_NONBLOCK or O_NDELAY, O_PATH, O_SYNC,