commit
[crak.git] / src / restore.c
blob4a8ce3797b1bfeb2046e4534ec3006f46d6d499d
1 #include <linux/smp.h>
2 #include <linux/kernel.h>
3 #include <linux/module.h>
4 #include <linux/fs.h>
5 #include <linux/cdev.h>
6 #include <linux/binfmts.h>
7 #include <asm/mman.h>
8 #include <asm/uaccess.h>
9 #include <linux/file.h>
10 #include <linux/sys.h>
11 #include <asm/page.h>
12 #include "config.h"
13 #include "ckpt.h"
14 #include "ckptlib.h"
16 #include <linux/mount.h>
17 #include <linux/swapops.h>
18 #include <linux/sched.h>
21 struct header * restore_header_struct(struct file *file)
23 static struct header hdr;
24 int ret;
27 ret = file->f_op->read(file, (char*)&hdr, sizeof(hdr), &file->f_pos);
29 if ((ret != sizeof(hdr)) || ckpt_strncmp(hdr.signature, "CKPT", 4) ||
30 hdr.major_version != CKPT_MAJOR ||
31 hdr.minor_version != CKPT_MINOR) {
32 printk("Invalid checkpoint file\n");
33 return NULL;
37 if (((hdr.uid != current->euid && hdr.uid != current->uid)
38 && (current->uid && current->euid)))
39 return NULL;
42 /* restore uid/gid */
43 if (current->uid == 0 || current->euid == 0) {
44 current->uid = hdr.uid;
45 current->euid = hdr.euid;
46 current->suid = hdr.suid;
47 current->fsuid = hdr.fsuid;
48 current->gid = hdr.gid;
49 current->egid = hdr.egid;
50 current->sgid = hdr.sgid;
51 current->fsgid = hdr.fsgid;
52 current->group_info->ngroups = hdr.ngroups;
55 return &hdr;
58 struct pt_regs * restore_registers(struct file *file)
60 static struct pt_regs regs;
62 if (verbose)
63 printk("Restoring registers\n");
66 file->f_op->read(file, (void*)&regs, sizeof(regs), &file->f_pos);
67 memcpy(task_pt_regs(current), &regs, sizeof(regs));
68 printk("REGISTERS:::TEST::: CS:%08x, SS:%08x, EIP:%p\n", regs.cs, regs.ss, (void*)regs.ip);
69 return &regs;
72 void restore_memory_struct(struct file *file, struct header *hdr)
74 struct memory mem;
76 if (verbose)
77 printk("Reading header: %d segments\n",hdr->num_segments);
79 ckpt_strncpy(current->comm, hdr->comm, 16);
82 current->state = TASK_INTERRUPTIBLE;
85 if (verbose)
86 printk("Restoring vm structure\n");
88 file->f_op->read(file, (void*)&mem, sizeof(struct memory), &file->f_pos);
90 current->mm->start_code = mem.start_code;
91 current->mm->end_code = mem.end_code;
92 current->mm->start_data = mem.start_data;
93 current->mm->end_data = mem.end_data;
94 current->mm->start_brk = mem.start_brk;
95 current->mm->brk = mem.brk;
96 current->mm->start_stack = mem.start_stack;
97 current->mm->arg_start = mem.arg_start;
98 current->mm->arg_end = mem.arg_end;
99 current->mm->env_start = mem.env_start;
100 current->mm->env_end = mem.env_end;
103 unsigned long restore_vm_areas(struct file *file, int count, int from)
105 int i;
106 int err;
107 unsigned long size;
108 unsigned long mmap_prot, mmap_flags, ret = 0;
109 struct segments seg;
110 mm_segment_t fs = get_fs();
112 if (verbose)
113 printk("Restoring vm areas\n");
115 /* Map all the segments */
116 for (i = 0; i < count; i++) {
117 printk("Restoring vm areas for the %d time(s)\n", i + 1);
120 set_fs(KERNEL_DS);
121 err = -EIO;
122 file->f_op->read(file, (void*)&seg, sizeof(struct segments), &file->f_pos);
123 size = seg.vm_end - seg.vm_start;
124 set_fs(fs);
126 mmap_prot = seg.flags & 7;
127 mmap_flags = get_mmap_flags(seg.flags);
129 if (!seg.shared) {
130 mmap_flags &= ~VM_EXECUTABLE;
133 if (!seg.shared) {
134 int growsdown = mmap_flags & MAP_GROWSDOWN;
136 mmap_flags &= ~ MAP_DENYWRITE;
137 if (growsdown)
138 mmap_flags &= ~MAP_GROWSDOWN;
140 ret = do_mmap(file, seg.vm_start, size, mmap_prot,
141 mmap_flags | MAP_FIXED, from);
142 if (growsdown)
143 mmap_flags |= MAP_GROWSDOWN;
145 from += size;
146 } else {
147 #if 1
148 struct file *mfile;
150 mmap_flags &= ~ MAP_DENYWRITE;
151 mfile = open_private_file(0, seg.filename, O_RDONLY,
152 mmap_prot & PROT_WRITE ?3:1);
153 ret = do_mmap(mfile, seg.vm_start, size, mmap_prot,
154 mmap_flags | MAP_FIXED, seg.pgoff);
155 #else
157 int growsdown = mmap_flags & MAP_GROWSDOWN;
159 mmap_flags &= ~ MAP_DENYWRITE;
160 if (growsdown)
161 mmap_flags &= ~MAP_GROWSDOWN;
163 ret = do_mmap(file, seg.vm_start, size, mmap_prot,
164 mmap_flags | MAP_FIXED, from);
165 if (growsdown)
166 mmap_flags |= MAP_GROWSDOWN;
168 from += size;
169 #endif
172 if (ret != seg.vm_start) {
173 printk("Restart: Mapping error at map #%d.",i + 1);
174 printk("Sent %lX and got %X (%ld)\n",
175 seg.vm_start, (__u32)ret, (signed long)ret);
177 return 0;
178 } else {
179 printk("file mapped successfuly at: %p\n", (void *)ret);
183 return from;
187 int restore_open_files(struct file *file)
189 struct open_files_hdr open_files_hdr;
190 struct open_files open_files;
191 int i;
194 if (verbose)
195 printk("Restoring file table\n");
197 if (file->f_op->read(file, (void*)&open_files_hdr, sizeof(struct open_files_hdr), &file->f_pos)
198 != sizeof(struct open_files_hdr)) {
199 return 1;
202 for (i = 0; i < open_files_hdr.number_open_files; i++) {
203 struct file *fdes;
204 struct inode *inode;
206 if (file->f_op->read(file, (void*)&open_files, sizeof(struct open_files), &file->f_pos)
207 != sizeof(struct open_files)) {
208 return 1;
211 fdes = current->files->fdt->fd[open_files.fd];
212 inode = fdes->f_dentry->d_inode;
214 switch (open_files.type) {
215 case CKPT_DUP:
216 case CKPT_FILE:
217 /* We don't need to do anything, since
218 someone (restart) has already dupped/opened the
219 file. We just skip this entry.
222 file->f_pos += open_files.entry_size - sizeof(struct open_files);
223 break;
224 /*! \todo Handle the case of restarting a pipe file. Refer to do_checkpoint()
225 for details.*/
228 case CKPT_PIPE:
229 if ( !fdes ||
230 !S_ISFIFO(inode->i_mode) ) {
231 printk("WARNING: restart: fd %d was not previously open or is not a pipe!!!\n",open_files.fd);
233 send_sig(SIGKILL, current, 0);
234 goto out;
237 // Now read the information left in the pipe
238 if (open_files.entry_size>0) {
239 f->f_op->read(f, (void*)PIPE_BASE(*inode), open_files.entry_size, &f->f_pos);
240 PIPE_LEN(*inode)+=open_files.entry_size;
242 break;
244 case CKPT_SOCK:
245 printk("Socket not supported\n");
246 return 1;
250 return 0;
254 void restore_signal(struct file *file)
256 sigset_t blocked;
257 struct sighand_struct sighand;
258 int i;
260 if (verbose)
261 printk("Restoring signal handlers\n");
263 file->f_op->read(file, (void*)&blocked, sizeof(sigset_t), &file->f_pos);
264 file->f_op->read(file, (void*)&sighand, sizeof(sighand), &file->f_pos);
266 spin_lock_irq(&current->sighand->siglock);
268 current->blocked = blocked;
269 for (i = 0; i < _NSIG; i++)
270 current->sighand->action[i] = sighand.action[i];
272 spin_unlock_irq(&current->sighand->siglock);
276 void restore_cwd(struct file *file)
278 int size;
280 /* just skip it */
281 file->f_op->read(file, (void*)&size, sizeof(int), &file->f_pos);
282 file->f_pos += size;