Example #1
0
/* NB: does not preserve file position! */
static uint32_t find_cdf_offset(void)
{
	cde_header_t cde_header;
	unsigned char *p;
	off_t end;
	unsigned char *buf = xzalloc(PEEK_FROM_END);

	end = xlseek(zip_fd, 0, SEEK_END);
	end -= PEEK_FROM_END;
	if (end < 0)
		end = 0;
	xlseek(zip_fd, end, SEEK_SET);
	full_read(zip_fd, buf, PEEK_FROM_END);

	p = buf;
	while (p <= buf + PEEK_FROM_END - CDE_HEADER_LEN - 4) {
		if (*p != 'P') {
			p++;
			continue;
		}
		if (*++p != 'K')
			continue;
		if (*++p != 5)
			continue;
		if (*++p != 6)
			continue;
		/* we found CDE! */
		memcpy(cde_header.raw, p + 1, CDE_HEADER_LEN);
		FIX_ENDIANNESS_CDE(cde_header);
		free(buf);
		return cde_header.formatted.cdf_offset;
	}
	//free(buf);
	bb_error_msg_and_die("can't find file table");
};
Example #2
0
int readahead_main(int argc UNUSED_PARAM, char **argv)
{
	int retval = EXIT_SUCCESS;

	if (!argv[1]) {
		bb_show_usage();
	}

	while (*++argv) {
		int fd = open_or_warn(*argv, O_RDONLY);
		if (fd >= 0) {
			off_t len;
			int r;

			/* fdlength was reported to be unreliable - use seek */
			len = xlseek(fd, 0, SEEK_END);
			xlseek(fd, 0, SEEK_SET);
			r = readahead(fd, 0, len);
			close(fd);
			if (r >= 0)
				continue;
		}
		retval = EXIT_FAILURE;
	}

	return retval;
}
Example #3
0
static void write_tables(void)
{
	/* Mark the superblock valid. */
	SB.s_state |= MINIX_VALID_FS;
	SB.s_state &= ~MINIX_ERROR_FS;

	msg_eol = "seek to 0 failed";
	xlseek(dev_fd, 0, SEEK_SET);

	msg_eol = "can't clear boot sector";
	xwrite(dev_fd, G.boot_block_buffer, 512);

	msg_eol = "seek to BLOCK_SIZE failed";
	xlseek(dev_fd, BLOCK_SIZE, SEEK_SET);

	msg_eol = "can't write superblock";
	xwrite(dev_fd, G.superblock_buffer, BLOCK_SIZE);

	msg_eol = "can't write inode map";
	xwrite(dev_fd, G.inode_map, SB_IMAPS * BLOCK_SIZE);

	msg_eol = "can't write zone map";
	xwrite(dev_fd, G.zone_map, SB_ZMAPS * BLOCK_SIZE);

	msg_eol = "can't write inodes";
	xwrite(dev_fd, G.inode_buffer, INODE_BUFFER_SIZE);

	msg_eol = "\n";
}
int tune2fs_main(int argc UNUSED_PARAM, char **argv)
{
	unsigned opts;
	const char *label, *str_c, *str_i, *str_C;
	struct ext2_super_block *sb;
	int fd;

	opt_complementary = "=1";
	opts = getopt32(argv, "L:c:i:C:", &label, &str_c, &str_i, &str_C);
	if (!opts)
		bb_show_usage();
	argv += optind; // argv[0] -- device

	// read superblock
	fd = xopen(argv[0], O_RDWR);
	xlseek(fd, 1024, SEEK_SET);
	sb = xzalloc(1024);
	xread(fd, sb, 1024);

	// mangle superblock
	//STORE_LE(sb->s_wtime, time(NULL)); - why bother?

	if (opts & OPT_C) {
		int n = xatoi_range(str_C, 1, 0xfffe);
		if (n == 0) n = 1;
		STORE_LE(sb->s_mnt_count, (unsigned)n);
	}

	// set the label
	if (opts & OPT_L)
		safe_strncpy((char *)sb->s_volume_name, label, sizeof(sb->s_volume_name));

	if (opts & OPT_c) {
		int n = xatoi_range(str_c, -1, 0xfffe);
		if (n == 0)
			n = -1;
		STORE_LE(sb->s_max_mnt_count, (unsigned)n);
	}

	if (opts & OPT_i) {
		unsigned n = xatou_range(str_i, 0, (unsigned)0xffffffff / (24*60*60)) * 24*60*60;
		STORE_LE(sb->s_checkinterval, n);
	}

	// write superblock
	xlseek(fd, 1024, SEEK_SET);
	xwrite(fd, sb, 1024);

	if (ENABLE_FEATURE_CLEAN_UP) {
		free(sb);
	}

	xclose(fd);
	return EXIT_SUCCESS;
}
Example #5
0
static ssize_t tail_read(int fd, char *buf, size_t count, int follow)
{
	ssize_t r;

	if (follow) {
		/* tail -f keeps following files even if they are truncated */
		off_t current;
		struct stat sbuf;

		/* /proc files report zero st_size, don't lseek them */
		if (fstat(fd, &sbuf) == 0 && sbuf.st_size > 0) {
			current = lseek(fd, 0, SEEK_CUR);
			if (sbuf.st_size < current)
				xlseek(fd, 0, SEEK_SET);
		}
	}

	r = full_read(fd, buf, count);
	if (r < 0) {
		bb_perror_msg(bb_msg_read_error);
		G.exitcode = EXIT_FAILURE;
	}

	return r;
}
Example #6
0
static void reset_beg_range_to_zero(void)
{
	bb_error_msg("restart failed");
	G.beg_range = 0;
	xlseek(G.output_fd, 0, SEEK_SET);
	/* Done at the end instead: */
	/* ftruncate(G.output_fd, 0); */
}
Example #7
0
/* NB: does not preserve file position! */
static uint32_t find_cdf_offset(void)
{
	cde_header_t cde_header;
	unsigned char *p;
	off_t end;
	unsigned char *buf = xzalloc(PEEK_FROM_END);

	end = xlseek(zip_fd, 0, SEEK_END);
	end -= PEEK_FROM_END;
	if (end < 0)
		end = 0;
	xlseek(zip_fd, end, SEEK_SET);
	full_read(zip_fd, buf, PEEK_FROM_END);

	cde_header.formatted.cdf_offset = BAD_CDF_OFFSET;
	p = buf;
	while (p <= buf + PEEK_FROM_END - CDE_HEADER_LEN - 4) {
		if (*p != 'P') {
			p++;
			continue;
		}
		if (*++p != 'K')
			continue;
		if (*++p != 5)
			continue;
		if (*++p != 6)
			continue;
		/* we found CDE! */
		memcpy(cde_header.raw, p + 1, CDE_HEADER_LEN);
		FIX_ENDIANNESS_CDE(cde_header);
		/*
		 * I've seen .ZIP files with seemingly valid CDEs
		 * where cdf_offset points past EOF - ??
		 * Ignore such CDEs:
		 */
		if (cde_header.formatted.cdf_offset < end + (p - buf))
			break;
		cde_header.formatted.cdf_offset = BAD_CDF_OFFSET;
	}
	free(buf);
	return cde_header.formatted.cdf_offset;
};
Example #8
0
static uint32_t read_next_cdf(uint32_t cdf_offset, cdf_header_t *cdf_ptr)
{
	off_t org;

	org = xlseek(zip_fd, 0, SEEK_CUR);

	if (!cdf_offset)
		cdf_offset = find_cdf_offset();

	xlseek(zip_fd, cdf_offset + 4, SEEK_SET);
	xread(zip_fd, cdf_ptr->raw, CDF_HEADER_LEN);
	FIX_ENDIANNESS_CDF(*cdf_ptr);
	cdf_offset += 4 + CDF_HEADER_LEN
		+ cdf_ptr->formatted.file_name_length
		+ cdf_ptr->formatted.extra_field_length
		+ cdf_ptr->formatted.file_comment_length;

	xlseek(zip_fd, org, SEEK_SET);
	return cdf_offset;
};
Example #9
0
static int
do_test (void)
{
  TEST_VERIFY_EXIT (setlocale (LC_ALL, "de_DE.UTF-8") != NULL);
  /* Fill the stdio buffer and advance the read pointer.  */
  TEST_VERIFY_EXIT (fgetwc (stdin) != WEOF);
  /* This calls _IO_wfile_sync, it should not crash.  */
  TEST_VERIFY_EXIT (setvbuf (stdin, NULL, _IONBF, 0) == 0);
  /* Verify that the external file offset has been synchronized.  */
  TEST_COMPARE (xlseek (0, 0, SEEK_CUR), 1);

  return 0;
}
Example #10
0
// Read (potentially big) files in one go. File size is estimated by
// lseek to end.
void *xmalloc_open_read_close(const char *filename, size_t *sizep)
{
	char *buf;
	size_t size = sizep ? *sizep : INT_MAX;
	int fd;
	off_t len;

	fd = xopen(filename, O_RDONLY);
	/* /proc/N/stat files report len 0 here */
	/* In order to make such files readable, we add small const */
	len = xlseek(fd, 0, SEEK_END) | 0x3ff; /* + up to 1k */
	xlseek(fd, 0, SEEK_SET);
	if (len < size)
		size = len;
	buf = xmalloc(size + 1);
	size = read_close(fd, buf, size);
	if ((ssize_t)size < 0)
		bb_perror_msg_and_die("'%s'", filename);
	xrealloc(buf, size + 1);
	buf[size] = '\0';
	if (sizep)
		*sizep = size;
	return buf;
}
Example #11
0
int
decompress_fd(int fdi, int fdo)
{
    uint8_t header[6];

    if (sizeof(header) != safe_read(fdi, header, sizeof(header)))
    {
        perror_msg("Failed to read header bytes");
        return -1;
    }

    xlseek(fdi, 0, SEEK_SET);

    if (is_format("xz", header, sizeof(header), s_xz_magic, sizeof(s_xz_magic)))
        return decompress_fd_xz(fdi, fdo);

    error_msg("Unsupported file format");
    return -1;
}
Example #12
0
static ssize_t tail_read(int fd, char *buf, size_t count)
{
	ssize_t r;
	off_t current;
	struct stat sbuf;

	/* /proc files report zero st_size, don't lseek them. */
	if (fstat(fd, &sbuf) == 0 && sbuf.st_size > 0) {
		current = lseek(fd, 0, SEEK_CUR);
		if (sbuf.st_size < current)
			xlseek(fd, 0, SEEK_SET);
	}

	r = full_read(fd, buf, count);
	if (r < 0) {
		bb_perror_msg(bb_msg_read_error);
		G.status = EXIT_FAILURE;
	}

	return r;
}
Example #13
0
int volname_main(int argc UNUSED_PARAM, char **argv)
{
    int fd;
    char buffer[32];
    const char *device;

    device = "/dev/cdrom";
    if (argv[1]) {
        device = argv[1];
        if (argv[2])
            bb_show_usage();
    }

    fd = xopen(device, O_RDONLY);
    xlseek(fd, 32808, SEEK_SET);
    xread(fd, buffer, 32);
    printf("%32.32s\n", buffer);
    if (ENABLE_FEATURE_CLEAN_UP) {
        close(fd);
    }
    return 0;
}
Example #14
0
int rpm_main(int argc, char **argv)
{
	int opt, func = 0;
	const unsigned pagesize = getpagesize();

	while ((opt = getopt(argc, argv, "iqpldc")) != -1) {
		switch (opt) {
		case 'i': /* First arg: Install mode, with q: Information */
			if (!func) func = rpm_install;
			else func |= rpm_query_info;
			break;
		case 'q': /* First arg: Query mode */
			if (func) bb_show_usage();
			func = rpm_query;
			break;
		case 'p': /* Query a package */
			func |= rpm_query_package;
			break;
		case 'l': /* List files in a package */
			func |= rpm_query_list;
			break;
		case 'd': /* List doc files in a package (implies list) */
			func |= rpm_query_list;
			func |= rpm_query_list_doc;
			break;
		case 'c': /* List config files in a package (implies list) */
			func |= rpm_query_list;
			func |= rpm_query_list_config;
			break;
		default:
			bb_show_usage();
		}
	}
	argv += optind;
	//argc -= optind;
	if (!argv[0]) {
		bb_show_usage();
	}

	while (*argv) {
		int rpm_fd;
		unsigned mapsize;
		const char *source_rpm;

		rpm_fd = xopen(*argv++, O_RDONLY);
		G.mytags = rpm_gettags(rpm_fd, &G.tagcount);
		if (!G.mytags)
			bb_error_msg_and_die("error reading rpm header");
		mapsize = xlseek(rpm_fd, 0, SEEK_CUR);
		mapsize = (mapsize + pagesize) & -(int)pagesize;
		/* Some NOMMU systems prefer MAP_PRIVATE over MAP_SHARED */
		G.map = mmap(0, mapsize, PROT_READ, MAP_PRIVATE, rpm_fd, 0);
//FIXME: error check?

		source_rpm = rpm_getstr(TAG_SOURCERPM, 0);

		if (func & rpm_install) {
			/* Backup any config files */
			loop_through_files(TAG_BASENAMES, fileaction_dobackup);
			/* Extact the archive */
			extract_cpio(rpm_fd, source_rpm);
			/* Set the correct file uid/gid's */
			loop_through_files(TAG_BASENAMES, fileaction_setowngrp);
		}
		else if ((func & (rpm_query|rpm_query_package)) == (rpm_query|rpm_query_package)) {
			if (!(func & (rpm_query_info|rpm_query_list))) {
				/* If just a straight query, just give package name */
				printf("%s-%s-%s\n", rpm_getstr(TAG_NAME, 0), rpm_getstr(TAG_VERSION, 0), rpm_getstr(TAG_RELEASE, 0));
			}
			if (func & rpm_query_info) {
				/* Do the nice printout */
				time_t bdate_time;
				struct tm *bdate_ptm;
				char bdatestring[50];
				const char *p;

				printf("%-12s: %s\n", "Name"        , rpm_getstr(TAG_NAME, 0));
				/* TODO compat: add "Epoch" here */
				printf("%-12s: %s\n", "Version"     , rpm_getstr(TAG_VERSION, 0));
				printf("%-12s: %s\n", "Release"     , rpm_getstr(TAG_RELEASE, 0));
				/* add "Architecture" */
				printf("%-12s: %s\n", "Install Date", "(not installed)");
				printf("%-12s: %s\n", "Group"       , rpm_getstr(TAG_GROUP, 0));
				printf("%-12s: %d\n", "Size"        , rpm_getint(TAG_SIZE, 0));
				printf("%-12s: %s\n", "License"     , rpm_getstr(TAG_LICENSE, 0));
				/* add "Signature" */
				printf("%-12s: %s\n", "Source RPM"  , source_rpm ? source_rpm : "(none)");
				bdate_time = rpm_getint(TAG_BUILDTIME, 0);
				bdate_ptm = localtime(&bdate_time);
				strftime(bdatestring, 50, "%a %d %b %Y %T %Z", bdate_ptm);
				printf("%-12s: %s\n", "Build Date"  , bdatestring);
				printf("%-12s: %s\n", "Build Host"  , rpm_getstr(TAG_BUILDHOST, 0));
				p = rpm_getstr(TAG_PREFIXS, 0);
				printf("%-12s: %s\n", "Relocations" , p ? p : "(not relocatable)");
				/* add "Packager" */
				p = rpm_getstr(TAG_VENDOR, 0);
				printf("%-12s: %s\n", "Vendor"      , p ? p : "(none)");
				printf("%-12s: %s\n", "URL"         , rpm_getstr(TAG_URL, 0));
				printf("%-12s: %s\n", "Summary"     , rpm_getstr(TAG_SUMMARY, 0));
				printf("Description :\n%s\n", rpm_getstr(TAG_DESCRIPTION, 0));
			}
			if (func & rpm_query_list) {
				int count, it, flags;
				count = rpm_getcount(TAG_BASENAMES);
				for (it = 0; it < count; it++) {
					flags = rpm_getint(TAG_FILEFLAGS, it);
					switch (func & (rpm_query_list_doc|rpm_query_list_config)) {
					case rpm_query_list_doc:
						if (!(flags & RPMFILE_DOC)) continue;
						break;
					case rpm_query_list_config:
						if (!(flags & RPMFILE_CONFIG)) continue;
						break;
					case rpm_query_list_doc|rpm_query_list_config:
						if (!(flags & (RPMFILE_CONFIG|RPMFILE_DOC))) continue;
						break;
					}
					printf("%s%s\n",
						rpm_getstr(TAG_DIRNAMES, rpm_getint(TAG_DIRINDEXES, it)),
						rpm_getstr(TAG_BASENAMES, it));
				}
			}
		}
		munmap(G.map, mapsize);
		free(G.mytags);
		close(rpm_fd);
	}
	return 0;
}
Example #15
0
static void write_block(int blk, char *buffer)
{
	xlseek(dev_fd, blk * BLOCK_SIZE, SEEK_SET);
	xwrite(dev_fd, buffer, BLOCK_SIZE);
}
Example #16
0
int rpm_main(int argc, char **argv)
{
	int opt = 0, func = 0, rpm_fd, offset;
	const int pagesize = getpagesize();

	while ((opt = getopt(argc, argv, "iqpldc")) != -1) {
		switch (opt) {
		case 'i': /* First arg: Install mode, with q: Information */
			if (!func) func = rpm_install;
			else func |= rpm_query_info;
			break;
		case 'q': /* First arg: Query mode */
			if (func) bb_show_usage();
			func = rpm_query;
			break;
		case 'p': /* Query a package */
			func |= rpm_query_package;
			break;
		case 'l': /* List files in a package */
			func |= rpm_query_list;
			break;
		case 'd': /* List doc files in a package (implies list) */
			func |= rpm_query_list;
			func |= rpm_query_list_doc;
			break;
		case 'c': /* List config files in a package (implies list) */
			func |= rpm_query_list;
			func |= rpm_query_list_config;
			break;
		default:
			bb_show_usage();
		}
	}
	argv += optind;
	argc -= optind;
	if (!argc) bb_show_usage();

	while (*argv) {
		rpm_fd = xopen(*argv++, O_RDONLY);
		mytags = rpm_gettags(rpm_fd, &tagcount);
		if (!mytags)
			bb_error_msg_and_die("error reading rpm header");
		offset = xlseek(rpm_fd, 0, SEEK_CUR);
		/* Mimimum is one page */
		map = mmap(0, offset > pagesize ? (offset + offset % pagesize) : pagesize, PROT_READ, MAP_PRIVATE, rpm_fd, 0);

		if (func & rpm_install) {
			/* Backup any config files */
			loop_through_files(TAG_BASENAMES, fileaction_dobackup);
			/* Extact the archive */
			extract_cpio_gz(rpm_fd);
			/* Set the correct file uid/gid's */
			loop_through_files(TAG_BASENAMES, fileaction_setowngrp);
		}
		else if ((func & (rpm_query|rpm_query_package)) == (rpm_query|rpm_query_package)) {
			if (!(func & (rpm_query_info|rpm_query_list))) {
				/* If just a straight query, just give package name */
				printf("%s-%s-%s\n", rpm_getstr(TAG_NAME, 0), rpm_getstr(TAG_VERSION, 0), rpm_getstr(TAG_RELEASE, 0));
			}
			if (func & rpm_query_info) {
				/* Do the nice printout */
				time_t bdate_time;
				struct tm *bdate;
				char bdatestring[50];
				printf("Name        : %-29sRelocations: %s\n", rpm_getstr(TAG_NAME, 0), rpm_getstr(TAG_PREFIXS, 0) ? rpm_getstr(TAG_PREFIXS, 0) : "(not relocateable)");
				printf("Version     : %-34sVendor: %s\n", rpm_getstr(TAG_VERSION, 0), rpm_getstr(TAG_VENDOR, 0) ? rpm_getstr(TAG_VENDOR, 0) : "(none)");
				bdate_time = rpm_getint(TAG_BUILDTIME, 0);
				bdate = localtime((time_t *) &bdate_time);
				strftime(bdatestring, 50, "%a %d %b %Y %T %Z", bdate);
				printf("Release     : %-30sBuild Date: %s\n", rpm_getstr(TAG_RELEASE, 0), bdatestring);
				printf("Install date: %-30sBuild Host: %s\n", "(not installed)", rpm_getstr(TAG_BUILDHOST, 0));
				printf("Group       : %-30sSource RPM: %s\n", rpm_getstr(TAG_GROUP, 0), rpm_getstr(TAG_SOURCERPM, 0));
				printf("Size        : %-33dLicense: %s\n", rpm_getint(TAG_SIZE, 0), rpm_getstr(TAG_LICENSE, 0));
				printf("URL         : %s\n", rpm_getstr(TAG_URL, 0));
				printf("Summary     : %s\n", rpm_getstr(TAG_SUMMARY, 0));
				printf("Description :\n%s\n", rpm_getstr(TAG_DESCRIPTION, 0));
			}
			if (func & rpm_query_list) {
				int count, it, flags;
				count = rpm_getcount(TAG_BASENAMES);
				for (it = 0; it < count; it++) {
					flags = rpm_getint(TAG_FILEFLAGS, it);
					switch (func & (rpm_query_list_doc|rpm_query_list_config)) {
					case rpm_query_list_doc:
						if (!(flags & RPMFILE_DOC)) continue;
						break;
					case rpm_query_list_config:
						if (!(flags & RPMFILE_CONFIG)) continue;
						break;
					case rpm_query_list_doc|rpm_query_list_config:
						if (!(flags & (RPMFILE_CONFIG|RPMFILE_DOC))) continue;
						break;
					}
					printf("%s%s\n",
						rpm_getstr(TAG_DIRNAMES, rpm_getint(TAG_DIRINDEXES, it)),
						rpm_getstr(TAG_BASENAMES, it));
				}
			}
		}
		free(mytags);
	}
	return 0;
}
Example #17
0
int flashcp_main(int argc UNUSED_PARAM, char **argv)
{
	int fd_f, fd_d; /* input file and mtd device file descriptors */
	int i;
	uoff_t erase_count;
	struct mtd_info_user mtd;
	struct erase_info_user e;
	struct stat statb;
//	const char *filename, *devicename;
	RESERVE_CONFIG_UBUFFER(buf, BUFSIZE);
	RESERVE_CONFIG_UBUFFER(buf2, BUFSIZE);

	opt_complementary = "=2"; /* exactly 2 non-option args: file, dev */
	/*opts =*/ getopt32(argv, "v");
	argv += optind;
//	filename = *argv++;
//	devicename = *argv;
#define filename argv[0]
#define devicename argv[1]

	/* open input file and mtd device and do sanity checks */
	fd_f = xopen(filename, O_RDONLY);
	fstat(fd_f, &statb);
	fd_d = xopen(devicename, O_SYNC | O_RDWR);
#if !MTD_DEBUG
	if (ioctl(fd_d, MEMGETINFO, &mtd) < 0) {
		bb_error_msg_and_die("%s is not a MTD flash device", devicename);
	}
	if (statb.st_size > mtd.size) {
		bb_error_msg_and_die("%s bigger than %s", filename, devicename);
	}
#else
	mtd.erasesize = 64 * 1024;
#endif

	/* always erase a complete block */
	erase_count = (uoff_t)(statb.st_size + mtd.erasesize - 1) / mtd.erasesize;
	/* erase 1 block at a time to be able to give verbose output */
	e.length = mtd.erasesize;
#if 0
/* (1) bloat
 * (2) will it work for multi-gigabyte devices?
 * (3) worse wrt error detection granularity
 */
	/* optimization: if not verbose, erase in one go */
	if (!opts) { // if (!(opts & OPT_v))
		e.length = mtd.erasesize * erase_count;
		erase_count = 1;
	}
#endif
	e.start = 0;
	for (i = 1; i <= erase_count; i++) {
		progress(-1, i, erase_count);
#if !MTD_DEBUG
		if (ioctl(fd_d, MEMERASE, &e) < 0) {
			bb_perror_msg_and_die("erase error at 0x%llx on %s",
				(long long)e.start, devicename);
		}
#else
		usleep(100*1000);
#endif
		e.start += mtd.erasesize;
	}
	progress_newline();

	/* doing this outer loop gives significantly smaller code
	 * than doing two separate loops for writing and verifying */
	for (i = 0; i <= 1; i++) {
		uoff_t done;
		unsigned count;

		xlseek(fd_f, 0, SEEK_SET);
		xlseek(fd_d, 0, SEEK_SET);
		done = 0;
		count = BUFSIZE;
		while (1) {
			uoff_t rem;

			progress(i, done / 1024, (uoff_t)statb.st_size / 1024);
			rem = statb.st_size - done;
			if (rem == 0)
				break;
			if (rem < BUFSIZE)
				count = rem;
			xread(fd_f, buf, count);
			if (i == 0) {
				int ret;
				if (count < BUFSIZE)
					memset((char*)buf + count, 0, BUFSIZE - count);
				errno = 0;
				ret = full_write(fd_d, buf, BUFSIZE);
				if (ret != BUFSIZE) {
					bb_perror_msg_and_die("write error at 0x%"OFF_FMT"x on %s, "
						"write returned %d",
						done, devicename, ret);
				}
			} else { /* i == 1 */
				xread(fd_d, buf2, count);
				if (memcmp(buf, buf2, count) != 0) {
					bb_error_msg_and_die("verification mismatch at 0x%"OFF_FMT"x", done);
				}
			}

			done += count;
		}

		progress_newline();
	}
	/* we won't come here if there was an error */

	return EXIT_SUCCESS;
}
Example #18
0
static void download_one_url(const char *url)
{
	bool use_proxy;                 /* Use proxies if env vars are set  */
	int redir_limit;
	len_and_sockaddr *lsa;
	FILE *sfp;                      /* socket to web/ftp server         */
	FILE *dfp;                      /* socket to ftp server (data)      */
	char *proxy = NULL;
	char *fname_out_alloc;
	char *redirected_path = NULL;
	struct host_info server;
	struct host_info target;

	server.allocated = NULL;
	target.allocated = NULL;
	server.user = NULL;
	target.user = NULL;

	parse_url(url, &target);

	/* Use the proxy if necessary */
	use_proxy = (strcmp(G.proxy_flag, "off") != 0);
	if (use_proxy) {
		proxy = getenv(target.is_ftp ? "ftp_proxy" : "http_proxy");
		use_proxy = (proxy && proxy[0]);
		if (use_proxy)
			parse_url(proxy, &server);
	}
	if (!use_proxy) {
		server.port = target.port;
		if (ENABLE_FEATURE_IPV6) {
			//free(server.allocated); - can't be non-NULL
			server.host = server.allocated = xstrdup(target.host);
		} else {
			server.host = target.host;
		}
	}

	if (ENABLE_FEATURE_IPV6)
		strip_ipv6_scope_id(target.host);

	/* If there was no -O FILE, guess output filename */
	fname_out_alloc = NULL;
	if (!(option_mask32 & WGET_OPT_OUTNAME)) {
		G.fname_out = bb_get_last_path_component_nostrip(target.path);
		/* handle "wget http://kernel.org//" */
		if (G.fname_out[0] == '/' || !G.fname_out[0])
			G.fname_out = (char*)"index.html";
		/* -P DIR is considered only if there was no -O FILE */
		if (G.dir_prefix)
			G.fname_out = fname_out_alloc = concat_path_file(G.dir_prefix, G.fname_out);
		else {
			/* redirects may free target.path later, need to make a copy */
			G.fname_out = fname_out_alloc = xstrdup(G.fname_out);
		}
	}
#if ENABLE_FEATURE_WGET_STATUSBAR
	G.curfile = bb_get_last_path_component_nostrip(G.fname_out);
#endif

	/* Determine where to start transfer */
	G.beg_range = 0;
	if (option_mask32 & WGET_OPT_CONTINUE) {
		G.output_fd = open(G.fname_out, O_WRONLY);
		if (G.output_fd >= 0) {
			G.beg_range = xlseek(G.output_fd, 0, SEEK_END);
		}
		/* File doesn't exist. We do not create file here yet.
		 * We are not sure it exists on remote side */
	}

	redir_limit = 5;
 resolve_lsa:
	lsa = xhost2sockaddr(server.host, server.port);
	if (!(option_mask32 & WGET_OPT_QUIET)) {
		char *s = xmalloc_sockaddr2dotted(&lsa->u.sa);
		fprintf(stderr, "Connecting to %s (%s)\n", server.host, s);
		free(s);
	}
 establish_session:
	/*G.content_len = 0; - redundant, got_clen = 0 is enough */
	G.got_clen = 0;
	G.chunked = 0;
	if (use_proxy || !target.is_ftp) {
		/*
		 *  HTTP session
		 */
		char *str;
		int status;


		/* Open socket to http server */
		sfp = open_socket(lsa);

		/* Send HTTP request */
		if (use_proxy) {
			fprintf(sfp, "GET %stp://%s/%s HTTP/1.1\r\n",
				target.is_ftp ? "f" : "ht", target.host,
				target.path);
		} else {
			if (option_mask32 & WGET_OPT_POST_DATA)
				fprintf(sfp, "POST /%s HTTP/1.1\r\n", target.path);
			else
				fprintf(sfp, "GET /%s HTTP/1.1\r\n", target.path);
		}

		fprintf(sfp, "Host: %s\r\nUser-Agent: %s\r\n",
			target.host, G.user_agent);

		/* Ask server to close the connection as soon as we are done
		 * (IOW: we do not intend to send more requests)
		 */
		fprintf(sfp, "Connection: close\r\n");

#if ENABLE_FEATURE_WGET_AUTHENTICATION
		if (target.user) {
			fprintf(sfp, "Proxy-Authorization: Basic %s\r\n"+6,
				base64enc(target.user));
		}
		if (use_proxy && server.user) {
			fprintf(sfp, "Proxy-Authorization: Basic %s\r\n",
				base64enc(server.user));
		}
#endif

		if (G.beg_range != 0)
			fprintf(sfp, "Range: bytes=%"OFF_FMT"u-\r\n", G.beg_range);

#if ENABLE_FEATURE_WGET_LONG_OPTIONS
		if (G.extra_headers)
			fputs(G.extra_headers, sfp);

		if (option_mask32 & WGET_OPT_POST_DATA) {
			fprintf(sfp,
				"Content-Type: application/x-www-form-urlencoded\r\n"
				"Content-Length: %u\r\n"
				"\r\n"
				"%s",
				(int) strlen(G.post_data), G.post_data
			);
		} else
#endif
		{
			fprintf(sfp, "\r\n");
		}

		fflush(sfp);

		/*
		 * Retrieve HTTP response line and check for "200" status code.
		 */
 read_response:
		fgets_and_trim(sfp);

		str = G.wget_buf;
		str = skip_non_whitespace(str);
		str = skip_whitespace(str);
		// FIXME: no error check
		// xatou wouldn't work: "200 OK"
		status = atoi(str);
		switch (status) {
		case 0:
		case 100:
			while (gethdr(sfp) != NULL)
				/* eat all remaining headers */;
			goto read_response;
		case 200:
/*
Response 204 doesn't say "null file", it says "metadata
has changed but data didn't":

"10.2.5 204 No Content
The server has fulfilled the request but does not need to return
an entity-body, and might want to return updated metainformation.
The response MAY include new or updated metainformation in the form
of entity-headers, which if present SHOULD be associated with
the requested variant.

If the client is a user agent, it SHOULD NOT change its document
view from that which caused the request to be sent. This response
is primarily intended to allow input for actions to take place
without causing a change to the user agent's active document view,
although any new or updated metainformation SHOULD be applied
to the document currently in the user agent's active view.

The 204 response MUST NOT include a message-body, and thus
is always terminated by the first empty line after the header fields."

However, in real world it was observed that some web servers
(e.g. Boa/0.94.14rc21) simply use code 204 when file size is zero.
*/
		case 204:
			if (G.beg_range != 0) {
				/* "Range:..." was not honored by the server.
				 * Restart download from the beginning.
				 */
				reset_beg_range_to_zero();
			}
			break;
		case 300:  /* redirection */
		case 301:
		case 302:
		case 303:
			break;
		case 206: /* Partial Content */
			if (G.beg_range != 0)
				/* "Range:..." worked. Good. */
				break;
			/* Partial Content even though we did not ask for it??? */
			/* fall through */
		default:
			bb_error_msg_and_die("server returned error: %s", sanitize_string(G.wget_buf));
		}

		/*
		 * Retrieve HTTP headers.
		 */
		while ((str = gethdr(sfp)) != NULL) {
			static const char keywords[] ALIGN1 =
				"content-length\0""transfer-encoding\0""location\0";
			enum {
				KEY_content_length = 1, KEY_transfer_encoding, KEY_location
			};
			smalluint key;

			/* gethdr converted "FOO:" string to lowercase */

			/* strip trailing whitespace */
			char *s = strchrnul(str, '\0') - 1;
			while (s >= str && (*s == ' ' || *s == '\t')) {
				*s = '\0';
				s--;
			}
			key = index_in_strings(keywords, G.wget_buf) + 1;
			if (key == KEY_content_length) {
				G.content_len = BB_STRTOOFF(str, NULL, 10);
				if (G.content_len < 0 || errno) {
					bb_error_msg_and_die("content-length %s is garbage", sanitize_string(str));
				}
				G.got_clen = 1;
				continue;
			}
			if (key == KEY_transfer_encoding) {
				if (strcmp(str_tolower(str), "chunked") != 0)
					bb_error_msg_and_die("transfer encoding '%s' is not supported", sanitize_string(str));
				G.chunked = 1;
			}
			if (key == KEY_location && status >= 300) {
				if (--redir_limit == 0)
					bb_error_msg_and_die("too many redirections");
				fclose(sfp);
				if (str[0] == '/') {
					free(redirected_path);
					target.path = redirected_path = xstrdup(str+1);
					/* lsa stays the same: it's on the same server */
				} else {
					parse_url(str, &target);
					if (!use_proxy) {
						free(server.allocated);
						server.allocated = NULL;
						server.host = target.host;
						/* strip_ipv6_scope_id(target.host); - no! */
						/* we assume remote never gives us IPv6 addr with scope id */
						server.port = target.port;
						free(lsa);
						goto resolve_lsa;
					} /* else: lsa stays the same: we use proxy */
				}
				goto establish_session;
			}
		}
//		if (status >= 300)
//			bb_error_msg_and_die("bad redirection (no Location: header from server)");

		/* For HTTP, data is pumped over the same connection */
		dfp = sfp;

	} else {
Example #19
0
int wget_main(int argc UNUSED_PARAM, char **argv)
{
    char buf[512];
    struct host_info server, target;
    len_and_sockaddr *lsa;
    unsigned opt;
    int redir_limit;
    char *proxy = NULL;
    char *dir_prefix = NULL;
#if ENABLE_FEATURE_WGET_LONG_OPTIONS
    char *post_data;
    char *extra_headers = NULL;
    llist_t *headers_llist = NULL;
#endif
    FILE *sfp;                      /* socket to web/ftp server         */
    FILE *dfp;                      /* socket to ftp server (data)      */
    char *fname_out;                /* where to direct output (-O)      */
    int output_fd = -1;
    bool use_proxy;                 /* Use proxies if env vars are set  */
    const char *proxy_flag = "on";  /* Use proxies if env vars are set  */
    const char *user_agent = "Wget";/* "User-Agent" header field        */

    static const char keywords[] ALIGN1 =
        "content-length\0""transfer-encoding\0""chunked\0""location\0";
    enum {
        KEY_content_length = 1, KEY_transfer_encoding, KEY_chunked, KEY_location
    };
#if ENABLE_FEATURE_WGET_LONG_OPTIONS
    static const char wget_longopts[] ALIGN1 =
        /* name, has_arg, val */
        "continue\0"         No_argument       "c"
        "spider\0"           No_argument       "s"
        "quiet\0"            No_argument       "q"
        "output-document\0"  Required_argument "O"
        "directory-prefix\0" Required_argument "P"
        "proxy\0"            Required_argument "Y"
        "user-agent\0"       Required_argument "U"
        /* Ignored: */
        // "tries\0"            Required_argument "t"
        // "timeout\0"          Required_argument "T"
        /* Ignored (we always use PASV): */
        "passive-ftp\0"      No_argument       "\xff"
        "header\0"           Required_argument "\xfe"
        "post-data\0"        Required_argument "\xfd"
        /* Ignored (we don't do ssl) */
        "no-check-certificate\0" No_argument   "\xfc"
        ;
#endif

    INIT_G();

#if ENABLE_FEATURE_WGET_LONG_OPTIONS
    applet_long_options = wget_longopts;
#endif
    /* server.allocated = target.allocated = NULL; */
    opt_complementary = "-1" IF_FEATURE_WGET_LONG_OPTIONS(":\xfe::");
    opt = getopt32(argv, "csqO:P:Y:U:" /*ignored:*/ "t:T:",
                   &fname_out, &dir_prefix,
                   &proxy_flag, &user_agent,
                   NULL, /* -t RETRIES */
                   NULL /* -T NETWORK_READ_TIMEOUT */
                   IF_FEATURE_WGET_LONG_OPTIONS(, &headers_llist)
                   IF_FEATURE_WGET_LONG_OPTIONS(, &post_data)
                  );
#if ENABLE_FEATURE_WGET_LONG_OPTIONS
    if (headers_llist) {
        int size = 1;
        char *cp;
        llist_t *ll = headers_llist;
        while (ll) {
            size += strlen(ll->data) + 2;
            ll = ll->link;
        }
        extra_headers = cp = xmalloc(size);
        while (headers_llist) {
            cp += sprintf(cp, "%s\r\n", (char*)llist_pop(&headers_llist));
        }
    }
#endif

    /* TODO: compat issue: should handle "wget URL1 URL2..." */

    target.user = NULL;
    parse_url(argv[optind], &target);

    /* Use the proxy if necessary */
    use_proxy = (strcmp(proxy_flag, "off") != 0);
    if (use_proxy) {
        proxy = getenv(target.is_ftp ? "ftp_proxy" : "http_proxy");
        if (proxy && proxy[0]) {
            server.user = NULL;
            parse_url(proxy, &server);
        } else {
            use_proxy = 0;
        }
    }
    if (!use_proxy) {
        server.port = target.port;
        if (ENABLE_FEATURE_IPV6) {
            server.host = xstrdup(target.host);
        } else {
            server.host = target.host;
        }
    }

    if (ENABLE_FEATURE_IPV6)
        strip_ipv6_scope_id(target.host);

    /* Guess an output filename, if there was no -O FILE */
    if (!(opt & WGET_OPT_OUTNAME)) {
        fname_out = bb_get_last_path_component_nostrip(target.path);
        /* handle "wget http://kernel.org//" */
        if (fname_out[0] == '/' || !fname_out[0])
            fname_out = (char*)"index.html";
        /* -P DIR is considered only if there was no -O FILE */
        if (dir_prefix)
            fname_out = concat_path_file(dir_prefix, fname_out);
    } else {
        if (LONE_DASH(fname_out)) {
            /* -O - */
            output_fd = 1;
            opt &= ~WGET_OPT_CONTINUE;
        }
    }
#if ENABLE_FEATURE_WGET_STATUSBAR
    G.curfile = bb_get_last_path_component_nostrip(fname_out);
#endif

    /* Impossible?
    if ((opt & WGET_OPT_CONTINUE) && !fname_out)
    	bb_error_msg_and_die("can't specify continue (-c) without a filename (-O)");
    */

    /* Determine where to start transfer */
    if (opt & WGET_OPT_CONTINUE) {
        output_fd = open(fname_out, O_WRONLY);
        if (output_fd >= 0) {
            G.beg_range = xlseek(output_fd, 0, SEEK_END);
        }
        /* File doesn't exist. We do not create file here yet.
         * We are not sure it exists on remove side */
    }

    redir_limit = 5;
resolve_lsa:
    lsa = xhost2sockaddr(server.host, server.port);
    if (!(opt & WGET_OPT_QUIET)) {
        char *s = xmalloc_sockaddr2dotted(&lsa->u.sa);
        fprintf(stderr, "Connecting to %s (%s)\n", server.host, s);
        free(s);
    }
establish_session:
    if (use_proxy || !target.is_ftp) {
        /*
         *  HTTP session
         */
        char *str;
        int status;

        /* Open socket to http server */
        sfp = open_socket(lsa);

        /* Send HTTP request */
        if (use_proxy) {
            fprintf(sfp, "GET %stp://%s/%s HTTP/1.1\r\n",
                    target.is_ftp ? "f" : "ht", target.host,
                    target.path);
        } else {
            if (opt & WGET_OPT_POST_DATA)
                fprintf(sfp, "POST /%s HTTP/1.1\r\n", target.path);
            else
                fprintf(sfp, "GET /%s HTTP/1.1\r\n", target.path);
        }

        fprintf(sfp, "Host: %s\r\nUser-Agent: %s\r\n",
                target.host, user_agent);

#if ENABLE_FEATURE_WGET_AUTHENTICATION
        if (target.user) {
            fprintf(sfp, "Proxy-Authorization: Basic %s\r\n"+6,
                    base64enc_512(buf, target.user));
        }
        if (use_proxy && server.user) {
            fprintf(sfp, "Proxy-Authorization: Basic %s\r\n",
                    base64enc_512(buf, server.user));
        }
#endif

        if (G.beg_range)
            fprintf(sfp, "Range: bytes=%"OFF_FMT"u-\r\n", G.beg_range);
#if ENABLE_FEATURE_WGET_LONG_OPTIONS
        if (extra_headers)
            fputs(extra_headers, sfp);

        if (opt & WGET_OPT_POST_DATA) {
            char *estr = URL_escape(post_data);
            fprintf(sfp, "Content-Type: application/x-www-form-urlencoded\r\n");
            fprintf(sfp, "Content-Length: %u\r\n" "\r\n" "%s",
                    (int) strlen(estr), estr);
            /*fprintf(sfp, "Connection: Keep-Alive\r\n\r\n");*/
            /*fprintf(sfp, "%s\r\n", estr);*/
            free(estr);
        } else
#endif
        {   /* If "Connection:" is needed, document why */
            fprintf(sfp, /* "Connection: close\r\n" */ "\r\n");
        }

        /*
         * Retrieve HTTP response line and check for "200" status code.
         */
read_response:
        if (fgets(buf, sizeof(buf), sfp) == NULL)
            bb_error_msg_and_die("no response from server");

        str = buf;
        str = skip_non_whitespace(str);
        str = skip_whitespace(str);
        // FIXME: no error check
        // xatou wouldn't work: "200 OK"
        status = atoi(str);
        switch (status) {
        case 0:
        case 100:
            while (gethdr(buf, sizeof(buf), sfp /*, &n*/) != NULL)
                /* eat all remaining headers */;
            goto read_response;
        case 200:
        /*
        Response 204 doesn't say "null file", it says "metadata
        has changed but data didn't":

        "10.2.5 204 No Content
        The server has fulfilled the request but does not need to return
        an entity-body, and might want to return updated metainformation.
        The response MAY include new or updated metainformation in the form
        of entity-headers, which if present SHOULD be associated with
        the requested variant.

        If the client is a user agent, it SHOULD NOT change its document
        view from that which caused the request to be sent. This response
        is primarily intended to allow input for actions to take place
        without causing a change to the user agent's active document view,
        although any new or updated metainformation SHOULD be applied
        to the document currently in the user agent's active view.

        The 204 response MUST NOT include a message-body, and thus
        is always terminated by the first empty line after the header fields."

        However, in real world it was observed that some web servers
        (e.g. Boa/0.94.14rc21) simply use code 204 when file size is zero.
        */
        case 204:
            break;
        case 300:	/* redirection */
        case 301:
        case 302:
        case 303:
            break;
        case 206:
            if (G.beg_range)
                break;
        /* fall through */
        default:
            bb_error_msg_and_die("server returned error: %s", sanitize_string(buf));
        }

        /*
         * Retrieve HTTP headers.
         */
        while ((str = gethdr(buf, sizeof(buf), sfp /*, &n*/)) != NULL) {
            /* gethdr converted "FOO:" string to lowercase */
            smalluint key;
            /* strip trailing whitespace */
            char *s = strchrnul(str, '\0') - 1;
            while (s >= str && (*s == ' ' || *s == '\t')) {
                *s = '\0';
                s--;
            }
            key = index_in_strings(keywords, buf) + 1;
            if (key == KEY_content_length) {
                G.content_len = BB_STRTOOFF(str, NULL, 10);
                if (G.content_len < 0 || errno) {
                    bb_error_msg_and_die("content-length %s is garbage", sanitize_string(str));
                }
                G.got_clen = 1;
                continue;
            }
            if (key == KEY_transfer_encoding) {
                if (index_in_strings(keywords, str_tolower(str)) + 1 != KEY_chunked)
                    bb_error_msg_and_die("transfer encoding '%s' is not supported", sanitize_string(str));
                G.chunked = G.got_clen = 1;
            }
            if (key == KEY_location && status >= 300) {
                if (--redir_limit == 0)
                    bb_error_msg_and_die("too many redirections");
                fclose(sfp);
                G.got_clen = 0;
                G.chunked = 0;
                if (str[0] == '/')
                    /* free(target.allocated); */
                    target.path = /* target.allocated = */ xstrdup(str+1);
                /* lsa stays the same: it's on the same server */
                else {
                    parse_url(str, &target);
                    if (!use_proxy) {
                        server.host = target.host;
                        /* strip_ipv6_scope_id(target.host); - no! */
                        /* we assume remote never gives us IPv6 addr with scope id */
                        server.port = target.port;
                        free(lsa);
                        goto resolve_lsa;
                    } /* else: lsa stays the same: we use proxy */
                }
                goto establish_session;
            }
        }
//		if (status >= 300)
//			bb_error_msg_and_die("bad redirection (no Location: header from server)");

        /* For HTTP, data is pumped over the same connection */
        dfp = sfp;

    } else {
        /*
         *  FTP session
         */
        sfp = prepare_ftp_session(&dfp, &target, lsa);
    }

    if (opt & WGET_OPT_SPIDER) {
        if (ENABLE_FEATURE_CLEAN_UP)
            fclose(sfp);
        return EXIT_SUCCESS;
    }

    if (output_fd < 0) {
        int o_flags = O_WRONLY | O_CREAT | O_TRUNC | O_EXCL;
        /* compat with wget: -O FILE can overwrite */
        if (opt & WGET_OPT_OUTNAME)
            o_flags = O_WRONLY | O_CREAT | O_TRUNC;
        output_fd = xopen(fname_out, o_flags);
    }

    retrieve_file_data(dfp, output_fd);
    xclose(output_fd);

    if (dfp != sfp) {
        /* It's ftp. Close it properly */
        fclose(dfp);
        if (ftpcmd(NULL, NULL, sfp, buf) != 226)
            bb_error_msg_and_die("ftp error: %s", sanitize_string(buf+4));
        /* ftpcmd("QUIT", NULL, sfp, buf); - why bother? */
    }

    return EXIT_SUCCESS;
}
Example #20
0
int lpqr_main(int argc UNUSED_PARAM, char *argv[])
{
	enum {
		OPT_P           = 1 << 0, // -P queue[@host[:port]]. If no -P is given use $PRINTER, then "lp@localhost:515"
		OPT_U           = 1 << 1, // -U username

		LPR_V           = 1 << 2, // -V: be verbose
		LPR_h           = 1 << 3, // -h: want banner printed
		LPR_C           = 1 << 4, // -C class: job "class" (? supposedly printed on banner)
		LPR_J           = 1 << 5, // -J title: the job title for the banner page
		LPR_m           = 1 << 6, // -m: send mail back to user

		LPQ_SHORT_FMT   = 1 << 2, // -s: short listing format
		LPQ_DELETE      = 1 << 3, // -d: delete job(s)
		LPQ_FORCE       = 1 << 4, // -f: force waiting job(s) to be printed
	};
	char tempfile[sizeof("/tmp/lprXXXXXX")];
	const char *job_title;
	const char *printer_class = "";   // printer class, max 32 char
	const char *queue;                // name of printer queue
	const char *server = "localhost"; // server[:port] of printer queue
	char *hostname;
	// N.B. IMHO getenv("USER") can be way easily spoofed!
	const char *user = xuid2uname(getuid());
	unsigned job;
	unsigned opts;
	int fd;

	queue = getenv("PRINTER");
	if (!queue)
		queue = "lp";

	// parse options
	// TODO: set opt_complementary: s,d,f are mutually exclusive
	opts = getopt32(argv,
		(/*lp*/'r' == applet_name[2]) ? "P:U:VhC:J:m" : "P:U:sdf"
		, &queue, &user
		, &printer_class, &job_title
	);
	argv += optind;

	{
		// queue name is to the left of '@'
		char *s = strchr(queue, '@');
		if (s) {
			// server name is to the right of '@'
			*s = '\0';
			server = s + 1;
		}
	}

	// do connect
	fd = create_and_connect_stream_or_die(server, 515);

	//
	// LPQ ------------------------
	//
	if (/*lp*/'q' == applet_name[2]) {
		char cmd;
		// force printing of every job still in queue
		if (opts & LPQ_FORCE) {
			cmd = 1;
			goto command;
		// delete job(s)
		} else if (opts & LPQ_DELETE) {
			fdprintf(fd, "\x5" "%s %s", queue, user);
			while (*argv) {
				fdprintf(fd, " %s", *argv++);
			}
			bb_putchar('\n');
		// dump current jobs status
		// N.B. periodical polling should be achieved
		// via "watch -n delay lpq"
		// They say it's the UNIX-way :)
		} else {
			cmd = (opts & LPQ_SHORT_FMT) ? 3 : 4;
 command:
			fdprintf(fd, "%c" "%s\n", cmd, queue);
			bb_copyfd_eof(fd, STDOUT_FILENO);
		}

		return EXIT_SUCCESS;
	}

	//
	// LPR ------------------------
	//
	if (opts & LPR_V)
		bb_error_msg("connected to server");

	job = getpid() % 1000;
	hostname = safe_gethostname();

	// no files given on command line? -> use stdin
	if (!*argv)
		*--argv = (char *)"-";

	fdprintf(fd, "\x2" "%s\n", queue);
	get_response_or_say_and_die(fd, "setting queue");

	// process files
	do {
		unsigned cflen;
		int dfd;
		struct stat st;
		char *c;
		char *remote_filename;
		char *controlfile;

		// if data file is stdin, we need to dump it first
		if (LONE_DASH(*argv)) {
			strcpy(tempfile, "/tmp/lprXXXXXX");
			dfd = xmkstemp(tempfile);
			bb_copyfd_eof(STDIN_FILENO, dfd);
			xlseek(dfd, 0, SEEK_SET);
			*argv = (char*)bb_msg_standard_input;
		} else {
			dfd = xopen(*argv, O_RDONLY);
		}

		st.st_size = 0; /* paranoia: fstat may theoretically fail */
		fstat(dfd, &st);

		/* Apparently, some servers are buggy and won't accept 0-sized jobs.
		 * Standard lpr works around it by refusing to send such jobs:
		 */
		if (st.st_size == 0) {
			bb_error_msg("nothing to print");
			continue;
		}

		/* "The name ... should start with ASCII "cfA",
		 * followed by a three digit job number, followed
		 * by the host name which has constructed the file."
		 * We supply 'c' or 'd' as needed for control/data file. */
		remote_filename = xasprintf("fA%03u%s", job, hostname);

		// create control file
		// TODO: all lines but 2 last are constants! How we can use this fact?
		controlfile = xasprintf(
			"H" "%.32s\n" "P" "%.32s\n" /* H HOST, P USER */
			"C" "%.32s\n" /* C CLASS - printed on banner page (if L cmd is also given) */
			"J" "%.99s\n" /* J JOBNAME */
			/* "class name for banner page and job name
			 * for banner page commands must precede L command" */
			"L" "%.32s\n" /* L USER - print banner page, with given user's name */
			"M" "%.32s\n" /* M WHOM_TO_MAIL */
			"l" "d%.31s\n" /* l DATA_FILE_NAME ("dfAxxx") */
			, hostname, user
			, printer_class /* can be "" */
			, ((opts & LPR_J) ? job_title : *argv)
			, (opts & LPR_h) ? user : ""
			, (opts & LPR_m) ? user : ""
			, remote_filename
		);
		// delete possible "\nX\n" (that is, one-char) patterns
		c = controlfile;
		while ((c = strchr(c, '\n')) != NULL) {
			if (c[1] && c[2] == '\n') {
				overlapping_strcpy(c, c+2);
			} else {
				c++;
			}
		}

		// send control file
		if (opts & LPR_V)
			bb_error_msg("sending control file");
		/* "Acknowledgement processing must occur as usual
		 * after the command is sent." */
		cflen = (unsigned)strlen(controlfile);
		fdprintf(fd, "\x2" "%u c%s\n", cflen, remote_filename);
		get_response_or_say_and_die(fd, "sending control file");
		/* "Once all of the contents have
		 * been delivered, an octet of zero bits is sent as
		 * an indication that the file being sent is complete.
		 * A second level of acknowledgement processing
		 * must occur at this point." */
		full_write(fd, controlfile, cflen + 1); /* writes NUL byte too */
		get_response_or_say_and_die(fd, "sending control file");

		// send data file, with name "dfaXXX"
		if (opts & LPR_V)
			bb_error_msg("sending data file");
		fdprintf(fd, "\x3" "%"FILESIZE_FMT"u d%s\n", st.st_size, remote_filename);
		get_response_or_say_and_die(fd, "sending data file");
		if (bb_copyfd_size(dfd, fd, st.st_size) != st.st_size) {
			// We're screwed. We sent less bytes than we advertised.
			bb_error_msg_and_die("local file changed size?!");
		}
		write(fd, "", 1); // send ACK
		get_response_or_say_and_die(fd, "sending data file");

		// delete temporary file if we dumped stdin
		if (*argv == (char*)bb_msg_standard_input)
			unlink(tempfile);

		// cleanup
		close(fd);
		free(remote_filename);
		free(controlfile);

		// say job accepted
		if (opts & LPR_V)
			bb_error_msg("job accepted");

		// next, please!
		job = (job + 1) % 1000;
	} while (*++argv);

	return EXIT_SUCCESS;
}
Example #21
0
FILE *start_wget(char *url, int *total)
{
	char buf[512];
	struct host_info server, target;
	len_and_sockaddr *lsa;
	int redir_limit;
#if ENABLE_FEATURE_WGET_LONG_OPTIONS
	char *post_data;
	char *extra_headers = NULL;
	llist_t *headers_llist = NULL;
#endif
	FILE *sfp;                      /* socket to web/ftp server         */
	int use_proxy = 0;              /* Use proxies if env vars are set  */
	const char *user_agent = "Wget";/* "User-Agent" header field        */
	struct globals state;
	char *str;
	int status;
    bzero(&state, sizeof(state));

	static const char keywords[] =
		"content-length\0""transfer-encoding\0""chunked\0""location\0";
	enum {
		KEY_content_length = 1, KEY_transfer_encoding, KEY_chunked, KEY_location
	};

	target.user = NULL;
	parse_url(url, &target);

	state.timeout_seconds = 900;
	server.port = target.port;
	server.host = target.host;

#if 0
	if (opt & WGET_OPT_CONTINUE) {
		output_fd = open(fname_out, O_WRONLY);
		if (output_fd >= 0) {
			state.beg_range = xlseek(output_fd, 0, SEEK_END);
		}
		/* File doesn't exist. We do not create file here yet.
		 * We are not sure it exists on remove side */
	}
#endif

	redir_limit = 5;
 resolve_lsa:
	lsa = xhost2sockaddr(server.host, server.port);
 establish_session:
	/*
	 *  HTTP session
	 */

	/* Open socket to http server */
	sfp = open_socket(lsa);
	if (!sfp) {
		ERROR("Couldn't connect to %s:%d", server.host, server.port);
		return NULL;
	}

	/* Send HTTP request */
	fprintf(sfp, "GET /%s HTTP/1.1\r\n", target.path);

	fprintf(sfp, "Host: %s\r\nUser-Agent: %s\r\n",
		target.host, user_agent);

	/* Ask server to close the connection as soon as we are done
	 * (IOW: we do not intend to send more requests)
	 */
	fprintf(sfp, "Connection: close\r\n");

	if (state.beg_range)
		fprintf(sfp, "Range: bytes=%lu-\r\n", state.beg_range);

	fprintf(sfp, "\r\n");
	fflush(sfp);


	/*
	 * Retrieve HTTP response line and check for "200" status code.
	 */
 read_response:
	if (fgets(buf, sizeof(buf), sfp) == NULL)
		ERROR("no response from server");

	str = buf;
	str = skip_non_whitespace(str);
	str = skip_whitespace(str);
	// FIXME: no error check
	// xatou wouldn't work: "200 OK"
	status = atoi(str);
	switch (status) {
	case 0:
	case 100:
		while (gethdr(buf, sizeof(buf), sfp /*, &n*/) != NULL)
			/* eat all remaining headers */;
		goto read_response;
	case 200:
/*
Response 204 doesn't say "null file", it says "metadata
has changed but data didn't":

"10.2.5 204 No Content
The server has fulfilled the request but does not need to return
an entity-body, and might want to return updated metainformation.
The response MAY include new or updated metainformation in the form
of entity-headers, which if present SHOULD be associated with
the requested variant.

If the client is a user agent, it SHOULD NOT change its document
view from that which caused the request to be sent. This response
is primarily intended to allow input for actions to take place
without causing a change to the user agent's active document view,
although any new or updated metainformation SHOULD be applied
to the document currently in the user agent's active view.

The 204 response MUST NOT include a message-body, and thus
is always terminated by the first empty line after the header fields."

However, in real world it was observed that some web servers
(e.g. Boa/0.94.14rc21) simply use code 204 when file size is zero.
*/
	case 204:
		break;
	case 300:  /* redirection */
	case 301:
	case 302:
	case 303:
		break;
	case 206:
		if (state.beg_range)
			break;
		/* fall through */
	default:
		ERROR("server returned error: %s", sanitize_string(buf));
	}

	/*
	 * Retrieve HTTP headers.
	 */
	while ((str = gethdr(buf, sizeof(buf), sfp /*, &n*/)) != NULL) {
		/* gethdr converted "FOO:" string to lowercase */
		smalluint key;
		/* strip trailing whitespace */
		char *s = strchrnul(str, '\0') - 1;
		while (s >= str && (*s == ' ' || *s == '\t')) {
			*s = '\0';
			s--;
		}
		key = index_in_strings(keywords, buf) + 1;
		if (key == KEY_content_length) {
			state.content_len = strtoul(str, NULL, 10);
			state.total_len   = strtoul(str, NULL, 10);
			if (state.content_len < 0 || errno) {
				ERROR("content-length %s is garbage", sanitize_string(str));
			}
			state.got_clen = 1;
			continue;
		}
		if (key == KEY_transfer_encoding) {
			if (index_in_strings(keywords, str_tolower(str)) + 1 != KEY_chunked)
				ERROR("transfer encoding '%s' is not supported", sanitize_string(str));
			state.chunked = state.got_clen = 1;
		}
		if (key == KEY_location && status >= 300) {
			if (--redir_limit == 0)
				ERROR("too many redirections");
			fclose(sfp);
			state.got_clen = 0;
			state.chunked = 0;
			if (str[0] == '/')
				/* free(target.allocated); */
				target.path = /* target.allocated = */ strdup(str+1);
				/* lsa stays the same: it's on the same server */
			else {
				parse_url(str, &target);
				if (!use_proxy) {
					server.host = target.host;
					server.port = target.port;
					free(lsa);
					goto resolve_lsa;
				} /* else: lsa stays the same: we use proxy */
			}
			goto establish_session;
		}
	}
//		if (status >= 300)
//			ERROR("bad redirection (no Location: header from server)");


	if (total)
		*total = state.content_len;
	ndelay_off(fileno(sfp));
	clearerr(sfp);
	return sfp;
#if 0
	if (retrieve_file_data(&state, sfp, progress, handle, data))
		return -1;
	handle(data, NULL, 0);

	return EXIT_SUCCESS;
#endif
}
Example #22
0
int crontab_main(int argc UNUSED_PARAM, char **argv)
{
	const struct passwd *pas;
	const char *crontab_dir = CRONTABS;
	char *tmp_fname;
	char *new_fname;
	char *user_name;  /* -u USER */
	int fd;
	int src_fd;
	int opt_ler;

	/* file [opts]     Replace crontab from file
	 * - [opts]        Replace crontab from stdin
	 * -u user         User
	 * -c dir          Crontab directory
	 * -l              List crontab for user
	 * -e              Edit crontab for user
	 * -r              Delete crontab for user
	 * bbox also supports -d == -r, but most other crontab
	 * implementations do not. Deprecated.
	 */
	enum {
		OPT_u = (1 << 0),
		OPT_c = (1 << 1),
		OPT_l = (1 << 2),
		OPT_e = (1 << 3),
		OPT_r = (1 << 4),
		OPT_ler = OPT_l + OPT_e + OPT_r,
	};

	opt_complementary = "?1:dr"; /* max one argument; -d implies -r */
	opt_ler = getopt32(argv, "u:c:lerd", &user_name, &crontab_dir);
	argv += optind;

	if (sanitize_env_if_suid()) { /* Clears dangerous stuff, sets PATH */
		/* run by non-root? */
		if (opt_ler & (OPT_u|OPT_c))
			bb_error_msg_and_die("only root can use -c or -u");
	}

	if (opt_ler & OPT_u) {
		pas = getpwnam(user_name);
		if (!pas)
			bb_error_msg_and_die("user %s is not known", user_name);
	} else {
/* XXX: xgetpwuid */
		uid_t my_uid = getuid();
		pas = getpwuid(my_uid);
		if (!pas)
			bb_perror_msg_and_die("unknown uid %d", (int)my_uid);
	}

#define user_name DONT_USE_ME_BEYOND_THIS_POINT

	/* From now on, keep only -l, -e, -r bits */
	opt_ler &= OPT_ler;
	if ((opt_ler - 1) & opt_ler) /* more than one bit set? */
		bb_show_usage();

	/* Read replacement file under user's UID/GID/group vector */
	src_fd = STDIN_FILENO;
	if (!opt_ler) { /* Replace? */
		if (!argv[0])
			bb_show_usage();
		if (NOT_LONE_DASH(argv[0])) {
			src_fd = open_as_user(pas, argv[0]);
			if (src_fd < 0)
				bb_error_msg_and_die("user %s cannot read %s",
						pas->pw_name, argv[0]);
		}
	}

	/* cd to our crontab directory */
	xchdir(crontab_dir);

	tmp_fname = NULL;

	/* Handle requested operation */
	switch (opt_ler) {

	default: /* case OPT_r: Delete */
		unlink(pas->pw_name);
		break;

	case OPT_l: /* List */
		{
			char *args[2] = { pas->pw_name, NULL };
			return bb_cat(args);
			/* list exits,
			 * the rest go play with cron update file */
		}

	case OPT_e: /* Edit */
		tmp_fname = xasprintf("%s.%u", crontab_dir, (unsigned)getpid());
		/* No O_EXCL: we don't want to be stuck if earlier crontabs
		 * were killed, leaving stale temp file behind */
		src_fd = xopen3(tmp_fname, O_RDWR|O_CREAT|O_TRUNC, 0600);
		fchown(src_fd, pas->pw_uid, pas->pw_gid);
		fd = open(pas->pw_name, O_RDONLY);
		if (fd >= 0) {
			bb_copyfd_eof(fd, src_fd);
			close(fd);
			xlseek(src_fd, 0, SEEK_SET);
		}
		close_on_exec_on(src_fd); /* don't want editor to see this fd */
		edit_file(pas, tmp_fname);
		/* fall through */

	case 0: /* Replace (no -l, -e, or -r were given) */
		new_fname = xasprintf("%s.new", pas->pw_name);
		fd = open(new_fname, O_WRONLY|O_CREAT|O_TRUNC|O_APPEND, 0600);
		if (fd >= 0) {
			bb_copyfd_eof(src_fd, fd);
			close(fd);
			xrename(new_fname, pas->pw_name);
		} else {
			bb_error_msg("cannot create %s/%s",
					crontab_dir, new_fname);
		}
		if (tmp_fname)
			unlink(tmp_fname);
		/*free(tmp_fname);*/
		/*free(new_fname);*/

	} /* switch */

	/* Bump notification file.  Handle window where crond picks file up
	 * before we can write our entry out.
	 */
	while ((fd = open(CRONUPDATE, O_WRONLY|O_CREAT|O_APPEND, 0600)) >= 0) {
		struct stat st;

		fdprintf(fd, "%s\n", pas->pw_name);
		if (fstat(fd, &st) != 0 || st.st_nlink != 0) {
			/*close(fd);*/
			break;
		}
		/* st.st_nlink == 0:
		 * file was deleted, maybe crond missed our notification */
		close(fd);
		/* loop */
	}
	if (fd < 0) {
		bb_error_msg("cannot append to %s/%s",
				crontab_dir, CRONUPDATE);
	}
	return 0;
}
Example #23
0
int nandwrite_main(int argc UNUSED_PARAM, char **argv)
{
	/* Buffer for OOB data */
	unsigned char *oobbuf;
	unsigned opts;
	int fd;
	ssize_t cnt;
	unsigned mtdoffset, meminfo_writesize, blockstart, limit;
	unsigned end_addr = ~0;
	struct mtd_info_user meminfo;
	struct mtd_oob_buf oob;
	unsigned char *filebuf;
	const char *opt_s = "0", *opt_f = "-", *opt_l;

	if (IS_NANDDUMP) {
		opt_complementary = "=1";
		opts = getopt32(argv, "os:bf:l:", &opt_s, &opt_f, &opt_l);
	} else { /* nandwrite */
		opt_complementary = "-1:?2";
		opts = getopt32(argv, "ps:", &opt_s);
	}
	argv += optind;

	if (IS_NANDWRITE && argv[1])
		opt_f = argv[1];
	if (!LONE_DASH(opt_f)) {
		int tmp_fd = xopen(opt_f,
			IS_NANDDUMP ? O_WRONLY | O_TRUNC | O_CREAT : O_RDONLY
		);
		xmove_fd(tmp_fd, IS_NANDDUMP ? STDOUT_FILENO : STDIN_FILENO);
	}

	fd = xopen(argv[0], O_RDWR);
	xioctl(fd, MEMGETINFO, &meminfo);

	mtdoffset = xstrtou(opt_s, 0);
	if (IS_NANDDUMP && (opts & OPT_l)) {
		unsigned length = xstrtou(opt_l, 0);
		if (length < meminfo.size - mtdoffset)
			end_addr = mtdoffset + length;
	}

	/* Pull it into a CPU register (hopefully) - smaller code that way */
	meminfo_writesize = meminfo.writesize;

	if (mtdoffset & (meminfo_writesize - 1))
		bb_error_msg_and_die("start address is not page aligned");

	filebuf = xmalloc(meminfo_writesize);
	oobbuf = xmalloc(meminfo.oobsize);

	oob.start  = 0;
	oob.length = meminfo.oobsize;
	oob.ptr    = oobbuf;

	blockstart = mtdoffset & ~(meminfo.erasesize - 1);
	if (blockstart != mtdoffset) {
		unsigned tmp;
		/* mtdoffset is in the middle of an erase block, verify that
		 * this block is OK. Advance mtdoffset only if this block is
		 * bad.
		 */
		tmp = next_good_eraseblock(fd, &meminfo, blockstart);
		if (tmp != blockstart) {
			/* bad block(s), advance mtdoffset */
			if (IS_NANDDUMP & !(opts & OPT_b)) {
				int bad_len = MIN(tmp, end_addr) - mtdoffset;
				dump_bad(&meminfo, bad_len, !(opts & OPT_o));
			}
			mtdoffset = tmp;
		}
	}

	cnt = -1;
	limit = MIN(meminfo.size, end_addr);
	while (mtdoffset < limit) {
		int input_fd = IS_NANDWRITE ? STDIN_FILENO : fd;
		int output_fd = IS_NANDWRITE ? fd : STDOUT_FILENO;

		blockstart = mtdoffset & ~(meminfo.erasesize - 1);
		if (blockstart == mtdoffset) {
			/* starting a new eraseblock */
			mtdoffset = next_good_eraseblock(fd, &meminfo, blockstart);
			if (IS_NANDWRITE)
				printf("Writing at 0x%08x\n", mtdoffset);
			else if (mtdoffset > blockstart) {
				int bad_len = MIN(mtdoffset, limit) - blockstart;
				dump_bad(&meminfo, bad_len, !(opts & OPT_o));
			}
			if (mtdoffset >= limit)
				break;
		}
		xlseek(fd, mtdoffset, SEEK_SET);

		/* get some more data from input */
		cnt = full_read(input_fd, filebuf, meminfo_writesize);
		if (cnt == 0) {
			/* even with -p, we do not pad past the end of input
			 * (-p only zero-pads last incomplete page)
			 */
			break;
		}
		if (cnt < meminfo_writesize) {
			if (IS_NANDDUMP)
				bb_error_msg_and_die("short read");
			if (!(opts & OPT_p))
				bb_error_msg_and_die("input size is not rounded up to page size, "
						"use -p to zero pad");
			/* zero pad to end of write block */
			memset(filebuf + cnt, 0, meminfo_writesize - cnt);
		}
		xwrite(output_fd, filebuf, meminfo_writesize);

		if (IS_NANDDUMP && !(opts & OPT_o)) {
			/* Dump OOB data */
			oob.start = mtdoffset;
			xioctl(fd, MEMREADOOB, &oob);
			xwrite(output_fd, oobbuf, meminfo.oobsize);
		}

		mtdoffset += meminfo_writesize;
		if (cnt < meminfo_writesize)
			break;
	}

	if (IS_NANDWRITE && cnt != 0) {
		/* We filled entire MTD, but did we reach EOF on input? */
		if (full_read(STDIN_FILENO, filebuf, meminfo_writesize) != 0) {
			/* no */
			bb_error_msg_and_die("not enough space in MTD device");
		}
	}

	if (ENABLE_FEATURE_CLEAN_UP) {
		free(filebuf);
		close(fd);
	}

	return EXIT_SUCCESS;
}
Example #24
0
int flash_eraseall_main(int argc UNUSED_PARAM, char **argv)
{
	struct jffs2_unknown_node cleanmarker;
	mtd_info_t meminfo;
	int fd, clmpos, clmlen;
	erase_info_t erase;
	struct stat st;
	unsigned int flags;
	char *mtd_name;

	opt_complementary = "=1";
	flags = BBTEST | getopt32(argv, "jq");

	mtd_name = argv[optind];
	fd = xopen(mtd_name, O_RDWR);
	fstat(fd, &st);
	if (!S_ISCHR(st.st_mode))
		bb_error_msg_and_die("%s: not a char device", mtd_name);

	xioctl(fd, MEMGETINFO, &meminfo);
	erase.length = meminfo.erasesize;
	if (meminfo.type == MTD_NANDFLASH)
		flags |= IS_NAND;

	clmpos = 0;
	clmlen = 8;
	if (flags & OPTION_J) {
		uint32_t *crc32_table;

		crc32_table = crc32_filltable(NULL, 0);

		cleanmarker.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
		cleanmarker.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER);
		if (!(flags & IS_NAND))
			cleanmarker.totlen = cpu_to_je32(sizeof(struct jffs2_unknown_node));
		else {
			struct nand_oobinfo oobinfo;

			xioctl(fd, MEMGETOOBSEL, &oobinfo);

			/* Check for autoplacement */
			if (oobinfo.useecc == MTD_NANDECC_AUTOPLACE) {
				/* Get the position of the free bytes */
				clmpos = oobinfo.oobfree[0][0];
				clmlen = oobinfo.oobfree[0][1];
				if (clmlen > 8)
					clmlen = 8;
				if (clmlen == 0)
					bb_error_msg_and_die("autoplacement selected and no empty space in oob");
			} else {
				/* Legacy mode */
				switch (meminfo.oobsize) {
				case 8:
					clmpos = 6;
					clmlen = 2;
					break;
				case 16:
					clmpos = 8;
					/*clmlen = 8;*/
					break;
				case 64:
					clmpos = 16;
					/*clmlen = 8;*/
					break;
				}
			}
			cleanmarker.totlen = cpu_to_je32(8);
		}

		cleanmarker.hdr_crc = cpu_to_je32(
			crc32_block_endian0(0, &cleanmarker, sizeof(struct jffs2_unknown_node) - 4, crc32_table)
		);
	}

	/* Don't want to destroy progress indicator by bb_error_msg's */
	applet_name = xasprintf("\n%s: %s", applet_name, mtd_name);

	for (erase.start = 0; erase.start < meminfo.size;
	     erase.start += meminfo.erasesize) {
		if (flags & BBTEST) {
			int ret;
			loff_t offset = erase.start;

			ret = ioctl(fd, MEMGETBADBLOCK, &offset);
			if (ret > 0) {
				if (!(flags & OPTION_Q))
					bb_info_msg("\nSkipping bad block at 0x%08x", erase.start);
				continue;
			}
			if (ret < 0) {
				/* Black block table is not available on certain flash
				 * types e.g. NOR
				 */
				if (errno == EOPNOTSUPP) {
					flags &= ~BBTEST;
					if (flags & IS_NAND)
						bb_error_msg_and_die("bad block check not available");
				} else {
					bb_perror_msg_and_die("MEMGETBADBLOCK error");
				}
			}
		}

		if (!(flags & OPTION_Q))
			show_progress(&meminfo, &erase);

		xioctl(fd, MEMERASE, &erase);

		/* format for JFFS2 ? */
		if (!(flags & OPTION_J))
			continue;

		/* write cleanmarker */
		if (flags & IS_NAND) {
			struct mtd_oob_buf oob;

			oob.ptr = (unsigned char *) &cleanmarker;
			oob.start = erase.start + clmpos;
			oob.length = clmlen;
			xioctl(fd, MEMWRITEOOB, &oob);
		} else {
			xlseek(fd, erase.start, SEEK_SET);
			/* if (lseek(fd, erase.start, SEEK_SET) < 0) {
				bb_perror_msg("MTD %s failure", "seek");
				continue;
			} */
			xwrite(fd, &cleanmarker, sizeof(cleanmarker));
			/* if (write(fd, &cleanmarker, sizeof(cleanmarker)) != sizeof(cleanmarker)) {
				bb_perror_msg("MTD %s failure", "write");
				continue;
			} */
		}
		if (!(flags & OPTION_Q))
			printf(" Cleanmarker written at %x.", erase.start);
	}
	if (!(flags & OPTION_Q)) {
		show_progress(&meminfo, &erase);
		bb_putchar('\n');
	}

	if (ENABLE_FEATURE_CLEAN_UP)
		close(fd);
	return EXIT_SUCCESS;
}
Example #25
0
static int rpm_gettags(const char *filename)
{
	rpm_index *tags;
	int fd;
	unsigned pass, idx;
	unsigned storepos;

	if (!filename) { /* rpm2cpio w/o filename? */
		filename = bb_msg_standard_output;
		fd = 0;
	} else {
		fd = xopen(filename, O_RDONLY);
	}

	storepos = xlseek(fd, 96, SEEK_CUR); /* Seek past the unused lead */
	G.tagcount = 0;
	tags = NULL;
	idx = 0;
	/* 1st pass is the signature headers, 2nd is the main stuff */
	for (pass = 0; pass < 2; pass++) {
		struct rpm_header header;
		unsigned cnt;

		xread(fd, &header, sizeof(header));
		if (header.magic_and_ver != htonl(RPM_HEADER_MAGICnVER))
			bb_error_msg_and_die("invalid RPM header magic in '%s'", filename);
		header.size = ntohl(header.size);
		cnt = ntohl(header.entries);
		storepos += sizeof(header) + cnt * 16;

		G.tagcount += cnt;
		tags = xrealloc(tags, sizeof(tags[0]) * G.tagcount);
		xread(fd, &tags[idx], sizeof(tags[0]) * cnt);
		while (cnt--) {
			rpm_index *tag = &tags[idx];
			tag->tag = ntohl(tag->tag);
			tag->type = ntohl(tag->type);
			tag->count = ntohl(tag->count);
			tag->offset = storepos + ntohl(tag->offset);
			if (pass == 0)
				tag->tag -= 743;
			idx++;
		}
		/* Skip padding to 8 byte boundary after reading signature headers */
		if (pass == 0)
			while (header.size & 7)
				header.size++;
		/* Seek past store */
		storepos = xlseek(fd, header.size, SEEK_CUR);
	}
	G.mytags = tags;

#if !ENABLE_PLATFORM_MINGW32
	/* Map the store */
	storepos = (storepos + G.pagesize) & -(int)G.pagesize;
	/* remember size for munmap */
	G.mapsize = storepos;
	/* some NOMMU systems prefer MAP_PRIVATE over MAP_SHARED */
	G.map = mmap(0, storepos, PROT_READ, MAP_PRIVATE, fd, 0);
	if (G.map == MAP_FAILED)
		bb_perror_msg_and_die("mmap '%s'", filename);
#else
# undef munmap
# define munmap(p, l) free(p)
	/* Allocate memory for the store */
	G.map = xmalloc(storepos);
	xlseek(fd, 0, SEEK_SET);
	full_read(fd, G.map, storepos);
#endif

	return fd;
}
Example #26
0
int last_main(int argc UNUSED_PARAM, char **argv)
{
	struct utmpx ut;
	const char *filename = _PATH_WTMP;
	llist_t *zlist;
	off_t pos;
	time_t start_time;
	time_t boot_time;
	time_t down_time;
	int file;
	smallint going_down;
	smallint boot_down;

	/*opt =*/ getopt32(argv, "Wf:" /* "H" */, &filename);
#ifdef BUT_UTIL_LINUX_LAST_HAS_NO_SUCH_OPT
	if (opt & LAST_OPT_H) {
		/* Print header line */
		if (opt & LAST_OPT_W) {
			printf(HEADER_FORMAT, HEADER_LINE_WIDE);
		} else {
			printf(HEADER_FORMAT, HEADER_LINE);
		}
	}
#endif

	file = xopen(filename, O_RDONLY);
	{
		/* in case the file is empty... */
		struct stat st;
		fstat(file, &st);
		start_time = st.st_ctime;
	}

	time(&down_time);
	going_down = 0;
	boot_down = NORMAL; /* 0 */
	zlist = NULL;
	boot_time = 0;
	/* get file size, rounding down to last full record */
	pos = xlseek(file, 0, SEEK_END) / sizeof(ut) * sizeof(ut);
	for (;;) {
		pos -= (off_t)sizeof(ut);
		if (pos < 0) {
			/* Beyond the beginning of the file boundary =>
			 * the whole file has been read. */
			break;
		}
		xlseek(file, pos, SEEK_SET);
		xread(file, &ut, sizeof(ut));
		/* rewritten by each record, eventially will have
		 * first record's ut_tv.tv_sec: */
		start_time = ut.ut_tv.tv_sec;

		switch (get_ut_type(&ut)) {
		case SHUTDOWN_TIME:
			down_time = ut.ut_tv.tv_sec;
			boot_down = DOWN;
			going_down = 1;
			break;
		case RUN_LVL:
			if (is_runlevel_shutdown(&ut)) {
				down_time = ut.ut_tv.tv_sec;
				going_down = 1;
				boot_down = DOWN;
			}
			break;
		case BOOT_TIME:
			strcpy(ut.ut_line, "system boot");
			show_entry(&ut, REBOOT, down_time);
			boot_down = CRASH;
			going_down = 1;
			break;
		case DEAD_PROCESS:
			if (!ut.ut_line[0]) {
				break;
			}
			/* add_entry */
			llist_add_to(&zlist, memcpy(xmalloc(sizeof(ut)), &ut, sizeof(ut)));
			break;
		case USER_PROCESS: {
			int show;

			if (!ut.ut_line[0]) {
				break;
			}
			/* find_entry */
			show = 1;
			{
				llist_t *el, *next;
				for (el = zlist; el; el = next) {
					struct utmpx *up = (struct utmpx *)el->data;
					next = el->link;
					if (strncmp(up->ut_line, ut.ut_line, __UT_LINESIZE) == 0) {
						if (show) {
							show_entry(&ut, NORMAL, up->ut_tv.tv_sec);
							show = 0;
						}
						llist_unlink(&zlist, el);
						free(el->data);
						free(el);
					}
				}
			}

			if (show) {
				int state = boot_down;

				if (boot_time == 0) {
					state = LOGGED;
					/* Check if the process is alive */
					if ((ut.ut_pid > 0)
					 && (kill(ut.ut_pid, 0) != 0)
					 && (errno == ESRCH)) {
						state = GONE;
					}
				}
				show_entry(&ut, state, boot_time);
			}
			/* add_entry */
			llist_add_to(&zlist, memcpy(xmalloc(sizeof(ut)), &ut, sizeof(ut)));
			break;
		}
		}

		if (going_down) {
			boot_time = ut.ut_tv.tv_sec;
			llist_free(zlist, free);
			zlist = NULL;
			going_down = 0;
		}
	}

	if (ENABLE_FEATURE_CLEAN_UP) {
		llist_free(zlist, free);
	}

	printf("\nwtmp begins %s", ctime(&start_time));

	if (ENABLE_FEATURE_CLEAN_UP)
		close(file);
	fflush_stdout_and_exit(EXIT_SUCCESS);
}