/* Close all file descriptors except the one specified. */ static void close_all_fds (void) { DIR *dir = __opendir ("/proc/self/fd"); if (dir != NULL) { struct dirent64 *d; while ((d = __readdir64 (dir)) != NULL) if (isdigit (d->d_name[0])) { char *endp; long int fd = strtol (d->d_name, &endp, 10); if (*endp == '\0' && fd != PTY_FILENO && fd != dirfd (dir)) __close_nocancel_nostatus (fd); } __closedir (dir); int nullfd = __open_nocancel (_PATH_DEVNULL, O_RDONLY); assert (nullfd == STDIN_FILENO); nullfd = __open_nocancel (_PATH_DEVNULL, O_WRONLY); assert (nullfd == STDOUT_FILENO); __dup2 (STDOUT_FILENO, STDERR_FILENO); } }
/* Open the database stored in FILE. If succesful, store either a pointer to the mapped file or a file handle for the file in H and return NSS_STATUS_SUCCESS. On failure, return the appropriate lookup status. */ enum nss_status internal_setent (const char *file, struct nss_db_map *mapping) { enum nss_status status = NSS_STATUS_UNAVAIL; int fd = __open_nocancel (file, O_RDONLY | O_LARGEFILE | O_CLOEXEC); if (fd != -1) { struct nss_db_header header; if (read (fd, &header, sizeof (header)) == sizeof (header)) { mapping->header = mmap (NULL, header.allocate, PROT_READ, MAP_PRIVATE, fd, 0); mapping->len = header.allocate; if (mapping->header != MAP_FAILED) status = NSS_STATUS_SUCCESS; else if (errno == ENOMEM) status = NSS_STATUS_TRYAGAIN; } __close_nocancel_nostatus (fd); } return status; }
static int setutent_file (void) { if (file_fd < 0) { const char *file_name; file_name = TRANSFORM_UTMP_FILE_NAME (__libc_utmp_file_name); file_writable = false; file_fd = __open_nocancel (file_name, O_RDONLY | O_LARGEFILE | O_CLOEXEC); if (file_fd == -1) return 0; } __lseek64 (file_fd, 0, SEEK_SET); file_offset = 0; /* Make sure the entry won't match. */ #if _HAVE_UT_TYPE - 0 last_entry.ut_type = -1; #else last_entry.ut_line[0] = '\177'; # if _HAVE_UT_ID - 0 last_entry.ut_id[0] = '\0'; # endif #endif return 1; }
static int has_cpuclock (void) { if (__builtin_expect (itc_usable == 0, 0)) { int newval = 1; int fd = __open_nocancel ("/proc/sal/itc_drift", O_RDONLY); if (__builtin_expect (fd != -1, 1)) { char buf[16]; /* We expect the file to contain a single digit followed by a newline. If the format changes we better not rely on the file content. */ if (__read_nocancel (fd, buf, sizeof buf) != 2 || buf[0] != '0' || buf[1] != '\n') newval = -1; __close_nocancel_nostatus (fd); } itc_usable = newval; } return itc_usable; }
int pthread_getname_np (pthread_t th, char *buf, size_t len) { const struct pthread *pd = (const struct pthread *) th; /* Unfortunately the kernel headers do not export the TASK_COMM_LEN macro. So we have to define it here. */ #define TASK_COMM_LEN 16 if (len < TASK_COMM_LEN) return ERANGE; if (pd == THREAD_SELF) return prctl (PR_GET_NAME, buf) ? errno : 0; #define FMT "/proc/self/task/%u/comm" char fname[sizeof (FMT) + 8]; sprintf (fname, FMT, (unsigned int) pd->tid); int fd = __open_nocancel (fname, O_RDONLY); if (fd == -1) return errno; int res = 0; ssize_t n = TEMP_FAILURE_RETRY (__read_nocancel (fd, buf, len)); if (n < 0) res = errno; else { if (buf[n - 1] == '\n') buf[n - 1] = '\0'; else if (n == len) res = ERANGE; else buf[n] = '\0'; } __close_nocancel_nostatus (fd); return res; }
int __get_nprocs (void) { static int cached_result = -1; static time_t timestamp; time_t now = time (NULL); time_t prev = timestamp; atomic_read_barrier (); if (now == prev && cached_result > -1) return cached_result; /* XXX Here will come a test for the new system call. */ const size_t buffer_size = __libc_use_alloca (8192) ? 8192 : 512; char *buffer = alloca (buffer_size); char *buffer_end = buffer + buffer_size; char *cp = buffer_end; char *re = buffer_end; const int flags = O_RDONLY | O_CLOEXEC; int fd = __open_nocancel ("/sys/devices/system/cpu/online", flags); char *l; int result = 0; if (fd != -1) { l = next_line (fd, buffer, &cp, &re, buffer_end); if (l != NULL) do { char *endp; unsigned long int n = strtoul (l, &endp, 10); if (l == endp) { result = 0; break; } unsigned long int m = n; if (*endp == '-') { l = endp + 1; m = strtoul (l, &endp, 10); if (l == endp) { result = 0; break; } } result += m - n + 1; l = endp; while (l < re && isspace (*l)) ++l; } while (l < re); __close_nocancel_nostatus (fd); if (result > 0) goto out; } cp = buffer_end; re = buffer_end; /* Default to an SMP system in case we cannot obtain an accurate number. */ result = 2; /* The /proc/stat format is more uniform, use it by default. */ fd = __open_nocancel ("/proc/stat", flags); if (fd != -1) { result = 0; while ((l = next_line (fd, buffer, &cp, &re, buffer_end)) != NULL) /* The current format of /proc/stat has all the cpu* entries at the front. We assume here that stays this way. */ if (strncmp (l, "cpu", 3) != 0) break; else if (isdigit (l[3])) ++result; __close_nocancel_nostatus (fd); } else { fd = __open_nocancel ("/proc/cpuinfo", flags); if (fd != -1) { GET_NPROCS_PARSER (fd, buffer, cp, re, buffer_end, result); __close_nocancel_nostatus (fd); } } out: cached_result = result; atomic_write_barrier (); timestamp = now; return result; }
int __open_catalog (const char *cat_name, const char *nlspath, const char *env_var, __nl_catd catalog) { int fd = -1; struct stat64 st; int swapping; size_t cnt; size_t max_offset; size_t tab_size; const char *lastp; int result = -1; char *buf = NULL; if (strchr (cat_name, '/') != NULL || nlspath == NULL) fd = __open_nocancel (cat_name, O_RDONLY); else { const char *run_nlspath = nlspath; #define ENOUGH(n) \ if (__glibc_unlikely (bufact + (n) >= bufmax)) \ { \ char *old_buf = buf; \ bufmax += (bufmax < 256 + (n)) ? 256 + (n) : bufmax; \ buf = realloc (buf, bufmax); \ if (__glibc_unlikely (buf == NULL)) \ { \ free (old_buf); \ return -1; \ } \ } /* The RUN_NLSPATH variable contains a colon separated list of descriptions where we expect to find catalogs. We have to recognize certain % substitutions and stop when we found the first existing file. */ size_t bufact; size_t bufmax = 0; size_t len; fd = -1; while (*run_nlspath != '\0') { bufact = 0; if (*run_nlspath == ':') { /* Leading colon or adjacent colons - treat same as %N. */ len = strlen (cat_name); ENOUGH (len); memcpy (&buf[bufact], cat_name, len); bufact += len; } else while (*run_nlspath != ':' && *run_nlspath != '\0') if (*run_nlspath == '%') { const char *tmp; ++run_nlspath; /* We have seen the `%'. */ switch (*run_nlspath++) { case 'N': /* Use the catalog name. */ len = strlen (cat_name); ENOUGH (len); memcpy (&buf[bufact], cat_name, len); bufact += len; break; case 'L': /* Use the current locale category value. */ len = strlen (env_var); ENOUGH (len); memcpy (&buf[bufact], env_var, len); bufact += len; break; case 'l': /* Use language element of locale category value. */ tmp = env_var; do { ENOUGH (1); buf[bufact++] = *tmp++; } while (*tmp != '\0' && *tmp != '_' && *tmp != '.'); break; case 't': /* Use territory element of locale category value. */ tmp = env_var; do ++tmp; while (*tmp != '\0' && *tmp != '_' && *tmp != '.'); if (*tmp == '_') { ++tmp; do { ENOUGH (1); buf[bufact++] = *tmp++; } while (*tmp != '\0' && *tmp != '.'); } break; case 'c': /* Use code set element of locale category value. */ tmp = env_var; do ++tmp; while (*tmp != '\0' && *tmp != '.'); if (*tmp == '.') { ++tmp; do { ENOUGH (1); buf[bufact++] = *tmp++; } while (*tmp != '\0'); } break; case '%': ENOUGH (1); buf[bufact++] = '%'; break; default: /* Unknown variable: ignore this path element. */ bufact = 0; while (*run_nlspath != '\0' && *run_nlspath != ':') ++run_nlspath; break; } } else { ENOUGH (1); buf[bufact++] = *run_nlspath++; } ENOUGH (1); buf[bufact] = '\0'; if (bufact != 0) { fd = __open_nocancel (buf, O_RDONLY); if (fd >= 0) break; } ++run_nlspath; } } /* Avoid dealing with directories and block devices */ if (__builtin_expect (fd, 0) < 0) { free (buf); return -1; } if (__builtin_expect (__fxstat64 (_STAT_VER, fd, &st), 0) < 0) goto close_unlock_return; if (__builtin_expect (!S_ISREG (st.st_mode), 0) || (size_t) st.st_size < sizeof (struct catalog_obj)) { /* `errno' is not set correctly but the file is not usable. Use an reasonable error value. */ __set_errno (EINVAL); goto close_unlock_return; } catalog->file_size = st.st_size; #ifdef _POSIX_MAPPED_FILES # ifndef MAP_COPY /* Linux seems to lack read-only copy-on-write. */ # define MAP_COPY MAP_PRIVATE # endif # ifndef MAP_FILE /* Some systems do not have this flag; it is superfluous. */ # define MAP_FILE 0 # endif catalog->file_ptr = (struct catalog_obj *) __mmap (NULL, st.st_size, PROT_READ, MAP_FILE|MAP_COPY, fd, 0); if (__builtin_expect (catalog->file_ptr != (struct catalog_obj *) MAP_FAILED, 1)) /* Tell the world we managed to mmap the file. */ catalog->status = mmapped; else #endif /* _POSIX_MAPPED_FILES */ { /* mmap failed perhaps because the system call is not implemented. Try to load the file. */ size_t todo; catalog->file_ptr = malloc (st.st_size); if (catalog->file_ptr == NULL) goto close_unlock_return; todo = st.st_size; /* Save read, handle partial reads. */ do { size_t now = __read_nocancel (fd, (((char *) catalog->file_ptr) + (st.st_size - todo)), todo); if (now == 0 || now == (size_t) -1) { #ifdef EINTR if (now == (size_t) -1 && errno == EINTR) continue; #endif free ((void *) catalog->file_ptr); goto close_unlock_return; } todo -= now; } while (todo > 0); catalog->status = malloced; } /* Determine whether the file is a catalog file and if yes whether it is written using the correct byte order. Else we have to swap the values. */ if (__glibc_likely (catalog->file_ptr->magic == CATGETS_MAGIC)) swapping = 0; else if (catalog->file_ptr->magic == SWAPU32 (CATGETS_MAGIC)) swapping = 1; else { invalid_file: /* Invalid file. Free the resources and mark catalog as not usable. */ #ifdef _POSIX_MAPPED_FILES if (catalog->status == mmapped) __munmap ((void *) catalog->file_ptr, catalog->file_size); else #endif /* _POSIX_MAPPED_FILES */ free (catalog->file_ptr); goto close_unlock_return; } #define SWAP(x) (swapping ? SWAPU32 (x) : (x)) /* Get dimensions of the used hashing table. */ catalog->plane_size = SWAP (catalog->file_ptr->plane_size); catalog->plane_depth = SWAP (catalog->file_ptr->plane_depth); /* The file contains two versions of the pointer tables. Pick the right one for the local byte order. */ #if __BYTE_ORDER == __LITTLE_ENDIAN catalog->name_ptr = &catalog->file_ptr->name_ptr[0]; #elif __BYTE_ORDER == __BIG_ENDIAN catalog->name_ptr = &catalog->file_ptr->name_ptr[catalog->plane_size * catalog->plane_depth * 3]; #else # error Cannot handle __BYTE_ORDER byte order #endif /* The rest of the file contains all the strings. They are addressed relative to the position of the first string. */ catalog->strings = (const char *) &catalog->file_ptr->name_ptr[catalog->plane_size * catalog->plane_depth * 3 * 2]; /* Determine the largest string offset mentioned in the table. */ max_offset = 0; tab_size = 3 * catalog->plane_size * catalog->plane_depth; for (cnt = 2; cnt < tab_size; cnt += 3) if (catalog->name_ptr[cnt] > max_offset) max_offset = catalog->name_ptr[cnt]; /* Now we can check whether the file is large enough to contain the tables it says it contains. */ if ((size_t) st.st_size <= (sizeof (struct catalog_obj) + 2 * tab_size + max_offset)) /* The last string is not contained in the file. */ goto invalid_file; lastp = catalog->strings + max_offset; max_offset = (st.st_size - sizeof (struct catalog_obj) + 2 * tab_size + max_offset); while (*lastp != '\0') { if (--max_offset == 0) goto invalid_file; ++lastp; } /* We succeeded. */ result = 0; /* Release the lock again. */ close_unlock_return: __close_nocancel_nostatus (fd); free (buf); return result; }