Alien-Libjio

 view release on metacpan or  search on metacpan

libjio/libjio/check.c  view on Meta::CPAN

			ret = J_ENOJOURNAL;
		goto exit;
	}
	fs.jfd = rv;

	fs.jmap = (unsigned int *) mmap(NULL, sizeof(unsigned int),
			PROT_READ | PROT_WRITE, MAP_SHARED, fs.jfd, 0);
	if (fs.jmap == MAP_FAILED) {
		ret = J_EIO;
		goto exit;
	}

	dir = opendir(fs.jdir);
	if (dir == NULL) {
		ret = J_EIO;
		if (errno == ENOENT)
			ret = J_ENOJOURNAL;
		goto exit;
	}

	/* find the greatest transaction number by looking into the journal
	 * directory */
	maxtid = 0;
	for (errno = 0, dent = readdir(dir); dent != NULL;
			errno = 0, dent = readdir(dir)) {
		/* see if the file is named like a transaction, ignore
		 * otherwise; as transactions are named as numbers > 0, a
		 * simple atoi() is enough testing */
		rv = atoi(dent->d_name);
		if (rv <= 0)
			continue;
		if (rv > maxtid)
			maxtid = rv;
	}
	if (errno) {
		ret = J_EIO;
		goto exit;
	}

	/* rewrite the lockfile, writing the new maxtid on it, so that when we
	 * rollback a transaction it doesn't step over existing ones */
	rv = spwrite(fs.jfd, &maxtid, sizeof(maxtid), 0);
	if (rv != sizeof(maxtid)) {
		ret = J_ENOMEM;
		goto exit;
	}

	/* remove the broken mark so we can call jtrans_commit() */
	snprintf(brokenname, PATH_MAX, "%s/broken", fs.jdir);
	rv = access(brokenname, F_OK);
	if (rv == 0) {
		if (unlink(brokenname) != 0) {
			ret = J_EIO;
			goto exit;
		}
	} else if (errno != ENOENT) {
		ret = J_EIO;
		goto exit;
	}

	/* verify (and possibly fix) all the transactions */
	for (i = 1; i <= maxtid; i++) {
		curts = jtrans_new(&fs, 0);
		if (curts == NULL) {
			ret = J_ENOMEM;
			goto exit;
		}

		curts->id = i;

		/* open the transaction file, using i as its name, so we are
		 * really looping in order (recovering transaction in a
		 * different order as they were applied would result in
		 * corruption) */
		get_jtfile(&fs, i, tname);
		tfd = open(tname, O_RDWR | O_SYNC, 0600);
		if (tfd < 0) {
			if (errno == ENOENT) {
				res->invalid++;
				goto nounlink_loop;
			} else {
				ret = J_EIO;
				goto exit;
			}
		}

		/* try to lock the transaction file, if it's locked then it is
		 * currently being used so we skip it */
		lr = plockf(tfd, F_TLOCKW, 0, 0);
		if (lr == -1) {
			res->in_progress++;
			goto loop;
		}

		filelen = lseek(tfd, 0, SEEK_END);
		if (filelen == 0) {
			res->broken++;
			goto loop;
		} else if (filelen < 0) {
			ret = J_EIO;
			goto exit;
		}

		/* no overflow problems because we know the transaction size
		 * is limited to SSIZE_MAX */
		map = mmap((void *) 0, filelen, PROT_READ, MAP_SHARED, tfd, 0);
		if (map == MAP_FAILED) {
			map = NULL;
			ret = J_EIO;
			goto exit;
		}

		rv = fill_trans(map, filelen, curts);
		if (rv == -1) {
			res->broken++;
			goto loop;
		} else if (rv == -2) {
			res->corrupt++;
			goto loop;
		}



( run in 0.819 second using v1.01-cache-2.11-cpan-754626df90b )