Changeset 0ce9eb8 in mainline for uspace/lib/fmgt/src
- Timestamp:
- 2026-02-10T12:52:07Z (20 hours ago)
- Branches:
- master
- Children:
- 857fba8
- Parents:
- 26a9388
- git-author:
- Jiri Svoboda <jiri@…> (2026-02-10 18:51:59)
- git-committer:
- Jiri Svoboda <jiri@…> (2026-02-10 12:52:07)
- Location:
- uspace/lib/fmgt/src
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/fmgt/src/copy.c
r26a9388 r0ce9eb8 1 1 /* 2 * Copyright (c) 202 5Jiri Svoboda2 * Copyright (c) 2026 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 50 50 }; 51 51 52 /** Open file. 53 * 54 * @param fmgt File management object 55 * @param fname File name 56 * @param rfd Place to store file descriptor 57 * @return EOK on success or an error code 58 */ 59 static errno_t fmgt_open(fmgt_t *fmgt, const char *fname, int *rfd) 60 { 61 fmgt_io_error_t err; 62 fmgt_error_action_t action; 63 errno_t rc; 64 65 do { 66 rc = vfs_lookup_open(fname, WALK_REGULAR, MODE_READ, rfd); 67 if (rc == EOK) 68 break; 69 70 /* I/O error */ 71 err.fname = fname; 72 err.optype = fmgt_io_open; 73 err.rc = rc; 74 fmgt_timer_stop(fmgt); 75 action = fmgt_io_error_query(fmgt, &err); 76 fmgt_timer_start(fmgt); 77 } while (action == fmgt_er_retry); 78 79 return rc; 80 } 81 82 /** Create file. 83 * 84 * @param fmgt File management object 85 * @param fname Destination file name 86 * @param rfd Place to store file descriptor 87 * @param rskip If @c true, skip existing file and continue 88 * @return EOK on success or an error code 89 */ 90 static errno_t fmgt_create_file(fmgt_t *fmgt, const char *fname, int *rfd, 91 bool *rskip) 92 { 93 fmgt_io_error_t err; 94 fmgt_error_action_t action; 95 fmgt_exists_t exists; 96 fmgt_exists_action_t exaction; 97 bool may_overwrite = false; 98 unsigned flags; 99 errno_t rc; 100 101 *rskip = false; 102 103 do { 104 flags = WALK_REGULAR | (may_overwrite ? WALK_MAY_CREATE : 105 WALK_MUST_CREATE); 106 rc = vfs_lookup_open(fname, flags, MODE_WRITE, rfd); 107 if (rc == EOK) 108 break; 109 110 if (rc == EEXIST) { 111 /* File exists */ 112 exists.fname = fname; 113 fmgt_timer_stop(fmgt); 114 exaction = fmgt_exists_query(fmgt, &exists); 115 fmgt_timer_start(fmgt); 116 117 if (exaction == fmgt_exr_skip) 118 *rskip = true; 119 if (exaction != fmgt_exr_overwrite) 120 break; 121 122 may_overwrite = true; 123 } else { 124 /* I/O error */ 125 err.fname = fname; 126 err.optype = fmgt_io_create; 127 err.rc = rc; 128 fmgt_timer_stop(fmgt); 129 action = fmgt_io_error_query(fmgt, &err); 130 fmgt_timer_start(fmgt); 131 132 if (action != fmgt_er_retry) 133 break; 134 } 135 } while (true); 136 137 return rc; 138 } 139 140 /** Create directory. 141 * 142 * @param fmgt File management object 143 * @param dname Directory name 144 * @return EOK on success or an error code 145 */ 146 static errno_t fmgt_create_dir(fmgt_t *fmgt, const char *dname) 147 { 148 fmgt_io_error_t err; 149 fmgt_error_action_t action; 150 errno_t rc; 151 152 do { 153 rc = vfs_link_path(dname, KIND_DIRECTORY, NULL); 154 155 /* It is okay if the directory exists. */ 156 if (rc == EOK || rc == EEXIST) 157 break; 158 159 /* I/O error */ 160 err.fname = dname; 161 err.optype = fmgt_io_create; 162 err.rc = rc; 163 164 fmgt_timer_stop(fmgt); 165 action = fmgt_io_error_query(fmgt, &err); 166 fmgt_timer_start(fmgt); 167 } while (action == fmgt_er_retry); 168 169 if (rc == EEXIST) 170 return EOK; 171 172 return rc; 173 } 174 175 /** Read data from file. 176 * 177 * @param fmgt File management object 178 * @param fd File descriptor 179 * @param fname File name (for printing diagnostics) 180 * @param pos Pointer to current position (will be updated) 181 * @param buffer Data buffer 182 * @param nbytes Number of bytes to read 183 * @param nr Place to store number of bytes read 184 * @return EOK on success or an error code 185 */ 186 static errno_t fmgt_read(fmgt_t *fmgt, int fd, const char *fname, 187 aoff64_t *pos, void *buffer, size_t nbytes, size_t *nr) 188 { 189 char *bp = (char *)buffer; 190 fmgt_io_error_t err; 191 fmgt_error_action_t action; 192 errno_t rc; 193 194 do { 195 rc = vfs_read(fd, pos, bp, nbytes, nr); 196 if (rc == EOK) 197 break; 198 199 /* I/O error */ 200 err.fname = fname; 201 err.optype = fmgt_io_read; 202 err.rc = rc; 203 fmgt_timer_stop(fmgt); 204 action = fmgt_io_error_query(fmgt, &err); 205 fmgt_timer_start(fmgt); 206 } while (action == fmgt_er_retry); 207 208 /* Not recovered? */ 209 if (rc != EOK) 210 return rc; 211 212 return EOK; 213 } 214 215 /** Write data to file. 216 * 217 * @param fmgt File management object 218 * @param fd File descriptor 219 * @param fname File name (for printing diagnostics) 220 * @param pos Pointer to current position (will be updated) 221 * @param buffer Pointer to data 222 * @param nbytes Number of bytes to write 223 * @return EOK on success or an error code 224 */ 52 225 static errno_t fmgt_write(fmgt_t *fmgt, int fd, const char *fname, 53 226 aoff64_t *pos, void *buffer, size_t nbytes) … … 97 270 { 98 271 fmgt_t *fmgt = (fmgt_t *)arg; 99 fmgt_io_error_t err; 100 fmgt_error_action_t action; 101 errno_t rc; 102 103 do { 104 rc = vfs_link_path(dest, KIND_DIRECTORY, NULL); 105 106 /* It is okay if the directory exists. */ 107 if (rc == EOK || rc == EEXIST) 108 break; 109 110 /* I/O error */ 111 err.fname = dest; 112 err.optype = fmgt_io_create; 113 err.rc = rc; 114 115 fmgt_timer_stop(fmgt); 116 action = fmgt_io_error_query(fmgt, &err); 117 fmgt_timer_start(fmgt); 118 } while (action == fmgt_er_retry); 119 120 return rc; 272 273 (void)dest; 274 return fmgt_create_dir(fmgt, dest); 121 275 } 122 276 … … 137 291 aoff64_t wpos = 0; 138 292 char *buffer; 139 fmgt_io_error_t err; 140 fmgt_error_action_t action; 293 bool skip; 141 294 errno_t rc; 142 295 … … 145 298 return ENOMEM; 146 299 147 do { 148 rc = vfs_lookup_open(src, WALK_REGULAR, MODE_READ, &rfd); 149 if (rc == EOK) 150 break; 151 152 /* I/O error */ 153 err.fname = src; 154 err.optype = fmgt_io_open; 155 err.rc = rc; 156 fmgt_timer_stop(fmgt); 157 action = fmgt_io_error_query(fmgt, &err); 158 fmgt_timer_start(fmgt); 159 } while (action == fmgt_er_retry); 160 161 /* Not recovered? */ 300 rc = fmgt_open(fmgt, src, &rfd); 162 301 if (rc != EOK) { 163 302 free(buffer); … … 165 304 } 166 305 167 do { 168 rc = vfs_lookup_open(dest, WALK_REGULAR | WALK_MAY_CREATE, 169 MODE_WRITE, &wfd); 170 if (rc == EOK) 171 break; 172 173 /* I/O error */ 174 err.fname = dest; 175 err.optype = fmgt_io_create; 176 err.rc = rc; 177 fmgt_timer_stop(fmgt); 178 action = fmgt_io_error_query(fmgt, &err); 179 fmgt_timer_start(fmgt); 180 } while (action == fmgt_er_retry); 181 306 rc = fmgt_create_file(fmgt, dest, &wfd, &skip); 182 307 if (rc != EOK) { 183 308 free(buffer); 184 309 vfs_put(rfd); 310 311 /* User decided to skip and continue. */ 312 if (rc == EEXIST && skip) 313 return EOK; 185 314 return rc; 186 315 } … … 189 318 190 319 do { 191 do { 192 rc = vfs_read(rfd, &rpos, buffer, BUFFER_SIZE, &nr); 193 if (rc == EOK) 194 break; 195 196 /* I/O error */ 197 err.fname = src; 198 err.optype = fmgt_io_read; 199 err.rc = rc; 200 fmgt_timer_stop(fmgt); 201 action = fmgt_io_error_query(fmgt, &err); 202 fmgt_timer_start(fmgt); 203 } while (action == fmgt_er_retry); 204 205 /* Not recovered? */ 320 rc = fmgt_read(fmgt, rfd, src, &rpos, buffer, BUFFER_SIZE, 321 &nr); 206 322 if (rc != EOK) 207 323 goto error; … … 233 349 } 234 350 235 /** copy files.351 /** Copy files. 236 352 * 237 353 * @param fmgt File management object -
uspace/lib/fmgt/src/fmgt.c
r26a9388 r0ce9eb8 1 1 /* 2 * Copyright (c) 202 5Jiri Svoboda2 * Copyright (c) 2026 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 283 283 } 284 284 285 /** Query caller how to recover from existing destination file/directory. 286 * 287 * @param fmgt File management object 288 * @param exists File/directory exists report 289 * @return What recovery action should be taken. 290 */ 291 fmgt_exists_action_t fmgt_exists_query(fmgt_t *fmgt, fmgt_exists_t *exists) 292 { 293 if (fmgt->cb != NULL && fmgt->cb->exists_query != NULL) 294 return fmgt->cb->exists_query(fmgt->cb_arg, exists); 295 else 296 return fmgt_exr_abort; 297 } 298 285 299 /** Return base name (without path component). 286 300 *
Note:
See TracChangeset
for help on using the changeset viewer.
