ER ev3_memfile_load()

in ev3-api/src/ev3api_fs.c [14:79]


ER ev3_memfile_load(const char *path, memfile_t *p_memfile) {
	ER ercd;

	memfile_t  memfile;
	FILE      *fin;
	fin = NULL;
	memfile.buffer = NULL;

	CHECK_COND(path != NULL, E_PAR);
	CHECK_COND(p_memfile != NULL, E_NOMEM);

	/**
	 * Open file
	 */
	fin = fopen(path, "rb");
	if (fin == NULL) {
		API_WARN("Path '%s' is invalid.", path);
		CHECK_COND(false, E_PAR);
	}

	/**
	 * Get file size & allocate memory
	 */
	long filesz;
	CHECK_COND(fseek(fin, 0, SEEK_END) == 0, E_OBJ);
	CHECK_COND((filesz = ftell(fin)) >= 0, E_OBJ); // TODO: Check when filesz == 0
	CHECK_COND(fseek(fin, 0, SEEK_SET) == 0, E_OBJ);
	memfile.buffersz = memfile.filesz = filesz;
	assert((long)memfile.filesz == filesz);
	CHECK_COND((memfile.buffer = malloc(memfile.buffersz)) != NULL, E_NOMEM);

	/**
	 * Perform reading
	 */
	uint8_t *bufptr = memfile.buffer;
	while (1) {
		size_t bytesleft = (uint8_t*)memfile.buffer + memfile.filesz - bufptr;
		if (bytesleft > 512) bytesleft = 512; // TODO: Check if this is really needed
		size_t bytesread = fread(bufptr, 1, bytesleft, fin);
		if (bytesread > 0) {
			bufptr += bytesread;
		} else {
			break;
		}
	}
	if (ferror(fin)) {
		API_WARN("I/O failure when reading.");
		CHECK_COND(false, E_PAR);
	}
	assert(bufptr == memfile.buffer + memfile.filesz);

	*p_memfile = memfile;
	ercd = E_OK;
	/* Fall through */

error_exit:

	if (ercd != E_OK) { // On error
		if (p_memfile != NULL) p_memfile->buffer = NULL;
		free(memfile.buffer);
	}

	if (fin != NULL) fclose(fin);

	return ercd;
}