Esempio n. 1
0
int
sentinel_write(struct volume *v, uint32_t _seq)
{
	int ret, block;
	struct stat s;
	uint32_t seq;

	if (stat("/tmp/config.tar.gz", &s)) {
		ULOG_ERR("failed to stat /tmp/config.tar.gz\n");
		return -1;
	}

	snapshot_next_free(v, &seq);
	if (_seq)
		seq = _seq;
	block = v->size / v->block_size;
	block -= pad_file_size(v, s.st_size) / v->block_size;
	if (block < 0)
		block = 0;

	ret = snapshot_write_file(v, block, "/tmp/config.tar.gz", seq, CONF);
	if (ret)
		ULOG_ERR("failed to write sentinel\n");
	else
		ULOG_INFO("wrote /tmp/config.tar.gz sentinel\n");
	return ret;
}
Esempio n. 2
0
int
snapshot_read_file(struct volume *v, int block, char *file, uint32_t type)
{
	struct file_header hdr;
	char buffer[256];
	int out, offset = 0;

	if (volume_read(v, &hdr, block * v->block_size, sizeof(struct file_header))) {
		ULOG_ERR("failed to read header\n");
		return -1;
	}
	be32_to_hdr(&hdr);

	if (hdr.magic != OWRT)
		return -1;

	if (hdr.type != type)
		return -1;

	if (valid_file_size(hdr.length))
		return -1;

	out = open(file, O_WRONLY | O_CREAT, 0700);
	if (!out) {
		ULOG_ERR("failed to open %s\n", file);
		return -1;
	}

	offset = block * v->block_size + sizeof(hdr);

	while (hdr.length > 0) {
		int len = sizeof(buffer);

		if (hdr.length < len)
			len = hdr.length;

		if (volume_read(v, buffer, offset, len))
			return -1;
		if (write(out, buffer, len) != len)
			return -1;
		offset += len;
		hdr.length -= len;
	}

	close(out);

	if (verify_file_hash(file, hdr.md5)) {
		ULOG_ERR("md5 verification failed\n");
		unlink(file);
		return 0;
	}

        block += pad_file_size(v, hdr.length) / v->block_size;

	return block;
}
Esempio n. 3
0
int
snapshot_write_file(struct volume *v, int block, char *file, uint32_t seq, uint32_t type)
{
	uint32_t md5[4] = { 0 };
	struct file_header hdr;
	struct stat s;
        char buffer[256];
	int in = 0, len, offset;
	int ret = -1;

	if (stat(file, &s) || md5sum(file, md5)) {
		ULOG_ERR("stat failed on %s\n", file);
		goto out;
	}

	if ((block * v->block_size) + pad_file_size(v, s.st_size) > v->size) {
		ULOG_ERR("upgrade is too big for the flash\n");
		goto out;
	}
	volume_erase(v, block * v->block_size, pad_file_size(v, s.st_size));
	volume_erase(v, block * v->block_size + pad_file_size(v, s.st_size), v->block_size);

	hdr.length = s.st_size;
	hdr.magic = OWRT;
	hdr.type = type;
	hdr.seq = seq;
	memcpy(hdr.md5, md5, sizeof(md5));
	hdr_to_be32(&hdr);

	if (volume_write(v, &hdr, block * v->block_size, sizeof(struct file_header))) {
		ULOG_ERR("failed to write header\n");
		goto out;
	}

	in = open(file, O_RDONLY);
	if (in < 1) {
		ULOG_ERR("failed to open %s\n", file);
		goto out;
	}

	offset = (block * v->block_size) + sizeof(struct file_header);

	while ((len = read(in, buffer, sizeof(buffer))) > 0) {
		if (volume_write(v, buffer, offset, len) < 0)
			goto out;
		offset += len;
	}

	ret = 0;

out:
	if (in > 0)
		close(in);

	return ret;
}
Esempio n. 4
0
int
config_find(struct volume *v, struct file_header *conf, struct file_header *sentinel)
{
	uint32_t seq;
	int i, next = snapshot_next_free(v, &seq);

	conf->magic = sentinel->magic = 0;

	if (!volume_read(v, conf, next, sizeof(*conf)))
		be32_to_hdr(conf);

	for (i = (v->size / v->block_size) - 1; i > 0; i--) {
		if (volume_read(v, sentinel,  i * v->block_size, sizeof(*sentinel))) {
			ULOG_ERR("failed to read header\n");
			return -1;
		}
		be32_to_hdr(sentinel);

		if (sentinel->magic == OWRT && sentinel->type == CONF && !valid_file_size(sentinel->length)) {
			if (next == i)
				return -1;
			return i;
		}
	}

	return -1;
}
Esempio n. 5
0
int
snapshot_next_free(struct volume *v, uint32_t *seq)
{
	struct file_header hdr = { 0 };
	int block = 0;

	*seq = rand();

	do {
		if (volume_read(v, &hdr, block * v->block_size, sizeof(struct file_header))) {
			ULOG_ERR("scanning for next free block failed\n");
			return 0;
		}

		be32_to_hdr(&hdr);

		if (hdr.magic != OWRT)
			break;

		if (hdr.type == DATA && !valid_file_size(hdr.length)) {
			if (*seq + 1 != hdr.seq && block)
				return block;
			*seq = hdr.seq;
			block += pad_file_size(v, hdr.length) / v->block_size;
		}
	} while (hdr.type == DATA);

	return block;
}
Esempio n. 6
0
int
verify_file_hash(char *file, uint32_t *hash)
{
	uint32_t md5[4];

	if (md5sum(file, md5)) {
		ULOG_ERR("failed to generate md5 sum\n");
		return -1;
	}

	if (memcmp(md5, hash, sizeof(md5))) {
		ULOG_ERR("failed to verify hash of %s.\n", file);
		return -1;
	}

	return 0;
}
Esempio n. 7
0
static int
snapshot_sync(struct volume *v)
{
	struct file_header sentinel, conf;
	int next, block = 0;
	uint32_t seq;

	next = snapshot_next_free(v, &seq);
	block = config_find(v, &conf, &sentinel);
	if (is_config(&conf) && conf.seq != seq) {
		conf.magic = 0;
		volume_erase(v, next * v->block_size, 2 * v->block_size);
	}

	if (is_config(&sentinel) && (sentinel.seq != seq)) {
		sentinel.magic = 0;
		volume_erase(v, block * v->block_size, v->block_size);
	}

	if (!is_config(&conf) && !is_config(&sentinel)) {
	//	ULOG_ERR("no config found\n");
	} else if (((is_config(&conf) && is_config(&sentinel)) &&
				(memcmp(conf.md5, sentinel.md5, sizeof(conf.md5)) || (conf.seq != sentinel.seq))) ||
			(is_config(&conf) && !is_config(&sentinel))) {
		uint32_t seq;
		int next = snapshot_next_free(v, &seq);
		int ret = snapshot_read_file(v, next, "/tmp/config.tar.gz", CONF);
		if (ret > 0) {
			if (sentinel_write(v, conf.seq))
				ULOG_ERR("failed to write sentinel data");
		}
	} else if (!is_config(&conf) && is_config(&sentinel) && next) {
		int ret = snapshot_read_file(v, block, "/tmp/config.tar.gz", CONF);
		if (ret > 0)
			if (volatile_write(v, sentinel.seq))
				ULOG_ERR("failed to write sentinel data");
	} else
		ULOG_INFO("config in sync\n");

	unlink("/tmp/config.tar.gz");

	return 0;
}
Esempio n. 8
0
int main(int argc, char **argv)
{
	struct volume *v;
	int ch, yes = 0, reset = 0;
	while ((ch = getopt(argc, argv, "yr")) != -1) {
		switch(ch) {
		case 'y':
			yes = 1;
			break;
		case 'r':
			reset = 1;
			break;
		}

	}

	if (!yes && ask_user())
		return -1;

	/*
	 * TODO: Currently this only checks if kernel supports OverlayFS. We
	 * should check if there is a mount point using it with rootfs_data
	 * as upperdir.
	 */
	if (find_filesystem("overlay")) {
		ULOG_ERR("overlayfs not supported by kernel\n");
		return -1;
	}

	v = volume_find("rootfs_data");
	if (!v) {
		ULOG_ERR("MTD partition 'rootfs_data' not found\n");
		return -1;
	}

	volume_init(v);
	if (!strcmp(*argv, "jffs2mark"))
		return jffs2_mark(v);
	return jffs2_reset(v, reset);
}
Esempio n. 9
0
static int jffs2_mark(struct volume *v)
{
	__u32 deadc0de = __cpu_to_be32(0xdeadc0de);
	size_t sz;
	int fd;

	fd = open(v->blk, O_WRONLY);
	ULOG_INFO("%s will be erased on next mount\n", v->blk);
	if (!fd) {
		ULOG_ERR("opening %s failed\n", v->blk);
		return -1;
	}

	sz = write(fd, &deadc0de, sizeof(deadc0de));
	close(fd);

	if (sz != 4) {
		ULOG_ERR("writing %s failed: %s\n", v->blk, strerror(errno));
		return -1;
	}

	return 0;
}
Esempio n. 10
0
json_object *hostspec_collect_block_device() {
  json_object *obj = json_object_new_object();
  assert(obj);

  DIR *dir = opendir("/sys/block");
  if (!dir) {
    ULOG_ERR("Unable to open /sys/block: %s\n", strerror(errno));
    goto error;
  }

  struct dirent *ent;
  while ((ent = readdir(dir))) {
    char const *name = ent->d_name;

    if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
      continue;
    }

    json_object *obj_dev = json_object_new_object();
    assert(obj_dev);
    json_object_object_add(obj, name, obj_dev);

    char buf[1024], *p;
    if ((p = fgets_close(buf, sizeof buf, fopenf("r", "/sys/block/%s/size", name)))) {
      int64_t size;
      if (json_parse_int64(p, &size) == 0) {
        json_object_object_add(obj_dev, "size", json_object_new_int64(size));
      }
    }

    if ((p = fgets_close(buf, sizeof buf, fopenf("r", "/sys/block/%s/removable", name)))) {
      int64_t removable;
      if (json_parse_int64(p, &removable) == 0) {
        json_object_object_add(obj_dev, "removable", json_object_new_int64(removable));
      }
    }
  }

  closedir(dir);
  return obj;

error:
  if (dir) {
    closedir(dir);
  }

  json_object_put(obj);
  return NULL;
}
Esempio n. 11
0
int
volatile_write(struct volume *v, uint32_t _seq)
{
	int block, ret;
	uint32_t seq;

	block = snapshot_next_free(v, &seq);
	if (_seq)
		seq = _seq;
	if (block < 0)
		block = 0;

	ret = snapshot_write_file(v, block, "/tmp/config.tar.gz", seq, CONF);
	if (ret)
		ULOG_ERR("failed to write /tmp/config.tar.gz\n");
	else
		ULOG_INFO("wrote /tmp/config.tar.gz\n");
	return ret;
}
Esempio n. 12
0
json_object *hostspec_collect_cpu() {
  json_object *obj = json_object_new_array();
  assert(obj);

  FILE *fp = fopen("/proc/cpuinfo", "r");
  if (!fp) {
    ULOG_ERR("Unable to open /proc/cpuinfo: %s\n", strerror(errno));
    goto error;
  }

  char buf[1024], *p;
  json_object *obj_proc = NULL;
  while ((p = fgets(buf, sizeof buf, fp))) {
    chomp(p);

    if (begin_with(p, "processor\t")) {
      obj_proc = json_object_new_object();
      json_object_array_add(obj, obj_proc);
    }

    // Only send the model name for now: this should work for x86/amd64/arm/mips
    if (obj_proc) {
      if (begin_with(p, "cpu model\t") || begin_with(p, "model name\t")) {
        json_object_object_add(obj_proc, "model_name", json_object_new_string(after_colon(p)));
      }
    }
  }

  fclose(fp);
  return obj;

error:
  if (fp) {
    fclose(fp);
  }

  json_object_put(obj);
  return NULL;
}
Esempio n. 13
0
File: ubi.c Progetto: unixz/fstools
static int ubi_volume_match(struct volume *v, char *name, int ubi_num, int volid)
{
	char voldir[BUFLEN], volblkdev[BUFLEN], *volname;
	struct ubi_priv *p;

	snprintf(voldir, sizeof(voldir), "%s/ubi%u/ubi%u_%u",
		ubi_dir_name, ubi_num, ubi_num, volid);

	snprintf(volblkdev, sizeof(volblkdev), "/dev/ubiblock%u_%u",
		ubi_num, volid);

	/* skip if ubiblock device exists */
	if (test_open(volblkdev))
		return -1;

	/* todo: skip existing gluebi device for legacy support */

	volname = read_string_from_file(voldir, "name");
	if (!volname) {
		ULOG_ERR("Couldn't read %s/name\n", voldir);
		return -1;
	}

	if (strncmp(name, volname, strlen(volname) + 1))
		return -1;

	p = calloc(1, sizeof(struct ubi_priv));
	if (!p)
		return -1;

	v->priv = p;
	v->drv = &ubi_driver;
	p->ubi_num = ubi_num;
	p->ubi_volid = volid;

	return ubi_volume_init(v);
}