/* Adapted from fish/alloc.c */ static int parse_size (const char *str, uint64_t estimate, uint64_t *size_rtn) { unsigned long long size; strtol_error xerr; int plus = 0; assert (str); if (str[0] == '+') { plus = 1; str++; } xerr = xstrtoull (str, NULL, 0, &size, "0kKMGTPEZY"); if (xerr != LONGINT_OK) { fprintf (stderr, _("%s: %s: invalid size parameter '%s' (%s returned %u)\n"), guestfs_int_program_name, "parse_size", str, "xstrtoull", xerr); return -1; } if (plus) *size_rtn = estimate + size; else *size_rtn = size; return 0; }
int parse_size (const char *str, off_t *size_rtn) { unsigned long long size; strtol_error xerr; xerr = xstrtoull (str, NULL, 0, &size, "0kKMGTPEZY"); if (xerr != LONGINT_OK) { fprintf (stderr, _("%s: invalid integer parameter (%s returned %d)\n"), "parse_size", "xstrtoull", xerr); return -1; } /* XXX 32 bit file offsets, if anyone uses them? GCC should give * a warning here anyhow. */ *size_rtn = size; return 0; }
int main(void) { struct dirent *de; unsigned int fd, target_fd; if (unshare(CLONE_FILES) == -1) return 1; /* Wipe fdtable. */ do { DIR *d; d = opendir("/proc/self/fd"); if (!d) return 1; de = xreaddir(d); assert(de->d_type == DT_DIR); assert(streq(de->d_name, ".")); de = xreaddir(d); assert(de->d_type == DT_DIR); assert(streq(de->d_name, "..")); next: de = xreaddir(d); if (de) { unsigned long long fd_ull; unsigned int fd; char *end; assert(de->d_type == DT_LNK); fd_ull = xstrtoull(de->d_name, &end); assert(*end == '\0'); assert(fd_ull == (unsigned int)fd_ull); fd = fd_ull; if (fd == dirfd(d)) goto next; close(fd); } closedir(d); } while (de); /* Now fdtable is clean. */ fd = open("/", O_PATH|O_DIRECTORY); assert(fd == 0); test_lookup(fd); close(fd); /* Clean again! */ fd = open("/", O_PATH|O_DIRECTORY); assert(fd == 0); /* Default RLIMIT_NOFILE-1 */ target_fd = 1023; while (target_fd > 0) { if (dup2(fd, target_fd) == target_fd) break; target_fd /= 2; } assert(target_fd > 0); close(fd); test_lookup(target_fd); close(target_fd); return 0; }