int cpu_dump_cpuinfo(void) { CpuinfoEntry cpu_info = CPUINFO_ENTRY__INIT; CpuinfoX86Entry cpu_x86_info = CPUINFO_X86_ENTRY__INIT; CpuinfoX86Entry *cpu_x86_info_ptr = &cpu_x86_info; struct cr_img *img; img = open_image(CR_FD_CPUINFO, O_DUMP); if (!img) return -1; cpu_info.x86_entry = &cpu_x86_info_ptr; cpu_info.n_x86_entry = 1; cpu_x86_info.vendor_id = (rt_cpu_info.x86_vendor == X86_VENDOR_INTEL) ? CPUINFO_X86_ENTRY__VENDOR__INTEL : CPUINFO_X86_ENTRY__VENDOR__AMD; cpu_x86_info.cpu_family = rt_cpu_info.x86_family; cpu_x86_info.model = rt_cpu_info.x86_model; cpu_x86_info.stepping = rt_cpu_info.x86_mask; cpu_x86_info.capability_ver = 1; cpu_x86_info.n_capability = ARRAY_SIZE(rt_cpu_info.x86_capability); cpu_x86_info.capability = (void *)rt_cpu_info.x86_capability; if (rt_cpu_info.x86_model_id[0]) cpu_x86_info.model_id = rt_cpu_info.x86_model_id; if (pb_write_one(img, &cpu_info, PB_CPUINFO) < 0) { close_image(img); return -1; } close_image(img); return 0; }
static int open_remap_ghost(struct reg_file_info *rfi, RemapFilePathEntry *rfe) { struct ghost_file *gf = container_of(rfi->remap, struct ghost_file, remap); GhostFileEntry *gfe = NULL; struct cr_img *img; if (rfi->remap->rpath[0]) return 0; img = open_image(CR_FD_GHOST_FILE, O_RSTR, rfe->remap_id); if (!img) goto err; if (pb_read_one(img, &gfe, PB_GHOST_FILE) < 0) goto close_ifd; /* * For old formats where optional has_[dev|ino] is * not present we will have zeros here which is quite * a sign for "absent" fields. */ gf->dev = gfe->dev; gf->ino = gfe->ino; gf->remap.rmnt_id = rfi->rfe->mnt_id; if (S_ISDIR(gfe->mode)) strncpy(gf->remap.rpath, rfi->path, PATH_MAX); else ghost_path(gf->remap.rpath, PATH_MAX, rfi, rfe); if (create_ghost(gf, gfe, img)) goto close_ifd; close_image(img); gf->remap.is_dir = S_ISDIR(gfe->mode); gf->remap.uid = gfe->uid; gf->remap.gid = gfe->gid; ghost_file_entry__free_unpacked(gfe, NULL); return 0; close_ifd: close_image(img); err: if (gfe) ghost_file_entry__free_unpacked(gfe, NULL); return -1; }
int dump_uts_ns(int ns_id) { int ret; struct cr_img *img; struct utsname ubuf; UtsnsEntry ue = UTSNS_ENTRY__INIT; img = open_image(CR_FD_UTSNS, O_DUMP, ns_id); if (!img) return -1; ret = uname(&ubuf); if (ret < 0) { pr_perror("Error calling uname"); goto err; } ue.nodename = ubuf.nodename; ue.domainname = ubuf.domainname; ret = pb_write_one(img, &ue, PB_UTSNS); err: close_image(img); return ret < 0 ? -1 : 0; }
static int prepare_ipc_var(int pid) { int ret; struct cr_img *img; IpcVarEntry *var; pr_info("Restoring IPC variables\n"); img = open_image(CR_FD_IPC_VAR, O_RSTR, pid); if (!img) return -1; ret = pb_read_one(img, &var, PB_IPC_VAR); close_image(img); if (ret <= 0) { pr_err("Failed to read IPC namespace variables\n"); return -EFAULT; } ret = ipc_sysctl_req(var, CTL_WRITE); ipc_var_entry__free_unpacked(var, NULL); if (ret < 0) { pr_err("Failed to prepare IPC namespace variables\n"); return -EFAULT; } return 0; }
int prepare_utsns(int pid) { int ret; struct cr_img *img; UtsnsEntry *ue; struct sysctl_req req[] = { { "kernel/hostname" }, { "kernel/domainname" }, }; img = open_image(CR_FD_UTSNS, O_RSTR, pid); if (!img) return -1; ret = pb_read_one(img, &ue, PB_UTSNS); if (ret < 0) goto out; req[0].arg = ue->nodename; req[0].type = CTL_STR(strlen(ue->nodename)); req[1].arg = ue->domainname; req[1].type = CTL_STR(strlen(ue->domainname)); ret = sysctl_op(req, ARRAY_SIZE(req), CTL_WRITE, CLONE_NEWUTS); utsns_entry__free_unpacked(ue, NULL); out: close_image(img); return ret; }
static int wlan_device_get_mac_addr(unsigned char *buf) { char macaddr[20]; int mac_len = 0; void *fp; if (!buf){ pr_err("%s, null parameter !!\n", __func__); return -EFAULT; } fp = open_image(CUSTOMER_MAC_FILE); if (fp == NULL) return -EFAULT; mac_len = get_image_block(macaddr, 17, fp); if (mac_len < 17) return -EFAULT; wlan_mac_addr[0] = (unsigned char)((char2bin(macaddr[0]) << 4) | char2bin(macaddr[1])); wlan_mac_addr[1] = (unsigned char)((char2bin(macaddr[3]) << 4) | char2bin(macaddr[4])); wlan_mac_addr[2] = (unsigned char)((char2bin(macaddr[6]) << 4) | char2bin(macaddr[7])); wlan_mac_addr[3] = (unsigned char)((char2bin(macaddr[9]) << 4) | char2bin(macaddr[10])); wlan_mac_addr[4] = (unsigned char)((char2bin(macaddr[12]) << 4) | char2bin(macaddr[13])); wlan_mac_addr[5] = (unsigned char)((char2bin(macaddr[15]) << 4) | char2bin(macaddr[16])); memcpy(buf, wlan_mac_addr, IFHWADDRLEN); pr_info("wifi mac: %x:%x:%x:%x:%x:%x\n", wlan_mac_addr[0], wlan_mac_addr[1], wlan_mac_addr[2], wlan_mac_addr[3], wlan_mac_addr[4], wlan_mac_addr[5]); close_image(fp); return 0; }
int check_img_inventory(void) { int ret = -1; struct cr_img *img; InventoryEntry *he; img = open_image(CR_FD_INVENTORY, O_RSTR); if (!img) return -1; if (pb_read_one(img, &he, PB_INVENTORY) < 0) goto out_close; fdinfo_per_id = he->has_fdinfo_per_id ? he->fdinfo_per_id : false; ns_per_id = he->has_ns_per_id ? he->ns_per_id : false; if (he->root_ids) { root_ids = xmalloc(sizeof(*root_ids)); if (!root_ids) goto out_err; memcpy(root_ids, he->root_ids, sizeof(*root_ids)); } if (he->has_root_cg_set) { if (he->root_cg_set == 0) { pr_err("Corrupted root cgset\n"); goto out_err; } root_cg_set = he->root_cg_set; } image_lsm = he->lsmtype; switch (he->img_version) { case CRTOOLS_IMAGES_V1: /* good old images. OK */ img_common_magic = false; break; case CRTOOLS_IMAGES_V1_1: /* newer images with extra magic in the head */ break; default: pr_err("Not supported images version %u\n", he->img_version); goto out_err; } ret = 0; out_err: inventory_entry__free_unpacked(he, NULL); out_close: close_image(img); return ret; }
int write_img_inventory(void) { struct cr_img *img; InventoryEntry he = INVENTORY_ENTRY__INIT; struct { struct pstree_item i; struct dmp_info d; } crt = { }; pr_info("Writing image inventory (version %u)\n", CRTOOLS_IMAGES_V1); img = open_image(CR_FD_INVENTORY, O_DUMP); if (!img) return -1; he.img_version = CRTOOLS_IMAGES_V1_1; he.fdinfo_per_id = true; he.has_fdinfo_per_id = true; he.ns_per_id = true; he.has_ns_per_id = true; he.lsmtype = host_lsm_type(); crt.i.state = TASK_ALIVE; crt.i.pid.real = getpid(); if (get_task_ids(&crt.i)) { close_image(img); return -1; } he.has_root_cg_set = true; if (dump_task_cgroup(NULL, &he.root_cg_set)) return -1; he.root_ids = crt.i.ids; if (pb_write_one(img, &he, PB_INVENTORY) < 0) return -1; xfree(crt.i.ids); close_image(img); return 0; }
static int prepare_ipc_sem(int pid) { int ret; struct cr_img *img; pr_info("Restoring IPC semaphores sets\n"); img = open_image(CR_FD_IPCNS_SEM, O_RSTR, pid); if (!img) return -1; while (1) { IpcSemEntry *sem; ret = pb_read_one_eof(img, &sem, PB_IPC_SEM); if (ret < 0) { ret = -EIO; goto err; } if (ret == 0) break; pr_info_ipc_sem_entry(sem); ret = prepare_ipc_sem_desc(img, sem); ipc_sem_entry__free_unpacked(sem, NULL); if (ret < 0) { pr_err("Failed to prepare semaphores set\n"); goto err; } } close_image(img); return 0; err: close_image(img); return ret; }
static int prepare_ipc_msg(int pid) { int ret; struct cr_img *img; pr_info("Restoring IPC message queues\n"); img = open_image(CR_FD_IPCNS_MSG, O_RSTR, pid); if (!img) return -1; while (1) { IpcMsgEntry *msq; ret = pb_read_one_eof(img, &msq, PB_IPCNS_MSG_ENT); if (ret < 0) { pr_err("Failed to read IPC messages queue\n"); ret = -EIO; goto err; } if (ret == 0) break; pr_info_ipc_msg_entry(msq); ret = prepare_ipc_msg_queue(img, msq); ipc_msg_entry__free_unpacked(msq, NULL); if (ret < 0) { pr_err("Failed to prepare messages queue\n"); goto err; } } close_image(img); return 0; err: close_image(img); return ret; }
static int prepare_ipc_shm(int pid) { int ret; struct cr_img *img; pr_info("Restoring IPC shared memory\n"); img = open_image(CR_FD_IPCNS_SHM, O_RSTR, pid); if (!img) return -1; while (1) { IpcShmEntry *shm; ret = pb_read_one_eof(img, &shm, PB_IPC_SHM); if (ret < 0) { pr_err("Failed to read IPC shared memory segment\n"); ret = -EIO; goto err; } if (ret == 0) break; pr_info_ipc_shm(shm); ret = prepare_ipc_shm_seg(img, shm); ipc_shm_entry__free_unpacked(shm, NULL); if (ret < 0) { pr_err("Failed to prepare shm segment\n"); goto err; } } close_image(img); return 0; err: close_image(img); return ret; }
static void __close_cr_imgset(struct cr_imgset *cr_imgset) { unsigned int i; if (!cr_imgset) return; for (i = 0; i < cr_imgset->fd_nr; i++) { if (!cr_imgset->_imgs[i]) continue; close_image(cr_imgset->_imgs[i]); cr_imgset->_imgs[i] = NULL; } }
InventoryEntry *get_parent_inventory(void) { struct cr_img *img; InventoryEntry *ie; int dir; dir = openat(get_service_fd(IMG_FD_OFF), CR_PARENT_LINK, O_RDONLY); if (dir == -1) { pr_warn("Failed to open parent directory\n"); return NULL; } img = open_image_at(dir, CR_FD_INVENTORY, O_RSTR); if (!img) { pr_warn("Failed to open parent pre-dump inventory image\n"); close(dir); return NULL; } if (pb_read_one(img, &ie, PB_INVENTORY) < 0) { pr_warn("Failed to read parent pre-dump inventory entry\n"); close_image(img); close(dir); return NULL; } if (!ie->has_dump_uptime) { pr_warn("Parent pre-dump inventory has no uptime\n"); inventory_entry__free_unpacked(ie, NULL); ie = NULL; } close_image(img); close(dir); return ie; }
void write_stats(int what) { StatsEntry stats = STATS_ENTRY__INIT; DumpStatsEntry ds_entry = DUMP_STATS_ENTRY__INIT; RestoreStatsEntry rs_entry = RESTORE_STATS_ENTRY__INIT; char *name; struct cr_img *img; pr_info("Writing stats\n"); if (what == DUMP_STATS) { stats.dump = &ds_entry; encode_time(TIME_FREEZING, &ds_entry.freezing_time); encode_time(TIME_FROZEN, &ds_entry.frozen_time); encode_time(TIME_MEMDUMP, &ds_entry.memdump_time); encode_time(TIME_MEMWRITE, &ds_entry.memwrite_time); ds_entry.has_irmap_resolve = true; encode_time(TIME_IRMAP_RESOLVE, &ds_entry.irmap_resolve); ds_entry.pages_scanned = dstats->counts[CNT_PAGES_SCANNED]; ds_entry.pages_skipped_parent = dstats->counts[CNT_PAGES_SKIPPED_PARENT]; ds_entry.pages_written = dstats->counts[CNT_PAGES_WRITTEN]; ds_entry.pages_zero = dstats->counts[CNT_PAGES_ZERO]; ds_entry.pages_lazy = dstats->counts[CNT_PAGES_LAZY]; name = "dump"; } else if (what == RESTORE_STATS) { stats.restore = &rs_entry; rs_entry.pages_compared = atomic_read(&rstats->counts[CNT_PAGES_COMPARED]); rs_entry.pages_skipped_cow = atomic_read(&rstats->counts[CNT_PAGES_SKIPPED_COW]); rs_entry.has_pages_restored = true; rs_entry.pages_restored = atomic_read(&rstats->counts[CNT_PAGES_RESTORED]); encode_time(TIME_FORK, &rs_entry.forking_time); encode_time(TIME_RESTORE, &rs_entry.restore_time); name = "restore"; } else return; img = open_image_at(AT_FDCWD, CR_FD_STATS, O_DUMP, name); if (img) { pb_write_one(img, &stats, PB_STATS); close_image(img); } }
int write_img_inventory(InventoryEntry *he) { struct cr_img *img; pr_info("Writing image inventory (version %u)\n", CRTOOLS_IMAGES_V1); img = open_image(CR_FD_INVENTORY, O_DUMP); if (!img) return -1; if (pb_write_one(img, he, PB_INVENTORY) < 0) return -1; xfree(he->root_ids); close_image(img); return 0; }
int check_img_inventory(void) { int ret = -1; struct cr_img *img; InventoryEntry *he; img = open_image(CR_FD_INVENTORY, O_RSTR); if (!img) return -1; if (pb_read_one(img, &he, PB_INVENTORY) < 0) goto out_close; fdinfo_per_id = he->has_fdinfo_per_id ? he->fdinfo_per_id : false; ns_per_id = he->has_ns_per_id ? he->ns_per_id : false; if (he->root_ids) { root_ids = xmalloc(sizeof(*root_ids)); if (!root_ids) goto out_err; memcpy(root_ids, he->root_ids, sizeof(*root_ids)); } if (he->has_root_cg_set) { if (he->root_cg_set == 0) { pr_err("Corrupted root cgset\n"); goto out_err; } root_cg_set = he->root_cg_set; } if (he->img_version != CRTOOLS_IMAGES_V1) { pr_err("Not supported images version %u\n", he->img_version); goto out_err; } ret = 0; out_err: inventory_entry__free_unpacked(he, NULL); out_close: close_image(img); return ret; }
int prepare_seccomp_filters(void) { struct cr_img *img; int ret; img = open_image(CR_FD_SECCOMP, O_RSTR); if (!img) return -1; ret = pb_read_one_eof(img, &se, PB_SECCOMP); close_image(img); if (ret <= 0) return 0; /* there were no filters */ BUG_ON(!se); return 0; }
int cpu_validate_cpuinfo(void) { CpuinfoX86Entry *img_x86_entry; CpuinfoEntry *img_cpu_info; struct cr_img *img; int ret = -1; img = open_image(CR_FD_CPUINFO, O_RSTR); if (!img) return -1; if (pb_read_one(img, &img_cpu_info, PB_CPUINFO) < 0) goto err; if (img_cpu_info->n_x86_entry != 1) { pr_err("No x86 related cpuinfo in image, " "corruption (n_x86_entry = %zi)\n", img_cpu_info->n_x86_entry); goto err; } img_x86_entry = img_cpu_info->x86_entry[0]; if (img_x86_entry->vendor_id != CPUINFO_X86_ENTRY__VENDOR__INTEL && img_x86_entry->vendor_id != CPUINFO_X86_ENTRY__VENDOR__AMD) { pr_err("Unknown cpu vendor %d\n", img_x86_entry->vendor_id); goto err; } if (img_x86_entry->n_capability != ARRAY_SIZE(rt_cpu_info.x86_capability)) { pr_err("Image carries %u words while %u expected\n", (unsigned)img_x86_entry->n_capability, (unsigned)ARRAY_SIZE(rt_cpu_info.x86_capability)); goto err; } ret = cpu_validate_features(img_x86_entry); err: close_image(img); return ret; }
struct cr_img *open_image_at(int dfd, int type, unsigned long flags, ...) { struct cr_img *img; unsigned long oflags; char path[PATH_MAX]; va_list args; bool lazy = false; if (dfd == -1) { dfd = get_service_fd(IMG_FD_OFF); lazy = (flags & O_CREAT); } img = xmalloc(sizeof(*img)); if (!img) return NULL; oflags = flags | imgset_template[type].oflags; va_start(args, flags); vsnprintf(path, PATH_MAX, imgset_template[type].fmt, args); va_end(args); if (lazy) { img->fd = LAZY_IMG_FD; img->type = type; img->oflags = oflags; img->path = xstrdup(path); return img; } else img->fd = EMPTY_IMG_FD; if (do_open_image(img, dfd, type, oflags, path)) { close_image(img); return NULL; } return img; }
int cpu_dump_cpuinfo(void) { CpuinfoEntry cpu_info = CPUINFO_ENTRY__INIT; CpuinfoPpc64Entry cpu_ppc64_info = CPUINFO_PPC64_ENTRY__INIT; CpuinfoPpc64Entry *cpu_ppc64_info_ptr = &cpu_ppc64_info; struct cr_img *img; int ret = -1; img = open_image(CR_FD_CPUINFO, O_DUMP); if (!img) return -1; cpu_info.ppc64_entry = &cpu_ppc64_info_ptr; cpu_info.n_ppc64_entry = 1; cpu_ppc64_info.endian = CURRENT_ENDIANNESS; cpu_ppc64_info.n_hwcap = 2; cpu_ppc64_info.hwcap = rt_cpuinfo.hwcap; ret = pb_write_one(img, &cpu_info, PB_CPUINFO); close_image(img); return ret; }
static int dump_tcp_conn_state(struct inet_sk_desc *sk) { int ret, aux; struct tcp_info ti; struct cr_img *img; TcpStreamEntry tse = TCP_STREAM_ENTRY__INIT; char *in_buf, *out_buf; ret = refresh_inet_sk(sk, &ti); if (ret < 0) goto err_r; /* * Read queue */ pr_info("Reading inq for socket\n"); tse.inq_len = sk->rqlen; ret = tcp_stream_get_queue(sk->rfd, TCP_RECV_QUEUE, &tse.inq_seq, tse.inq_len, &in_buf); if (ret < 0) goto err_in; /* * Write queue */ pr_info("Reading outq for socket\n"); tse.outq_len = sk->wqlen; tse.unsq_len = sk->uwqlen; tse.has_unsq_len = true; ret = tcp_stream_get_queue(sk->rfd, TCP_SEND_QUEUE, &tse.outq_seq, tse.outq_len, &out_buf); if (ret < 0) goto err_out; /* * Initial options */ pr_info("Reading options for socket\n"); ret = tcp_stream_get_options(sk->rfd, &ti, &tse); if (ret < 0) goto err_opt; if (tcp_get_window(sk->rfd, &tse)) goto err_opt; /* * TCP socket options */ if (dump_opt(sk->rfd, SOL_TCP, TCP_NODELAY, &aux)) goto err_opt; if (aux) { tse.has_nodelay = true; tse.nodelay = true; } if (dump_opt(sk->rfd, SOL_TCP, TCP_CORK, &aux)) goto err_opt; if (aux) { tse.has_cork = true; tse.cork = true; } /* * Push the stuff to image */ img = open_image(CR_FD_TCP_STREAM, O_DUMP, sk->sd.ino); if (!img) goto err_img; ret = pb_write_one(img, &tse, PB_TCP_STREAM); if (ret < 0) goto err_iw; if (in_buf) { ret = write_img_buf(img, in_buf, tse.inq_len); if (ret < 0) goto err_iw; } if (out_buf) { ret = write_img_buf(img, out_buf, tse.outq_len); if (ret < 0) goto err_iw; } pr_info("Done\n"); err_iw: close_image(img); err_img: err_opt: xfree(out_buf); err_out: xfree(in_buf); err_in: err_r: return ret; }
int cpu_validate_cpuinfo(void) { CpuinfoEntry *cpu_info; CpuinfoPpc64Entry *cpu_ppc64_entry; struct cr_img *img; int ret = -1; img = open_image(CR_FD_CPUINFO, O_RSTR); if (!img) return -1; if (pb_read_one(img, &cpu_info, PB_CPUINFO) < 0) goto error; if (cpu_info->n_ppc64_entry != 1) { pr_err("No PPC64 related entry in image"); goto error; } cpu_ppc64_entry = cpu_info->ppc64_entry[0]; if (cpu_ppc64_entry->endian != CURRENT_ENDIANNESS) { pr_err("Bad endianness"); goto error; } if (cpu_ppc64_entry->n_hwcap != 2) { pr_err("Hardware capabilities information missing\n"); goto error; } #define CHECK_FEATURE(s,f) do { \ if ((cpu_ppc64_entry->hwcap[s] & f) && \ !(rt_cpuinfo.hwcap[s] & f)) { \ pr_err("CPU Feature %s required by image " \ "is not supported on host.\n", #f); \ goto error; \ } \ } while(0) #define REQUIRE_FEATURE(s,f) do { \ if (!(cpu_ppc64_entry->hwcap[s] & f)) { \ pr_err("CPU Feature %s missing in image.\n", #f); \ goto error; \ } \ } while(0) REQUIRE_FEATURE(0, PPC_FEATURE_64); REQUIRE_FEATURE(0, PPC_FEATURE_HAS_FPU); REQUIRE_FEATURE(0, PPC_FEATURE_HAS_MMU); REQUIRE_FEATURE(0, PPC_FEATURE_HAS_VSX); REQUIRE_FEATURE(1, PPC_FEATURE2_ARCH_2_07); CHECK_FEATURE(0, PPC_FEATURE_TRUE_LE); CHECK_FEATURE(1, PPC_FEATURE2_HTM); CHECK_FEATURE(1, PPC_FEATURE2_DSCR); CHECK_FEATURE(1, PPC_FEATURE2_EBB); CHECK_FEATURE(1, PPC_FEATURE2_ISEL); CHECK_FEATURE(1, PPC_FEATURE2_TAR); CHECK_FEATURE(1, PPC_FEATURE2_VEC_CRYPTO); ret = 0; error: close_image(img); return ret; }
int prepare_inventory(InventoryEntry *he) { struct pid pid; struct { struct pstree_item i; struct dmp_info d; } crt = { .i.pid = &pid }; pr_info("Perparing image inventory (version %u)\n", CRTOOLS_IMAGES_V1); he->img_version = CRTOOLS_IMAGES_V1_1; he->fdinfo_per_id = true; he->has_fdinfo_per_id = true; he->ns_per_id = true; he->has_ns_per_id = true; he->has_lsmtype = true; he->lsmtype = host_lsm_type(); crt.i.pid->state = TASK_ALIVE; crt.i.pid->real = getpid(); if (get_task_ids(&crt.i)) return -1; he->has_root_cg_set = true; if (dump_task_cgroup(NULL, &he->root_cg_set, NULL)) return -1; he->root_ids = crt.i.ids; return 0; } static struct cr_imgset *alloc_cr_imgset(int nr) { struct cr_imgset *cr_imgset; unsigned int i; cr_imgset = xmalloc(sizeof(*cr_imgset)); if (cr_imgset == NULL) return NULL; cr_imgset->_imgs = xmalloc(nr * sizeof(struct cr_img *)); if (cr_imgset->_imgs == NULL) { xfree(cr_imgset); return NULL; } for (i = 0; i < nr; i++) cr_imgset->_imgs[i] = NULL; cr_imgset->fd_nr = nr; return cr_imgset; } static void __close_cr_imgset(struct cr_imgset *cr_imgset) { unsigned int i; if (!cr_imgset) return; for (i = 0; i < cr_imgset->fd_nr; i++) { if (!cr_imgset->_imgs[i]) continue; close_image(cr_imgset->_imgs[i]); cr_imgset->_imgs[i] = NULL; } }
static int open_remap_ghost(struct reg_file_info *rfi, RemapFilePathEntry *rfe) { struct ghost_file *gf; GhostFileEntry *gfe = NULL; struct cr_img *img; list_for_each_entry(gf, &ghost_files, list) if (gf->id == rfe->remap_id) goto gf_found; /* * Ghost not found. We will create one in the same dir * as the very first client of it thus resolving any * issues with cross-device links. */ pr_info("Opening ghost file %#x for %s\n", rfe->remap_id, rfi->path); gf = shmalloc(sizeof(*gf)); if (!gf) return -1; gf->remap.rpath = xmalloc(PATH_MAX); if (!gf->remap.rpath) goto err; img = open_image(CR_FD_GHOST_FILE, O_RSTR, rfe->remap_id); if (!img) goto err; if (pb_read_one(img, &gfe, PB_GHOST_FILE) < 0) goto close_ifd; /* * For old formats where optional has_[dev|ino] is * not present we will have zeros here which is quite * a sign for "absent" fields. */ gf->dev = gfe->dev; gf->ino = gfe->ino; gf->remap.rmnt_id = rfi->rfe->mnt_id; if (S_ISDIR(gfe->mode)) strncpy(gf->remap.rpath, rfi->path, PATH_MAX); else ghost_path(gf->remap.rpath, PATH_MAX, rfi, rfe); if (create_ghost(gf, gfe, img)) goto close_ifd; ghost_file_entry__free_unpacked(gfe, NULL); close_image(img); gf->id = rfe->remap_id; gf->remap.users = 0; gf->remap.is_dir = S_ISDIR(gfe->mode); gf->remap.owner = gfe->uid; list_add_tail(&gf->list, &ghost_files); gf_found: rfi->remap = &gf->remap; return 0; close_ifd: close_image(img); err: if (gfe) ghost_file_entry__free_unpacked(gfe, NULL); xfree(gf->remap.rpath); shfree_last(gf); return -1; }
int main(int argc, char *argv[]) { int fd; /* fd to Erlang node */ unsigned char buf[BUFSIZE]; /* Buffer for incoming message */ ErlMessage emsg; /* Incoming message */ int c_node; /* C-Node number */ char cookie[EI_MAX_COOKIE_SIZE+1]; /* Shared cookie */ short creation; /* ?? */ char *erlang_node; /* Erlang node to connect to */ char *cookie_opt; /* Where to source our cookie */ char *cookie_data; /* Either the filename or literal cookie */ ETERM *fromp, *msgp, *fnp, *argp, *resp; int received, loop = 1; if (argc < 5) { quit_with_error("invalid_args"); } c_node = atoi(argv[1]); cookie_opt = argv[2]; cookie_data = argv[3]; creation = 0; erlang_node = argv[4]; erl_init(NULL, 0); get_cookie(cookie_opt, cookie_data, cookie); if (!erl_connect_init(c_node, cookie, creation)) { quit_with_error("erl_connect_init"); } if ((fd = erl_connect(erlang_node)) < 0) { quit_with_error("erl_connect"); } while (loop) { received = erl_receive_msg(fd, buf, BUFSIZE, &emsg); if (received == ERL_TICK) { /* ignore */ } else if (received == ERL_ERROR) { loop = 0; } else { if (emsg.type == ERL_REG_SEND) { fromp = erl_element(2, emsg.msg); msgp = erl_element(3, emsg.msg); fnp = erl_element(1, msgp); argp = erl_element(2, msgp); if (is_function(fnp, "stop")) { loop = 0; resp = erl_format("{c_node, ~i, ok}", c_node); } else if (is_function(fnp, "new_image_blank")) { resp = new_image_blank(argp, c_node); } else if (is_function(fnp, "write_to_png")) { resp = write_to_png(argp, c_node); } else if (is_function(fnp, "close_image")) { resp = close_image(argp, c_node); } else if (is_function(fnp, "save")) { resp = save(argp, c_node); } else if (is_function(fnp, "restore")) { resp = restore(argp, c_node); } else if (is_function(fnp, "set_line_width")) { resp = set_line_width(argp, c_node); } else if (is_function(fnp, "set_source_rgba")) { resp = set_source_rgba(argp, c_node); } else if (is_function(fnp, "set_operator")) { resp = set_operator(argp, c_node); } else if (is_function(fnp, "move_to")) { resp = move_to(argp, c_node); } else if (is_function(fnp, "line_to")) { resp = line_to(argp, c_node); } else if (is_function(fnp, "curve_to")) { resp = curve_to(argp, c_node); } else if (is_function(fnp, "rel_move_to")) { resp = rel_move_to(argp, c_node); } else if (is_function(fnp, "rel_line_to")) { resp = rel_line_to(argp, c_node); } else if (is_function(fnp, "rel_curve_to")) { resp = rel_curve_to(argp, c_node); } else if (is_function(fnp, "rectangle")) { resp = rectangle(argp, c_node); } else if (is_function(fnp, "arc")) { resp = arc(argp, c_node); } else if (is_function(fnp, "arc_negative")) { resp = arc_negative(argp, c_node); } else if (is_function(fnp, "close_path")) { resp = close_path(argp, c_node); } else if (is_function(fnp, "paint")) { resp = paint(argp, c_node); } else if (is_function(fnp, "fill")) { resp = fill(argp, c_node); } else if (is_function(fnp, "fill_preserve")) { resp = fill_preserve(argp, c_node); } else if (is_function(fnp, "stroke")) { resp = stroke(argp, c_node); } else if (is_function(fnp, "stroke_preserve")) { resp = stroke_preserve(argp, c_node); } else if (is_function(fnp, "translate")) { resp = translate(argp, c_node); } else if (is_function(fnp, "scale")) { resp = scale(argp, c_node); } else if (is_function(fnp, "rotate")) { resp = rotate(argp, c_node); } else if (is_function(fnp, "select_font")) { resp = select_font_face(argp, c_node); } else if (is_function(fnp, "set_font_size")) { resp = set_font_size(argp, c_node); } else if (is_function(fnp, "show_text")) { resp = show_text(argp, c_node); } else if (is_function(fnp, "text_extents")) { resp = text_extents(argp, c_node); } else if (is_function(fnp, "surface_create_from_png")) { resp = surface_create_from_png(argp, c_node); } else if (is_function(fnp, "surface_create_from_png_stream")) { resp = surface_create_from_png_stream(argp, c_node); } else if (is_function(fnp, "surface_get_width")) { resp = surface_get_width(argp, c_node); } else if (is_function(fnp, "surface_get_height")) { resp = surface_get_height(argp, c_node); } else if (is_function(fnp, "surface_destroy")) { resp = surface_destroy(argp, c_node); } else if (is_function(fnp, "set_source_surface")) { resp = set_source_surface(argp, c_node); } else if (is_function(fnp, "write_to_png_stream")) { resp = write_to_png_stream(argp, c_node); } else { resp = erl_format("{c_node, ~i, {error, '~s'}}", c_node, "unknown command"); } erl_send(fd, fromp, resp); erl_free_term(emsg.from); erl_free_term(emsg.msg); erl_free_term(fromp); erl_free_term(msgp); erl_free_term(fnp); erl_free_term(argp); erl_free_term(resp); } } } exit(EXIT_SUCCESS); }