当路径名太长时,glibc 的系统调用打开设置 ENAMETOOLONG errno 的实现在哪里?
where does the glibc's implementation of syscall open set ENAMETOOLONG errno when pathname is too long?
来自男主开启:
int open(const char *pathname, int flags);
...
ENAMETOOLONG
pathname was too long.
open
会被设置为 errno
到 ENAMETOOLONG
,但是我在 glibc 的源代码中找不到这个赋值(也许它会调用内核函数,但我也找不到)
以下是我已经在 glibc 中探索过的函数:
/* Open FILE with access OFLAG. If O_CREAT or O_TMPFILE is in OFLAG,
a third argument is the file protection. */
int
__libc_open (const char *file, int oflag)
{
int mode;
if (file == NULL)
{
__set_errno (EINVAL);
return -1;
}
if (__OPEN_NEEDS_MODE (oflag))
{
va_list arg;
va_start(arg, oflag);
mode = va_arg(arg, int);
va_end(arg);
}
__set_errno (ENOSYS);
return -1;
}
int
__open_nocancel (const char *file, int oflag, ...)
{
int mode = 0;
if (__OPEN_NEEDS_MODE (oflag))
{
va_list arg;
va_start (arg, oflag);
mode = va_arg (arg, int);
va_end (arg);
}
return INLINE_SYSCALL_CALL (openat, AT_FDCWD, file, oflag, mode);
}
/* Open FILE with access OFLAG. Interpret relative paths relative to
the directory associated with FD. If O_CREAT or O_TMPFILE is in OFLAG, a
third argument is the file protection. */
int
__openat (int fd, const char *file, int oflag, ...)
{
int mode;
if (file == NULL)
{
__set_errno (EINVAL);
return -1;
}
if (fd != AT_FDCWD && file[0] != '/')
{
/* Check FD is associated with a directory. */
struct stat64 st;
if (__fxstat64 (_STAT_VER, fd, &st) != 0)
return -1;
if (!S_ISDIR (st.st_mode))
{
__set_errno (ENOTDIR);
return -1;
}
}
if (__OPEN_NEEDS_MODE (oflag))
{
va_list arg;
va_start (arg, oflag);
mode = va_arg (arg, int);
va_end (arg);
ignore_value (mode);
}
__set_errno (ENOSYS);
return -1;
}
/* Issue a syscall defined by syscall number plus any other argument
required. Any error will be handled using arch defined macros and errno
will be set accordingly.
It is similar to INLINE_SYSCALL macro, but without the need to pass the
expected argument number as second parameter. */
#define INLINE_SYSCALL_CALL(...) \
__INLINE_SYSCALL_DISP (__INLINE_SYSCALL, __VA_ARGS__)
#define SYSCALL_CANCEL(...) \
({ \
long int sc_ret; \
if (SINGLE_THREAD_P) \
sc_ret = INLINE_SYSCALL_CALL (__VA_ARGS__); \
else \
{ \
int sc_cancel_oldtype = LIBC_CANCEL_ASYNC (); \
sc_ret = INLINE_SYSCALL_CALL (__VA_ARGS__); \
LIBC_CANCEL_RESET (sc_cancel_oldtype); \
} \
sc_ret; \
})
它由文件系统处理,因为名称太长的规则可能非常复杂并且特定于文件系统。例如,参见 EXT4 中的 this code。
来自男主开启:
int open(const char *pathname, int flags);
...
ENAMETOOLONG
pathname was too long.
open
会被设置为 errno
到 ENAMETOOLONG
,但是我在 glibc 的源代码中找不到这个赋值(也许它会调用内核函数,但我也找不到)
以下是我已经在 glibc 中探索过的函数:
/* Open FILE with access OFLAG. If O_CREAT or O_TMPFILE is in OFLAG,
a third argument is the file protection. */
int
__libc_open (const char *file, int oflag)
{
int mode;
if (file == NULL)
{
__set_errno (EINVAL);
return -1;
}
if (__OPEN_NEEDS_MODE (oflag))
{
va_list arg;
va_start(arg, oflag);
mode = va_arg(arg, int);
va_end(arg);
}
__set_errno (ENOSYS);
return -1;
}
int
__open_nocancel (const char *file, int oflag, ...)
{
int mode = 0;
if (__OPEN_NEEDS_MODE (oflag))
{
va_list arg;
va_start (arg, oflag);
mode = va_arg (arg, int);
va_end (arg);
}
return INLINE_SYSCALL_CALL (openat, AT_FDCWD, file, oflag, mode);
}
/* Open FILE with access OFLAG. Interpret relative paths relative to
the directory associated with FD. If O_CREAT or O_TMPFILE is in OFLAG, a
third argument is the file protection. */
int
__openat (int fd, const char *file, int oflag, ...)
{
int mode;
if (file == NULL)
{
__set_errno (EINVAL);
return -1;
}
if (fd != AT_FDCWD && file[0] != '/')
{
/* Check FD is associated with a directory. */
struct stat64 st;
if (__fxstat64 (_STAT_VER, fd, &st) != 0)
return -1;
if (!S_ISDIR (st.st_mode))
{
__set_errno (ENOTDIR);
return -1;
}
}
if (__OPEN_NEEDS_MODE (oflag))
{
va_list arg;
va_start (arg, oflag);
mode = va_arg (arg, int);
va_end (arg);
ignore_value (mode);
}
__set_errno (ENOSYS);
return -1;
}
/* Issue a syscall defined by syscall number plus any other argument
required. Any error will be handled using arch defined macros and errno
will be set accordingly.
It is similar to INLINE_SYSCALL macro, but without the need to pass the
expected argument number as second parameter. */
#define INLINE_SYSCALL_CALL(...) \
__INLINE_SYSCALL_DISP (__INLINE_SYSCALL, __VA_ARGS__)
#define SYSCALL_CANCEL(...) \
({ \
long int sc_ret; \
if (SINGLE_THREAD_P) \
sc_ret = INLINE_SYSCALL_CALL (__VA_ARGS__); \
else \
{ \
int sc_cancel_oldtype = LIBC_CANCEL_ASYNC (); \
sc_ret = INLINE_SYSCALL_CALL (__VA_ARGS__); \
LIBC_CANCEL_RESET (sc_cancel_oldtype); \
} \
sc_ret; \
})
它由文件系统处理,因为名称太长的规则可能非常复杂并且特定于文件系统。例如,参见 EXT4 中的 this code。