/* Send COUNT bytes from file associated with IN_FD starting at OFFSET to descriptor OUT_FD. */ ssize_t sendfile64 (int out_fd, int in_fd, off64_t *offset, size_t count) { __set_errno (ENOSYS); return -1; }
long double __nextafterl(long double x, long double y) { int32_t ix,iy,esx,esy; u_int32_t hx,hy,lx,ly; GET_LDOUBLE_WORDS(esx,hx,lx,x); GET_LDOUBLE_WORDS(esy,hy,ly,y); ix = esx&0x7fff; /* |x| */ iy = esy&0x7fff; /* |y| */ if(((ix==0x7fff)&&((hx&0x7fffffff)|lx)!=0) || /* x is nan */ ((iy==0x7fff)&&((hy&0x7fffffff)|ly)!=0)) /* y is nan */ return x+y; if(x==y) return y; /* x=y, return y */ if((ix|hx|lx)==0) { /* x == 0 */ SET_LDOUBLE_WORDS(x,esy&0x8000,0,1);/* return +-minsubnormal */ y = x*x; math_force_eval (y); /* raise underflow flag */ return x; } if(esx>=0) { /* x > 0 */ if(esx>esy||((esx==esy) && (hx>hy||((hx==hy)&&(lx>ly))))) { /* x > y, x -= ulp */ if(lx==0) { if (ix != 0 && hx == 0x80000000) hx = 0; if (hx==0) esx -= 1; hx -= 1; } lx -= 1; } else { /* x < y, x += ulp */ lx += 1; if(lx==0) { hx += 1; if (hx==0) { hx = 0x80000000; esx += 1; } } } } else { /* x < 0 */ if(esy>=0||esx>esy||((esx==esy) && (hx>hy||((hx==hy)&&(lx>ly))))){ /* x < y, x -= ulp */ if(lx==0) { if (ix != 0 && hx == 0x80000000) hx = 0; if (hx==0) esx -= 1; hx -= 1; } lx -= 1; } else { /* x > y, x += ulp */ lx += 1; if(lx==0) { hx += 1; if (hx==0) { hx = 0x80000000; esx += 1; } } } } esy = esx&0x7fff; if(esy==0x7fff) { long double u = x + x; /* overflow */ math_force_eval (u); __set_errno (ERANGE); } if(esy==0 && (hx & 0x80000000) == 0) { /* underflow */ y = x*x; math_force_eval (y); /* raise underflow flag */ __set_errno (ERANGE); } SET_LDOUBLE_WORDS(x,esx,hx,lx); return x; }
char * chroot_canon (const char *chroot, const char *name) { char *rpath; char *dest; char *extra_buf = NULL; char *rpath_root; const char *start; const char *end; const char *rpath_limit; int num_links = 0; size_t chroot_len = strlen (chroot); if (chroot_len < 1) { __set_errno (EINVAL); return NULL; } rpath = malloc (chroot_len + PATH_MAX); if (rpath == NULL) return NULL; rpath_limit = rpath + chroot_len + PATH_MAX; rpath_root = (char *) mempcpy (rpath, chroot, chroot_len) - 1; if (*rpath_root != '/') *++rpath_root = '/'; dest = rpath_root + 1; for (start = end = name; *start; start = end) { struct stat64 st; int n; /* Skip sequence of multiple path-separators. */ while (*start == '/') ++start; /* Find end of path component. */ for (end = start; *end && *end != '/'; ++end) /* Nothing. */; if (end - start == 0) break; else if (end - start == 1 && start[0] == '.') /* nothing */; else if (end - start == 2 && start[0] == '.' && start[1] == '.') { /* Back up to previous component, ignore if at root already. */ if (dest > rpath_root + 1) while ((--dest)[-1] != '/'); } else { size_t new_size; if (dest[-1] != '/') *dest++ = '/'; if (dest + (end - start) >= rpath_limit) { ptrdiff_t dest_offset = dest - rpath; char *new_rpath; new_size = rpath_limit - rpath; if (end - start + 1 > PATH_MAX) new_size += end - start + 1; else new_size += PATH_MAX; new_rpath = (char *) realloc (rpath, new_size); if (new_rpath == NULL) goto error; rpath = new_rpath; rpath_limit = rpath + new_size; dest = rpath + dest_offset; } dest = mempcpy (dest, start, end - start); *dest = '\0'; if (lstat64 (rpath, &st) < 0) { if (*end == '\0') goto done; goto error; } if (S_ISLNK (st.st_mode)) { char *buf = alloca (PATH_MAX); size_t len; if (++num_links > MAXSYMLINKS) { __set_errno (ELOOP); goto error; } n = readlink (rpath, buf, PATH_MAX); if (n < 0) { if (*end == '\0') goto done; goto error; } buf[n] = '\0'; if (!extra_buf) extra_buf = alloca (PATH_MAX); len = strlen (end); if ((long int) (n + len) >= PATH_MAX) { __set_errno (ENAMETOOLONG); goto error; } /* Careful here, end may be a pointer into extra_buf... */ memmove (&extra_buf[n], end, len + 1); name = end = memcpy (extra_buf, buf, n); if (buf[0] == '/') dest = rpath_root + 1; /* It's an absolute symlink */ else /* Back up to previous component, ignore if at root already: */ if (dest > rpath_root + 1) while ((--dest)[-1] != '/'); } } } done: if (dest > rpath_root + 1 && dest[-1] == '/') --dest; *dest = '\0'; return rpath; error: free (rpath); return NULL; }
int __munmap (__ptr_t addr, size_t len) { __set_errno (ENOSYS); return -1; }
/* Perform the I/O control operation specified by REQUEST on FD. The actual type and use of ARG and the return value depend on REQUEST. */ int __ioctl (int fd, unsigned long int request, ...) { __set_errno (ENOSYS); return -1; }
int setcontext (const ucontext_t *ucp) { __set_errno (ENOSYS); return -1; }
INT INTERNAL (strtol) (const STRING_TYPE *nptr, STRING_TYPE **endptr, int base, int group LOCALE_PARAM_PROTO) { int negative; register unsigned LONG int cutoff; register unsigned int cutlim; register unsigned LONG int i; register const STRING_TYPE *s; register UCHAR_TYPE c; const STRING_TYPE *save, *end; int overflow; #ifdef USE_NUMBER_GROUPING # ifdef USE_IN_EXTENDED_LOCALE_MODEL struct locale_data *current = loc->__locales[LC_NUMERIC]; # endif /* The thousands character of the current locale. */ wchar_t thousands = L'\0'; /* The numeric grouping specification of the current locale, in the format described in <locale.h>. */ const char *grouping; if (group) { grouping = _NL_CURRENT (LC_NUMERIC, GROUPING); if (*grouping <= 0 || *grouping == CHAR_MAX) grouping = NULL; else { /* Figure out the thousands separator character. */ # if defined _LIBC || defined _HAVE_BTOWC thousands = __btowc (*_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP)); if (thousands == WEOF) thousands = L'\0'; # endif if (thousands == L'\0') grouping = NULL; } } else grouping = NULL; #endif if (base < 0 || base == 1 || base > 36) { __set_errno (EINVAL); return 0; } save = s = nptr; /* Skip white space. */ while (ISSPACE (*s)) ++s; if (*s == L_('\0')) goto noconv; /* Check for a sign. */ if (*s == L_('-')) { negative = 1; ++s; } else if (*s == L_('+')) { negative = 0; ++s; } else negative = 0; /* Recognize number prefix and if BASE is zero, figure it out ourselves. */ if (*s == L_('0')) { if ((base == 0 || base == 16) && TOUPPER (s[1]) == L_('X')) { s += 2; base = 16; } else if (base == 0) base = 8; } else if (base == 0) base = 10; /* Save the pointer so we can check later if anything happened. */ save = s; #ifdef USE_NUMBER_GROUPING if (group) { /* Find the end of the digit string and check its grouping. */ end = s; for (c = *end; c != L_('\0'); c = *++end) if ((wchar_t) c != thousands && ((wchar_t) c < L_('0') || (wchar_t) c > L_('9')) && (!ISALPHA (c) || (int) (TOUPPER (c) - L_('A') + 10) >= base)) break; if (*s == thousands) end = s; else end = correctly_grouped_prefix (s, end, thousands, grouping); } else #endif end = NULL; cutoff = STRTOL_ULONG_MAX / (unsigned LONG int) base; cutlim = STRTOL_ULONG_MAX % (unsigned LONG int) base; overflow = 0; i = 0; for (c = *s; c != L_('\0'); c = *++s) { if (s == end) break; if (c >= L_('0') && c <= L_('9')) c -= L_('0'); else if (ISALPHA (c)) c = TOUPPER (c) - L_('A') + 10; else break; if ((int) c >= base) break; /* Check for overflow. */ if (i > cutoff || (i == cutoff && c > cutlim)) overflow = 1; else { i *= (unsigned LONG int) base; i += c; } } /* Check if anything actually happened. */ if (s == save) goto noconv; /* Store in ENDPTR the address of one character past the last character we converted. */ if (endptr != NULL) *endptr = (STRING_TYPE *) s; #if !UNSIGNED /* Check for a value that is within the range of `unsigned LONG int', but outside the range of `LONG int'. */ if (overflow == 0 && i > (negative ? -((unsigned LONG int) (STRTOL_LONG_MIN + 1)) + 1 : (unsigned LONG int) STRTOL_LONG_MAX)) overflow = 1; #endif if (overflow) { __set_errno (ERANGE); #if UNSIGNED return STRTOL_ULONG_MAX; #else return negative ? STRTOL_LONG_MIN : STRTOL_LONG_MAX; #endif } /* Return the result of the appropriate sign. */ return negative ? -i : i; noconv: /* We must handle a special case here: the base is 0 or 16 and the first two characters are '0' and 'x', but the rest are no hexadecimal digits. This is no error case. We return 0 and ENDPTR points to the `x`. */ if (endptr != NULL) { if (save - nptr >= 2 && TOUPPER (save[-1]) == L_('X') && save[-2] == L_('0')) *endptr = (STRING_TYPE *) &save[-1]; else /* There was no number to convert. */ *endptr = (STRING_TYPE *) nptr; } return 0L; }
int getloadavg (double loadavg[], int nelem) { __set_errno (ENOSYS); return -1; }
FTS * fts_open (char * const *argv, register int options, int (*compar) (FTSENT const **, FTSENT const **)) { register FTS *sp; register FTSENT *p, *root; register size_t nitems; FTSENT *parent = NULL; FTSENT *tmp = NULL; /* pacify gcc */ size_t len; bool defer_stat; /* Options check. */ if (options & ~FTS_OPTIONMASK) { __set_errno (EINVAL); return (NULL); } if ((options & FTS_NOCHDIR) && (options & FTS_CWDFD)) { __set_errno (EINVAL); return (NULL); } if ( ! (options & (FTS_LOGICAL | FTS_PHYSICAL))) { __set_errno (EINVAL); return (NULL); } /* Allocate/initialize the stream */ if ((sp = malloc(sizeof(FTS))) == NULL) return (NULL); memset(sp, 0, sizeof(FTS)); sp->fts_compar = compar; sp->fts_options = options; /* Logical walks turn on NOCHDIR; symbolic links are too hard. */ if (ISSET(FTS_LOGICAL)) { SET(FTS_NOCHDIR); CLR(FTS_CWDFD); } /* Initialize fts_cwd_fd. */ sp->fts_cwd_fd = AT_FDCWD; if ( ISSET(FTS_CWDFD) && ! HAVE_OPENAT_SUPPORT) { /* While it isn't technically necessary to open "." this early, doing it here saves us the trouble of ensuring later (where it'd be messier) that "." can in fact be opened. If not, revert to FTS_NOCHDIR mode. */ int fd = open (".", O_RDONLY); if (fd < 0) { /* Even if `.' is unreadable, don't revert to FTS_NOCHDIR mode on systems like Linux+PROC_FS, where our openat emulation is good enough. Note: on a system that emulates openat via /proc, this technique can still fail, but only in extreme conditions, e.g., when the working directory cannot be saved (i.e. save_cwd fails) -- and that happens on Linux only when "." is unreadable and the CWD would be longer than PATH_MAX. FIXME: once Linux kernel openat support is well established, replace the above open call and this entire if/else block with the body of the if-block below. */ if ( openat_needs_fchdir ()) { SET(FTS_NOCHDIR); CLR(FTS_CWDFD); } } else { close (fd); } } /* * Start out with 1K of file name space, and enough, in any case, * to hold the user's file names. */ #ifndef MAXPATHLEN # define MAXPATHLEN 1024 #endif { size_t maxarglen = fts_maxarglen(argv); if (! fts_palloc(sp, MAX(maxarglen, MAXPATHLEN))) goto mem1; } /* Allocate/initialize root's parent. */ if (*argv != NULL) { if ((parent = fts_alloc(sp, "", 0)) == NULL) goto mem2; parent->fts_level = FTS_ROOTPARENTLEVEL; } /* The classic fts implementation would call fts_stat with a new entry for each iteration of the loop below. If the comparison function is not specified or if the FTS_DEFER_STAT option is in effect, don't stat any entry in this loop. This is an attempt to minimize the interval between the initial stat/lstat/fstatat and the point at which a directory argument is first opened. This matters for any directory command line argument that resides on a file system without genuine i-nodes. If you specify FTS_DEFER_STAT along with a comparison function, that function must not access any data via the fts_statp pointer. */ defer_stat = (compar == NULL || ISSET(FTS_DEFER_STAT)); /* Allocate/initialize root(s). */ for (root = NULL, nitems = 0; *argv != NULL; ++argv, ++nitems) { /* Don't allow zero-length file names. */ if ((len = strlen(*argv)) == 0) { __set_errno (ENOENT); goto mem3; } if ((p = fts_alloc(sp, *argv, len)) == NULL) goto mem3; p->fts_level = FTS_ROOTLEVEL; p->fts_parent = parent; p->fts_accpath = p->fts_name; /* Even when defer_stat is true, be sure to stat the first command line argument, since fts_read (at least with FTS_XDEV) requires that. */ if (defer_stat && root != NULL) { p->fts_info = FTS_NSOK; fts_set_stat_required(p, true); } else { p->fts_info = fts_stat(sp, p, false); } /* * If comparison routine supplied, traverse in sorted * order; otherwise traverse in the order specified. */ if (compar) { p->fts_link = root; root = p; } else { p->fts_link = NULL; if (root == NULL) tmp = root = p; else { tmp->fts_link = p; tmp = p; } } } if (compar && nitems > 1) root = fts_sort(sp, root, nitems); /* * Allocate a dummy pointer and make fts_read think that we've just * finished the node before the root(s); set p->fts_info to FTS_INIT * so that everything about the "current" node is ignored. */ if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL) goto mem3; sp->fts_cur->fts_link = root; sp->fts_cur->fts_info = FTS_INIT; if (! setup_dir (sp)) goto mem3; /* * If using chdir(2), grab a file descriptor pointing to dot to ensure * that we can get back here; this could be avoided for some file names, * but almost certainly not worth the effort. Slashes, symbolic links, * and ".." are all fairly nasty problems. Note, if we can't get the * descriptor we run anyway, just more slowly. */ if (!ISSET(FTS_NOCHDIR) && !ISSET(FTS_CWDFD) && (sp->fts_rfd = diropen (sp, ".")) < 0) SET(FTS_NOCHDIR); i_ring_init (&sp->fts_fd_ring, -1); return (sp); mem3: fts_lfree(root); free(parent); mem2: free(sp->fts_path); mem1: free(sp); return (NULL); }
int __sigqueue (pid_t pid, int sig, const union sigval val) { __set_errno (ENOSYS); return -1; }
int __F_NAME(__cenvarg,__wcenvarg)( /* * Build environment and command line for new process. Length of environment * (in bytes) is returned on success. -1 is returned on failure. */ const CHAR_TYPE *const argv[], /* i: arguments for new process */ const CHAR_TYPE *const envp[], /* i: env strings for new process */ CHAR_TYPE **envptr, /* o: allocated memory for env */ CHAR_TYPE **envstrings, /* o: pointer to environment strings */ unsigned *envseg, /* o: start of env (on para boundary) */ size_t *cmdline_len, /* o: size required to hold cmd line */ int exec ) /* i: TRUE if for exec */ { unsigned length; unsigned oamblksiz; CHAR_TYPE *p; CHAR_TYPE _WCNEAR *np; unsigned len; int i; if( envp == NULL ){ #ifdef __WIDECHAR__ if( _RWD_wenviron == NULL ) __create_wide_environment(); #endif envp = (const CHAR_TYPE * const *)__F_NAME(_RWD_environ,_RWD_wenviron); } length = 0; if( envp != NULL ){ for( i = 0; envp[i] != NULL; i++ ) { length += __F_NAME(strlen,wcslen)( envp[i] ) + 1; } } ++length; /* trailing \0 for env */ if( exec ){ /* store argv[0] at 2 bytes past end of env */ length += 2 + __F_NAME(strlen,wcslen)( argv[0] ) + 1; } length += 15; /* so we can start on a paragraph boundary */ oamblksiz = _RWD_amblksiz; _RWD_amblksiz = 16; /* force allocation in 16 byte increments */ p = np = lib_nmalloc( length*sizeof(CHAR_TYPE) ); if( np == NULL ){ /* 03-aug-88 */ p = lib_malloc( length*sizeof(CHAR_TYPE) ); if( p == NULL ){ __set_errno( ENOMEM ); __set_doserrno( E_nomem ); _RWD_amblksiz = oamblksiz; return( -1 ); } } _RWD_amblksiz = oamblksiz; *envptr = p; #if defined( _M_I86 ) && defined( __DOS__ ) #if defined(__SMALL_DATA__) p = (char *) (((unsigned) p + 15) & 0xfff0); #else /* large data models */ /* 12-aug-88 */ p = MK_FP( FP_SEG(p), (( FP_OFF(p) + 15) & 0xfff0) ); #endif { CHAR_TYPE _WCFAR *temp; temp = p; *envseg = FP_SEG( temp ) + FP_OFF( temp )/16; } #else *envseg = 0; #endif *envstrings = p; /* save ptr to env strings. 07-oct-92 */ if( envp != NULL ){ for( i = 0; envp[i] != NULL; ++i ){ p = stpcpy( p, envp[i] ) + 1; } } *p++ = '\0'; if( exec ) { __F_NAME(strcpy,wcscpy)( p + 2, argv[0] ); } len = 0; if( argv[0] != NULL ) { for( i = 1; argv[i] != NULL; ++i ){ if( len != 0 ) ++len; /* plus 1 for blank separator */ len += __F_NAME(strlen,wcslen)( argv[i] ); } } #if defined( __NT__ ) // we are going to add quotes around program name (argv[0]) len += _MAX_PATH2 + 3; #elif defined( __OS2__ ) len += _MAX_PATH2 + 1; #elif defined( __RDOS__ ) len += _MAX_PATH2 + 1; #else if( len > 126 ) { __set_errno( E2BIG ); __set_doserrno( E_badenv ); lib_free( *envptr ); return( -1 ); } len = _MAX_PATH; /* always use _MAX_PATH chars for DOS */ #endif *cmdline_len = len; return( length / 16 ); }
char * __realpath (const char *name, char *resolved) { char *rpath, *dest, *extra_buf = NULL; const char *start, *end, *rpath_limit; long int path_max; int num_links = 0; size_t prefix_len; if (name == NULL) { /* As per Single Unix Specification V2 we must return an error if either parameter is a null pointer. We extend this to allow the RESOLVED parameter to be NULL in case the we are expected to allocate the room for the return value. */ __set_errno (EINVAL); return NULL; } if (name[0] == '\0') { /* As per Single Unix Specification V2 we must return an error if the name argument points to an empty string. */ __set_errno (ENOENT); return NULL; } #ifdef PATH_MAX path_max = PATH_MAX; #else path_max = pathconf (name, _PC_PATH_MAX); if (path_max <= 0) path_max = 8192; #endif if (resolved == NULL) { rpath = malloc (path_max); if (rpath == NULL) { /* It's easier to set errno to ENOMEM than to rely on the 'malloc-posix' gnulib module. */ errno = ENOMEM; return NULL; } } else rpath = resolved; rpath_limit = rpath + path_max; /* This is always zero for Posix hosts, but can be 2 for MS-Windows and MS-DOS X:/foo/bar file names. */ prefix_len = FILE_SYSTEM_PREFIX_LEN (name); if (!IS_ABSOLUTE_FILE_NAME (name)) { if (!__getcwd (rpath, path_max)) { rpath[0] = '\0'; goto error; } dest = strchr (rpath, '\0'); start = name; prefix_len = FILE_SYSTEM_PREFIX_LEN (rpath); } else { dest = rpath; if (prefix_len) { memcpy (rpath, name, prefix_len); dest += prefix_len; } *dest++ = '/'; if (DOUBLE_SLASH_IS_DISTINCT_ROOT) { if (ISSLASH (name[1]) && !ISSLASH (name[2]) && !prefix_len) *dest++ = '/'; *dest = '\0'; } start = name + prefix_len; } for (end = start; *start; start = end) { #ifdef _LIBC struct stat64 st; #else struct stat st; #endif int n; /* Skip sequence of multiple path-separators. */ while (ISSLASH (*start)) ++start; /* Find end of path component. */ for (end = start; *end && !ISSLASH (*end); ++end) /* Nothing. */; if (end - start == 0) break; else if (end - start == 1 && start[0] == '.') /* nothing */; else if (end - start == 2 && start[0] == '.' && start[1] == '.') { /* Back up to previous component, ignore if at root already. */ if (dest > rpath + prefix_len + 1) for (--dest; dest > rpath && !ISSLASH (dest[-1]); --dest) continue; if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1 && !prefix_len && ISSLASH (*dest) && !ISSLASH (dest[1])) dest++; } else { size_t new_size; if (!ISSLASH (dest[-1])) *dest++ = '/'; if (dest + (end - start) >= rpath_limit) { ptrdiff_t dest_offset = dest - rpath; char *new_rpath; if (resolved) { __set_errno (ENAMETOOLONG); if (dest > rpath + prefix_len + 1) dest--; *dest = '\0'; goto error; } new_size = rpath_limit - rpath; if (end - start + 1 > path_max) new_size += end - start + 1; else new_size += path_max; new_rpath = (char *) realloc (rpath, new_size); if (new_rpath == NULL) { /* It's easier to set errno to ENOMEM than to rely on the 'realloc-posix' gnulib module. */ errno = ENOMEM; goto error; } rpath = new_rpath; rpath_limit = rpath + new_size; dest = rpath + dest_offset; } #ifdef _LIBC dest = __mempcpy (dest, start, end - start); #else memcpy (dest, start, end - start); dest += end - start; #endif *dest = '\0'; #ifdef _LIBC if (__lxstat64 (_STAT_VER, rpath, &st) < 0) #else if (lstat (rpath, &st) < 0) #endif goto error; if (S_ISLNK (st.st_mode)) { char *buf; size_t len; if (++num_links > MAXSYMLINKS) { __set_errno (ELOOP); goto error; } buf = malloca (path_max); if (!buf) { errno = ENOMEM; goto error; } n = __readlink (rpath, buf, path_max - 1); if (n < 0) { int saved_errno = errno; freea (buf); errno = saved_errno; goto error; } buf[n] = '\0'; if (!extra_buf) { extra_buf = malloca (path_max); if (!extra_buf) { freea (buf); errno = ENOMEM; goto error; } } len = strlen (end); if ((long int) (n + len) >= path_max) { freea (buf); __set_errno (ENAMETOOLONG); goto error; } /* Careful here, end may be a pointer into extra_buf... */ memmove (&extra_buf[n], end, len + 1); name = end = memcpy (extra_buf, buf, n); if (IS_ABSOLUTE_FILE_NAME (buf)) { size_t pfxlen = FILE_SYSTEM_PREFIX_LEN (buf); if (pfxlen) memcpy (rpath, buf, pfxlen); dest = rpath + pfxlen; *dest++ = '/'; /* It's an absolute symlink */ if (DOUBLE_SLASH_IS_DISTINCT_ROOT) { if (ISSLASH (buf[1]) && !ISSLASH (buf[2]) && !pfxlen) *dest++ = '/'; *dest = '\0'; } /* Install the new prefix to be in effect hereafter. */ prefix_len = pfxlen; } else { /* Back up to previous component, ignore if at root already: */ if (dest > rpath + prefix_len + 1) for (--dest; dest > rpath && !ISSLASH (dest[-1]); --dest) continue; if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1 && ISSLASH (*dest) && !ISSLASH (dest[1]) && !prefix_len) dest++; } } else if (!S_ISDIR (st.st_mode) && *end != '\0') { __set_errno (ENOTDIR); goto error; } } } if (dest > rpath + prefix_len + 1 && ISSLASH (dest[-1])) --dest; if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1 && !prefix_len && ISSLASH (*dest) && !ISSLASH (dest[1])) dest++; *dest = '\0'; if (extra_buf) freea (extra_buf); return rpath; error: { int saved_errno = errno; if (extra_buf) freea (extra_buf); if (resolved == NULL) free (rpath); errno = saved_errno; } return NULL; }
/* Get information about the file NAME relative to FD in ST. */ int __fxstatat (int vers, int fd, const char *file, struct stat *st, int flag) { int result; INTERNAL_SYSCALL_DECL (err); struct stat64 st64; #ifdef __NR_fstatat64 # ifndef __ASSUME_ATFCTS if (__have_atfcts >= 0) # endif { result = INTERNAL_SYSCALL (fstatat64, err, 4, fd, file, &st64, flag); # ifndef __ASSUME_ATFCTS if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 1) && INTERNAL_SYSCALL_ERRNO (result, err) == ENOSYS) __have_atfcts = -1; else # endif if (!__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 1)) return __xstat32_conv (vers, &st64, st); else { __set_errno (INTERNAL_SYSCALL_ERRNO (result, err)); return -1; } } #endif #ifndef __ASSUME_ATFCTS if (__builtin_expect (flag & ~AT_SYMLINK_NOFOLLOW, 0)) { __set_errno (EINVAL); return -1; } char *buf = NULL; if (fd != AT_FDCWD && file[0] != '/') { size_t filelen = strlen (file); if (__builtin_expect (filelen == 0, 0)) { __set_errno (ENOENT); return -1; } static const char procfd[] = "/proc/self/fd/%d/%s"; /* Buffer for the path name we are going to use. It consists of - the string /proc/self/fd/ - the file descriptor number - the file name provided. The final NUL is included in the sizeof. A bit of overhead due to the format elements compensates for possible negative numbers. */ size_t buflen = sizeof (procfd) + sizeof (int) * 3 + filelen; buf = alloca (buflen); __snprintf (buf, buflen, procfd, fd, file); file = buf; } if (vers == _STAT_VER_KERNEL) { if (flag & AT_SYMLINK_NOFOLLOW) result = INTERNAL_SYSCALL (lstat, err, 2, CHECK_STRING (file), CHECK_1 ((struct kernel_stat *) st)); else result = INTERNAL_SYSCALL (stat, err, 2, CHECK_STRING (file), CHECK_1 ((struct kernel_stat *) st)); goto out; } if (flag & AT_SYMLINK_NOFOLLOW) result = INTERNAL_SYSCALL (lstat64, err, 2, CHECK_STRING (file), __ptrvalue (&st64)); else result = INTERNAL_SYSCALL (stat64, err, 2, CHECK_STRING (file), __ptrvalue (&st64)); if (__builtin_expect (!INTERNAL_SYSCALL_ERROR_P (result, err), 1)) return __xstat32_conv (vers, &st64, st); out: if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 0)) { __atfct_seterrno (INTERNAL_SYSCALL_ERRNO (result, err), fd, buf); result = -1; } return result; #endif }
/* This routine is jumped to by all the syscall handlers, to stash an error number into errno. */ int __syscall_error (int dummy, int err) { __set_errno (err); return -1; }
/* Give the socket FD the local address ADDR (which is LEN bytes long). */ int __bind (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len) { __set_errno (ENOSYS); return -1; }
FTSENT * fts_read (register FTS *sp) { register FTSENT *p, *tmp; register unsigned short int instr; register char *t; /* If finished or unrecoverable error, return NULL. */ if (sp->fts_cur == NULL || ISSET(FTS_STOP)) return (NULL); /* Set current node pointer. */ p = sp->fts_cur; /* Save and zero out user instructions. */ instr = p->fts_instr; p->fts_instr = FTS_NOINSTR; /* Any type of file may be re-visited; re-stat and re-turn. */ if (instr == FTS_AGAIN) { p->fts_info = fts_stat(sp, p, false); return (p); } Dprintf (("fts_read: p=%s\n", p->fts_info == FTS_INIT ? "" : p->fts_path)); /* * Following a symlink -- SLNONE test allows application to see * SLNONE and recover. If indirecting through a symlink, have * keep a pointer to current location. If unable to get that * pointer, follow fails. */ if (instr == FTS_FOLLOW && (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) { p->fts_info = fts_stat(sp, p, true); if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) { if ((p->fts_symfd = diropen (sp, ".")) < 0) { p->fts_errno = errno; p->fts_info = FTS_ERR; } else p->fts_flags |= FTS_SYMFOLLOW; } goto check_for_dir; } /* Directory in pre-order. */ if (p->fts_info == FTS_D) { /* If skipped or crossed mount point, do post-order visit. */ if (instr == FTS_SKIP || (ISSET(FTS_XDEV) && p->fts_statp->st_dev != sp->fts_dev)) { if (p->fts_flags & FTS_SYMFOLLOW) (void)close(p->fts_symfd); if (sp->fts_child) { fts_lfree(sp->fts_child); sp->fts_child = NULL; } p->fts_info = FTS_DP; LEAVE_DIR (sp, p, "1"); return (p); } /* Rebuild if only read the names and now traversing. */ if (sp->fts_child != NULL && ISSET(FTS_NAMEONLY)) { CLR(FTS_NAMEONLY); fts_lfree(sp->fts_child); sp->fts_child = NULL; } /* * Cd to the subdirectory. * * If have already read and now fail to chdir, whack the list * to make the names come out right, and set the parent errno * so the application will eventually get an error condition. * Set the FTS_DONTCHDIR flag so that when we logically change * directories back to the parent we don't do a chdir. * * If haven't read do so. If the read fails, fts_build sets * FTS_STOP or the fts_info field of the node. */ if (sp->fts_child != NULL) { if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) { p->fts_errno = errno; p->fts_flags |= FTS_DONTCHDIR; for (p = sp->fts_child; p != NULL; p = p->fts_link) p->fts_accpath = p->fts_parent->fts_accpath; } } else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) { if (ISSET(FTS_STOP)) return (NULL); /* If fts_build's call to fts_safe_changedir failed because it was not able to fchdir into a subdirectory, tell the caller. */ if (p->fts_errno && p->fts_info != FTS_DNR) p->fts_info = FTS_ERR; LEAVE_DIR (sp, p, "2"); return (p); } p = sp->fts_child; sp->fts_child = NULL; goto name; } /* Move to the next node on this level. */ next: tmp = p; if ((p = p->fts_link) != NULL) { sp->fts_cur = p; free(tmp); /* * If reached the top, return to the original directory (or * the root of the tree), and load the file names for the next * root. */ if (p->fts_level == FTS_ROOTLEVEL) { if (RESTORE_INITIAL_CWD(sp)) { SET(FTS_STOP); return (NULL); } fts_load(sp, p); goto check_for_dir; } /* * User may have called fts_set on the node. If skipped, * ignore. If followed, get a file descriptor so we can * get back if necessary. */ if (p->fts_instr == FTS_SKIP) goto next; if (p->fts_instr == FTS_FOLLOW) { p->fts_info = fts_stat(sp, p, true); if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) { if ((p->fts_symfd = diropen (sp, ".")) < 0) { p->fts_errno = errno; p->fts_info = FTS_ERR; } else p->fts_flags |= FTS_SYMFOLLOW; } p->fts_instr = FTS_NOINSTR; } name: t = sp->fts_path + NAPPEND(p->fts_parent); *t++ = '/'; memmove(t, p->fts_name, p->fts_namelen + 1); check_for_dir: sp->fts_cur = p; if (p->fts_info == FTS_NSOK) { if (p->fts_statp->st_size == FTS_STAT_REQUIRED) p->fts_info = fts_stat(sp, p, false); else fts_assert (p->fts_statp->st_size == FTS_NO_STAT_REQUIRED); } if (p->fts_info == FTS_D) { /* Now that P->fts_statp is guaranteed to be valid, if this is a command-line directory, record its device number, to be used for FTS_XDEV. */ if (p->fts_level == FTS_ROOTLEVEL) sp->fts_dev = p->fts_statp->st_dev; Dprintf ((" entering: %s\n", p->fts_path)); if (! enter_dir (sp, p)) { __set_errno (ENOMEM); return NULL; } } return p; } /* Move up to the parent node. */ p = tmp->fts_parent; sp->fts_cur = p; free(tmp); if (p->fts_level == FTS_ROOTPARENTLEVEL) { /* * Done; free everything up and set errno to 0 so the user * can distinguish between error and EOF. */ free(p); __set_errno (0); return (sp->fts_cur = NULL); } fts_assert (p->fts_info != FTS_NSOK); /* NUL terminate the file name. */ sp->fts_path[p->fts_pathlen] = '\0'; /* * Return to the parent directory. If at a root node, restore * the initial working directory. If we came through a symlink, * go back through the file descriptor. Otherwise, move up * one level, via "..". */ if (p->fts_level == FTS_ROOTLEVEL) { if (RESTORE_INITIAL_CWD(sp)) { p->fts_errno = errno; SET(FTS_STOP); } } else if (p->fts_flags & FTS_SYMFOLLOW) { if (FCHDIR(sp, p->fts_symfd)) { int saved_errno = errno; (void)close(p->fts_symfd); __set_errno (saved_errno); p->fts_errno = errno; SET(FTS_STOP); } (void)close(p->fts_symfd); } else if (!(p->fts_flags & FTS_DONTCHDIR) && fts_safe_changedir(sp, p->fts_parent, -1, "..")) { p->fts_errno = errno; SET(FTS_STOP); } p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP; if (p->fts_errno == 0) LEAVE_DIR (sp, p, "3"); return ISSET(FTS_STOP) ? NULL : p; }
/* Write LENGTH bytes of randomness starting at BUFFER. Return the number of bytes written, or -1 on error. */ ssize_t getrandom (void *buffer, size_t length, unsigned int flags) { __set_errno (ENOSYS); return -1; }
/* Duplicate FD, returning a new file descriptor open on the same file. */ int __dup (int fd) { __set_errno (ENOSYS); return -1; }
int __fgetpwent_r (FILE* stream, struct passwd* result_buf, char* buffer, size_t buflen, struct passwd** result) { char* write_crs = buffer; size_t bytes_used = 0; char** fields[10]; int numerical_error = 0; enum parse_state { init = 0, name = 1, password = 2, age = 3, uid = 4, gid = 5, gecos = 6, home = 7, shell = 8, finished = 9 } state; if (stream == NULL || result == NULL || result_buf == NULL) { __set_errno (EFAULT); return -1; } else if (buffer == NULL) buflen = 0; fields[0] = NULL; fields[1] = &result_buf->pw_name; fields[2] = &result_buf->pw_passwd; fields[3] = &result_buf->pw_age; fields[4] = NULL; fields[5] = NULL; fields[6] = &result_buf->pw_gecos; fields[7] = &result_buf->pw_dir; fields[8] = &result_buf->pw_shell; fields[9] = NULL; *result = NULL; /* Now parse the passwd file. The technique looks awkwared but I don't see anything better. We read characters one by one from the passwd file keeping track of the current parse state. If we are in a state that reads a string then we copy the currently read byte into the user-supplied buffer. For numerical fields we re-calculate the current value. Thus we optimize the usage of the buffer and we stay re-entrant. */ state = init; memset (result_buf, 0, sizeof *result_buf); result_buf->pw_name = result_buf->pw_passwd = result_buf->pw_age = result_buf->pw_gecos = result_buf->pw_comment = result_buf->pw_dir = result_buf->pw_shell = space; while (state != finished) { int the_char = my_getc (stream); if (state == init) { if (the_char == ' ' || the_char == '\t' || the_char == '\r' || the_char == '\n') continue; else if (the_char == '#') { /* A comment, eat up the rest of the line. */ while (1) { the_char = my_getc (stream); if (the_char == '\n') break; else if (the_char == EOF) { *result = NULL; return -1; } } continue; } else if (the_char == EOF) { *result = NULL; return -1; } else { state++; ungetc (the_char, stream); *fields[state] = write_crs; continue; } } if (the_char == ':') { if (fields[state] != NULL && *fields[state] != NULL) { *write_crs++ = '\0'; bytes_used++; } ++state; if (state == age) /* No password aging found. */ ++state; if (bytes_used < buflen && fields[state] != NULL) *fields[state] = write_crs; numerical_error = 0; continue; } else if (the_char == '\n' || the_char == EOF) { /* Hm, what about crippled entries? Let the program handle this. */ if (state > init) { if (bytes_used < buflen && fields[state] != NULL && *fields[state] != NULL) { *write_crs++ = '\0'; bytes_used++; } else if (fields[state] != NULL) *fields[state] = NULL; /* Invalidates last read entry. */ state = finished; } else if (the_char == EOF) { *result = NULL; return -1; } continue; } if (bytes_used < buflen && fields[state] != NULL && *fields[state] != NULL) { *write_crs++ = the_char; bytes_used++; } switch (state) { case uid: if (the_char < '0' || the_char > '9') numerical_error = 1; /* Should we return an error instead? */ else if (!numerical_error) { result_buf->pw_uid *= 10; result_buf->pw_uid += the_char - '0'; } break; case gid: if (the_char < '0' || the_char > '9') numerical_error = 1; /* Should we return an error instead? */ else if (!numerical_error) { result_buf->pw_gid *= 10; result_buf->pw_gid += the_char - '0'; } break; case password: if (the_char == ',') { /* Age count found. */ if (bytes_used <= buflen && fields[state] != NULL && *fields[state] != NULL) { /* The comma has already been written. */ write_crs[-1] = '\0'; } ++state; if (bytes_used < buflen && fields[state] != NULL) *fields[state] = write_crs; } break; default: break; } } result_buf->pw_comment = result_buf->pw_gecos; *result = result_buf; return 0; }
/* Remove shared memory object. */ int shm_unlink (const char *name) { __set_errno (ENOSYS); return -1; }
int __old_ustat (dev_t dev, struct ustat *ust) { __set_errno (ENOSYS); return -1; }
int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval, struct hsearch_data *htab, int flag) { unsigned int hval; unsigned int count; unsigned int len = strlen(item.key); unsigned int idx; unsigned int first_deleted = 0; int ret; /* Compute an value for the given string. Perhaps use a better method. */ hval = len; count = len; while (count-- > 0) { hval <<= 4; hval += item.key[count]; } /* * First hash function: * simply take the modul but prevent zero. */ hval %= htab->size; if (hval == 0) ++hval; /* The first index tried. */ idx = hval; if (htab->table[idx].used) { /* * Further action might be required according to the * action value. */ unsigned hval2; if (htab->table[idx].used == -1 && !first_deleted) first_deleted = idx; ret = _compare_and_overwrite_entry(item, action, retval, htab, flag, hval, idx); if (ret != -1) return ret; /* * Second hash function: * as suggested in [Knuth] */ hval2 = 1 + hval % (htab->size - 2); do { /* * Because SIZE is prime this guarantees to * step through all available indices. */ if (idx <= hval2) idx = htab->size + idx - hval2; else idx -= hval2; /* * If we visited all entries leave the loop * unsuccessfully. */ if (idx == hval) break; /* If entry is found use it. */ ret = _compare_and_overwrite_entry(item, action, retval, htab, flag, hval, idx); if (ret != -1) return ret; } while (htab->table[idx].used); } /* An empty bucket has been found. */ if (action == ENTER) { /* * If table is full and another entry should be * entered return with error. */ if (htab->filled == htab->size) { __set_errno(ENOMEM); *retval = NULL; return 0; } /* * Create new entry; * create copies of item.key and item.data */ if (first_deleted) idx = first_deleted; htab->table[idx].used = hval; htab->table[idx].entry.key = strdup(item.key); htab->table[idx].entry.data = strdup(item.data); if (!htab->table[idx].entry.key || !htab->table[idx].entry.data) { __set_errno(ENOMEM); *retval = NULL; return 0; } ++htab->filled; /* This is a new entry, so look up a possible callback */ env_callback_init(&htab->table[idx].entry); /* Also look for flags */ env_flags_init(&htab->table[idx].entry); /* check for permission */ if (htab->change_ok != NULL && htab->change_ok( &htab->table[idx].entry, item.data, env_op_create, flag)) { debug("change_ok() rejected setting variable " "%s, skipping it!\n", item.key); _hdelete(item.key, htab, &htab->table[idx].entry, idx); __set_errno(EPERM); *retval = NULL; return 0; } /* If there is a callback, call it */ if (htab->table[idx].entry.callback && htab->table[idx].entry.callback(item.key, item.data, env_op_create, flag)) { debug("callback() rejected setting variable " "%s, skipping it!\n", item.key); _hdelete(item.key, htab, &htab->table[idx].entry, idx); __set_errno(EINVAL); *retval = NULL; return 0; } /* return new entry */ *retval = &htab->table[idx].entry; return 1; } __set_errno(ESRCH); *retval = NULL; return 0; }
/* Get the real user ID of the calling process. */ uid_t __getuid (void) { __set_errno (ENOSYS); return -1; }
int himport_r(struct hsearch_data *htab, const char *env, size_t size, const char sep, int flag, int nvars, char *const vars[]) { char *data, *sp, *dp, *name, *value; char *localvars[nvars]; int i; /* Test for correct arguments. */ if (htab == NULL) { __set_errno(EINVAL); return 0; } /* We allocate new space to make sure we can write to the array */ if ((data = malloc(size)) == NULL) { debug("himport_r: can't malloc %zu bytes\n", size); __set_errno(ENOMEM); return 0; } memcpy(data, env, size); dp = data; /* make a local copy of the list of variables */ if (nvars) memcpy(localvars, vars, sizeof(vars[0]) * nvars); if ((flag & H_NOCLEAR) == 0) { /* Destroy old hash table if one exists */ debug("Destroy Hash Table: %p table = %p\n", htab, htab->table); if (htab->table) hdestroy_r(htab); } /* * Create new hash table (if needed). The computation of the hash * table size is based on heuristics: in a sample of some 70+ * existing systems we found an average size of 39+ bytes per entry * in the environment (for the whole key=value pair). Assuming a * size of 8 per entry (= safety factor of ~5) should provide enough * safety margin for any existing environment definitions and still * allow for more than enough dynamic additions. Note that the * "size" argument is supposed to give the maximum enviroment size * (CONFIG_ENV_SIZE). This heuristics will result in * unreasonably large numbers (and thus memory footprint) for * big flash environments (>8,000 entries for 64 KB * envrionment size), so we clip it to a reasonable value. * On the other hand we need to add some more entries for free * space when importing very small buffers. Both boundaries can * be overwritten in the board config file if needed. */ if (!htab->table) { int nent = CONFIG_ENV_MIN_ENTRIES + size / 8; if (nent > CONFIG_ENV_MAX_ENTRIES) nent = CONFIG_ENV_MAX_ENTRIES; debug("Create Hash Table: N=%d\n", nent); if (hcreate_r(nent, htab) == 0) { free(data); return 0; } } /* Parse environment; allow for '\0' and 'sep' as separators */ do { ENTRY e, *rv; /* skip leading white space */ while (isblank(*dp)) ++dp; /* skip comment lines */ if (*dp == '#') { while (*dp && (*dp != sep)) ++dp; ++dp; continue; } /* parse name */ for (name = dp; (*dp != '=') && (*dp) && (*dp != sep); ++dp) ; /* deal with "name" and "name=" entries (delete var) */ if (*dp == '\0' || *(dp + 1) == '\0' || *dp == sep || *(dp + 1) == sep) { if (*dp == '=') *dp++ = '\0'; *dp++ = '\0'; debug("DELETE CANDIDATE: \"%s\"\n", name); if (!drop_var_from_set(name, nvars, localvars)) continue; if (hdelete_r(name, htab, flag) == 0) debug("DELETE ERROR ####################\n"); continue; } *dp++ = '\0'; /* terminate name */ /* parse value; deal with escapes */ for (value = sp = dp; (*dp) && (*dp != sep); ++dp ) { if ((*dp == '\\') && *(dp +1)) ++dp; *sp++ = *dp; } *sp++ = '\0'; /* terminate value */ ++dp; if (*name == 0) { debug("INSERT: unable to use an empty key\n"); __set_errno(EINVAL); return 0; } /* Skip variables which are not supposed to be processed */ if (!drop_var_from_set(name, nvars, localvars)) continue; /* enter into hash table */ e.key = name; e.data = value; hsearch_r(e, ENTER, &rv, htab, flag); if (rv == NULL) printf("himport_r: can't insert \"%s=%s\" " "into hash table\n", name, value); debug("INSERT: table %p, filled %d/%d rv %p ==> " "name=\"%s\" value=\"%s\"\n", htab, htab->filled, htab->size, rv, name, value); } while((dp < data + size) && *dp); debug("INSERT: free(data = %p)\n", data); free(data); /* process variables which were not considered */ for (i = 0; i < nvars; i++) { if (localvars[i] == NULL) continue; /* * All variables which were not deleted from the variable list * were not present in the imported env * This could mean two things: * a) if the variable was present in current env, we delete it * b) if the variable was not present in current env, we notify * it might be a typo */ if (hdelete_r(localvars[i], htab, flag) == 0) printf("WARNING: '%s' neither in running nor " "in imported env!\n", localvars[i]); else printf("WARNING: '%s' not in imported env, " "deleting it!\n", localvars[i]); } debug("INSERT: done\n"); return 1; /* everything OK */ }
/* We are going to use the `nanosleep' syscall of the kernel. But the kernel does not implement the sstupid SysV SIGCHLD vs. SIG_IGN behaviour for this syscall. Therefore we have to emulate it here. */ unsigned int sleep (unsigned int seconds) { struct timespec ts = { tv_sec: (long int) seconds, tv_nsec: 0 }; sigset_t set, oset; unsigned int result; /* This is not necessary but some buggy programs depend on this. */ if (seconds == 0) return 0; /* Linux will wake up the system call, nanosleep, when SIGCHLD arrives even if SIGCHLD is ignored. We have to deal with it in libc. We block SIGCHLD first. */ if (__sigemptyset (&set) < 0 || __sigaddset (&set, SIGCHLD) < 0 || sigprocmask (SIG_BLOCK, &set, &oset)) return -1; /* If SIGCHLD is already blocked, we don't have to do anything. */ if (!__sigismember (&oset, SIGCHLD)) { int saved_errno; struct sigaction oact; if (__sigemptyset (&set) < 0 || __sigaddset (&set, SIGCHLD) < 0) return -1; /* We get the signal handler for SIGCHLD. */ if (sigaction (SIGCHLD, (struct sigaction *) NULL, &oact) < 0) { saved_errno = errno; /* Restore the original signal mask. */ (void) sigprocmask (SIG_SETMASK, &oset, (sigset_t *) NULL); __set_errno (saved_errno); return -1; } if (oact.sa_handler == SIG_IGN) { /* We should leave SIGCHLD blocked. */ result = nanosleep (&ts, &ts); saved_errno = errno; /* Restore the original signal mask. */ (void) sigprocmask (SIG_SETMASK, &oset, (sigset_t *) NULL); __set_errno (saved_errno); } else { /* We should unblock SIGCHLD. Restore the original signal mask. */ (void) sigprocmask (SIG_SETMASK, &oset, (sigset_t *) NULL); result = nanosleep (&ts, &ts); } } else result = nanosleep (&ts, &ts); if (result != 0) /* Round remaining time. */ result = (unsigned int) ts.tv_sec + (ts.tv_nsec >= 500000000L); return result; }
int __new_shmctl (int shmid, int cmd, struct shmid_ds *buf) { #if __ASSUME_32BITUIDS > 0 return INLINE_SYSCALL (shmctl, 3, shmid, cmd | __IPC_64, CHECK_1 (buf)); #else switch (cmd) { case SHM_STAT: case IPC_STAT: case IPC_SET: case IPC_INFO: break; default: return INLINE_SYSCALL (shmctl, 3, shmid, cmd, CHECK_1 (buf)); } { int save_errno = errno, result; struct __old_shmid_ds old; /* Unfortunately there is no way how to find out for sure whether we should use old or new shmctl. */ result = INLINE_SYSCALL (shmctl, 3, shmid, cmd | __IPC_64, CHECK_1 (buf)); if (result != -1 || errno != EINVAL) return result; __set_errno(save_errno); if (cmd == IPC_SET) { old.shm_perm.uid = buf->shm_perm.uid; old.shm_perm.gid = buf->shm_perm.gid; old.shm_perm.mode = buf->shm_perm.mode; if (old.shm_perm.uid != buf->shm_perm.uid || old.shm_perm.gid != buf->shm_perm.gid) { __set_errno (EINVAL); return -1; } } result = INLINE_SYSCALL (shmctl, 3, shmid, cmd, __ptrvalue (&old)); if (result != -1 && (cmd == SHM_STAT || cmd == IPC_STAT)) { memset(buf, 0, sizeof(*buf)); buf->shm_perm.__key = old.shm_perm.__key; buf->shm_perm.uid = old.shm_perm.uid; buf->shm_perm.gid = old.shm_perm.gid; buf->shm_perm.cuid = old.shm_perm.cuid; buf->shm_perm.cgid = old.shm_perm.cgid; buf->shm_perm.mode = old.shm_perm.mode; buf->shm_perm.__seq = old.shm_perm.__seq; buf->shm_atime = old.shm_atime; buf->shm_dtime = old.shm_dtime; buf->shm_ctime = old.shm_ctime; buf->shm_segsz = old.shm_segsz; buf->shm_nattch = old.shm_nattch; buf->shm_cpid = old.shm_cpid; buf->shm_lpid = old.shm_lpid; } else if (result != -1 && cmd == IPC_INFO) { struct __old_shminfo *oldi = (void *)&old; struct shminfo *i = (struct shminfo *)buf; memset(i, 0, sizeof(*i)); i->shmmax = oldi->shmmax; i->shmmin = oldi->shmmin; i->shmmni = oldi->shmmni; i->shmseg = oldi->shmseg; i->shmall = oldi->shmall; } return result; } #endif }
/* Generate a temporary file name based on TMPL. TMPL must match the rules for mk[s]temp (i.e. end in "XXXXXX"). The name constructed does not exist at the time of the call to __gen_tempname. TMPL is overwritten with the result. KIND may be one of: __GT_NOCREATE: simply verify that the name does not exist at the time of the call. __GT_FILE: create the file using open(O_CREAT|O_EXCL) and return a read-write fd. The file is mode 0600. __GT_DIR: create a directory, which will be mode 0700. We use a clever algorithm to get hard-to-predict names. */ int __gen_tempname (char *tmpl, int flags, int kind) { int len; char *XXXXXX; static uint64_t value; uint64_t random_time_bits; unsigned int count; int fd = -1; int save_errno = errno; struct_stat64 st; /* A lower bound on the number of temporary files to attempt to generate. The maximum total number of temporary file names that can exist for a given template is 62**6. It should never be necessary to try all these combinations. Instead if a reasonable number of names is tried (we define reasonable as 62**3) fail to give the system administrator the chance to remove the problems. */ #define ATTEMPTS_MIN (62 * 62 * 62) /* The number of times to attempt to generate a temporary file. To conform to POSIX, this must be no smaller than TMP_MAX. */ #if ATTEMPTS_MIN < TMP_MAX unsigned int attempts = TMP_MAX; #else unsigned int attempts = ATTEMPTS_MIN; #endif len = strlen (tmpl); if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX")) { __set_errno (EINVAL); return -1; } /* This is where the Xs start. */ XXXXXX = &tmpl[len - 6]; /* Get some more or less random data. */ #ifdef RANDOM_BITS RANDOM_BITS (random_time_bits); #else # if HAVE_GETTIMEOFDAY || _LIBC { struct timeval tv; __gettimeofday (&tv, NULL); random_time_bits = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; } # else random_time_bits = time (NULL); # endif #endif value += random_time_bits ^ __getpid (); for (count = 0; count < attempts; value += 7777, ++count) { uint64_t v = value; /* Fill in the random bits. */ XXXXXX[0] = letters[v % 62]; v /= 62; XXXXXX[1] = letters[v % 62]; v /= 62; XXXXXX[2] = letters[v % 62]; v /= 62; XXXXXX[3] = letters[v % 62]; v /= 62; XXXXXX[4] = letters[v % 62]; v /= 62; XXXXXX[5] = letters[v % 62]; switch (kind) { case __GT_FILE: fd = __open (tmpl, (flags & ~O_ACCMODE) | O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); break; case __GT_DIR: fd = __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR); break; case __GT_NOCREATE: /* This case is backward from the other three. __gen_tempname succeeds if __xstat fails because the name does not exist. Note the continue to bypass the common logic at the bottom of the loop. */ if (__lxstat64 (_STAT_VER, tmpl, &st) < 0) { if (errno == ENOENT) { __set_errno (save_errno); return 0; } else /* Give up now. */ return -1; } continue; default: assert (! "invalid KIND in __gen_tempname"); } if (fd >= 0) { __set_errno (save_errno); return fd; } else if (errno != EEXIST) return -1; } /* We got out of the loop because we ran out of combinations to try. */ __set_errno (EEXIST); return -1; }
int __new_shmctl (int shmid, int cmd, struct shmid_ds *buf) { #if __ASSUME_32BITUIDS > 0 return INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, shmid, cmd | __IPC_64, 0, CHECK_1 (buf)); #else switch (cmd) { case SHM_STAT: case IPC_STAT: case IPC_SET: # if __WORDSIZE != 32 case IPC_INFO: # endif break; default: return INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, shmid, cmd, 0, CHECK_1 (buf)); } { struct __old_shmid_ds old; int result; # ifdef __NR_getuid32 if (__libc_missing_32bit_uids <= 0) { if (__libc_missing_32bit_uids < 0) { int save_errno = errno; /* Test presence of new IPC by testing for getuid32 syscall. */ result = INLINE_SYSCALL (getuid32, 0); if (result == -1 && errno == ENOSYS) __libc_missing_32bit_uids = 1; else __libc_missing_32bit_uids = 0; __set_errno(save_errno); } if (__libc_missing_32bit_uids <= 0) return INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, shmid, cmd | __IPC_64, 0, CHECK_1 (buf)); } # endif if (cmd == IPC_SET) { old.shm_perm.uid = buf->shm_perm.uid; old.shm_perm.gid = buf->shm_perm.gid; old.shm_perm.mode = buf->shm_perm.mode; if (old.shm_perm.uid != buf->shm_perm.uid || old.shm_perm.gid != buf->shm_perm.gid) { __set_errno (EINVAL); return -1; } } result = INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, shmid, cmd, 0, __ptrvalue (&old)); if (result != -1 && (cmd == SHM_STAT || cmd == IPC_STAT)) { memset(buf, 0, sizeof(*buf)); buf->shm_perm.__key = old.shm_perm.__key; buf->shm_perm.uid = old.shm_perm.uid; buf->shm_perm.gid = old.shm_perm.gid; buf->shm_perm.cuid = old.shm_perm.cuid; buf->shm_perm.cgid = old.shm_perm.cgid; buf->shm_perm.mode = old.shm_perm.mode; buf->shm_perm.__seq = old.shm_perm.__seq; buf->shm_atime = old.shm_atime; buf->shm_dtime = old.shm_dtime; buf->shm_ctime = old.shm_ctime; buf->shm_segsz = old.shm_segsz; buf->shm_nattch = old.shm_nattch; buf->shm_cpid = old.shm_cpid; buf->shm_lpid = old.shm_lpid; } # if __WORDSIZE != 32 else if (result != -1 && cmd == IPC_INFO) { struct __old_shminfo *oldi = (struct __old_shminfo *)&old; struct shminfo *i = (struct shminfo *)buf; memset(i, 0, sizeof(*i)); i->shmmax = oldi->shmmax; i->shmmin = oldi->shmmin; i->shmmni = oldi->shmmni; i->shmseg = oldi->shmseg; i->shmall = oldi->shmall; } # endif return result; } #endif }
int __ptsname_internal (int fd, char *buf, size_t buflen, struct stat64 *stp) { int save_errno = errno; unsigned int ptyno; if (!__isatty (fd)) { __set_errno (ENOTTY); return ENOTTY; } #ifdef TIOCGPTN if (__ioctl (fd, TIOCGPTN, &ptyno) == 0) { /* Buffer we use to print the number in. For a maximum size for `int' of 8 bytes we never need more than 20 digits. */ char numbuf[21]; const char *devpts = _PATH_DEVPTS; const size_t devptslen = strlen (_PATH_DEVPTS); char *p; numbuf[sizeof (numbuf) - 1] = '\0'; p = _itoa_word (ptyno, &numbuf[sizeof (numbuf) - 1], 10, 0); if (buflen < devptslen + (&numbuf[sizeof (numbuf)] - p)) { __set_errno (ERANGE); return ERANGE; } memcpy (__stpcpy (buf, devpts), p, &numbuf[sizeof (numbuf)] - p); } else if (errno != EINVAL) return errno; else #endif { char *p; if (buflen < strlen (_PATH_TTY) + 3) { __set_errno (ERANGE); return ERANGE; } if (__fxstat64 (_STAT_VER, fd, stp) < 0) return errno; /* Check if FD really is a master pseudo terminal. */ if (! MASTER_P (stp->st_rdev)) { __set_errno (ENOTTY); return ENOTTY; } ptyno = minor (stp->st_rdev); if (ptyno / 16 >= strlen (__libc_ptyname1)) { __set_errno (ENOTTY); return ENOTTY; } p = __stpcpy (buf, _PATH_TTY); p[0] = __libc_ptyname1[ptyno / 16]; p[1] = __libc_ptyname2[ptyno % 16]; p[2] = '\0'; } if (__xstat64 (_STAT_VER, buf, stp) < 0) return errno; /* Check if the name we're about to return really corresponds to a slave pseudo terminal. */ if (! S_ISCHR (stp->st_mode) || ! SLAVE_P (stp->st_rdev)) { /* This really is a configuration problem. */ __set_errno (ENOTTY); return ENOTTY; } __set_errno (save_errno); return 0; }
double __ieee754_j1 (double x) { double z, s, c, ss, cc, r, u, v, y, r1, r2, s1, s2, s3, z2, z4; int32_t hx, ix; GET_HIGH_WORD (hx, x); ix = hx & 0x7fffffff; if (__glibc_unlikely (ix >= 0x7ff00000)) return one / x; y = fabs (x); if (ix >= 0x40000000) /* |x| >= 2.0 */ { __sincos (y, &s, &c); ss = -s - c; cc = s - c; if (ix < 0x7fe00000) /* make sure y+y not overflow */ { z = __cos (y + y); if ((s * c) > zero) cc = z / ss; else ss = z / cc; } /* * j1(x) = 1/sqrt(pi) * (P(1,x)*cc - Q(1,x)*ss) / sqrt(x) * y1(x) = 1/sqrt(pi) * (P(1,x)*ss + Q(1,x)*cc) / sqrt(x) */ if (ix > 0x48000000) z = (invsqrtpi * cc) / __ieee754_sqrt (y); else { u = pone (y); v = qone (y); z = invsqrtpi * (u * cc - v * ss) / __ieee754_sqrt (y); } if (hx < 0) return -z; else return z; } if (__glibc_unlikely (ix < 0x3e400000)) /* |x|<2**-27 */ { if (huge + x > one) /* inexact if x!=0 necessary */ { double ret = math_narrow_eval (0.5 * x); math_check_force_underflow (ret); if (ret == 0 && x != 0) __set_errno (ERANGE); return ret; } } z = x * x; r1 = z * R[0]; z2 = z * z; r2 = R[1] + z * R[2]; z4 = z2 * z2; r = r1 + z2 * r2 + z4 * R[3]; r *= x; s1 = one + z * S[1]; s2 = S[2] + z * S[3]; s3 = S[4] + z * S[5]; s = s1 + z2 * s2 + z4 * s3; return (x * 0.5 + r / s); }