glibc源码分析之stat系列函数
2017-08-14 19:58
841 查看
glibc中stat系列函数有stat,fstat,lstat。它们都是系统调用的封装函数。
关于stat的系统调用有oldstat(18),oldfstat(28),oldlstat(84),stat(106),lstat(107),fstat(108),stat64(195),lstat64(196),fstat64(197)。oldstat系列系统调用被stat系列系统调用替代了。stat系列系统调用用于获取文件属性,文件属性为32位,而stat64系列系统调用则用于获取文件属性,文件属性是64位。所以stat系列系统调用不能获取长度超过32位的文件的属性。
stat,fstat,lstat函数在封装是都是使用stat64系列系统调用,而不是使用stat系列系统调用。
查看stat函数的源码:
函数__stat调用了__xstat 函数。而__xstat 函数定义在sysdeps/unix/sysv/linux/i386/xstat.c文件中。
如果参数vers 等于_STAT_VER_KERNEL,则直接调用stat系统调用。显然,__stat传入的参数是_STAT_VER。
__xstat 函数首先调用stat64系统调用,获取了文件属性。然后,判断返回值是否出错,如果是则返回-1,并设置errno。如果执行正确,则将文件属性转化为32位,并返回0。
文件属性转换源码:
fstat函数源码:
__fstat函数调用了__fxstat 函数。而__fxstat 函数定义在sysdeps/unix/sysv/linux/i386/fxstat.c文件中。
__fxstat 函数调用过程类似于__xstat函数。
lstat函数源码:
__lstat函数调用了__fxstat 函数。而__lxstat 函数定义在sysdeps/unix/sysv/linux/i386/lxstat.c文件中。
__lxstat 函数调用过程类似于__xstat函数。
关于stat的系统调用有oldstat(18),oldfstat(28),oldlstat(84),stat(106),lstat(107),fstat(108),stat64(195),lstat64(196),fstat64(197)。oldstat系列系统调用被stat系列系统调用替代了。stat系列系统调用用于获取文件属性,文件属性为32位,而stat64系列系统调用则用于获取文件属性,文件属性是64位。所以stat系列系统调用不能获取长度超过32位的文件的属性。
stat,fstat,lstat函数在封装是都是使用stat64系列系统调用,而不是使用stat系列系统调用。
查看stat函数的源码:
#undef stat int attribute_hidden __stat (const char *file, struct stat *buf) { return __xstat (_STAT_VER, file, buf); } weak_hidden_alias (__stat, stat)
函数__stat调用了__xstat 函数。而__xstat 函数定义在sysdeps/unix/sysv/linux/i386/xstat.c文件中。
int __xstat (int vers, const char *name, struct stat *buf) { int result; if (vers == _STAT_VER_KERNEL) return INLINE_SYSCALL (stat, 2, name, buf); { struct stat64 buf64; INTERNAL_SYSCALL_DECL (err); result = INTERNAL_SYSCALL (stat64, err, 2, name, &buf64); if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result, err))) return INLINE_SYSCALL_ERROR_RETURN_VALUE (INTERNAL_SYSCALL_ERRNO (result, err)); else return __xstat32_conv (vers, &buf64, buf); } } hidden_def (__xstat) weak_alias (__xstat, _xstat);
如果参数vers 等于_STAT_VER_KERNEL,则直接调用stat系统调用。显然,__stat传入的参数是_STAT_VER。
__xstat 函数首先调用stat64系统调用,获取了文件属性。然后,判断返回值是否出错,如果是则返回-1,并设置errno。如果执行正确,则将文件属性转化为32位,并返回0。
文件属性转换源码:
int __xstat32_conv (int vers, struct stat64 *kbuf, struct stat *buf) { switch (vers) { case _STAT_VER_LINUX: { buf->st_dev = kbuf->st_dev; #ifdef _HAVE_STAT___PAD1 buf->__pad1 = 0; #endif #ifdef _HAVE_STAT64___ST_INO # if !__ASSUME_ST_INO_64_BIT if (kbuf->st_ino == 0) buf->st_ino = kbuf->__st_ino; else # endif { buf->st_ino = kbuf->st_ino; if (sizeof (buf->st_ino) != sizeof (kbuf->st_ino) && buf->st_ino != kbuf->st_ino) return INLINE_SYSCALL_ERROR_RETURN_VALUE (EOVERFLOW); } #else buf->st_ino = kbuf->st_ino; if (sizeof (buf->st_ino) != sizeof (kbuf->st_ino) && buf->st_ino != kbuf->st_ino) return INLINE_SYSCALL_ERROR_RETURN_VALUE (EOVERFLOW); #endif buf->st_mode = kbuf->st_mode; buf->st_nlink = kbuf->st_nlink; buf->st_uid = kbuf->st_uid; buf->st_gid = kbuf->st_gid; buf->st_rdev = kbuf->st_rdev; #ifdef _HAVE_STAT___PAD2 buf->__pad2 = 0; #endif buf->st_size = kbuf->st_size; /* Check for overflow. */ if (sizeof (buf->st_size) != sizeof (kbuf->st_size) && buf->st_size != kbuf->st_size) return INLINE_SYSCALL_ERROR_RETURN_VALUE (EOVERFLOW); buf->st_blksize = kbuf->st_blksize; buf->st_blocks = kbuf->st_blocks; /* Check for overflow. */ if (sizeof (buf->st_blocks) != sizeof (kbuf->st_blocks) && buf->st_blocks != kbuf->st_blocks) return INLINE_SYSCALL_ERROR_RETURN_VALUE (EOVERFLOW); #ifdef _HAVE_STAT_NSEC buf->st_atim.tv_sec = kbuf->st_atim.tv_sec; buf->st_atim.tv_nsec = kbuf->st_atim.tv_nsec; buf->st_mtim.tv_sec = kbuf->st_mtim.tv_sec; buf->st_mtim.tv_nsec = kbuf->st_mtim.tv_nsec; buf->st_ctim.tv_sec = kbuf->st_ctim.tv_sec; buf->st_ctim.tv_nsec = kbuf->st_ctim.tv_nsec; #else buf->st_atime = kbuf->st_atime; buf->st_mtime = kbuf->st_mtime; buf->st_ctime = kbuf->st_ctime; #endif #ifdef _HAVE_STAT___UNUSED1 buf->__glibc_reserved1 = 0; #endif #ifdef _HAVE_STAT___UNUSED2 buf->__glibc_reserved2 = 0; #endif #ifdef _HAVE_STAT___UNUSED3 buf->__glibc_reserved3 = 0; #endif #ifdef _HAVE_STAT___UNUSED4 buf->__glibc_reserved4 = 0; #endif #ifdef _HAVE_STAT___UNUSED5 buf->__glibc_reserved5 = 0; #endif } break; /* If struct stat64 is different from struct stat then _STAT_VER_KERNEL does not make sense. */ case _STAT_VER_KERNEL: default: return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL); } return 0; }
#define _STAT_VER_LINUX 3 #define _STAT_VER _STAT_VER_LINUX /* The one defined below. */
fstat函数源码:
#undef fstat #undef __fstat int attribute_hidden __fstat (int fd, struct stat *buf) { return __fxstat (_STAT_VER, fd, buf); } weak_hidden_alias (__fstat, fstat)
__fstat函数调用了__fxstat 函数。而__fxstat 函数定义在sysdeps/unix/sysv/linux/i386/fxstat.c文件中。
int __fxstat (int vers, int fd, struct stat *buf) { int result; if (vers == _STAT_VER_KERNEL) return INLINE_SYSCALL (fstat, 2, fd, buf); { struct stat64 buf64; INTERNAL_SYSCALL_DECL (err); result = INTERNAL_SYSCALL (fstat64, err, 2, fd, &buf64); if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result, err))) return INLINE_SYSCALL_ERROR_RETURN_VALUE (INTERNAL_SYSCALL_ERRNO (result, err)); else return __xstat32_conv (vers, &buf64, buf); } } hidden_def (__fxstat) weak_alias (__fxstat, _fxstat);
__fxstat 函数调用过程类似于__xstat函数。
lstat函数源码:
#undef lstat #undef __lstat int attribute_hidden __lstat (const char *file, struct stat *buf) { return __lxstat (_STAT_VER, file, buf); } weak_hidden_alias (__lstat, lstat)
__lstat函数调用了__fxstat 函数。而__lxstat 函数定义在sysdeps/unix/sysv/linux/i386/lxstat.c文件中。
int __lxstat (int vers, const char *name, struct stat *buf) { int result; if (vers == _STAT_VER_KERNEL) return INLINE_SYSCALL (lstat, 2, name, buf); { struct stat64 buf64; INTERNAL_SYSCALL_DECL (err); result = INTERNAL_SYSCALL (lstat64, err, 2, name, &buf64); if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result, err))) return INLINE_SYSCALL_ERROR_RETURN_VALUE (INTERNAL_SYSCALL_ERRNO (result, err)); else return __xstat32_conv (vers, &buf64, buf); } } hidden_def (__lxstat) weak_alias (__lxstat, _lxstat);
__lxstat 函数调用过程类似于__xstat函数。
相关文章推荐
- glibc源码分析之truncate系列函数
- glibc源码分析之chown系列函数
- glibc源码分析之utime系列函数
- glibc源码分析之chmod系列函数
- glibc源码分析之stat64系列函数
- glibc源码分析之statfs系列函数
- Linux-0.11内核源码分析系列:内存管理copy_page_tables()函数分析
- jQuery-1.9.1源码分析系列(六) 延时对象续——辅助函数jQuery.when
- Muduo网络库源码分析(三)线程间使用eventfd通信和EventLoop::runInLoop系列函数
- Linux-0.11内核源码分析系列:内存管理get_free_page()函数分析
- Linux-0.11内核源码分析系列:内存管理get_empty_page()与put_page()函数分析
- Linux-0.11内核源码分析系列:内存管理up_wp_page()与do_wp_page()函数分析
- Linux-0.11内核源码分析系列:内存管理try_to_share()与share_page()函数分析
- Linux-0.11内核源码分析系列:内存管理free_page()与free_page_tables()函数分析
- jQuery-1.9.1源码分析系列(十六)ajax——ajax处理流程以及核心函数
- Linux-0.11内核源码分析系列:进程调度sleep_on()函数分析
- Linux-0.11内核源码分析系列:内存管理up_wp_page()与do_wp_page()函数分析
- Linux-0.11内核源码分析系列:内存管理get_empty_page()与put_page()函数分析
- jQuery-1.9.1源码分析系列(六) 延时对象续——辅助函数jQuery.when
- Linux下库函数动态链接过程分析-结合glibc-2.11源码