Index: uspace/lib/futil/src/futil.c
===================================================================
--- uspace/lib/futil/src/futil.c	(revision 04e520e4cef5045e53cdd7a3b92461ae3a1f7b36)
+++ uspace/lib/futil/src/futil.c	(revision f167c851099aef2600cce71c5e10cc3f3dc8ee11)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2024 Jiri Svoboda
+ * Copyright (c) 2025 Jiri Svoboda
  * All rights reserved.
  *
@@ -47,6 +47,37 @@
 static char buf[BUF_SIZE];
 
+/** Create file utility instance.
+ *
+ * @param cb Callback functions
+ * @param arg Argument to callback functions
+ * @param rfutil Place to store pointer to new file utility instance
+ * @return EOK on succcess, ENOMEM if out of memory.
+ */
+errno_t futil_create(futil_cb_t *cb, void *arg, futil_t **rfutil)
+{
+	futil_t *futil;
+
+	futil = calloc(1, sizeof(futil_t));
+	if (futil == NULL)
+		return ENOMEM;
+
+	futil->cb = cb;
+	futil->cb_arg = arg;
+	*rfutil = futil;
+	return EOK;
+}
+
+/** Destroy file utility instance.
+ *
+ * @param futil File utility instance
+ */
+void futil_destroy(futil_t *futil)
+{
+	free(futil);
+}
+
 /** Copy file.
  *
+ * @param futil File utility instance
  * @param srcp Source path
  * @param dstp Destination path
@@ -54,5 +85,5 @@
  * @return EOK on success, EIO on I/O error
  */
-errno_t futil_copy_file(const char *srcp, const char *destp)
+errno_t futil_copy_file(futil_t *futil, const char *srcp, const char *destp)
 {
 	int sf, df;
@@ -61,5 +92,6 @@
 	aoff64_t posr = 0, posw = 0;
 
-	printf("Copy '%s' to '%s'.\n", srcp, destp);
+	if (futil->cb != NULL && futil->cb->copy_file != NULL)
+		futil->cb->copy_file(futil->cb_arg, srcp, destp);
 
 	rc = vfs_lookup_open(srcp, WALK_REGULAR, MODE_READ, &sf);
@@ -99,4 +131,5 @@
 /** Copy contents of srcdir (recursively) into destdir.
  *
+ * @param futil File utility instance
  * @param srcdir Source directory
  * @param destdir Destination directory
@@ -104,5 +137,6 @@
  * @return EOK on success, ENOMEM if out of memory, EIO on I/O error
  */
-errno_t futil_rcopy_contents(const char *srcdir, const char *destdir)
+errno_t futil_rcopy_contents(futil_t *futil, const char *srcdir,
+    const char *destdir)
 {
 	DIR *dir;
@@ -128,13 +162,14 @@
 
 		if (s.is_file) {
-			rc = futil_copy_file(srcp, destp);
+			rc = futil_copy_file(futil, srcp, destp);
 			if (rc != EOK)
 				return EIO;
 		} else if (s.is_directory) {
-			printf("Create directory '%s'\n", destp);
+			if (futil->cb != NULL && futil->cb->create_dir != NULL)
+				futil->cb->create_dir(futil->cb_arg, destp);
 			rc = vfs_link_path(destp, KIND_DIRECTORY, NULL);
 			if (rc != EOK)
 				return EIO;
-			rc = futil_rcopy_contents(srcp, destp);
+			rc = futil_rcopy_contents(futil, srcp, destp);
 			if (rc != EOK)
 				return EIO;
@@ -151,4 +186,5 @@
 /** Return file contents as a heap-allocated block of bytes.
  *
+ * @param futil File utility instance
  * @param srcp File path
  * @param rdata Place to store pointer to data
@@ -158,5 +194,6 @@
  *         I/O error, ENOMEM if out of memory
  */
-errno_t futil_get_file(const char *srcp, void **rdata, size_t *rsize)
+errno_t futil_get_file(futil_t *futil, const char *srcp, void **rdata,
+    size_t *rsize)
 {
 	int sf;
