Index: uspace/lib/riff/include/riff/chunk.h
===================================================================
--- uspace/lib/riff/include/riff/chunk.h	(revision aaf962e6b6b4ce31f98624e6c289f5d564a6aa86)
+++ uspace/lib/riff/include/riff/chunk.h	(revision dd65f4f775ec6d7b7e31bc45c83b102ca1c5e613)
@@ -55,4 +55,5 @@
 extern errno_t riff_rchunk_list_match(riff_rchunk_t *, riff_ltype_t,
     riff_rchunk_t *);
+extern errno_t riff_rchunk_seek(riff_rchunk_t *, long, int);
 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/src/chunk.c
===================================================================
--- uspace/lib/riff/src/chunk.c	(revision aaf962e6b6b4ce31f98624e6c289f5d564a6aa86)
+++ uspace/lib/riff/src/chunk.c	(revision dd65f4f775ec6d7b7e31bc45c83b102ca1c5e613)
@@ -393,4 +393,44 @@
 }
 
+/** Seek to position in chunk.
+ *
+ * @param rchunk RIFF chunk
+ * @param offset Offset
+ * @param whence SEEK_SET, SEEK_CUR or SEEK_END
+ * @return EOK on success or an error code
+ */
+errno_t riff_rchunk_seek(riff_rchunk_t *rchunk, long offset, int whence)
+{
+	long pos;
+	long dest;
+	int rv;
+
+	switch (whence) {
+	case SEEK_SET:
+		dest = rchunk->ckstart + offset;
+		break;
+	case SEEK_END:
+		dest = rchunk->ckstart + rchunk->cksize + offset;
+		break;
+	case SEEK_CUR:
+		pos = ftell(rchunk->riffr->f);
+		if (pos < 0)
+			return EIO;
+		dest = pos + offset;
+		break;
+	default:
+		return EINVAL;
+	}
+
+	if (dest < rchunk->ckstart || dest > rchunk->ckstart + rchunk->cksize)
+		return ELIMIT;
+
+	rv = fseek(rchunk->riffr->f, dest, SEEK_SET);
+	if (rv < 0)
+		return EIO;
+
+	return EOK;
+}
+
 /** Return chunk data size.
  *
@@ -431,5 +471,6 @@
 /** Finish reading RIFF chunk.
  *
- * Seek to the first byte after end of chunk.
+ * Seek to the first byte after end of chunk. It is allowed, though,
+ * to return to the chunk later, e.g. using riff_rchunk_seek(@a rchunk, ..).
  *
  * @param rchunk Chunk structure
@@ -444,5 +485,4 @@
 		return EIO;
 
-	rchunk->riffr = NULL;
 	return EOK;
 }
Index: uspace/lib/riff/test/chunk.c
===================================================================
--- uspace/lib/riff/test/chunk.c	(revision aaf962e6b6b4ce31f98624e6c289f5d564a6aa86)
+++ uspace/lib/riff/test/chunk.c	(revision dd65f4f775ec6d7b7e31bc45c83b102ca1c5e613)
@@ -544,3 +544,109 @@
 }
 
+/** Seek back to different positions in a chunk */
+PCUT_TEST(rchunk_seek)
+{
+	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 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_write_uint32(rw, 2);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = riff_write_uint32(rw, 3);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = riff_write_uint32(rw, 4);
+	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);
+
+	/* Read data chunk */
+
+	rc = riff_rchunk_start(&rriffck, &rdatack);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_INT_EQUALS(CKID_dat1, rdatack.ckid);
+
+	rc = riff_read_uint32(&rdatack, &rword);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_INT_EQUALS(1, rword);
+
+	rc = riff_rchunk_end(&rdatack);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	/* Try reading first word of data chunk again */
+
+	rc = riff_rchunk_seek(&rdatack, 0, SEEK_SET);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = riff_read_uint32(&rdatack, &rword);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_INT_EQUALS(1, rword);
+
+	/* Try reading last word of data chunk */
+
+	rc = riff_rchunk_seek(&rdatack, -4, SEEK_END);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = riff_read_uint32(&rdatack, &rword);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_INT_EQUALS(4, rword);
+
+	/* Try reading previous word of data chunk */
+
+	rc = riff_rchunk_seek(&rdatack, -8, SEEK_CUR);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = riff_read_uint32(&rdatack, &rword);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_INT_EQUALS(3, rword);
+
+	rc = riff_rclose(rr);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	(void) remove(p);
+}
+
 PCUT_EXPORT(chunk);
