Index: uspace/lib/futil/include/futil.h
===================================================================
--- uspace/lib/futil/include/futil.h	(revision 3e7948ce465036902ba4c25b7c9e439e0aa5a84f)
+++ uspace/lib/futil/include/futil.h	(revision 0b477813dc5a5ebce898b3650c9eab0de6cc05f3)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2024 Jiri Svoboda
+ * Copyright (c) 2025 Jiri Svoboda
  * All rights reserved.
  *
@@ -38,9 +38,13 @@
 #define FUTIL_H
 
+#include <errno.h>
 #include <stddef.h>
+#include "types/futil.h"
 
-extern errno_t futil_copy_file(const char *, const char *);
-extern errno_t futil_rcopy_contents(const char *, const char *);
-extern errno_t futil_get_file(const char *, void **, size_t *);
+extern errno_t futil_create(futil_cb_t *, void *, futil_t **);
+extern void futil_destroy(futil_t *);
+extern errno_t futil_copy_file(futil_t *, const char *, const char *);
+extern errno_t futil_rcopy_contents(futil_t *, const char *, const char *);
+extern errno_t futil_get_file(futil_t *, const char *, void **, size_t *);
 
 #endif
Index: uspace/lib/futil/include/types/futil.h
===================================================================
--- uspace/lib/futil/include/types/futil.h	(revision 0b477813dc5a5ebce898b3650c9eab0de6cc05f3)
+++ uspace/lib/futil/include/types/futil.h	(revision 0b477813dc5a5ebce898b3650c9eab0de6cc05f3)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2025 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup futil
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#ifndef TYPES_FUTIL_H
+#define TYPES_FUTIL_H
+
+/** File utility callbacks */
+typedef struct {
+	/** Copying file */
+	void (*copy_file)(void *, const char *, const char *);
+	/** Creating directory */
+	void (*create_dir)(void *, const char *);
+} futil_cb_t;
+
+typedef struct {
+	/** Callback functions */
+	futil_cb_t *cb;
+	/** Argument to callback functions */
+	void *cb_arg;
+} futil_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/futil/src/futil.c
===================================================================
--- uspace/lib/futil/src/futil.c	(revision 3e7948ce465036902ba4c25b7c9e439e0aa5a84f)
+++ uspace/lib/futil/src/futil.c	(revision 0b477813dc5a5ebce898b3650c9eab0de6cc05f3)
@@ -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;
Index: uspace/lib/ui/src/msgdialog.c
===================================================================
--- uspace/lib/ui/src/msgdialog.c	(revision 3e7948ce465036902ba4c25b7c9e439e0aa5a84f)
+++ uspace/lib/ui/src/msgdialog.c	(revision 0b477813dc5a5ebce898b3650c9eab0de6cc05f3)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2024 Jiri Svoboda
+ * Copyright (c) 2025 Jiri Svoboda
  * All rights reserved.
  *
@@ -125,5 +125,5 @@
 		wparams.rect.p0.x = 0;
 		wparams.rect.p0.y = 0;
-		wparams.rect.p1.x = 400;
+		wparams.rect.p1.x = 440;
 		wparams.rect.p1.y = 110;
 	}
@@ -154,5 +154,5 @@
 		rect.p0.x = 10;
 		rect.p0.y = 35;
-		rect.p1.x = 390;
+		rect.p1.x = 430;
 		rect.p1.y = 50;
 	}
