Exemplo n.º 1
0
/*
 * Copy one copy table entry form /proc/vmcore to dump partition
 */
static int copy_table_entry_write(int fdin, int fdout,
				  struct copy_table_entry *entry,
				  unsigned long offset)
{
	unsigned long buf_size, bytes_left, off;
	void *map;

	if (entry->size == 0)
		return 0;
	off = entry->off;
	bytes_left = entry->size;
	if (lseek(fdout, entry->off + offset, SEEK_SET) < 0)
		return -1;
	while (bytes_left > 0) {
		buf_size = MIN(COPY_BUF_SIZE, bytes_left);
		map = mmap(0, buf_size, PROT_READ, MAP_SHARED, fdin, off);
		if (map == (void *)-1) {
			PRINT_PERR("Mapping failed\n");
			return -1;
		}
		if (write(fdout, map, buf_size) < 0) {
			PRINT_PERR("Write to partition failed\n");
			return -1;
		}
		munmap(map, buf_size);
		bytes_left -= buf_size;
		off += buf_size;
		show_progress(buf_size);
	}
	return 0;
}
/*
 * Mount the dump device
 * Return:    0 - ok
 *         != 0 - error
 */
static int mount_dump_device(void)
{
	int pid;
	char dump_part[16];

	PRINT_TRACE("e2fsck\n");
	sprintf(dump_part, "%s%i", DEV_SCSI, atoi(g.parm_part));

	pid = fork();
	if (pid < 0) {
		PRINT_PERR("fork failed\n");
		return -1;
	} else if (pid == 0) {
		execl("/bin/e2fsck", "e2fsck", dump_part, "-y", NULL);
		execl("/sbin/e2fsck", "e2fsck", dump_part, "-y", NULL);
		exit(1);
	} else {
		waitpid(pid, NULL, 0);
	}

	PRINT_TRACE("mount\n");
	if (mount(dump_part, DUMP_DIR, "ext3", 0, NULL) == 0)
		return 0;
	if (mount(dump_part, DUMP_DIR, "ext2", 0, NULL) != 0) {
		PRINT_PERR("mount failed\n");
		return -1;
	}
	return 0;
}
/*
 * Get dump parameters from /proc/cmdline
 * Return: 0       - ok
 *         (!= 0)  - error
 */
static int parse_parmline(void)
{
	int fh, i, count, token_cnt;
	char *token;
	char *parms[KERN_PARM_MAX];

	/* setting defaults */

	g.parm_compress = PARM_COMP_DFLT;
	g.parm_dir      = PARM_DIR_DFLT;
	g.parm_part     = PARM_PART_DFLT;
	g.parm_debug    = PARM_DEBUG_DFLT;
	g.parm_mode     = PARM_MODE_NUM_DFLT;
	g.parm_mem      = PARM_MEM_DFLT;

	fh = open(PROC_CMDLINE, O_RDONLY);
	if (fh == -1) {
		PRINT_PERR("open %s failed\n", PROC_CMDLINE);
		return -1;
	}
	count = read(fh, g.parmline, CMDLINE_MAX_LEN);
	if (count == -1) {
		PRINT_PERR("read %s failed\n", PROC_CMDLINE);
		close(fh);
		return -1;
	}
	g.parmline[count-1] = '\0'; /* remove \n */
	token_cnt = 0;
	token = strtok(g.parmline, " \t\n");
	while (token != NULL) {
		parms[token_cnt] = token;
		token = strtok(NULL, " \t\n");
		token_cnt++;
		if (token_cnt >= KERN_PARM_MAX) {
			PRINT_WARN("More than %i kernel parmameters "
				   "specified\n", KERN_PARM_MAX);
			break;
		}
	}
	for (i = 0; i < token_cnt; i++) {
		if (parse_parameter(parms[i])) {
			close(fh);
			return -1;
		}
	}
	PRINT_TRACE("dump dir  : %s\n", g.parm_dir);
	PRINT_TRACE("dump part : %s\n", g.parm_part);
	PRINT_TRACE("dump comp : %s\n", g.parm_compress);
	PRINT_TRACE("dump debug: %d\n", g.parm_debug);
	PRINT_TRACE("dump mem:   %llx\n", (unsigned long long) g.parm_mem);

	if (g.parm_mode == PARM_MODE_AUTO_NUM)
		PRINT_TRACE("dump mode : %s\n", PARM_MODE_AUTO);
	if (g.parm_mode == PARM_MODE_INTERACT_NUM)
		PRINT_TRACE("dump mode : %s\n", PARM_MODE_INTERACT);

	sprintf(g.dump_dir, "%s/%s", DUMP_DIR, g.parm_dir);
	close(fh);
	return 0;
}
/*
 * unmount the dump device
 * Return:    0 - ok
 *         != 0 - error
 */
static int umount_dump_device(void)
{
	if (umount(DUMP_DIR) != 0) {
		PRINT_PERR("umount failed\n");
		return -1;
	}
	return 0;
}
Exemplo n.º 5
0
/*
 * Update superblock checksum on SCSI disk
 */
static int csum_update(int fd)
{
	/* Write crc into zfcpdump header */
	if (csum_get(dump_sb.part_start + dump_sb.csum_off,
		     dump_sb.csum_size, &dump_sb.csum)) {
		PRINT_ERR("Get check sum failed\n");
		return -1;
	}
	if (lseek(fd, mbr.boot_info.sb_off, SEEK_SET) < 0) {
		PRINT_PERR("Seek failed\n");
		return -1;
	}
	if (write(fd, &dump_sb, sizeof(dump_sb)) < 0) {
		PRINT_PERR("Write failed\n");
		return -1;
	}
	return 0;
}
static int write_to_file(const char *file, const char *command)
{
	int fh;

	PRINT_TRACE("Write: %s - %s\n", file, command);
	fh = open(file, O_WRONLY);
	if (fh == -1) {
		PRINT_PERR("Could not open %s\n", file);
		return -1;
	}
	if (write(fh, command, strlen(command)) == -1) {
		PRINT_PERR("Write to %s failed\n", file);
		close(fh);
		return -1;
	};
	close(fh);
	return 0;
}
static int read_file(const char *file, char *buf, int size)
{
	int fh;

	PRINT_TRACE("Read: %s:\n", file);
	fh = open(file, O_RDONLY);
	if (fh == -1) {
		PRINT_PERR("open %s failed\n", file);
		return -1;
	}
	if (read(fh, buf, size) < 0) {
		PRINT_PERR("read %s failed\n", file);
		close(fh);
		return -1;
	}
	if (buf[strlen(buf) - 1] == '\n')
		buf[strlen(buf) - 1] = 0; /* strip newline */
	close(fh);
	PRINT_TRACE("'%s'\n", buf);

	return 0;
}
Exemplo n.º 8
0
/*
 * Read file at given offset
 */
static int pread_file(const char *path, char *buf, int size, uint64_t off)
{
	int fd;

	PRINT_TRACE("Read: %s:\n", path);
	fd = open(path, O_RDONLY);
	if (fd == -1) {
		PRINT_PERR("open %s failed\n", path);
		return -1;
	}
	if (lseek(fd, off, SEEK_SET) < 0) {
		PRINT_PERR("seek %s offset %llu failed\n", path,
			   (unsigned long long) off);
		return -1;
	}
	if (read(fd, buf, size) < 0) {
		PRINT_PERR("read %s failed\n", path);
		close(fd);
		return -1;
	}
	close(fd);
	return 0;
}
Exemplo n.º 9
0
/*
 * Finds the matching partition to a given start and end. If a matching
 * partition is found, the partition number is returned.
 */
int find_part_num(uint64_t start, uint64_t size)
{
	struct hd_geometry geo;
	uint32_t block_size;
	uint64_t part_size;
	char path[11];
	int fd, i;

	PRINT_TRACE("Partiton to dump start: 0x%llx end: 0x%llx\n",
		    (unsigned long long) start, (unsigned long long) size);
	for (i = 1; i < 16; i++) {
		snprintf(path, sizeof(path), DEV_SCSI "%d", i);
		fd = open(path, O_RDONLY);
		if (fd == -1)
			continue;
		if (ioctl(fd, HDIO_GETGEO, &geo) != 0) {
			PRINT_PERR("Could not retrieve partition"
				   " geometry information\n");
			return -1;
		}
		if (ioctl(fd, BLKGETSIZE64, &part_size)) {
			PRINT_PERR("Could not retrieve partition"
				   " size information\n");
			return -1;
		}
		if (ioctl(fd, BLKSSZGET, &block_size)) {
			PRINT_PERR("Could not get blocksize");
			return -1;
		}
		PRINT_TRACE("Partiton %s start: 0x%llx end: 0x%llx\n", path,
			    (unsigned long long) geo.start * block_size,
			    (unsigned long long) part_size);
		if ((start == geo.start * block_size) && (size == part_size))
			return i;
	}
	return -1;
}
/*
 * Get dump number of either new dump or dump to erase
 * Parameter: dumpdir - dump directory (absolute path)
 *            mode    - DUMP_FIRST: Find smallest dump number in directory
 *                    - DUMP_LAST:  Find highest dump number in directory
 * Return: >= 0 - dump number
 *         -1   - no dump found in directory
 *         <-1  - error
 */
static int get_dump_num(const char *dumpdir, int mode)
{
	DIR *dir = NULL;
	struct dirent *dir_ent;
	int dump_found, rc;

	rc = 0;
	dump_found = 0;
	dir = opendir(dumpdir);
	if (!dir) {
		PRINT_PERR("Cannot evalute dump number\n");
		return -2;
	}

	while ((dir_ent = readdir(dir))) {
		int num;
		if (sscanf(dir_ent->d_name, "dump.%ui", &num) == 1) {
			char suffix[1024] = {};

			/*
			 * check if we have something like dump.001
			 * this is not treated as dump, since we do not allow
			 * leading zeros.
			 * Also files like dump.-1, dump.-10 are ignored.
			 */
			sscanf(dir_ent->d_name, "dump.%s", suffix);
			if (suffix[0] == '-')
				continue;
			if ((suffix[0] == '0') && isdigit(suffix[1]))
				continue;
			if (!dump_found) {
				dump_found = 1;
				rc = num;
			} else if (mode == DUMP_LAST) {
				rc = MAX(num, rc);
			} else if (mode == DUMP_FIRST) {
				rc = MIN(num, rc);
			}
		}
	}
	if (!dump_found)
		rc = NO_DUMP;
	closedir(dir);

	return rc;
}
/*
 * Erase oldest dump in dump directory
 * Return:    0 - ok
 *          !=0 - error
 */
static int erase_oldest_dump(void)
{
	int dump_nr;
	char dname[1024] = {};
	char answ[1024] = {};

	dump_nr = get_dump_num(g.dump_dir, DUMP_FIRST);
	if (dump_nr < 0) {
		PRINT_ERR("Internal error: dump number cannot be evaluated\n");
		return -1;
	}
	sprintf(dname, "dump.%i", dump_nr);
	if (dump_nr == g.dump_nr) {
		PRINT_ERR("Sorry, cannot delete any more dumps!\n");
		return -1;
	}
	if (g.parm_mode == PARM_MODE_AUTO_NUM) {
		PRINT("Removing oldest dump: '%s'\n", dname);
	} else {
		while ((strcmp(answ, "y") != 0) && (strcmp(answ, "n") != 0)) {
			PRINT("Remove oldest dump: '%s' (y/n)? ", dname);
			scanf("%s", answ);
		}
		if (strcmp(answ, "n") == 0)
			return -1;
	}
	sprintf(dname, "%s/dump.%i", g.dump_dir, dump_nr);
	if (unlink(dname) == -1) {
		PRINT_PERR("Could not remove dump\n");
		return -1;
	}
	sync();
	/*
	 * Wait some seconds in order to give ext3 time to discover that file
	 * has been removed.
	 */
	sleep(WAIT_TIME_ERASE);
	PRINT("Dump removed!\n");
	return 0;
}