summaryrefslogtreecommitdiffstats
path: root/cpukit/libfs/src/imfs/imfs_link.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/libfs/src/imfs/imfs_link.c')
-rw-r--r--cpukit/libfs/src/imfs/imfs_link.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/cpukit/libfs/src/imfs/imfs_link.c b/cpukit/libfs/src/imfs/imfs_link.c
index 61b9f43e96..9e25f044c4 100644
--- a/cpukit/libfs/src/imfs/imfs_link.c
+++ b/cpukit/libfs/src/imfs/imfs_link.c
@@ -62,3 +62,77 @@ int IMFS_link(
return 0;
}
+
+static int IMFS_stat_hard_link(
+ const rtems_filesystem_location_info_t *loc,
+ struct stat *buf
+)
+{
+ const IMFS_link_t *hard_link = loc->node_access;
+ rtems_filesystem_location_info_t targetloc = *loc;
+
+ targetloc.node_access = hard_link->link_node;
+ IMFS_Set_handlers( &targetloc );
+
+ return (targetloc.handlers->fstat_h)( &targetloc, buf );
+}
+
+static const rtems_filesystem_file_handlers_r IMFS_link_handlers = {
+ .open_h = rtems_filesystem_default_open,
+ .close_h = rtems_filesystem_default_close,
+ .read_h = rtems_filesystem_default_read,
+ .write_h = rtems_filesystem_default_write,
+ .ioctl_h = rtems_filesystem_default_ioctl,
+ .lseek_h = rtems_filesystem_default_lseek,
+ .fstat_h = IMFS_stat_hard_link,
+ .ftruncate_h = rtems_filesystem_default_ftruncate,
+ .fsync_h = rtems_filesystem_default_fsync_or_fdatasync,
+ .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync,
+ .fcntl_h = rtems_filesystem_default_fcntl,
+ .kqfilter_h = rtems_filesystem_default_kqfilter,
+ .poll_h = rtems_filesystem_default_poll,
+ .readv_h = rtems_filesystem_default_readv,
+ .writev_h = rtems_filesystem_default_writev
+};
+
+static IMFS_jnode_t *IMFS_node_initialize_hard_link(
+ IMFS_jnode_t *node,
+ void *arg
+)
+{
+ IMFS_link_t *hard_link = (IMFS_link_t *) node;
+
+ hard_link->link_node = arg;
+
+ return node;
+}
+
+static IMFS_jnode_t *IMFS_node_remove_hard_link(
+ IMFS_jnode_t *node
+)
+{
+ IMFS_link_t *hard_link = (IMFS_link_t *) node;
+ IMFS_jnode_t *target = hard_link->link_node;
+
+ _Assert( target != NULL );
+
+ if ( target->st_nlink == 1) {
+ target = (*target->control->node_remove)( target );
+ if ( target == NULL ) {
+ node = NULL;
+ }
+ } else {
+ --target->st_nlink;
+ IMFS_update_ctime( target );
+ }
+
+ return node;
+}
+
+const IMFS_node_control IMFS_node_control_hard_link = {
+ .handlers = &IMFS_link_handlers,
+ .node_size = sizeof(IMFS_link_t),
+ .node_initialize = IMFS_node_initialize_hard_link,
+ .node_remove = IMFS_node_remove_hard_link,
+ .node_destroy = IMFS_node_destroy_default
+};