Index: uspace/lib/riff/include/riff/chunk.h
===================================================================
--- uspace/lib/riff/include/riff/chunk.h	(revision d145ecbb23dd631ab7c9bcf5f13b55867dd2dac9)
+++ uspace/lib/riff/include/riff/chunk.h	(revision aaf962e6b6b4ce31f98624e6c289f5d564a6aa86)
@@ -52,4 +52,7 @@
 extern errno_t riff_read_uint32(riff_rchunk_t *, uint32_t *);
 extern errno_t riff_rchunk_start(riff_rchunk_t *, riff_rchunk_t *);
+extern errno_t riff_rchunk_match(riff_rchunk_t *, riff_ckid_t, riff_rchunk_t *);
+extern errno_t riff_rchunk_list_match(riff_rchunk_t *, riff_ltype_t,
+    riff_rchunk_t *);
 extern errno_t riff_rchunk_end(riff_rchunk_t *);
 extern errno_t riff_read(riff_rchunk_t *, void *, size_t, size_t *);
Index: uspace/lib/riff/include/types/riff/chunk.h
===================================================================
--- uspace/lib/riff/include/types/riff/chunk.h	(revision d145ecbb23dd631ab7c9bcf5f13b55867dd2dac9)
+++ uspace/lib/riff/include/types/riff/chunk.h	(revision aaf962e6b6b4ce31f98624e6c289f5d564a6aa86)
@@ -42,4 +42,5 @@
 typedef uint32_t riff_ckid_t;
 typedef uint32_t riff_cksize_t;
+typedef uint32_t riff_ltype_t;
 
 /** RIFF writer */
Index: uspace/lib/riff/src/chunk.c
===================================================================
--- uspace/lib/riff/src/chunk.c	(revision d145ecbb23dd631ab7c9bcf5f13b55867dd2dac9)
+++ uspace/lib/riff/src/chunk.c	(revision aaf962e6b6b4ce31f98624e6c289f5d564a6aa86)
@@ -39,4 +39,5 @@
 #include <macros.h>
 #include <riff/chunk.h>
+#include <stdbool.h>
 #include <stdlib.h>
 
@@ -271,5 +272,5 @@
  * @param rchunk RIFF chunk
  * @param v  Place to store value
- * @return EOK on success, EIO on error.
+ * @return EOK on success, ELIMIT if at the end of parent chunk, EIO on error.
  */
 errno_t riff_read_uint32(riff_rchunk_t *rchunk, uint32_t *v)
@@ -295,5 +296,6 @@
  * @param rchunk Pointer to chunk structure to fill in
  *
- * @return EOK on success, EIO on error.
+ * @return EOK on success, ELIMIT if at the end of parent chunk,
+ *         EIO on error.
  */
 errno_t riff_rchunk_start(riff_rchunk_t *parent, riff_rchunk_t *rchunk)
@@ -320,4 +322,73 @@
 error:
 	return rc;
+}
+
+/** Find and start reading RIFF chunk of with specific chunk ID.
+ * Other types of chunks are skipped.
+ *
+ * @param parent Parent chunk
+ * @param rchunk Pointer to chunk structure to fill in
+ *
+ * @return EOK on success, ENOENT chunk was not found and end was reached
+ *         EIO on error.
+ */
+errno_t riff_rchunk_match(riff_rchunk_t *parent, riff_ckid_t ckid,
+    riff_rchunk_t *rchunk)
+{
+	errno_t rc;
+
+	while (true) {
+		rc = riff_rchunk_start(parent, rchunk);
+		if (rc == ELIMIT)
+			return ENOENT;
+		if (rc != EOK)
+			return rc;
+
+		if (rchunk->ckid == ckid)
+			break;
+
+		rc = riff_rchunk_end(rchunk);
+		if (rc != EOK)
+			return rc;
+	}
+
+	return EOK;
+}
+
+/** Find and start reading RIFF LIST chunk of specified type.
+ * Other chunks or LIST chunks of other type are skipped.
+ *
+ * @param parent Parent chunk
+ * @param rchunk Pointer to chunk structure to fill in
+ *
+ * @return EOK on success, ENOENT chunk was not found and end was reached
+ *         EIO on error.
+ */
+errno_t riff_rchunk_list_match(riff_rchunk_t *parent, riff_ltype_t ltype,
+    riff_rchunk_t *rchunk)
+{
+	errno_t rc;
+	riff_ltype_t rltype;
+
+	while (true) {
+		rc = riff_rchunk_match(parent, CKID_LIST, rchunk);
+		if (rc == ELIMIT)
+			return ENOENT;
+		if (rc != EOK)
+			return rc;
+
+		rc = riff_read_uint32(parent, &rltype);
+		if (rc != EOK)
+			return rc;
+
+		if (rltype == ltype)
+			break;
+
+		rc = riff_rchunk_end(rchunk);
+		if (rc != EOK)
+			return rc;
+	}
+
+	return EOK;
 }
 
Index: uspace/lib/riff/test/chunk.c
===================================================================
--- uspace/lib/riff/test/chunk.c	(revision d145ecbb23dd631ab7c9bcf5f13b55867dd2dac9)
+++ uspace/lib/riff/test/chunk.c	(revision aaf962e6b6b4ce31f98624e6c289f5d564a6aa86)
@@ -327,6 +327,220 @@
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
-//	(void) remove(p);
+	(void) remove(p);
 }
 
+/** Match specific chunk type in a RIFF file */
+PCUT_TEST(match_chunk)
+{
+	char fname[L_tmpnam];
+	char *p;
+	riffw_t *rw;
+	riffr_t *rr;
+	riff_wchunk_t wriffck;
+	riff_wchunk_t wdatack;
+	riff_rchunk_t rriffck;
+	riff_rchunk_t rdatack;
+	uint32_t rword;
+	errno_t rc;
+
+	p = tmpnam(fname);
+	PCUT_ASSERT_NOT_NULL(p);
+
+	/* Write RIFF file */
+
+	rc = riff_wopen(p, &rw);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_NOT_NULL(rw);
+
+	rc = riff_wchunk_start(rw, CKID_RIFF, &wriffck);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	/* Write first data chunk */
+
+	rc = riff_wchunk_start(rw, CKID_dat1, &wdatack);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = riff_write_uint32(rw, 1);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = riff_wchunk_end(rw, &wdatack);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	/* Write second data chunk */
+
+	rc = riff_wchunk_start(rw, CKID_dat2, &wdatack);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = riff_write_uint32(rw, 2);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = riff_wchunk_end(rw, &wdatack);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	/* Write third data chunk */
+
+	rc = riff_wchunk_start(rw, CKID_dat1, &wdatack);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = riff_write_uint32(rw, 3);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = riff_wchunk_end(rw, &wdatack);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = riff_wchunk_end(rw, &wriffck);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = riff_wclose(rw);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	/* Read back RIFF file */
+
+	rc = riff_ropen(p, &rriffck, &rr);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_NOT_NULL(rr);
+
+	PCUT_ASSERT_INT_EQUALS(CKID_RIFF, rriffck.ckid);
+
+	/* Match second data chunk */
+
+	rc = riff_rchunk_match(&rriffck, CKID_dat2, &rdatack);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_INT_EQUALS(CKID_dat2, rdatack.ckid);
+
+	rc = riff_read_uint32(&rdatack, &rword);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	PCUT_ASSERT_INT_EQUALS(2, rword);
+
+	rc = riff_rchunk_end(&rdatack);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	/* Try matching dat2 again (should not match) */
+
+	rc = riff_rchunk_match(&rriffck, CKID_dat2, &rdatack);
+	PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
+
+	/* Try matching dat1 again (but there's nothing left) */
+
+	rc = riff_rchunk_match(&rriffck, CKID_dat1, &rdatack);
+	PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
+
+	rc = riff_rclose(rr);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	(void) remove(p);
+}
+
+/** Match specific LIST chunk type in a RIFF file */
+PCUT_TEST(list_match)
+{
+	char fname[L_tmpnam];
+	char *p;
+	riffw_t *rw;
+	riffr_t *rr;
+	riff_wchunk_t wriffck;
+	riff_wchunk_t wdatack;
+	riff_rchunk_t rriffck;
+	riff_rchunk_t rdatack;
+	uint32_t rword;
+	errno_t rc;
+
+	p = tmpnam(fname);
+	PCUT_ASSERT_NOT_NULL(p);
+
+	/* Write RIFF file */
+
+	rc = riff_wopen(p, &rw);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_NOT_NULL(rw);
+
+	rc = riff_wchunk_start(rw, CKID_RIFF, &wriffck);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	/* Write first LIST chunk */
+
+	rc = riff_wchunk_start(rw, CKID_LIST, &wdatack);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = riff_write_uint32(rw, LTYPE_lst1);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = riff_write_uint32(rw, 1);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = riff_wchunk_end(rw, &wdatack);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	/* Write second data chunk */
+
+	rc = riff_wchunk_start(rw, CKID_LIST, &wdatack);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = riff_write_uint32(rw, LTYPE_lst2);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = riff_write_uint32(rw, 2);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = riff_wchunk_end(rw, &wdatack);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	/* Write third data chunk */
+
+	rc = riff_wchunk_start(rw, CKID_LIST, &wdatack);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = riff_write_uint32(rw, LTYPE_lst1);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = riff_write_uint32(rw, 3);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = riff_wchunk_end(rw, &wdatack);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = riff_wchunk_end(rw, &wriffck);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = riff_wclose(rw);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	/* Read back RIFF file */
+
+	rc = riff_ropen(p, &rriffck, &rr);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_NOT_NULL(rr);
+
+	PCUT_ASSERT_INT_EQUALS(CKID_RIFF, rriffck.ckid);
+
+	/* Match second LIST chunk */
+
+	rc = riff_rchunk_list_match(&rriffck, LTYPE_lst2, &rdatack);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = riff_read_uint32(&rdatack, &rword);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	PCUT_ASSERT_INT_EQUALS(2, rword);
+
+	rc = riff_rchunk_end(&rdatack);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	/* Try matching lst2 again (should not match) */
+
+	rc = riff_rchunk_list_match(&rriffck, LTYPE_lst2, &rdatack);
+	PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
+
+	/* Try matching lst1 again (but there's nothing left) */
+
+	rc = riff_rchunk_list_match(&rriffck, LTYPE_lst1, &rdatack);
+	PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
+
+	rc = riff_rclose(rr);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	(void) remove(p);
+}
+
 PCUT_EXPORT(chunk);
