commit
[crak.git] / src / restore.c
blob95254e86f5c33bdf44570b661192f3c89385afb5
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 * get_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);
68 return &regs;
71 void restore_memory_struct(struct file *file, struct header *hdr)
73 struct memory mem;
75 if (verbose)
76 printk("Reading header: %d segments\n",hdr->num_segments);
78 ckpt_strncpy(current->comm, hdr->comm, 16);
81 current->state = TASK_INTERRUPTIBLE;
84 if (verbose)
85 printk("Restoring vm structure\n");
87 file->f_op->read(file, (void*)&mem, sizeof(struct memory), &file->f_pos);
89 current->mm->start_code = mem.start_code;
90 current->mm->end_code = mem.end_code;
91 current->mm->start_data = mem.start_data;
92 current->mm->end_data = mem.end_data;
93 current->mm->start_brk = mem.start_brk;
94 current->mm->brk = mem.brk;
95 current->mm->start_stack = mem.start_stack;
96 current->mm->arg_start = mem.arg_start;
97 current->mm->arg_end = mem.arg_end;
98 current->mm->env_start = mem.env_start;
99 current->mm->env_end = mem.env_end;
102 unsigned long restore_vm_areas(struct file *file, int count, int from)
104 int i;
105 int err;
106 unsigned long size;
107 unsigned long mmap_prot, mmap_flags, ret = 0;
108 struct segments seg;
109 mm_segment_t fs = get_fs();
111 if (verbose)
112 printk("Restoring vm areas\n");
114 /* Map all the segments */
115 for (i = 0; i < count; i++) {
116 printk("Restoring vm areas for the %d time(s)\n", i + 1);
119 set_fs(KERNEL_DS);
120 err = -EIO;
121 file->f_op->read(file, (void*)&seg, sizeof(struct segments), &file->f_pos);
122 size = seg.vm_end - seg.vm_start;
123 set_fs(fs);
125 mmap_prot = seg.flags & 7;
126 mmap_flags = get_mmap_flags(seg.flags);
128 if (!seg.shared) {
129 mmap_flags &= ~VM_EXECUTABLE;
132 if (!seg.shared) {
133 int growsdown = mmap_flags & MAP_GROWSDOWN;
135 mmap_flags &= ~ MAP_DENYWRITE;
136 if (growsdown)
137 mmap_flags &= ~MAP_GROWSDOWN;
139 ret = do_mmap(file, seg.vm_start, size, mmap_prot,
140 mmap_flags | MAP_FIXED, from);
141 if (growsdown)
142 mmap_flags |= MAP_GROWSDOWN;
144 from += size;
145 } else {
146 #if 1
147 struct file *mfile;
149 print_prot(mmap_prot); print_flags(seg.flags);
150 mmap_flags &= ~ MAP_DENYWRITE;
151 mmap_flags |= VM_EXECUTABLE;
152 mfile = open_private_file(0, seg.filename, O_RDONLY,
153 mmap_prot & PROT_WRITE ?3:1);
154 if (!mfile) {
155 printk("open file %s error\n", seg.filename);
156 return -1;
158 printk("size: %ld == pgoff: %ld\n", size, seg.pgoff);
159 ret = do_mmap(mfile, seg.vm_start, size,
160 mmap_prot, mmap_flags | MAP_FIXED,
161 seg.pgoff * PAGE_SIZE);
162 #else
164 int growsdown = mmap_flags & MAP_GROWSDOWN;
166 mmap_flags &= ~ MAP_DENYWRITE;
167 if (growsdown)
168 mmap_flags &= ~MAP_GROWSDOWN;
170 ret = do_mmap(file, seg.vm_start, size, mmap_prot,
171 mmap_flags | MAP_FIXED, from);
172 if (growsdown)
173 mmap_flags |= MAP_GROWSDOWN;
175 from += size;
176 #endif
179 if (ret != seg.vm_start) {
180 printk("Restart: Mapping error at map #%d.",i + 1);
181 printk("Sent %lX and got %X (%ld)\n",
182 seg.vm_start, (__u32)ret, (signed long)ret);
184 return ret;
185 } else {
186 printk("file mapped successfuly at: %p\n", (void *)ret);
190 return from;
194 int restore_open_files(struct file *file)
196 struct open_files_hdr open_files_hdr;
197 struct open_files open_files;
198 int i;
201 if (verbose)
202 printk("Restoring file table\n");
204 if (file->f_op->read(file, (void*)&open_files_hdr, sizeof(struct open_files_hdr), &file->f_pos)
205 != sizeof(struct open_files_hdr)) {
206 return 1;
209 for (i = 0; i < open_files_hdr.number_open_files; i++) {
210 struct file *fdes;
211 struct inode *inode;
213 if (file->f_op->read(file, (void*)&open_files, sizeof(struct open_files), &file->f_pos)
214 != sizeof(struct open_files)) {
215 return 1;
218 fdes = current->files->fdt->fd[open_files.fd];
219 inode = fdes->f_dentry->d_inode;
221 switch (open_files.type) {
222 case CKPT_DUP:
223 case CKPT_FILE:
224 /* We don't need to do anything, since
225 someone (restart) has already dupped/opened the
226 file. We just skip this entry.
229 file->f_pos += open_files.entry_size - sizeof(struct open_files);
230 break;
231 /*! \todo Handle the case of restarting a pipe file. Refer to do_checkpoint()
232 for details.*/
235 case CKPT_PIPE:
236 if ( !fdes ||
237 !S_ISFIFO(inode->i_mode) ) {
238 printk("WARNING: restart: fd %d was not previously open or is not a pipe!!!\n",open_files.fd);
240 send_sig(SIGKILL, current, 0);
241 goto out;
244 // Now read the information left in the pipe
245 if (open_files.entry_size>0) {
246 f->f_op->read(f, (void*)PIPE_BASE(*inode), open_files.entry_size, &f->f_pos);
247 PIPE_LEN(*inode)+=open_files.entry_size;
249 break;
251 case CKPT_SOCK:
252 printk("Socket not supported\n");
253 return 1;
257 return 0;
261 void restore_signal(struct file *file)
263 sigset_t blocked;
264 struct sighand_struct sighand;
265 int i;
267 if (verbose)
268 printk("Restoring signal handlers\n");
270 file->f_op->read(file, (void*)&blocked, sizeof(sigset_t), &file->f_pos);
271 file->f_op->read(file, (void*)&sighand, sizeof(sighand), &file->f_pos);
273 spin_lock_irq(&current->sighand->siglock);
275 current->blocked = blocked;
276 for (i = 0; i < _NSIG; i++)
277 current->sighand->action[i] = sighand.action[i];
279 spin_unlock_irq(&current->sighand->siglock);
283 void restore_cwd(struct file *file)
285 int size;
287 /* just skip it */
288 file->f_op->read(file, (void*)&size, sizeof(int), &file->f_pos);
289 file->f_pos += size;