Changeset d101368 in mainline
- Timestamp:
- 2025-11-14T16:41:33Z (3 months ago)
- Branches:
- master
- Children:
- 3a4c6d9
- Parents:
- 4b2065a6
- git-author:
- Jiri Svoboda <jiri@…> (2025-11-14 16:32:57)
- git-committer:
- Jiri Svoboda <jiri@…> (2025-11-14 16:41:33)
- Location:
- uspace/lib/fmgt
- Files:
-
- 4 added
- 5 edited
-
include/fmgt.h (modified) (2 diffs)
-
include/fmgt/newfile.h (added)
-
meson.build (modified) (2 diffs)
-
private/fmgt.h (added)
-
src/fmgt.c (modified) (9 diffs)
-
src/newfile.c (added)
-
test/fmgt.c (modified) (2 diffs)
-
test/main.c (modified) (1 diff)
-
test/newfile.c (added)
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/fmgt/include/fmgt.h
r4b2065a6 rd101368 42 42 #include <stddef.h> 43 43 #include <stdint.h> 44 #include "fmgt/newfile.h" 44 45 #include "types/fmgt.h" 45 46 … … 48 49 extern void fmgt_destroy(fmgt_t *); 49 50 extern void fmgt_set_init_update(fmgt_t *, bool); 50 extern errno_t fmgt_new_file_suggest(char **);51 extern errno_t fmgt_new_file(fmgt_t *, const char *, uint64_t, fmgt_nf_flags_t);52 51 53 52 #endif -
uspace/lib/fmgt/meson.build
r4b2065a6 rd101368 29 29 src = files( 30 30 'src/fmgt.c', 31 'src/newfile.c' 31 32 ) 32 33 … … 34 35 'test/fmgt.c', 35 36 'test/main.c', 37 'test/newfile.c' 36 38 ) -
uspace/lib/fmgt/src/fmgt.c
r4b2065a6 rd101368 44 44 45 45 #include "fmgt.h" 46 47 #define NEWNAME_LEN 64 48 #define BUFFER_SIZE 16384 46 #include "../private/fmgt.h" 49 47 50 48 /** Create file management library instance. … … 106 104 } 107 105 108 /** Suggest file name for new file.109 *110 * @param fmgt File management object111 * @param rstr Place to store pointer to newly allocated string112 * @return EOK on success or an error code113 */114 errno_t fmgt_new_file_suggest(char **rstr)115 {116 errno_t rc;117 vfs_stat_t stat;118 unsigned u;119 char name[NEWNAME_LEN];120 121 u = 0;122 while (true) {123 snprintf(name, sizeof(name), "noname%02u.txt", u);124 rc = vfs_stat_path(name, &stat);125 if (rc != EOK)126 break;127 128 ++u;129 }130 131 *rstr = str_dup(name);132 if (*rstr == NULL)133 return ENOMEM;134 135 return EOK;136 }137 138 106 /** Get progress update report. 139 107 * … … 180 148 * @param fmgt File management object 181 149 */ 182 staticvoid fmgt_initial_progress_update(fmgt_t *fmgt)150 void fmgt_initial_progress_update(fmgt_t *fmgt) 183 151 { 184 152 if (fmgt->do_init_update) … … 192 160 * @param fmgt File management object 193 161 */ 194 staticvoid fmgt_final_progress_update(fmgt_t *fmgt)162 void fmgt_final_progress_update(fmgt_t *fmgt) 195 163 { 196 164 if (fmgt->curf_progr) … … 216 184 * @param fmgt File management object 217 185 */ 218 staticvoid fmgt_timer_start(fmgt_t *fmgt)186 void fmgt_timer_start(fmgt_t *fmgt) 219 187 { 220 188 fibril_timer_set(fmgt->timer, 500000, fmgt_timer_fun, (void *)fmgt); … … 225 193 * @param fmgt File management object 226 194 */ 227 staticvoid fmgt_timer_stop(fmgt_t *fmgt)195 void fmgt_timer_stop(fmgt_t *fmgt) 228 196 { 229 197 (void)fibril_timer_clear(fmgt->timer); … … 235 203 * @return @c true iff operation should be aborted 236 204 */ 237 staticbool fmgt_abort_query(fmgt_t *fmgt)205 bool fmgt_abort_query(fmgt_t *fmgt) 238 206 { 239 207 if (fmgt->cb != NULL && fmgt->cb->abort_query != NULL) … … 249 217 * @return What error recovery action should be taken. 250 218 */ 251 staticfmgt_error_action_t fmgt_io_error_query(fmgt_t *fmgt,219 fmgt_error_action_t fmgt_io_error_query(fmgt_t *fmgt, 252 220 fmgt_io_error_t *err) 253 221 { … … 258 226 } 259 227 260 /** Create new file.261 *262 * @param fmgt File management object263 * @param fname File name264 * @param fsize Size of new file (number of zero bytes to fill in)265 * @param flags New file flags266 * @return EOK on success or an error code267 */268 errno_t fmgt_new_file(fmgt_t *fmgt, const char *fname, uint64_t fsize,269 fmgt_nf_flags_t flags)270 {271 int fd;272 size_t nw;273 aoff64_t pos = 0;274 uint64_t now;275 char *buffer;276 fmgt_io_error_t err;277 fmgt_error_action_t action;278 errno_t rc;279 280 buffer = calloc(BUFFER_SIZE, 1);281 if (buffer == NULL)282 return ENOMEM;283 284 rc = vfs_lookup_open(fname, WALK_REGULAR | WALK_MUST_CREATE,285 MODE_WRITE, &fd);286 if (rc != EOK) {287 free(buffer);288 return rc;289 }290 291 fmgt->curf_procb = 0;292 fmgt->curf_totalb = fsize;293 fmgt->curf_progr = false;294 fmgt_timer_start(fmgt);295 296 fmgt_initial_progress_update(fmgt);297 298 /* Create sparse file? */299 if ((flags & nf_sparse) != 0) {300 fmgt->curf_procb = fsize - 1;301 pos = fsize - 1;302 }303 304 while (fmgt->curf_procb < fsize) {305 now = fsize - fmgt->curf_procb;306 if (now > BUFFER_SIZE)307 now = BUFFER_SIZE;308 309 do {310 rc = vfs_write(fd, &pos, buffer, now, &nw);311 if (rc == EOK)312 break;313 314 /* I/O error */315 err.fname = fname;316 err.optype = fmgt_io_write;317 err.rc = rc;318 fmgt_timer_stop(fmgt);319 action = fmgt_io_error_query(fmgt, &err);320 fmgt_timer_start(fmgt);321 } while (action == fmgt_er_retry);322 323 /* Not recovered? */324 if (rc != EOK) {325 free(buffer);326 vfs_put(fd);327 fmgt_final_progress_update(fmgt);328 return rc;329 }330 331 fmgt->curf_procb += nw;332 333 /* User requested abort? */334 if (fmgt_abort_query(fmgt)) {335 free(buffer);336 vfs_put(fd);337 fmgt_final_progress_update(fmgt);338 return EINTR;339 }340 }341 342 free(buffer);343 vfs_put(fd);344 fmgt_final_progress_update(fmgt);345 return EOK;346 }347 348 228 /** @} 349 229 */ -
uspace/lib/fmgt/test/fmgt.c
r4b2065a6 rd101368 37 37 PCUT_TEST_SUITE(fmgt); 38 38 39 #define TEMP_DIR "/tmp"40 41 static void test_fmgt_progress(void *, fmgt_progress_t *);42 43 static fmgt_cb_t test_fmgt_cb = {44 .progress = test_fmgt_progress45 };46 47 typedef struct {48 unsigned nupdates;49 } test_resp_t;50 51 39 /** Create and destroy file management object succeeds. */ 52 40 PCUT_TEST(create_destroy) … … 62 50 } 63 51 64 /** Suggesting new file name succeeds and returns unique name. */65 PCUT_TEST(new_file_suggest)66 {67 FILE *f = NULL;68 char *fname1 = NULL;69 char *fname2 = NULL;70 errno_t rc;71 int rv;72 73 rc = vfs_cwd_set(TEMP_DIR);74 PCUT_ASSERT_ERRNO_VAL(EOK, rc);75 76 /* Suggest unique file name. */77 rc = fmgt_new_file_suggest(&fname1);78 PCUT_ASSERT_ERRNO_VAL(EOK, rc);79 80 /* See if we can actually create the file. */81 f = fopen(fname1, "wx");82 PCUT_ASSERT_NOT_NULL(f);83 (void) fclose(f);84 85 /* Now suggest another unique file name. */86 rc = fmgt_new_file_suggest(&fname2);87 PCUT_ASSERT_ERRNO_VAL(EOK, rc);88 89 /* They should be different. */90 PCUT_ASSERT_FALSE(str_cmp(fname1, fname2) == 0);91 92 /* Remove the file. */93 rv = remove(fname1);94 PCUT_ASSERT_INT_EQUALS(0, rv);95 96 free(fname1);97 free(fname2);98 }99 100 /** New empty file can be created. */101 PCUT_TEST(new_file_empty)102 {103 fmgt_t *fmgt = NULL;104 char *fname = NULL;105 errno_t rc;106 int rv;107 108 rc = vfs_cwd_set(TEMP_DIR);109 PCUT_ASSERT_ERRNO_VAL(EOK, rc);110 111 rc = fmgt_create(&fmgt);112 PCUT_ASSERT_ERRNO_VAL(EOK, rc);113 114 /* Suggest unique file name. */115 rc = fmgt_new_file_suggest(&fname);116 PCUT_ASSERT_ERRNO_VAL(EOK, rc);117 118 rc = fmgt_new_file(fmgt, fname, 0, nf_none);119 PCUT_ASSERT_ERRNO_VAL(EOK, rc);120 121 /* Remove the file [this also verifies the file exists]. */122 rv = remove(fname);123 PCUT_ASSERT_INT_EQUALS(0, rv);124 125 free(fname);126 fmgt_destroy(fmgt);127 }128 129 /** New zero-filled file can be created. */130 PCUT_TEST(new_file_zerofill)131 {132 FILE *f = NULL;133 fmgt_t *fmgt = NULL;134 char *fname = NULL;135 char buf[128];136 errno_t rc;137 size_t nr;138 size_t total_rd;139 size_t i;140 int rv;141 142 rc = vfs_cwd_set(TEMP_DIR);143 PCUT_ASSERT_ERRNO_VAL(EOK, rc);144 145 rc = fmgt_create(&fmgt);146 PCUT_ASSERT_ERRNO_VAL(EOK, rc);147 148 /* Suggest unique file name. */149 rc = fmgt_new_file_suggest(&fname);150 PCUT_ASSERT_ERRNO_VAL(EOK, rc);151 152 rc = fmgt_new_file(fmgt, fname, 20000, nf_none);153 PCUT_ASSERT_ERRNO_VAL(EOK, rc);154 155 /* Verify the file. */156 f = fopen(fname, "rb");157 PCUT_ASSERT_NOT_NULL(f);158 total_rd = 0;159 do {160 nr = fread(buf, 1, sizeof(buf), f);161 for (i = 0; i < nr; i++)162 PCUT_ASSERT_INT_EQUALS(0, buf[i]);163 164 total_rd += nr;165 } while (nr > 0);166 167 PCUT_ASSERT_INT_EQUALS(20000, total_rd);168 169 (void)fclose(f);170 171 /* Remove the file. */172 rv = remove(fname);173 PCUT_ASSERT_INT_EQUALS(0, rv);174 175 free(fname);176 fmgt_destroy(fmgt);177 }178 179 /** New sparse file can be created. */180 PCUT_TEST(new_file_sparse)181 {182 FILE *f = NULL;183 fmgt_t *fmgt = NULL;184 char *fname = NULL;185 char buf[128];186 errno_t rc;187 size_t nr;188 size_t total_rd;189 size_t i;190 int rv;191 192 rc = vfs_cwd_set(TEMP_DIR);193 PCUT_ASSERT_ERRNO_VAL(EOK, rc);194 195 rc = fmgt_create(&fmgt);196 PCUT_ASSERT_ERRNO_VAL(EOK, rc);197 198 /* Suggest unique file name. */199 rc = fmgt_new_file_suggest(&fname);200 PCUT_ASSERT_ERRNO_VAL(EOK, rc);201 202 rc = fmgt_new_file(fmgt, fname, 20000, nf_sparse);203 PCUT_ASSERT_ERRNO_VAL(EOK, rc);204 205 /* Verify the file. */206 f = fopen(fname, "rb");207 PCUT_ASSERT_NOT_NULL(f);208 total_rd = 0;209 do {210 nr = fread(buf, 1, sizeof(buf), f);211 for (i = 0; i < nr; i++)212 PCUT_ASSERT_INT_EQUALS(0, buf[i]);213 214 total_rd += nr;215 } while (nr > 0);216 217 PCUT_ASSERT_INT_EQUALS(20000, total_rd);218 219 (void)fclose(f);220 221 /* Remove the file. */222 rv = remove(fname);223 PCUT_ASSERT_INT_EQUALS(0, rv);224 225 free(fname);226 fmgt_destroy(fmgt);227 }228 229 /** Initial update provided when requested while creating new file. */230 PCUT_TEST(new_file_init_upd)231 {232 FILE *f = NULL;233 fmgt_t *fmgt = NULL;234 char *fname = NULL;235 char buf[128];236 errno_t rc;237 size_t nr;238 size_t total_rd;239 size_t i;240 test_resp_t resp;241 int rv;242 243 rc = vfs_cwd_set(TEMP_DIR);244 PCUT_ASSERT_ERRNO_VAL(EOK, rc);245 246 rc = fmgt_create(&fmgt);247 PCUT_ASSERT_ERRNO_VAL(EOK, rc);248 249 fmgt_set_cb(fmgt, &test_fmgt_cb, (void *)&resp);250 resp.nupdates = 0;251 252 fmgt_set_init_update(fmgt, true);253 254 /* Suggest unique file name. */255 rc = fmgt_new_file_suggest(&fname);256 PCUT_ASSERT_ERRNO_VAL(EOK, rc);257 258 rc = fmgt_new_file(fmgt, fname, 20000, nf_none);259 PCUT_ASSERT_ERRNO_VAL(EOK, rc);260 261 /* Verify the file. */262 f = fopen(fname, "rb");263 PCUT_ASSERT_NOT_NULL(f);264 total_rd = 0;265 do {266 nr = fread(buf, 1, sizeof(buf), f);267 for (i = 0; i < nr; i++)268 PCUT_ASSERT_INT_EQUALS(0, buf[i]);269 270 total_rd += nr;271 } while (nr > 0);272 273 PCUT_ASSERT_INT_EQUALS(20000, total_rd);274 275 (void)fclose(f);276 277 PCUT_ASSERT_TRUE(resp.nupdates > 0);278 279 /* Remove the file. */280 rv = remove(fname);281 PCUT_ASSERT_INT_EQUALS(0, rv);282 283 free(fname);284 fmgt_destroy(fmgt);285 }286 287 static void test_fmgt_progress(void *arg, fmgt_progress_t *progress)288 {289 test_resp_t *resp = (test_resp_t *)arg;290 291 (void)progress;292 ++resp->nupdates;293 }294 295 52 PCUT_EXPORT(fmgt); -
uspace/lib/fmgt/test/main.c
r4b2065a6 rd101368 32 32 33 33 PCUT_IMPORT(fmgt); 34 PCUT_IMPORT(newfile); 34 35 35 36 PCUT_MAIN();
Note:
See TracChangeset
for help on using the changeset viewer.
