source: mainline/uspace/lib/futil/src/futil.c

Last change on this file was 629b480, checked in by Jiri Svoboda <jiri@…>, 2 months ago

Assorted installer fixes.

  • Property mode set to 100644
File size: 5.6 KB
RevLine 
[3a34852]1/*
[a188131]2 * Copyright (c) 2025 Jiri Svoboda
[3a34852]3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
[04e520e]29/** @addtogroup futil
[3a34852]30 * @{
31 */
[04e520e]32/** @file File manipulation utility functions
[3a34852]33 */
34
35#include <dirent.h>
36#include <errno.h>
37#include <stdbool.h>
38#include <stdio.h>
39#include <stdlib.h>
[8d2dd7f2]40#include <stddef.h>
[23a0368]41#include <vfs/vfs.h>
[3a34852]42#include <dirent.h>
43
44#include "futil.h"
45
46#define BUF_SIZE 16384
47static char buf[BUF_SIZE];
48
[a188131]49/** Create file utility instance.
50 *
51 * @param cb Callback functions
52 * @param arg Argument to callback functions
53 * @param rfutil Place to store pointer to new file utility instance
54 * @return EOK on succcess, ENOMEM if out of memory.
55 */
56errno_t futil_create(futil_cb_t *cb, void *arg, futil_t **rfutil)
57{
58 futil_t *futil;
59
60 futil = calloc(1, sizeof(futil_t));
61 if (futil == NULL)
62 return ENOMEM;
63
64 futil->cb = cb;
65 futil->cb_arg = arg;
66 *rfutil = futil;
67 return EOK;
68}
69
70/** Destroy file utility instance.
71 *
72 * @param futil File utility instance
73 */
74void futil_destroy(futil_t *futil)
75{
76 free(futil);
77}
78
[3a34852]79/** Copy file.
80 *
[a188131]81 * @param futil File utility instance
[3a34852]82 * @param srcp Source path
83 * @param dstp Destination path
84 *
85 * @return EOK on success, EIO on I/O error
86 */
[a188131]87errno_t futil_copy_file(futil_t *futil, const char *srcp, const char *destp)
[3a34852]88{
89 int sf, df;
[8e3498b]90 size_t nr, nw;
[b7fd2a0]91 errno_t rc;
[58898d1d]92 aoff64_t posr = 0, posw = 0;
[3a34852]93
[a188131]94 if (futil->cb != NULL && futil->cb->copy_file != NULL)
95 futil->cb->copy_file(futil->cb_arg, srcp, destp);
[3a34852]96
[f77c1c9]97 rc = vfs_lookup_open(srcp, WALK_REGULAR, MODE_READ, &sf);
98 if (rc != EOK)
[3a34852]99 return EIO;
100
[629b480]101 rc = vfs_lookup_open(destp, WALK_REGULAR | WALK_MAY_CREATE, MODE_WRITE,
102 &df);
103 if (rc != EOK) {
104 vfs_put(sf);
[3a34852]105 return EIO;
[629b480]106 }
[3a34852]107
108 do {
[8e3498b]109 rc = vfs_read(sf, &posr, buf, BUF_SIZE, &nr);
110 if (rc != EOK)
111 goto error;
[3a34852]112 if (nr == 0)
113 break;
114
[1433ecda]115 rc = vfs_write(df, &posw, buf, nr, &nw);
[8e3498b]116 if (rc != EOK)
117 goto error;
118
119 } while (nr == BUF_SIZE);
[3a34852]120
[9c4cf0d]121 (void) vfs_put(sf);
[3a34852]122
[9c4cf0d]123 rc = vfs_put(df);
[f77c1c9]124 if (rc != EOK)
[3a34852]125 return EIO;
126
127 return EOK;
[8e3498b]128error:
129 vfs_put(sf);
130 vfs_put(df);
131 return rc;
[3a34852]132}
133
134/** Copy contents of srcdir (recursively) into destdir.
135 *
[a188131]136 * @param futil File utility instance
[3a34852]137 * @param srcdir Source directory
138 * @param destdir Destination directory
139 *
140 * @return EOK on success, ENOMEM if out of memory, EIO on I/O error
141 */
[a188131]142errno_t futil_rcopy_contents(futil_t *futil, const char *srcdir,
143 const char *destdir)
[3a34852]144{
145 DIR *dir;
146 struct dirent *de;
[39330200]147 vfs_stat_t s;
[3a34852]148 char *srcp, *destp;
[b7fd2a0]149 errno_t rc;
[3a34852]150
151 dir = opendir(srcdir);
152 if (dir == NULL)
153 return EIO;
154
155 de = readdir(dir);
156 while (de != NULL) {
[629b480]157 if (asprintf(&srcp, "%s/%s", srcdir, de->d_name) < 0) {
158 rc = ENOMEM;
159 goto error;
160 }
161
162 if (asprintf(&destp, "%s/%s", destdir, de->d_name) < 0) {
163 rc = ENOMEM;
164 goto error;
165 }
[3a34852]166
[23a0368]167 rc = vfs_stat_path(srcp, &s);
[3a34852]168 if (rc != EOK)
[629b480]169 goto error;
[3a34852]170
171 if (s.is_file) {
[a188131]172 rc = futil_copy_file(futil, srcp, destp);
[629b480]173 if (rc != EOK) {
174 rc = EIO;
175 goto error;
176 }
[3a34852]177 } else if (s.is_directory) {
[a188131]178 if (futil->cb != NULL && futil->cb->create_dir != NULL)
179 futil->cb->create_dir(futil->cb_arg, destp);
[a6fc88a]180 rc = vfs_link_path(destp, KIND_DIRECTORY, NULL);
[3a34852]181 if (rc != EOK)
[629b480]182 goto error;
[a188131]183 rc = futil_rcopy_contents(futil, srcp, destp);
[3a34852]184 if (rc != EOK)
[629b480]185 goto error;
[3a34852]186 } else {
[629b480]187 rc = EIO;
188 goto error;
[3a34852]189 }
190
191 de = readdir(dir);
192 }
193
[629b480]194 closedir(dir);
[3a34852]195 return EOK;
[629b480]196error:
197 closedir(dir);
198 return rc;
[3a34852]199}
200
201/** Return file contents as a heap-allocated block of bytes.
202 *
[a188131]203 * @param futil File utility instance
[3a34852]204 * @param srcp File path
205 * @param rdata Place to store pointer to data
206 * @param rsize Place to store size of data
207 *
208 * @return EOK on success, ENOENT if failed to open file, EIO on other
209 * I/O error, ENOMEM if out of memory
210 */
[a188131]211errno_t futil_get_file(futil_t *futil, const char *srcp, void **rdata,
212 size_t *rsize)
[3a34852]213{
214 int sf;
[8e3498b]215 size_t nr;
[b7fd2a0]216 errno_t rc;
[3a34852]217 size_t fsize;
218 char *data;
[39330200]219 vfs_stat_t st;
[3a34852]220
[f77c1c9]221 rc = vfs_lookup_open(srcp, WALK_REGULAR, MODE_READ, &sf);
222 if (rc != EOK)
[3a34852]223 return ENOENT;
224
[23a0368]225 if (vfs_stat(sf, &st) != EOK) {
[9c4cf0d]226 vfs_put(sf);
[3a34852]227 return EIO;
[8e3498b]228 }
[3a34852]229
[58898d1d]230 fsize = st.size;
[3a34852]231
232 data = calloc(fsize, 1);
[58898d1d]233 if (data == NULL) {
[9c4cf0d]234 vfs_put(sf);
[3a34852]235 return ENOMEM;
[58898d1d]236 }
[3a34852]237
[8e3498b]238 rc = vfs_read(sf, (aoff64_t []) { 0 }, data, fsize, &nr);
239 if (rc != EOK || nr != fsize) {
[9c4cf0d]240 vfs_put(sf);
[58898d1d]241 free(data);
[3a34852]242 return EIO;
[58898d1d]243 }
[3a34852]244
[9c4cf0d]245 (void) vfs_put(sf);
[3a34852]246 *rdata = data;
247 *rsize = fsize;
248
249 return EOK;
250}
251
252/** @}
253 */
Note: See TracBrowser for help on using the repository browser.