_public_ int sd_id128_get_boot(sd_id128_t *ret) { static thread_local sd_id128_t saved_boot_id; static thread_local bool saved_boot_id_valid = false; _cleanup_close_ int fd = -1; char buf[36]; unsigned j; sd_id128_t t; char *p; int r; assert_return(ret, -EINVAL); if (saved_boot_id_valid) { *ret = saved_boot_id; return 0; } fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY|O_CLOEXEC|O_NOCTTY); if (fd < 0) return -errno; r = loop_read_exact(fd, buf, 36, false); if (r < 0) return r; for (j = 0, p = buf; j < 16; j++) { int a, b; if (p >= buf + 35) return -EIO; if (*p == '-') { p++; if (p >= buf + 35) return -EIO; } a = unhexchar(p[0]); b = unhexchar(p[1]); if (a < 0 || b < 0) return -EIO; t.bytes[j] = a << 4 | b; p += 2; } saved_boot_id = t; saved_boot_id_valid = true; *ret = t; return 0; }
int dev_urandom(void *p, size_t n) { #if 0 /* NM_IGNORED */ static int have_syscall = -1; _cleanup_close_ int fd = -1; int r; /* Gathers some randomness from the kernel. This call will * never block, and will always return some data from the * kernel, regardless if the random pool is fully initialized * or not. It thus makes no guarantee for the quality of the * returned entropy, but is good enough for our usual usecases * of seeding the hash functions for hashtable */ /* Use the getrandom() syscall unless we know we don't have * it, or when the requested size is too large for it. */ if (have_syscall != 0 || (size_t) (int) n != n) { r = getrandom(p, n, GRND_NONBLOCK); if (r == (int) n) { have_syscall = true; return 0; } if (r < 0) { if (errno == ENOSYS) /* we lack the syscall, continue with * reading from /dev/urandom */ have_syscall = false; else if (errno == EAGAIN) /* not enough entropy for now. Let's * remember to use the syscall the * next time, again, but also read * from /dev/urandom for now, which * doesn't care about the current * amount of entropy. */ have_syscall = true; else return -errno; } else /* too short read? */ return -ENODATA; } #else /* NM_IGNORED */ _cleanup_close_ int fd = -1; #endif /* NM_IGNORED */ fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY); if (fd < 0) return errno == ENOENT ? -ENOSYS : -errno; return loop_read_exact(fd, p, n, true); }
_public_ int sd_id128_get_machine(sd_id128_t *ret) { static thread_local sd_id128_t saved_machine_id; static thread_local bool saved_machine_id_valid = false; _cleanup_close_ int fd = -1; char buf[33]; unsigned j; sd_id128_t t; int r; assert_return(ret, -EINVAL); if (saved_machine_id_valid) { *ret = saved_machine_id; return 0; } fd = open("/etc/machine-id", O_RDONLY|O_CLOEXEC|O_NOCTTY); if (fd < 0) return -errno; r = loop_read_exact(fd, buf, 33, false); if (r < 0) return r; if (buf[32] !='\n') return -EIO; for (j = 0; j < 16; j++) { int a, b; a = unhexchar(buf[j*2]); b = unhexchar(buf[j*2+1]); if (a < 0 || b < 0) return -EIO; t.bytes[j] = a << 4 | b; } saved_machine_id = t; saved_machine_id_valid = true; *ret = t; return 0; }
static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; union autofs_v5_packet_union packet; Automount *a = AUTOMOUNT(userdata); struct stat st; Unit *trigger; int r; assert(a); assert(fd == a->pipe_fd); if (events != EPOLLIN) { log_unit_error(UNIT(a), "Got invalid poll event %"PRIu32" on pipe (fd=%d)", events, fd); goto fail; } r = loop_read_exact(a->pipe_fd, &packet, sizeof(packet), true); if (r < 0) { log_unit_error_errno(UNIT(a), r, "Invalid read from pipe: %m"); goto fail; } switch (packet.hdr.type) { case autofs_ptype_missing_direct: if (packet.v5_packet.pid > 0) { _cleanup_free_ char *p = NULL; get_process_comm(packet.v5_packet.pid, &p); log_unit_info(UNIT(a), "Got automount request for %s, triggered by %"PRIu32" (%s)", a->where, packet.v5_packet.pid, strna(p)); } else log_unit_debug(UNIT(a), "Got direct mount request on %s", a->where); r = set_ensure_allocated(&a->tokens, NULL); if (r < 0) { log_unit_error(UNIT(a), "Failed to allocate token set."); goto fail; } r = set_put(a->tokens, UINT_TO_PTR(packet.v5_packet.wait_queue_token)); if (r < 0) { log_unit_error_errno(UNIT(a), r, "Failed to remember token: %m"); goto fail; } automount_enter_runnning(a); break; case autofs_ptype_expire_direct: log_unit_debug(UNIT(a), "Got direct umount request on %s", a->where); automount_stop_expire(a); r = set_ensure_allocated(&a->expire_tokens, NULL); if (r < 0) { log_unit_error(UNIT(a), "Failed to allocate token set."); goto fail; } r = set_put(a->expire_tokens, UINT_TO_PTR(packet.v5_packet.wait_queue_token)); if (r < 0) { log_unit_error_errno(UNIT(a), r, "Failed to remember token: %m"); goto fail; } /* Before we do anything, let's see if somebody is playing games with us? */ if (lstat(a->where, &st) < 0) { log_unit_warning_errno(UNIT(a), errno, "Failed to stat automount point: %m"); goto fail; } if (!S_ISDIR(st.st_mode) || st.st_dev == a->dev_id) { log_unit_info(UNIT(a), "Automount point already unmounted?"); automount_send_ready(a, a->expire_tokens, 0); break; } trigger = UNIT_TRIGGER(UNIT(a)); if (!trigger) { log_unit_error(UNIT(a), "Unit to trigger vanished."); goto fail; } r = manager_add_job(UNIT(a)->manager, JOB_STOP, trigger, JOB_REPLACE, &error, NULL); if (r < 0) { log_unit_warning(UNIT(a), "Failed to queue umount startup job: %s", bus_error_message(&error, r)); goto fail; } break; default: log_unit_error(UNIT(a), "Received unknown automount request %i", packet.hdr.type); break; } return 0; fail: automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES); return 0; }
int decompress_stream_lz4(int fdf, int fdt, off_t max_bytes) { #ifdef HAVE_LZ4 _cleanup_free_ char *buf = NULL, *out = NULL; size_t buf_size = 0; LZ4_streamDecode_t lz4_data = {}; le32_t header; size_t total_in = sizeof(header), total_out = 0; assert(fdf >= 0); assert(fdt >= 0); out = malloc(4*LZ4_BUFSIZE); if (!out) return log_oom(); for (;;) { ssize_t m; int r; r = loop_read_exact(fdf, &header, sizeof(header), false); if (r < 0) return r; m = le32toh(header); if (m == 0) break; /* We refuse to use a bigger decompression buffer than * the one used for compression by 4 times. This means * that compression buffer size can be enlarged 4 * times. This can be changed, but old binaries might * not accept buffers compressed by newer binaries then. */ if (m > LZ4_COMPRESSBOUND(LZ4_BUFSIZE * 4)) { log_error("Compressed stream block too big: %zd bytes", m); return -EBADMSG; } total_in += sizeof(header) + m; if (!GREEDY_REALLOC(buf, buf_size, m)) return log_oom(); r = loop_read_exact(fdf, buf, m, false); if (r < 0) return r; r = LZ4_decompress_safe_continue(&lz4_data, buf, out, m, 4*LZ4_BUFSIZE); if (r <= 0) log_error("LZ4 decompression failed."); total_out += r; if (max_bytes != -1 && total_out > (size_t) max_bytes) { log_debug("Decompressed stream longer than %zd bytes", max_bytes); return -EFBIG; } r = loop_write(fdt, out, r, false); if (r < 0) return r; } log_debug("LZ4 decompression finished (%zu -> %zu bytes, %.1f%%)", total_in, total_out, (double) total_out / total_in * 100); return 0; #else log_error("Cannot decompress file. Compiled without LZ4 support."); return -EPROTONOSUPPORT; #endif }