File indexing completed on 2025-05-11 08:24:18
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 #ifdef HAVE_CONFIG_H
0040 #include "config.h"
0041 #endif
0042
0043 #include <inttypes.h>
0044 #include <string.h>
0045
0046 #include <rtems/rfs/rtems-rfs-block.h>
0047 #include <rtems/rfs/rtems-rfs-buffer.h>
0048 #include <rtems/rfs/rtems-rfs-file-system.h>
0049 #include <rtems/rfs/rtems-rfs-trace.h>
0050 #include <rtems/rfs/rtems-rfs-dir.h>
0051 #include <rtems/rfs/rtems-rfs-dir-hash.h>
0052 #include <rtems/rfs/rtems-rfs-link.h>
0053
0054 int
0055 rtems_rfs_link (rtems_rfs_file_system* fs,
0056 const char* name,
0057 int length,
0058 rtems_rfs_ino parent,
0059 rtems_rfs_ino target,
0060 bool link_dir)
0061 {
0062 rtems_rfs_inode_handle parent_inode;
0063 rtems_rfs_inode_handle target_inode;
0064 uint16_t links;
0065 int rc;
0066
0067 if (rtems_rfs_trace (RTEMS_RFS_TRACE_LINK))
0068 {
0069 int c;
0070 printf ("rtems-rfs: link: parent(%" PRIu32 ") -> ", parent);
0071 for (c = 0; c < length; c++)
0072 printf ("%c", name[c]);
0073 printf ("(%" PRIu32 ")\n", target);
0074 }
0075
0076 rc = rtems_rfs_inode_open (fs, target, &target_inode, true);
0077 if (rc)
0078 return rc;
0079
0080
0081
0082
0083
0084 if (!link_dir && S_ISDIR (rtems_rfs_inode_get_mode (&target_inode)))
0085 {
0086 rtems_rfs_inode_close (fs, &target_inode);
0087 return ENOTSUP;
0088 }
0089
0090 rc = rtems_rfs_inode_open (fs, parent, &parent_inode, true);
0091 if (rc)
0092 {
0093 rtems_rfs_inode_close (fs, &target_inode);
0094 return rc;
0095 }
0096
0097 rc = rtems_rfs_dir_add_entry (fs, &parent_inode, name, length, target);
0098 if (rc > 0)
0099 {
0100 rtems_rfs_inode_close (fs, &parent_inode);
0101 rtems_rfs_inode_close (fs, &target_inode);
0102 return rc;
0103 }
0104
0105 links = rtems_rfs_inode_get_links (&target_inode) + 1;
0106 rtems_rfs_inode_set_links (&target_inode, links);
0107
0108 rc = rtems_rfs_inode_time_stamp_now (&parent_inode, true, true);
0109 if (rc > 0)
0110 {
0111 rtems_rfs_inode_close (fs, &parent_inode);
0112 rtems_rfs_inode_close (fs, &target_inode);
0113 return rc;
0114 }
0115
0116 rc = rtems_rfs_inode_close (fs, &parent_inode);
0117 if (rc > 0)
0118 {
0119 rtems_rfs_inode_close (fs, &target_inode);
0120 return rc;
0121 }
0122
0123 rc = rtems_rfs_inode_close (fs, &target_inode);
0124
0125 return rc;
0126 }
0127
0128 int
0129 rtems_rfs_unlink (rtems_rfs_file_system* fs,
0130 rtems_rfs_ino parent,
0131 rtems_rfs_ino target,
0132 uint32_t doff,
0133 rtems_rfs_unlink_dir dir_mode)
0134 {
0135 rtems_rfs_inode_handle parent_inode;
0136 rtems_rfs_inode_handle target_inode;
0137 uint16_t links;
0138 bool dir;
0139 int rc;
0140
0141 if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
0142 printf ("rtems-rfs: unlink: parent(%" PRIu32 ") -X-> (%" PRIu32 ")\n", parent, target);
0143
0144 rc = rtems_rfs_inode_open (fs, target, &target_inode, true);
0145 if (rc)
0146 return rc;
0147
0148
0149
0150
0151
0152 dir = RTEMS_RFS_S_ISDIR (rtems_rfs_inode_get_mode (&target_inode));
0153 if (dir)
0154 {
0155 switch (dir_mode)
0156 {
0157 case rtems_rfs_unlink_dir_denied:
0158 if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
0159 printf ("rtems-rfs: link is a directory\n");
0160 rtems_rfs_inode_close (fs, &target_inode);
0161 return EISDIR;
0162
0163 case rtems_rfs_unlink_dir_if_empty:
0164 rc = rtems_rfs_dir_empty (fs, &target_inode);
0165 if (rc > 0)
0166 {
0167 if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
0168 printf ("rtems-rfs: dir-empty: %d: %s\n", rc, strerror (rc));
0169 rtems_rfs_inode_close (fs, &target_inode);
0170 return rc;
0171 }
0172 break;
0173
0174 default:
0175 break;
0176 }
0177 }
0178
0179 rc = rtems_rfs_inode_open (fs, parent, &parent_inode, true);
0180 if (rc)
0181 {
0182 if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
0183 printf ("rtems-rfs: link: inode-open failed: %d: %s\n",
0184 rc, strerror (rc));
0185 rtems_rfs_inode_close (fs, &target_inode);
0186 return rc;
0187 }
0188
0189 rc = rtems_rfs_dir_del_entry (fs, &parent_inode, target, doff);
0190 if (rc > 0)
0191 {
0192 if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
0193 printf ("rtems-rfs: unlink: dir-del failed: %d: %s\n",
0194 rc, strerror (rc));
0195 rtems_rfs_inode_close (fs, &parent_inode);
0196 rtems_rfs_inode_close (fs, &target_inode);
0197 return rc;
0198 }
0199
0200 links = rtems_rfs_inode_get_links (&target_inode);
0201
0202 if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
0203 printf ("rtems-rfs: unlink: target:%" PRIu32 " links:%u\n", target, links);
0204
0205 if (links > 1)
0206 {
0207 links--;
0208 rtems_rfs_inode_set_links (&target_inode, links);
0209 }
0210 else
0211 {
0212
0213
0214
0215 rc = rtems_rfs_inode_delete (fs, &target_inode);
0216 if (rc > 0)
0217 {
0218 if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
0219 printf ("rtems-rfs: unlink: inode-del failed: %d: %s\n",
0220 rc, strerror (rc));
0221 rtems_rfs_inode_close (fs, &parent_inode);
0222 rtems_rfs_inode_close (fs, &target_inode);
0223 return rc;
0224 }
0225
0226 if (dir)
0227 {
0228 links = rtems_rfs_inode_get_links (&parent_inode);
0229 if (links > 1)
0230 links--;
0231 rtems_rfs_inode_set_links (&parent_inode, links);
0232 }
0233 }
0234
0235 rc = rtems_rfs_inode_time_stamp_now (&parent_inode, true, true);
0236 if (rc > 0)
0237 {
0238 if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
0239 printf ("rtems-rfs: link: inode-time-stamp failed: %d: %s\n",
0240 rc, strerror (rc));
0241 rtems_rfs_inode_close (fs, &parent_inode);
0242 rtems_rfs_inode_close (fs, &target_inode);
0243 return rc;
0244 }
0245
0246 rc = rtems_rfs_inode_close (fs, &parent_inode);
0247 if (rc > 0)
0248 {
0249 if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
0250 printf ("rtems-rfs: link: parent inode-close failed: %d: %s\n",
0251 rc, strerror (rc));
0252 rtems_rfs_inode_close (fs, &target_inode);
0253 return rc;
0254 }
0255
0256 rc = rtems_rfs_inode_close (fs, &target_inode);
0257
0258 if ((rc > 0) && rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
0259 printf ("rtems-rfs: link: target inode-close failed: %d: %s\n",
0260 rc, strerror (rc));
0261
0262 return rc;
0263 }
0264
0265 int
0266 rtems_rfs_symlink (rtems_rfs_file_system* fs,
0267 const char* name,
0268 int length,
0269 const char* link,
0270 int link_length,
0271 uid_t uid,
0272 gid_t gid,
0273 rtems_rfs_ino parent)
0274 {
0275 rtems_rfs_inode_handle inode;
0276 rtems_rfs_ino ino;
0277 int rc;
0278
0279 if (rtems_rfs_trace (RTEMS_RFS_TRACE_SYMLINK))
0280 {
0281 int c;
0282 printf ("rtems-rfs: symlink: parent:%" PRIu32 " name:", parent);
0283 for (c = 0; c < length; c++)
0284 printf ("%c", name[c]);
0285 printf (" link:");
0286 for (c = 0; c < link_length; c++)
0287 printf ("%c", link[c]);
0288 }
0289
0290 if (link_length >= rtems_rfs_fs_block_size (fs))
0291 return ENAMETOOLONG;
0292
0293 rc = rtems_rfs_inode_create (fs, parent, name, strlen (name),
0294 RTEMS_RFS_S_SYMLINK,
0295 1, uid, gid, &ino);
0296 if (rc > 0)
0297 return rc;
0298
0299 rc = rtems_rfs_inode_open (fs, ino, &inode, true);
0300 if (rc > 0)
0301 return rc;
0302
0303
0304
0305
0306
0307
0308 if (link_length < RTEMS_RFS_INODE_DATA_NAME_SIZE)
0309 {
0310 memset (inode.node->data.name, 0, RTEMS_RFS_INODE_DATA_NAME_SIZE);
0311 memcpy (inode.node->data.name, link, link_length);
0312 rtems_rfs_inode_set_block_count (&inode, 0);
0313 }
0314 else
0315 {
0316 rtems_rfs_block_map map;
0317 rtems_rfs_block_no block;
0318 rtems_rfs_buffer_handle buffer;
0319 uint8_t* data;
0320
0321 rc = rtems_rfs_block_map_open (fs, &inode, &map);
0322 if (rc > 0)
0323 {
0324 rtems_rfs_inode_close (fs, &inode);
0325 return rc;
0326 }
0327
0328 rc = rtems_rfs_block_map_grow (fs, &map, 1, &block);
0329 if (rc > 0)
0330 {
0331 rtems_rfs_block_map_close (fs, &map);
0332 rtems_rfs_inode_close (fs, &inode);
0333 return rc;
0334 }
0335
0336 rc = rtems_rfs_buffer_handle_open (fs, &buffer);
0337 if (rc > 0)
0338 {
0339 rtems_rfs_block_map_close (fs, &map);
0340 rtems_rfs_inode_close (fs, &inode);
0341 return rc;
0342 }
0343
0344 rc = rtems_rfs_buffer_handle_request (fs, &buffer, block, false);
0345 if (rc > 0)
0346 {
0347 rtems_rfs_block_map_close (fs, &map);
0348 rtems_rfs_inode_close (fs, &inode);
0349 return rc;
0350 }
0351
0352 data = rtems_rfs_buffer_data (&buffer);
0353
0354 memset (data, 0xff, rtems_rfs_fs_block_size (fs));
0355 memcpy (data, link, link_length);
0356
0357 rc = rtems_rfs_buffer_handle_close (fs, &buffer);
0358 if (rc > 0)
0359 {
0360 rtems_rfs_block_map_close (fs, &map);
0361 rtems_rfs_inode_close (fs, &inode);
0362 return rc;
0363 }
0364
0365 rc = rtems_rfs_block_map_close (fs, &map);
0366 if (rc > 0)
0367 {
0368 rtems_rfs_inode_close (fs, &inode);
0369 return rc;
0370 }
0371 }
0372
0373 rtems_rfs_inode_set_block_offset (&inode, link_length);
0374
0375 rc = rtems_rfs_inode_close (fs, &inode);
0376
0377 return rc;
0378 }
0379
0380 int
0381 rtems_rfs_symlink_read (rtems_rfs_file_system* fs,
0382 rtems_rfs_ino link,
0383 char* path,
0384 size_t size,
0385 size_t* length)
0386 {
0387 rtems_rfs_inode_handle inode;
0388 int rc;
0389
0390 if (rtems_rfs_trace (RTEMS_RFS_TRACE_SYMLINK_READ))
0391 printf ("rtems-rfs: symlink-read: link:%" PRIu32 "\n", link);
0392
0393 rc = rtems_rfs_inode_open (fs, link, &inode, true);
0394 if (rc)
0395 return rc;
0396
0397 if (!RTEMS_RFS_S_ISLNK (rtems_rfs_inode_get_mode (&inode)))
0398 {
0399 rtems_rfs_inode_close (fs, &inode);
0400 return EINVAL;
0401 }
0402
0403 *length = rtems_rfs_inode_get_block_offset (&inode);
0404
0405 if (size < *length)
0406 {
0407 *length = size;
0408 }
0409
0410 if (rtems_rfs_inode_get_block_count (&inode) == 0)
0411 {
0412 memcpy (path, inode.node->data.name, *length);
0413 }
0414 else
0415 {
0416 rtems_rfs_block_map map;
0417 rtems_rfs_block_no block;
0418 rtems_rfs_buffer_handle buffer;
0419 char* data;
0420
0421 rc = rtems_rfs_block_map_open (fs, &inode, &map);
0422 if (rc > 0)
0423 {
0424 rtems_rfs_inode_close (fs, &inode);
0425 return rc;
0426 }
0427
0428 rc = rtems_rfs_block_map_seek (fs, &map, 0, &block);
0429 if (rc > 0)
0430 {
0431 rtems_rfs_block_map_close (fs, &map);
0432 rtems_rfs_inode_close (fs, &inode);
0433 return rc;
0434 }
0435
0436 rc = rtems_rfs_buffer_handle_open (fs, &buffer);
0437 if (rc > 0)
0438 {
0439 rtems_rfs_block_map_close (fs, &map);
0440 rtems_rfs_inode_close (fs, &inode);
0441 return rc;
0442 }
0443
0444 rc = rtems_rfs_buffer_handle_request (fs, &buffer, block, false);
0445 if (rc > 0)
0446 {
0447 rtems_rfs_block_map_close (fs, &map);
0448 rtems_rfs_inode_close (fs, &inode);
0449 return rc;
0450 }
0451
0452 data = rtems_rfs_buffer_data (&buffer);
0453 memcpy (path, data, *length);
0454
0455 rc = rtems_rfs_buffer_handle_close (fs, &buffer);
0456 if (rc > 0)
0457 {
0458 rtems_rfs_block_map_close (fs, &map);
0459 rtems_rfs_inode_close (fs, &inode);
0460 return rc;
0461 }
0462
0463 rc = rtems_rfs_block_map_close (fs, &map);
0464 if (rc > 0)
0465 {
0466 rtems_rfs_inode_close (fs, &inode);
0467 return rc;
0468 }
0469 }
0470
0471 rc = rtems_rfs_inode_close (fs, &inode);
0472
0473 return rc;
0474 }