예제 #1
0
파일: tape.c 프로젝트: Alkzndr/freebsd
/*
 * skip over bit maps on the tape
 */
void
skipmaps(void)
{

	while (spcl.c_type == TS_BITS || spcl.c_type == TS_CLRI)
		skipfile();
}
예제 #2
0
/*
 * skip over all the directories on the tape
 */
void
skipdirs(void)
{

	while (curfile.dip && (curfile.dip->di_mode & IFMT) == IFDIR) {
		skipfile();
	}
}
예제 #3
0
파일: dirs.c 프로젝트: sofuture/bitrig
/*
 * skip over all the directories on the tape
 */
void
skipdirs(void)
{

	while (curfile.ino && (curfile.mode & IFMT) == IFDIR) {
		skipfile();
	}
}
예제 #4
0
파일: tape.c 프로젝트: Alkzndr/freebsd
int
extractfile(char *name)
{
	int flags;
	uid_t uid;
	gid_t gid;
	mode_t mode;
	int extsize;
	struct timeval mtimep[2], ctimep[2];
	struct entry *ep;
	char *buf;

	curfile.name = name;
	curfile.action = USING;
	mtimep[0].tv_sec = curfile.atime_sec;
	mtimep[0].tv_usec = curfile.atime_nsec / 1000;
	mtimep[1].tv_sec = curfile.mtime_sec;
	mtimep[1].tv_usec = curfile.mtime_nsec / 1000;
	ctimep[0].tv_sec = curfile.atime_sec;
	ctimep[0].tv_usec = curfile.atime_nsec / 1000;
	ctimep[1].tv_sec = curfile.birthtime_sec;
	ctimep[1].tv_usec = curfile.birthtime_nsec / 1000;
	extsize = curfile.extsize;
	uid = getuid();
	if (uid == 0)
		uid = curfile.uid;
	gid = curfile.gid;
	mode = curfile.mode;
	flags = curfile.file_flags;
	switch (mode & IFMT) {

	default:
		fprintf(stderr, "%s: unknown file mode 0%o\n", name, mode);
		skipfile();
		return (FAIL);

	case IFSOCK:
		vprintf(stdout, "skipped socket %s\n", name);
		skipfile();
		return (GOOD);

	case IFDIR:
		if (mflag) {
			ep = lookupname(name);
			if (ep == NULL || ep->e_flags & EXTRACT)
				panic("unextracted directory %s\n", name);
			skipfile();
			return (GOOD);
		}
		vprintf(stdout, "extract file %s\n", name);
		return (genliteraldir(name, curfile.ino));

	case IFLNK:
		lnkbuf[0] = '\0';
		pathlen = 0;
		buf = setupextattr(extsize);
		getfile(xtrlnkfile, xtrattr, xtrlnkskip);
		if (pathlen == 0) {
			vprintf(stdout,
			    "%s: zero length symbolic link (ignored)\n", name);
			return (GOOD);
		}
		if (linkit(lnkbuf, name, SYMLINK) == GOOD) {
			if (extsize > 0)
				set_extattr_link(name, buf, extsize);
			(void) lchown(name, uid, gid);
			(void) lchmod(name, mode);
			(void) lutimes(name, ctimep);
			(void) lutimes(name, mtimep);
			(void) lchflags(name, flags);
			return (GOOD);
		}
		return (FAIL);

	case IFIFO:
		vprintf(stdout, "extract fifo %s\n", name);
		if (Nflag) {
			skipfile();
			return (GOOD);
		}
		if (uflag)
			(void) unlink(name);
		if (mkfifo(name, 0600) < 0) {
			fprintf(stderr, "%s: cannot create fifo: %s\n",
			    name, strerror(errno));
			skipfile();
			return (FAIL);
		}
		if (extsize == 0) {
			skipfile();
		} else {
			buf = setupextattr(extsize);
			getfile(xtrnull, xtrattr, xtrnull);
			set_extattr_file(name, buf, extsize);
		}
		(void) chown(name, uid, gid);
		(void) chmod(name, mode);
		(void) utimes(name, ctimep);
		(void) utimes(name, mtimep);
		(void) chflags(name, flags);
		return (GOOD);

	case IFCHR:
	case IFBLK:
		vprintf(stdout, "extract special file %s\n", name);
		if (Nflag) {
			skipfile();
			return (GOOD);
		}
		if (uflag)
			(void) unlink(name);
		if (mknod(name, (mode & (IFCHR | IFBLK)) | 0600,
		    (int)curfile.rdev) < 0) {
			fprintf(stderr, "%s: cannot create special file: %s\n",
			    name, strerror(errno));
			skipfile();
			return (FAIL);
		}
		if (extsize == 0) {
			skipfile();
		} else {
			buf = setupextattr(extsize);
			getfile(xtrnull, xtrattr, xtrnull);
			set_extattr_file(name, buf, extsize);
		}
		(void) chown(name, uid, gid);
		(void) chmod(name, mode);
		(void) utimes(name, ctimep);
		(void) utimes(name, mtimep);
		(void) chflags(name, flags);
		return (GOOD);

	case IFREG:
		vprintf(stdout, "extract file %s\n", name);
		if (Nflag) {
			skipfile();
			return (GOOD);
		}
		if (uflag)
			(void) unlink(name);
		if ((ofile = open(name, O_WRONLY | O_CREAT | O_TRUNC,
		    0600)) < 0) {
			fprintf(stderr, "%s: cannot create file: %s\n",
			    name, strerror(errno));
			skipfile();
			return (FAIL);
		}
		buf = setupextattr(extsize);
		getfile(xtrfile, xtrattr, xtrskip);
		if (extsize > 0)
			set_extattr_fd(ofile, name, buf, extsize);
		(void) fchown(ofile, uid, gid);
		(void) fchmod(ofile, mode);
		(void) futimes(ofile, ctimep);
		(void) futimes(ofile, mtimep);
		(void) fchflags(ofile, flags);
		(void) close(ofile);
		return (GOOD);
	}
	/* NOTREACHED */
}
예제 #5
0
/*
 * This is the routine used to extract files for the 'x' and 'i' commands.
 * Efficiently extract a subset of the files on a tape.
 */
void
createfiles(void)
{
	ino_t first, next, last;
	struct entry *ep;
	long curvol;

	vprintf(stdout, "Extract requested files\n");
	curfile.action = SKIP;
	getvol((long)1);
	skipmaps();
	skipdirs();
	first = lowerbnd(ROOTINO);
	last = upperbnd(maxino - 1);
	for (;;) {
		curvol = volno;
		first = lowerbnd(first);
		last = upperbnd(last);
		/*
		 * Check to see if any files remain to be extracted
		 */
		if (first > last)
			return;
		if (Dflag) {
			if (curfile.ino == maxino)
				return;
			if((ep = lookupino(curfile.ino)) != NULL &&
			    (ep->e_flags & (NEW|EXTRACT))) {
				goto justgetit;
			} else {
				skipfile();
				continue;
			}
		}
		/*
		 * Reject any volumes with inodes greater than the last
		 * one needed, so that we can quickly skip backwards to
		 * a volume containing useful inodes. We can't do this
		 * if there are no further volumes available (curfile.ino
		 * >= maxino) or if we are already at the first tape.
		 */
		if (curfile.ino > last && curfile.ino < maxino && volno > 1) {
			curfile.action = SKIP;
			getvol((long)0);
			skipmaps();
			skipdirs();
			continue;
		}
		/*
		 * Decide on the next inode needed.
		 * Skip across the inodes until it is found
		 * or a volume change is encountered
		 */
		if (curfile.ino < maxino) {
			next = lowerbnd(curfile.ino);
			while (next > curfile.ino && volno == curvol)
				skipfile();
			if (volno != curvol) {
				skipmaps();
				skipdirs();
				continue;
			}
		} else {
			/*
			 * No further volumes or inodes available. Set
			 * `next' to the first inode, so that a warning
			 * is emitted below for each missing file.
			 */
			next = first;
		}
		/*
		 * If the current inode is greater than the one we were
		 * looking for then we missed the one we were looking for.
		 * Since we only attempt to extract files listed in the
		 * dump map, the lost files must have been due to a tape
		 * read error, or a file that was removed while the dump
		 * was in progress. Thus we report all requested files
		 * between the one we were looking for, and the one we
		 * found as missing, and delete their request flags.
		 */
		while (next < curfile.ino) {
			ep = lookupino(next);
			if (ep == NULL)
				panic("corrupted symbol table\n");
			fprintf(stderr, "%s: not found on tape\n", myname(ep));
			ep->e_flags &= ~NEW;
			next = lowerbnd(next);
		}
		/*
		 * The current inode is the one that we are looking for,
		 * so extract it per its requested name.
		 */
		if (next == curfile.ino && next <= last) {
			ep = lookupino(next);
			if (ep == NULL)
				panic("corrupted symbol table\n");
justgetit:
			(void) extractfile(myname(ep));
			ep->e_flags &= ~NEW;
			if (volno != curvol)
				skipmaps();
		}
	}
}
예제 #6
0
/*
 * This is the routine used to extract files for the 'r' command.
 * Extract new leaves.
 */
void
createleaves(char *symtabfile)
{
	struct entry *ep;
	ino_t first;
	long curvol;

	if (command == 'R') {
		vprintf(stdout, "Continue extraction of new leaves\n");
	} else {
		vprintf(stdout, "Extract new leaves.\n");
		dumpsymtable(symtabfile, volno);
	}
	first = lowerbnd(ROOTINO);
	curvol = volno;
	while (curfile.ino < maxino) {
		first = lowerbnd(first);
		/*
		 * If the next available file is not the one which we
		 * expect then we have missed one or more files. Since
		 * we do not request files that were not on the tape,
		 * the lost files must have been due to a tape read error,
		 * or a file that was removed while the dump was in progress.
		 */
		while (first < curfile.ino) {
			ep = lookupino(first);
			if (ep == NULL)
				panic("%ju: bad first\n", (uintmax_t)first);
			fprintf(stderr, "%s: not found on tape\n", myname(ep));
			ep->e_flags &= ~(NEW|EXTRACT);
			first = lowerbnd(first);
		}
		/*
		 * If we find files on the tape that have no corresponding
		 * directory entries, then we must have found a file that
		 * was created while the dump was in progress. Since we have
		 * no name for it, we discard it knowing that it will be
		 * on the next incremental tape.
		 */
		if (first != curfile.ino) {
			fprintf(stderr, "expected next file %ju, got %ju\n",
			    (uintmax_t)first, (uintmax_t)curfile.ino);
			skipfile();
			goto next;
		}
		ep = lookupino(curfile.ino);
		if (ep == NULL)
			panic("unknown file on tape\n");
		if ((ep->e_flags & (NEW|EXTRACT)) == 0)
			badentry(ep, "unexpected file on tape");
		/*
		 * If the file is to be extracted, then the old file must
		 * be removed since its type may change from one leaf type
		 * to another (e.g. "file" to "character special").
		 */
		if ((ep->e_flags & EXTRACT) != 0) {
			removeleaf(ep);
			ep->e_flags &= ~REMOVED;
		}
		(void) extractfile(myname(ep));
		ep->e_flags &= ~(NEW|EXTRACT);
		/*
		 * We checkpoint the restore after every tape reel, so
		 * as to simplify the amount of work required by the
		 * 'R' command.
		 */
	next:
		if (curvol != volno) {
			dumpsymtable(symtabfile, volno);
			skipmaps();
			curvol = volno;
		}
	}
}
예제 #7
0
파일: tape.c 프로젝트: sofuture/bitrig
int
extractfile(char *name)
{
	u_int flags;
	uid_t uid;
	gid_t gid;
	mode_t mode;
	struct timeval mtimep[2], ctimep[2];
	struct entry *ep;
	int setbirth;

	curfile.name = name;
	curfile.action = USING;
	mtimep[0].tv_sec = curfile.atime_sec;
	mtimep[0].tv_usec = curfile.atime_nsec / 1000;
	mtimep[1].tv_sec = curfile.mtime_sec;
	mtimep[1].tv_usec = curfile.mtime_nsec / 1000;

	setbirth = curfile.birthtime_sec != 0;
	if (setbirth) {
		ctimep[0].tv_sec = curfile.atime_sec;
		ctimep[0].tv_usec = curfile.atime_nsec / 1000;
		ctimep[1].tv_sec = curfile.birthtime_sec;
		ctimep[1].tv_usec = curfile.birthtime_nsec / 1000;
	}
	uid = curfile.uid;
	gid = curfile.gid;
	mode = curfile.mode;
	flags = curfile.file_flags;
	switch (mode & IFMT) {

	default:
		fprintf(stderr, "%s: unknown file mode 0%o\n", name, mode);
		skipfile();
		return (FAIL);

	case IFSOCK:
		Vprintf(stdout, "skipped socket %s\n", name);
		skipfile();
		return (GOOD);

	case IFDIR:
		if (mflag) {
			ep = lookupname(name);
			if (ep == NULL || ep->e_flags & EXTRACT)
				panic("unextracted directory %s\n", name);
			skipfile();
			return (GOOD);
		}
		Vprintf(stdout, "extract file %s\n", name);
		return (genliteraldir(name, curfile.ino));

	case IFLNK: {
			lnkbuf[0] = '\0';
			pathlen = 0;
			getfile(xtrlnkfile, xtrlnkskip);
			if (pathlen == 0) {
				Vprintf(stdout,
				    "%s: zero length symbolic link (ignored)\n",
				     name);
				return (GOOD);
			}
			if (linkit(lnkbuf, name, SYMLINK) == FAIL)
				return (FAIL);
			(void)lchown(name, uid, gid);
			return (GOOD);
		}

	case IFCHR:
	case IFBLK:
		Vprintf(stdout, "extract special file %s\n", name);
		if (Nflag) {
			skipfile();
			return (GOOD);
		}
		if (mknod(name, mode, (int)curfile.rdev) < 0) {
			warn("%s: cannot create special file", name);
			skipfile();
			return (FAIL);
		}
		(void)chown(name, uid, gid);
		(void)chmod(name, mode);
		(void)chflags(name, flags);
		skipfile();
		if (setbirth)
			(void)utimes(name, ctimep);
		(void)utimes(name, mtimep);
		return (GOOD);

	case IFIFO:
		Vprintf(stdout, "extract fifo %s\n", name);
		if (Nflag) {
			skipfile();
			return (GOOD);
		}
		if (mkfifo(name, mode) < 0) {
			warn("%s: cannot create fifo", name);
			skipfile();
			return (FAIL);
		}
		(void)chown(name, uid, gid);
		(void)chmod(name, mode);
		(void)chflags(name, flags);
		skipfile();
		if (setbirth)
			(void)utimes(name, ctimep);
		(void)utimes(name, mtimep);
		return (GOOD);

	case IFREG:
		Vprintf(stdout, "extract file %s\n", name);
		if (Nflag) {
			skipfile();
			return (GOOD);
		}
		if ((ofile = open(name, O_WRONLY | O_CREAT | O_TRUNC,
		    0666)) < 0) {
			warn("%s: cannot create file", name);
			skipfile();
			return (FAIL);
		}
		(void)fchown(ofile, curfile.uid, curfile.gid);
		(void)fchmod(ofile, mode);
		(void)fchflags(ofile, flags);
		getfile(xtrfile, xtrskip);
		(void)close(ofile);
		if (setbirth)
			(void)utimes(name, ctimep);
		(void)utimes(name, mtimep);
		return (GOOD);
	}
	/* NOTREACHED */
}
예제 #8
0
int
extractfile(char *name)
{
	int flags;
	uid_t uid;
	gid_t gid;
	mode_t mode;
	struct timeval timep[2];
	struct entry *ep;

	curfile.name = name;
	curfile.action = USING;
	timep[0].tv_sec = curfile.dip->di_atime;
	timep[0].tv_usec = curfile.dip->di_atimensec / 1000;
	timep[1].tv_sec = curfile.dip->di_mtime;
	timep[1].tv_usec = curfile.dip->di_mtimensec / 1000;
	uid = curfile.dip->di_uid;
	gid = curfile.dip->di_gid;
	mode = curfile.dip->di_mode;
	flags = curfile.dip->di_flags;
	switch (mode & IFMT) {

	default:
		fprintf(stderr, "%s: unknown file mode 0%o\n", name, mode);
		skipfile();
		return (FAIL);

	case IFSOCK:
		vprintf(stdout, "skipped socket %s\n", name);
		skipfile();
		return (GOOD);

	case IFDIR:
		if (mflag) {
			ep = lookupname(name);
			if (ep == NULL || ep->e_flags & EXTRACT)
				panic("unextracted directory %s\n", name);
			skipfile();
			return (GOOD);
		}
		vprintf(stdout, "extract file %s\n", name);
		return (genliteraldir(name, curfile.ino));

	case IFLNK:
		lnkbuf[0] = '\0';
		pathlen = 0;
		getfile(xtrlnkfile, xtrlnkskip);
		if (pathlen == 0) {
			vprintf(stdout,
			    "%s: zero length symbolic link (ignored)\n", name);
			return (GOOD);
		}
		if (linkit(lnkbuf, name, SYMLINK) == GOOD) {
			lchown(name, uid, gid);
			lchmod(name, mode);
			lutimes(name, timep);
			return (GOOD);
		}
		return (FAIL);

	case IFIFO:
		vprintf(stdout, "extract fifo %s\n", name);
		if (Nflag) {
			skipfile();
			return (GOOD);
		}
		if (uflag && !Nflag)
			unlink(name);
		if (mkfifo(name, mode) < 0) {
			fprintf(stderr, "%s: cannot create fifo: %s\n",
			    name, strerror(errno));
			skipfile();
			return (FAIL);
		}
		chown(name, uid, gid);
		chmod(name, mode);
		utimes(name, timep);
		chflags(name, flags);
		skipfile();
		return (GOOD);

	case IFCHR:
	case IFBLK:
		vprintf(stdout, "extract special file %s\n", name);
		if (Nflag) {
			skipfile();
			return (GOOD);
		}
		if (uflag)
			unlink(name);
		if (mknod(name, mode, (int)curfile.dip->di_rdev) < 0) {
			fprintf(stderr, "%s: cannot create special file: %s\n",
			    name, strerror(errno));
			skipfile();
			return (FAIL);
		}
		chown(name, uid, gid);
		chmod(name, mode);
		utimes(name, timep);
		chflags(name, flags);
		skipfile();
		return (GOOD);

	case IFREG:
		vprintf(stdout, "extract file %s\n", name);
		if (Nflag) {
			skipfile();
			return (GOOD);
		}
		if (uflag)
			unlink(name);
		if ((ofile = open(name, O_WRONLY | O_CREAT | O_TRUNC,
		    0666)) < 0) {
			fprintf(stderr, "%s: cannot create file: %s\n",
			    name, strerror(errno));
			skipfile();
			return (FAIL);
		}
		fchown(ofile, uid, gid);
		fchmod(ofile, mode);
		getfile(xtrfile, xtrskip);
		close(ofile);
		utimes(name, timep);
		chflags(name, flags);
		return (GOOD);
	}
	/* NOTREACHED */
}
예제 #9
0
/*
 * This is the routine used to extract files for the 'x' and 'i' commands.
 * Efficiently extract a subset of the files on a tape.
 */
void
createfiles(void)
{
	ino_t first, next, last;
	struct entry *ep;
	long curvol;

	Vprintf(stdout, "Extract requested files\n");
	curfile.action = SKIP;
	getvol((long)1);
	skipmaps();
	skipdirs();
	first = lowerbnd(ROOTINO);
	last = upperbnd(maxino - 1);
	for (;;) {
		first = lowerbnd(first);
		last = upperbnd(last);
		/*
		 * Check to see if any files remain to be extracted
		 */
		if (first > last)
			return;
		/*
		 * Reject any volumes with inodes greater
		 * than the last one needed
		 */
		while (curfile.ino > last) {
			curfile.action = SKIP;
			getvol((long)0);
			skipmaps();
			skipdirs();
		}
		/*
		 * Decide on the next inode needed.
		 * Skip across the inodes until it is found
		 * or an out of order volume change is encountered
		 */
		next = lowerbnd(curfile.ino);
		do	{
			curvol = volno;
			while (next > curfile.ino && volno == curvol)
				skipfile();
			skipmaps();
			skipdirs();
		} while (volno == curvol + 1);
		/*
		 * If volume change out of order occurred the
		 * current state must be recalculated
		 */
		if (volno != curvol)
			continue;
		/*
		 * If the current inode is greater than the one we were
		 * looking for then we missed the one we were looking for.
		 * Since we only attempt to extract files listed in the
		 * dump map, the lost files must have been due to a tape
		 * read error, or a file that was removed while the dump
		 * was in progress. Thus we report all requested files
		 * between the one we were looking for, and the one we
		 * found as missing, and delete their request flags.
		 */
		while (next < curfile.ino) {
			ep = lookupino(next);
			if (ep == NULL)
				panic("corrupted symbol table\n");
			fprintf(stderr, "%s: not found on tape\n", myname(ep));
			ep->e_flags &= ~NEW;
			next = lowerbnd(next);
		}
		/*
		 * The current inode is the one that we are looking for,
		 * so extract it per its requested name.
		 */
		if (next == curfile.ino && next <= last) {
			ep = lookupino(next);
			if (ep == NULL)
				panic("corrupted symbol table\n");
			(void)extractfile(myname(ep));
			ep->e_flags &= ~NEW;
			if (volno != curvol)
				skipmaps();
		}
	}
}
예제 #10
0
static void
scan_directory(const char *basedir, const char *subdir)
{
	char		path[MAXPGPATH];
	DIR		   *dir;
	struct dirent *de;

	snprintf(path, sizeof(path), "%s/%s", basedir, subdir);
	dir = opendir(path);
	if (!dir)
	{
		fprintf(stderr, _("%s: could not open directory \"%s\": %s\n"),
				progname, path, strerror(errno));
		exit(1);
	}
	while ((de = readdir(dir)) != NULL)
	{
		char		fn[MAXPGPATH];
		struct stat st;

		if (strcmp(de->d_name, ".") == 0 ||
			strcmp(de->d_name, "..") == 0)
			continue;

		/* Skip temporary files */
		if (strncmp(de->d_name,
					PG_TEMP_FILE_PREFIX,
					strlen(PG_TEMP_FILE_PREFIX)) == 0)
			continue;

		/* Skip temporary folders */
		if (strncmp(de->d_name,
					PG_TEMP_FILES_DIR,
					strlen(PG_TEMP_FILES_DIR)) == 0)
			return;

		snprintf(fn, sizeof(fn), "%s/%s", path, de->d_name);
		if (lstat(fn, &st) < 0)
		{
			fprintf(stderr, _("%s: could not stat file \"%s\": %s\n"),
					progname, fn, strerror(errno));
			exit(1);
		}
		if (S_ISREG(st.st_mode))
		{
			char		fnonly[MAXPGPATH];
			char	   *forkpath,
					   *segmentpath;
			BlockNumber segmentno = 0;

			if (skipfile(de->d_name))
				continue;

			/*
			 * Cut off at the segment boundary (".") to get the segment number
			 * in order to mix it into the checksum. Then also cut off at the
			 * fork boundary, to get the relfilenode the file belongs to for
			 * filtering.
			 */
			strlcpy(fnonly, de->d_name, sizeof(fnonly));
			segmentpath = strchr(fnonly, '.');
			if (segmentpath != NULL)
			{
				*segmentpath++ = '\0';
				segmentno = atoi(segmentpath);
				if (segmentno == 0)
				{
					fprintf(stderr, _("%s: invalid segment number %d in file name \"%s\"\n"),
							progname, segmentno, fn);
					exit(1);
				}
			}

			forkpath = strchr(fnonly, '_');
			if (forkpath != NULL)
				*forkpath++ = '\0';

			if (only_relfilenode && strcmp(only_relfilenode, fnonly) != 0)
				/* Relfilenode not to be included */
				continue;

			scan_file(fn, segmentno);
		}
#ifndef WIN32
		else if (S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode))
#else
		else if (S_ISDIR(st.st_mode) || pgwin32_is_junction(fn))
#endif
			scan_directory(path, de->d_name);
	}
	closedir(dir);
}
예제 #11
0
int main(int argc, char **argv) {
  int fd = -1;
  char magicbuf[MAGIC_LEN], *restorename;
  char *version = PACKAGE_VERSION;

  restorename = argv[1];
  if (argc == 1 || (strcmp(argv[1], "--help") == 0 && argc == 2)) {
    printf("%s", theUsage);
    return 1;
  } else if (strcmp (argv[1], "--version") == 0 && argc == 2) {
    printf("%s\n", (version[0] == '\0' ? "Standalone MTCP" : version));
    return 1;
  } else if (restorename[0] == '-' && restorename[1] == '\0') {
    fd = 0; /* read from stdin */
  } else {    /* argv[1] should be a real filename */
    if (-1 == (fd = open(restorename, O_RDONLY))) {
      perror("open");
      return 1; }
  }

  memset(magicbuf, 0, sizeof magicbuf);
  readall(fd, magicbuf, MAGIC_LEN);
  if (memcmp (magicbuf, "DMTCP_CHECKPOINT", MAGIC_LEN) == 0) {
    while (memcmp(magicbuf, MAGIC, MAGIC_LEN) != 0) {
      int i;
      for (i = 0; i < MAGIC_LEN-1; i++)
        magicbuf[i] = magicbuf[i+1];
      magicbuf[MAGIC_LEN-1] = '\0'; /* MAGIC should be a string w/o '\0' */
      if (0 == readall(fd, magicbuf+(MAGIC_LEN-1), 1)) /* if EOF */
        break;
    }
  }
  if (memcmp (magicbuf, MAGIC, MAGIC_LEN) != 0) {
    char command[512];
    fprintf (stderr, "readmtcp: Not an mtcp image; trying it as dmtcp image\n");
    sprintf (command, "gzip -dc %s | %s -", restorename, argv[0]);
    exit( system(command) );
  }


  /* Find where the restore image goes */
  VA restore_begin;
  size_t restore_size;
  void *restore_start; /* will be bound to fnc, mtcp_restore_start */
  void (*finishrestore) (void);

  /* Set the resource limits for stack from saved values */
  struct rlimit stack_rlimit;

#ifdef FAST_CKPT_RST_VIA_MMAP
  Area area;
  fastckpt_read_header(fd, &stack_rlimit, &area, (VA*) &restore_start);
  restore_begin = area.addr;
  restore_size = area.size;
  finishrestore = (void*) fastckpt_get_finishrestore();

  printf("mtcp_restart: saved stack resource limit:" \
	 " soft_lim: %lu, hard_lim: %lu\n",
	 stack_rlimit.rlim_cur, stack_rlimit.rlim_max);
  printf("*** restored libmtcp.so\n");

  printf("%p-%p rwxp %p 00:00 0          [libmtcp.so]\n",
	restore_begin, restore_begin + restore_size, restore_begin);
  printf("restore_start routine: %p\n", restore_start);

  printf("*** finishrestore\n");
  printf("finishrestore routine: %p\n", finishrestore);
#else
  readcs (fd, CS_STACKRLIMIT); /* resource limit for stack */
  readall(fd, &stack_rlimit, sizeof stack_rlimit);
  printf("mtcp_restart: saved stack resource limit:" \
	 " soft_lim: %lu, hard_lim: %lu\n",
	 stack_rlimit.rlim_cur, stack_rlimit.rlim_max);

  printf("*** restored libmtcp.so\n");
  readcs (fd, CS_RESTOREBEGIN); /* beginning of checkpointed libmtcp.so image */
  readall(fd, &restore_begin, sizeof restore_begin);
  readcs (fd, CS_RESTORESIZE); /* size of checkpointed libmtcp.so image */
  readall(fd, &restore_size, sizeof restore_size);
  readcs (fd, CS_RESTORESTART);
  readall(fd, &restore_start, sizeof restore_start);
  readcs (fd, CS_RESTOREIMAGE);
  skipfile (fd, restore_size);

  printf("%p-%p rwxp %p 00:00 0          [libmtcp.so]\n",
	restore_begin, restore_begin + restore_size, restore_begin);
  printf("restore_start routine: %p\n", restore_start);


  printf("*** finishrestore\n");
  readcs (fd, CS_FINISHRESTORE);
  readall(fd, &finishrestore, sizeof finishrestore);
  printf("finishrestore routine: %p\n", finishrestore);


  char linkbuf[FILENAMESIZE];
  int fdnum, linklen ;
  struct stat statbuf;
  off_t offset;

  printf("*** file descriptors\n");
  readcs (fd, CS_FILEDESCRS);
  while (1) {

    /* Read parameters of next file to restore */

    readall(fd, &fdnum, sizeof fdnum);
    if (fdnum < 0) break;
    readall(fd, &statbuf, sizeof statbuf);
    readall(fd, &offset, sizeof offset);
    readall(fd, &linklen, sizeof linklen);
    if ((size_t)linklen >= sizeof linkbuf) {
      printf ("filename too long %d\n", linklen);
      exit(1);
    }
    readall(fd, linkbuf, linklen);
    linkbuf[linklen] = '\0';
  }
#endif

  printf("*** memory sections\n");
  while(1) {
    Area area;
    char cstype;
#ifdef FAST_CKPT_RST_VIA_MMAP
    if (fastckpt_get_next_area_dscr(&area) == 0) break;
#else
    readall(fd, &cstype, sizeof cstype);
    if (cstype == CS_THEEND) break;
    if (cstype != CS_AREADESCRIP) {
      printf ("readmtcp: expected CS_AREADESCRIP but had %d\n", cstype);
      exit(1);
    }

    readall(fd, &area, sizeof area);
    readcs (fd, CS_AREACONTENTS);
#ifdef ANDROID
    if ((area.prot & MTCP_PROT_SKIP_PAGE) != 0) {
      printf("%p-%p %s skipped\n", area.addr, area.addr + area.size, area.name);
    } else
#endif
    if ((area.prot & MTCP_PROT_ZERO_PAGE) == 0) {
      skipfile (fd, area.size);
    }
#endif
    printf("%p-%p %c%c%c%c %8x 00:00 0          %s\n",
	   area.addr, area.addr + area.size,
	    ( area.prot & PROT_READ  ? 'r' : '-' ),
	    ( area.prot & PROT_WRITE ? 'w' : '-' ),
	    ( area.prot & PROT_EXEC  ? 'x' : '-' ),
	    ( area.flags & MAP_SHARED ? 's'
              : ( area.flags & MAP_ANONYMOUS ? 'p' : '-' ) ),
	    0, area.name);
  }

  printf("*** done\n");
   close (fd);
   mtcp_restore_cpfd = -1;
   return 0;
}