summaryrefslogtreecommitdiffstats
path: root/cpukit
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2009-10-08 07:07:36 +0000
committerChris Johns <chrisj@rtems.org>2009-10-08 07:07:36 +0000
commiteb649786c8528f349a39b35ae2965e3f874e2088 (patch)
tree194f40f18f42b9f12ee58df2bee39b0e7d7a4cc3 /cpukit
parentRegenerate (diff)
downloadrtems-eb649786c8528f349a39b35ae2965e3f874e2088.tar.bz2
2009-10-08 Chris Johns <chrisj@rtems.org>
* Makefile.am, preinstall.am: Added statvfs.h. * libcsupport/Makefile.am: Add statvfs.c. * libcsupport/include/sys/statvfs.h, libcsupport/src/statvfs.c: New. * libcsupport/include/rtems/libio.h: Add a file system handler for the statvfs call. * libfs/src/devfs/devfs_init.c, libfs/src/dosfs/msdos_init.c, libfs/src/imfs/imfs_init.c, libfs/src/nfsclient/src/nfs.c: Set the statvfs handler to NULL. * include/rtems/fs.h: Add a second node access field for the RFS file system to hold a directory offset while the existing field holds the inode number. This save a rescan of the directory when working with directories. * libblock/include/rtems/bdbuf.h: Added references and user fields to the buffer descriptor. * libblock/src/bdbuf.c: Added dynamic buffer support for different block sizes. Fixed a number of bugs. * libblock/src/blkdev.c: Release the disk device on an error. * libblock/src/diskdevs.c: Set the block size to the media block size during initialisation of the disk device. * libblock/src/flashdisk.c, libblock/src/nvdisk.c, libblock/src/ramdisk.c: Updated the drivers to handle variable block sizes. * libfs/src/dosfs/fat.c, libfs/src/dosfs/fat.h: Release any buffers when an error occurs. The FAT buffer layer hangs onto a single buffer while mounted. This should be fixed. * sapi/inline/rtems/chain.inl: Added rtems_chain_set_off_chain, rtems_chain_is_node_off_chain, and rtems_chain_previous. * score/inline/rtems/score/chain.inl: Added _Chain_Set_off_chain, and _Chain_Is_node_off_chain. * libmisc/shell/main_ln.c, libmisc/shell/main_mknod.c, libmisc/shell/mknod-pack_dev.c, libmisc/shell/mknod-pack_dev.h: New shell commands. * libmisc/Makefile.am, libmisc/shell/shellconfig.h: Added ln and mknod commands. * libmisc/shell/hexdump-display.c: Fixed the reopen bug which showed up as a free with a bad pointer. * libmisc/shell/main_mount.c: List the user adding file system when listing the available file systems to mount. * libmisc/shell/utils-cp.c: Remove the fixed static copy buffer and use a large dynamic buffer. * score/inline/rtems/score/address.inl, score/src/coremsgsubmit.c, score/src/objectallocate.c, score/src/objectfree.c: Remove warnings.
Diffstat (limited to 'cpukit')
-rw-r--r--cpukit/ChangeLog47
-rw-r--r--cpukit/Makefile.am5
-rw-r--r--cpukit/include/rtems/fs.h1
-rw-r--r--cpukit/libblock/include/rtems/bdbuf.h4
-rw-r--r--cpukit/libblock/src/bdbuf.c509
-rw-r--r--cpukit/libblock/src/blkdev.c5
-rw-r--r--cpukit/libblock/src/diskdevs.c2
-rw-r--r--cpukit/libblock/src/flashdisk.c50
-rw-r--r--cpukit/libblock/src/nvdisk.c58
-rw-r--r--cpukit/libblock/src/ramdisk.c52
-rw-r--r--cpukit/libcsupport/Makefile.am2
-rw-r--r--cpukit/libcsupport/include/rtems/libio.h7
-rw-r--r--cpukit/libcsupport/include/sys/statvfs.h45
-rw-r--r--cpukit/libcsupport/src/statvfs.c60
-rw-r--r--cpukit/libfs/src/devfs/devfs_init.c1
-rw-r--r--cpukit/libfs/src/dosfs/fat.c24
-rw-r--r--cpukit/libfs/src/dosfs/fat.h3
-rw-r--r--cpukit/libfs/src/dosfs/msdos_init.c1
-rw-r--r--cpukit/libfs/src/imfs/imfs_init.c3
-rw-r--r--cpukit/libfs/src/nfsclient/src/nfs.c1
-rw-r--r--cpukit/libmisc/Makefile.am4
-rw-r--r--cpukit/libmisc/shell/hexdump-display.c30
-rw-r--r--cpukit/libmisc/shell/main_ln.c305
-rw-r--r--cpukit/libmisc/shell/main_mknod.c459
-rw-r--r--cpukit/libmisc/shell/main_mount.c8
-rw-r--r--cpukit/libmisc/shell/mknod-pack_dev.c296
-rw-r--r--cpukit/libmisc/shell/mknod-pack_dev.h52
-rw-r--r--cpukit/libmisc/shell/shellconfig.h12
-rw-r--r--cpukit/libmisc/shell/utils-cp.c26
-rw-r--r--cpukit/preinstall.am4
-rw-r--r--cpukit/sapi/inline/rtems/chain.inl48
-rw-r--r--cpukit/score/inline/rtems/score/address.inl8
-rw-r--r--cpukit/score/inline/rtems/score/chain.inl30
-rw-r--r--cpukit/score/src/coremsgsubmit.c2
-rw-r--r--cpukit/score/src/objectallocate.c2
-rw-r--r--cpukit/score/src/objectfree.c4
36 files changed, 1873 insertions, 297 deletions
diff --git a/cpukit/ChangeLog b/cpukit/ChangeLog
index f3a27c18ae..51eb505f6d 100644
--- a/cpukit/ChangeLog
+++ b/cpukit/ChangeLog
@@ -1,3 +1,50 @@
+2009-10-08 Chris Johns <chrisj@rtems.org>
+
+ * Makefile.am, preinstall.am: Added statvfs.h.
+ * libcsupport/Makefile.am: Add statvfs.c.
+ * libcsupport/include/sys/statvfs.h, libcsupport/src/statvfs.c:
+ New.
+ * libcsupport/include/rtems/libio.h: Add a file system handler for
+ the statvfs call.
+ * libfs/src/devfs/devfs_init.c, libfs/src/dosfs/msdos_init.c,
+ libfs/src/imfs/imfs_init.c, libfs/src/nfsclient/src/nfs.c: Set the
+ statvfs handler to NULL.
+ * include/rtems/fs.h: Add a second node access field for the RFS
+ file system to hold a directory offset while the existing field
+ holds the inode number. This save a rescan of the directory when
+ working with directories.
+ * libblock/include/rtems/bdbuf.h: Added references and user fields
+ to the buffer descriptor.
+ * libblock/src/bdbuf.c: Added dynamic buffer support for different
+ block sizes. Fixed a number of bugs.
+ * libblock/src/blkdev.c: Release the disk device on an error.
+ * libblock/src/diskdevs.c: Set the block size to the media block
+ size during initialisation of the disk device.
+ * libblock/src/flashdisk.c, libblock/src/nvdisk.c,
+ libblock/src/ramdisk.c: Updated the drivers to handle variable
+ block sizes.
+ * libfs/src/dosfs/fat.c, libfs/src/dosfs/fat.h: Release any
+ buffers when an error occurs. The FAT buffer layer hangs onto a
+ single buffer while mounted. This should be fixed.
+ * sapi/inline/rtems/chain.inl: Added rtems_chain_set_off_chain,
+ rtems_chain_is_node_off_chain, and rtems_chain_previous.
+ * score/inline/rtems/score/chain.inl: Added _Chain_Set_off_chain,
+ and _Chain_Is_node_off_chain.
+ * libmisc/shell/main_ln.c, libmisc/shell/main_mknod.c,
+ libmisc/shell/mknod-pack_dev.c, libmisc/shell/mknod-pack_dev.h:
+ New shell commands.
+ * libmisc/Makefile.am, libmisc/shell/shellconfig.h: Added ln and
+ mknod commands.
+ * libmisc/shell/hexdump-display.c: Fixed the reopen bug which
+ showed up as a free with a bad pointer.
+ * libmisc/shell/main_mount.c: List the user adding file system
+ when listing the available file systems to mount.
+ * libmisc/shell/utils-cp.c: Remove the fixed static copy buffer
+ and use a large dynamic buffer.
+ * score/inline/rtems/score/address.inl, score/src/coremsgsubmit.c,
+ score/src/objectallocate.c, score/src/objectfree.c: Remove
+ warnings.
+
2009-10-06 Joel Sherrill <joel.sherrill@oarcorp.com>
* sapi/src/ioregisterdriver.c: Reowork so this is a context switch
diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am
index c39f99741b..662fb91b1f 100644
--- a/cpukit/Makefile.am
+++ b/cpukit/Makefile.am
@@ -55,8 +55,9 @@ include_HEADERS += libnetworking/memory.h
include_sys_HEADERS += libcsupport/include/sys/ioccom.h \
libcsupport/include/sys/filio.h libcsupport/include/sys/ioctl.h \
- libcsupport/include/sys/sockio.h libcsupport/include/sys/ttycom.h \
- libcsupport/include/sys/termios.h libcsupport/include/sys/utsname.h
+ libcsupport/include/sys/statvfs.h libcsupport/include/sys/sockio.h \
+ libcsupport/include/sys/ttycom.h libcsupport/include/sys/termios.h \
+ libcsupport/include/sys/utsname.h
include_sys_HEADERS += libnetworking/sys/uio.h
include_sys_HEADERS += include/sys/priority.h
diff --git a/cpukit/include/rtems/fs.h b/cpukit/include/rtems/fs.h
index 01ae4ab28d..888c13f1b4 100644
--- a/cpukit/include/rtems/fs.h
+++ b/cpukit/include/rtems/fs.h
@@ -46,6 +46,7 @@ typedef struct _rtems_filesystem_operations_table
struct rtems_filesystem_location_info_tt
{
void *node_access;
+ void *node_access_2;
const rtems_filesystem_file_handlers_r *handlers;
const rtems_filesystem_operations_table *ops;
rtems_filesystem_mount_table_entry_t *mt_entry;
diff --git a/cpukit/libblock/include/rtems/bdbuf.h b/cpukit/libblock/include/rtems/bdbuf.h
index da9e05011f..f74fd4b353 100644
--- a/cpukit/libblock/include/rtems/bdbuf.h
+++ b/cpukit/libblock/include/rtems/bdbuf.h
@@ -190,6 +190,7 @@ typedef struct rtems_bdbuf_buffer
} avl;
dev_t dev; /**< device number */
+
rtems_blkdev_bnum block; /**< block number on the device */
unsigned char* buffer; /**< Pointer to the buffer memory area */
@@ -204,6 +205,9 @@ typedef struct rtems_bdbuf_buffer
* part of. */
volatile uint32_t hold_timer; /**< Timer to indicate how long a buffer
* has been held in the cache modified. */
+
+ int references; /**< Allow reference counting by owner. */
+ void* user; /**< User data. */
} rtems_bdbuf_buffer;
/**
diff --git a/cpukit/libblock/src/bdbuf.c b/cpukit/libblock/src/bdbuf.c
index 8bf58ae928..de5468fd6a 100644
--- a/cpukit/libblock/src/bdbuf.c
+++ b/cpukit/libblock/src/bdbuf.c
@@ -37,10 +37,7 @@
#include <limits.h>
#include <errno.h>
#include <assert.h>
-
-#if RTEMS_BDBUF_TRACE
#include <stdio.h>
-#endif
#include "rtems/bdbuf.h"
@@ -55,9 +52,10 @@
*/
typedef struct rtems_bdbuf_swapout_transfer
{
- rtems_chain_control bds; /**< The transfer list of BDs. */
- dev_t dev; /**< The device the transfer is for. */
- rtems_blkdev_request* write_req; /**< The write request array. */
+ rtems_chain_control bds; /**< The transfer list of BDs. */
+ dev_t dev; /**< The device the transfer is for. */
+ rtems_blkdev_request* write_req; /**< The write request array. */
+ uint32_t bufs_per_bd; /**< Number of buffers per bd. */
} rtems_bdbuf_swapout_transfer;
/**
@@ -151,13 +149,14 @@ typedef struct rtems_bdbuf_cache
#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_WAIT_1 RTEMS_BLKDEV_FATAL_ERROR(15)
#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_WAIT_2 RTEMS_BLKDEV_FATAL_ERROR(16)
#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_WAIT_3 RTEMS_BLKDEV_FATAL_ERROR(17)
-#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_WAKE RTEMS_BLKDEV_FATAL_ERROR(18)
-#define RTEMS_BLKDEV_FATAL_BDBUF_SO_WAKE RTEMS_BLKDEV_FATAL_ERROR(19)
-#define RTEMS_BLKDEV_FATAL_BDBUF_SO_NOMEM RTEMS_BLKDEV_FATAL_ERROR(20)
-#define RTEMS_BLKDEV_FATAL_BDBUF_SO_WK_CREATE RTEMS_BLKDEV_FATAL_ERROR(21)
-#define RTEMS_BLKDEV_FATAL_BDBUF_SO_WK_START RTEMS_BLKDEV_FATAL_ERROR(22)
-#define BLKDEV_FATAL_BDBUF_SWAPOUT_RE RTEMS_BLKDEV_FATAL_ERROR(23)
-#define BLKDEV_FATAL_BDBUF_SWAPOUT_TS RTEMS_BLKDEV_FATAL_ERROR(24)
+#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_WAIT_TO RTEMS_BLKDEV_FATAL_ERROR(18)
+#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_WAKE RTEMS_BLKDEV_FATAL_ERROR(19)
+#define RTEMS_BLKDEV_FATAL_BDBUF_SO_WAKE RTEMS_BLKDEV_FATAL_ERROR(20)
+#define RTEMS_BLKDEV_FATAL_BDBUF_SO_NOMEM RTEMS_BLKDEV_FATAL_ERROR(21)
+#define RTEMS_BLKDEV_FATAL_BDBUF_SO_WK_CREATE RTEMS_BLKDEV_FATAL_ERROR(22)
+#define RTEMS_BLKDEV_FATAL_BDBUF_SO_WK_START RTEMS_BLKDEV_FATAL_ERROR(23)
+#define BLKDEV_FATAL_BDBUF_SWAPOUT_RE RTEMS_BLKDEV_FATAL_ERROR(24)
+#define BLKDEV_FATAL_BDBUF_SWAPOUT_TS RTEMS_BLKDEV_FATAL_ERROR(25)
/**
* The events used in this code. These should be system events rather than
@@ -193,6 +192,16 @@ typedef struct rtems_bdbuf_cache
(RTEMS_PRIORITY | RTEMS_SIMPLE_BINARY_SEMAPHORE | \
RTEMS_NO_INHERIT_PRIORITY | RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL)
+/**
+ * Waiter timeout. Set to non-zero to find some info on a waiter that is
+ * waiting too long.
+ */
+#define RTEMS_BDBUF_WAIT_TIMEOUT RTEMS_NO_TIMEOUT
+#if !defined (RTEMS_BDBUF_WAIT_TIMEOUT)
+#define RTEMS_BDBUF_WAIT_TIMEOUT \
+ (TOD_MICROSECONDS_TO_TICKS (20000000))
+#endif
+
/*
* The swap out task.
*/
@@ -203,27 +212,81 @@ static rtems_task rtems_bdbuf_swapout_task(rtems_task_argument arg);
*/
static rtems_bdbuf_cache bdbuf_cache;
+#if RTEMS_BDBUF_TRACE
/**
- * Print a message to the bdbuf trace output and flush it.
- *
- * @param format The format string. See printf for details.
- * @param ... The arguments for the format text.
- * @return int The number of bytes written to the output.
+ * If true output the trace message.
*/
-#if RTEMS_BDBUF_TRACE
bool rtems_bdbuf_tracer;
-static void
-rtems_bdbuf_printf (const char *format, ...)
+
+/**
+ * Return the number of items on the list.
+ *
+ * @param list The chain control.
+ * @return uint32_t The number of items on the list.
+ */
+uint32_t
+rtems_bdbuf_list_count (rtems_chain_control* list)
{
- va_list args;
- va_start (args, format);
- if (rtems_bdbuf_tracer)
+ rtems_chain_node* node = rtems_chain_first (list);
+ uint32_t count = 0;
+ while (!rtems_chain_is_tail (list, node))
{
- fprintf (stdout, "bdbuf:");
- vfprintf (stdout, format, args);
- fflush (stdout);
+ count++;
+ node = rtems_chain_next (node);
}
+ return count;
+}
+
+/**
+ * Show the usage for the bdbuf cache.
+ */
+void
+rtems_bdbuf_show_usage (void)
+{
+ uint32_t group;
+ uint32_t total = 0;
+ uint32_t val;
+ for (group = 0; group < bdbuf_cache.group_count; group++)
+ total += bdbuf_cache.groups[group].users;
+ printf ("bdbuf:group users=%lu", total);
+ val = rtems_bdbuf_list_count (&bdbuf_cache.ready);
+ printf (", ready=%lu", val);
+ total = val;
+ val = rtems_bdbuf_list_count (&bdbuf_cache.lru);
+ printf (", lru=%lu", val);
+ total += val;
+ val = rtems_bdbuf_list_count (&bdbuf_cache.modified);
+ printf (", mod=%lu", val);
+ total += val;
+ val = rtems_bdbuf_list_count (&bdbuf_cache.sync);
+ printf (", sync=%lu", val);
+ total += val;
+ printf (", total=%lu\n", total);
}
+
+/**
+ * Show the users for a group of a bd.
+ *
+ * @param where A label to show the context of output.
+ * @param bd The bd to show the users of.
+ */
+void
+rtems_bdbuf_show_users (const char* where, rtems_bdbuf_buffer* bd)
+{
+ const char* states[] =
+ { "EM", "RA", "CH", "AC", "MD", "AM", "SY", "TR" };
+ printf ("bdbuf:users: %15s: [%ld (%s)] %ld:%ld = %lu %s\n",
+ where,
+ bd->block, states[bd->state],
+ bd->group - bdbuf_cache.groups,
+ bd - bdbuf_cache.bds,
+ bd->group->users,
+ bd->group->users > 8 ? "<<<<<<<" : "");
+}
+#else
+#define rtems_bdbuf_tracer (0)
+#define rtems_bdbuf_show_usage()
+#define rtems_bdbuf_show_users(_w, _b)
#endif
/**
@@ -332,7 +395,7 @@ rtems_bdbuf_avl_insert(rtems_bdbuf_buffer** root,
p = q;
}
-
+
q->avl.left = q->avl.right = NULL;
q->avl.bal = 0;
modified = true;
@@ -722,6 +785,23 @@ rtems_bdbuf_avl_remove(rtems_bdbuf_buffer** root,
}
/**
+ * Change the block number for the block size to the block number for the media
+ * block size. We have to use 64bit maths. There is no short cut here.
+ *
+ * @param block The logical block number in the block size terms.
+ * @param block_size The block size.
+ * @param media_block_size The block size of the media.
+ * @return rtems_blkdev_bnum The media block number.
+ */
+static rtems_blkdev_bnum
+rtems_bdbuf_media_block (rtems_blkdev_bnum block,
+ size_t block_size,
+ size_t media_block_size)
+{
+ return (((uint64_t) block) * block_size) / media_block_size;
+}
+
+/**
* Lock the mutex. A single task can nest calls.
*
* @param lock The mutex to lock.
@@ -837,7 +917,10 @@ rtems_bdbuf_wait (rtems_id* sema, volatile uint32_t* waiters)
*/
rtems_bdbuf_unlock_cache ();
- sc = rtems_semaphore_obtain (*sema, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ sc = rtems_semaphore_obtain (*sema, RTEMS_WAIT, RTEMS_BDBUF_WAIT_TIMEOUT);
+
+ if (sc == RTEMS_TIMEOUT)
+ rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CACHE_WAIT_TO);
if (sc != RTEMS_UNSATISFIED)
rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CACHE_WAIT_2);
@@ -962,26 +1045,30 @@ rtems_bdbuf_group_realloc (rtems_bdbuf_group* group, size_t new_bds_per_group)
int b;
size_t bufs_per_bd;
+ if (rtems_bdbuf_tracer)
+ printf ("bdbuf:realloc: %lu: %ld -> %ld\n",
+ group - bdbuf_cache.groups, group->bds_per_group,
+ new_bds_per_group);
+
bufs_per_bd = bdbuf_cache.max_bds_per_group / group->bds_per_group;
for (b = 0, bd = group->bdbuf;
b < group->bds_per_group;
b++, bd += bufs_per_bd)
{
- if ((bd->state == RTEMS_BDBUF_STATE_MODIFIED) ||
- (bd->state == RTEMS_BDBUF_STATE_ACCESS) ||
- (bd->state == RTEMS_BDBUF_STATE_ACCESS_MODIFIED) ||
- (bd->state == RTEMS_BDBUF_STATE_SYNC) ||
- (bd->state == RTEMS_BDBUF_STATE_TRANSFER))
- rtems_fatal_error_occurred ((bd->state << 16) |
- RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_8);
-
- if ((bd->state == RTEMS_BDBUF_STATE_CACHED) ||
- (bd->state == RTEMS_BDBUF_STATE_READ_AHEAD))
+ switch (bd->state)
{
- if (rtems_bdbuf_avl_remove (&bdbuf_cache.tree, bd) != 0)
+ case RTEMS_BDBUF_STATE_EMPTY:
+ break;
+ case RTEMS_BDBUF_STATE_CACHED:
+ case RTEMS_BDBUF_STATE_READ_AHEAD:
+ if (rtems_bdbuf_avl_remove (&bdbuf_cache.tree, bd) != 0)
+ rtems_fatal_error_occurred ((bd->state << 16) |
+ RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_1);
+ break;
+ default:
rtems_fatal_error_occurred ((bd->state << 16) |
- RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_1);
+ RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_8);
}
rtems_chain_extract (&bd->link);
@@ -1015,6 +1102,12 @@ rtems_bdbuf_get_next_bd (size_t bds_per_group,
{
rtems_bdbuf_buffer* bd = (rtems_bdbuf_buffer*) node;
+ if (rtems_bdbuf_tracer)
+ printf ("bdbuf:next-bd: %lu (%ld:%ld) %ld -> %ld\n",
+ bd - bdbuf_cache.bds,
+ bd->group - bdbuf_cache.groups, bd->group->users,
+ bd->group->bds_per_group, bds_per_group);
+
/*
* If this bd is already part of a group that supports the same number of
* BDs per group return it. If the bd is part of another group check the
@@ -1057,9 +1150,8 @@ rtems_bdbuf_init (void)
int cache_aligment;
rtems_status_code sc;
-#if RTEMS_BDBUF_TRACE
- rtems_bdbuf_printf ("init\n");
-#endif
+ if (rtems_bdbuf_tracer)
+ printf ("bdbuf:init\n");
/*
* Check the configuration table values.
@@ -1167,10 +1259,20 @@ rtems_bdbuf_init (void)
}
/*
+ * Compute the various number of elements in the cache.
+ */
+ bdbuf_cache.buffer_min_count =
+ bdbuf_config.size / bdbuf_config.buffer_min;
+ bdbuf_cache.max_bds_per_group =
+ bdbuf_config.buffer_max / bdbuf_config.buffer_min;
+ bdbuf_cache.group_count =
+ bdbuf_cache.buffer_min_count / bdbuf_cache.max_bds_per_group;
+
+ /*
* Allocate the memory for the buffer descriptors.
*/
bdbuf_cache.bds = calloc (sizeof (rtems_bdbuf_buffer),
- bdbuf_config.size / bdbuf_config.buffer_min);
+ bdbuf_cache.buffer_min_count);
if (!bdbuf_cache.bds)
{
rtems_semaphore_delete (bdbuf_cache.transfer);
@@ -1183,16 +1285,6 @@ rtems_bdbuf_init (void)
}
/*
- * Compute the various number of elements in the cache.
- */
- bdbuf_cache.buffer_min_count =
- bdbuf_config.size / bdbuf_config.buffer_min;
- bdbuf_cache.max_bds_per_group =
- bdbuf_config.buffer_max / bdbuf_config.buffer_min;
- bdbuf_cache.group_count =
- bdbuf_cache.buffer_min_count / bdbuf_cache.max_bds_per_group;
-
- /*
* Allocate the memory for the buffer descriptors.
*/
bdbuf_cache.groups = calloc (sizeof (rtems_bdbuf_group),
@@ -1213,6 +1305,8 @@ rtems_bdbuf_init (void)
* Allocate memory for buffer memory. The buffer memory will be cache
* aligned. It is possible to free the memory allocated by rtems_memalign()
* with free(). Return 0 if allocated.
+ *
+ * The memory allocate allows a
*/
if (rtems_memalign ((void **) &bdbuf_cache.buffers,
cache_aligment,
@@ -1247,6 +1341,8 @@ rtems_bdbuf_init (void)
bd->error = 0;
bd->waiters = 0;
bd->hold_timer = 0;
+ bd->references = 0;
+ bd->user = NULL;
rtems_chain_append (&bdbuf_cache.ready, &bd->link);
@@ -1444,10 +1540,20 @@ rtems_bdbuf_get_buffer (rtems_disk_device* dd,
if (bd)
{
/*
- * Remove the buffer from the AVL tree.
+ * Remove the buffer from the AVL tree if the state says it is in the
+ * cache or a read ahead buffer. The buffer could be in the empty
+ * state as a result of reallocations.
*/
- if (rtems_bdbuf_avl_remove (&bdbuf_cache.tree, bd) != 0)
- rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_2);
+ switch (bd->state)
+ {
+ case RTEMS_BDBUF_STATE_CACHED:
+ case RTEMS_BDBUF_STATE_READ_AHEAD:
+ if (rtems_bdbuf_avl_remove (&bdbuf_cache.tree, bd) != 0)
+ rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_2);
+ break;
+ default:
+ break;
+ }
}
else
{
@@ -1522,6 +1628,11 @@ rtems_bdbuf_get_buffer (rtems_disk_device* dd,
*/
if (bd->group->bds_per_group != bds_per_group)
{
+ /*
+ * Remove the buffer from the AVL tree.
+ */
+ if (rtems_bdbuf_avl_remove (&bdbuf_cache.tree, bd) != 0)
+ rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_2);
bd->state = RTEMS_BDBUF_STATE_EMPTY;
rtems_chain_extract (&bd->link);
rtems_chain_prepend (&bdbuf_cache.ready, &bd->link);
@@ -1533,7 +1644,8 @@ rtems_bdbuf_get_buffer (rtems_disk_device* dd,
/*
* If the buffer is for read ahead and it exists in the AVL cache or is being
- * accessed or being transfered then return NULL.
+ * accessed or being transfered then return NULL stopping further read ahead
+ * requests.
*/
if (read_ahead)
return NULL;
@@ -1556,16 +1668,14 @@ rtems_bdbuf_get_buffer (rtems_disk_device* dd,
case RTEMS_BDBUF_STATE_ACCESS:
case RTEMS_BDBUF_STATE_ACCESS_MODIFIED:
bd->waiters++;
- rtems_bdbuf_wait (&bdbuf_cache.access,
- &bdbuf_cache.access_waiters);
+ rtems_bdbuf_wait (&bdbuf_cache.access, &bdbuf_cache.access_waiters);
bd->waiters--;
break;
case RTEMS_BDBUF_STATE_SYNC:
case RTEMS_BDBUF_STATE_TRANSFER:
bd->waiters++;
- rtems_bdbuf_wait (&bdbuf_cache.transfer,
- &bdbuf_cache.transfer_waiters);
+ rtems_bdbuf_wait (&bdbuf_cache.transfer, &bdbuf_cache.transfer_waiters);
bd->waiters--;
break;
@@ -1589,6 +1699,7 @@ rtems_bdbuf_get (dev_t device,
{
rtems_disk_device* dd;
rtems_bdbuf_buffer* bd;
+ rtems_blkdev_bnum media_block;
size_t bds_per_group;
if (!bdbuf_cache.initialised)
@@ -1601,10 +1712,18 @@ rtems_bdbuf_get (dev_t device,
if (!dd)
return RTEMS_INVALID_ID;
- if (block >= dd->size)
+ /*
+ * Compute the media block number. Drivers work with media block number not
+ * the block number a BD may have as this depends on the block size set by
+ * the user.
+ */
+ media_block = rtems_bdbuf_media_block (block,
+ dd->block_size,
+ dd->media_block_size);
+ if (media_block >= dd->size)
{
- rtems_disk_release (dd);
- return RTEMS_INVALID_ADDRESS;
+ rtems_disk_release(dd);
+ return RTEMS_INVALID_NUMBER;
}
bds_per_group = rtems_bdbuf_bds_per_group (dd->block_size);
@@ -1613,26 +1732,43 @@ rtems_bdbuf_get (dev_t device,
rtems_disk_release (dd);
return RTEMS_INVALID_NUMBER;
}
-
+
+ media_block += dd->start;
+
rtems_bdbuf_lock_cache ();
-#if RTEMS_BDBUF_TRACE
- /* Print the block index relative to the physical disk */
- rtems_bdbuf_printf ("get: %d (dev = %08x)\n", block + dd->start, device);
-#endif
+ /*
+ * Print the block index relative to the physical disk.
+ */
+ if (rtems_bdbuf_tracer)
+ printf ("bdbuf:get: %lu (%lu) (dev = %08x)\n",
+ media_block, block, (unsigned int) device);
- bd = rtems_bdbuf_get_buffer (dd, bds_per_group, block + dd->start, false);
+ bd = rtems_bdbuf_get_buffer (dd, bds_per_group, media_block, false);
+ /*
+ * This could be considered a bug in the caller because you should not be
+ * getting an already modified buffer but user may have modified a byte in a
+ * block then decided to seek the start and write the whole block and the
+ * file system will have no record of this so just gets the block to fill.
+ */
if (bd->state == RTEMS_BDBUF_STATE_MODIFIED)
bd->state = RTEMS_BDBUF_STATE_ACCESS_MODIFIED;
else
+ {
bd->state = RTEMS_BDBUF_STATE_ACCESS;
-
- /*
- * Indicate a buffer in this group is being used.
- */
- bd->group->users++;
+ /*
+ * Indicate a buffer in this group is being used.
+ */
+ bd->group->users++;
+ }
+ if (rtems_bdbuf_tracer)
+ {
+ rtems_bdbuf_show_users ("get", bd);
+ rtems_bdbuf_show_usage ();
+ }
+
rtems_bdbuf_unlock_cache ();
rtems_disk_release(dd);
@@ -1673,6 +1809,8 @@ rtems_bdbuf_read (dev_t device,
uint32_t read_ahead_count;
rtems_blkdev_request* req;
size_t bds_per_group;
+ rtems_blkdev_bnum media_block;
+ rtems_blkdev_bnum media_block_count;
if (!bdbuf_cache.initialised)
return RTEMS_NOT_CONFIGURED;
@@ -1693,7 +1831,16 @@ rtems_bdbuf_read (dev_t device,
if (!dd)
return RTEMS_INVALID_ID;
- if (block >= dd->size) {
+ /*
+ * Compute the media block number. Drivers work with media block number not
+ * the block number a BD may have as this depends on the block size set by
+ * the user.
+ */
+ media_block = rtems_bdbuf_media_block (block,
+ dd->block_size,
+ dd->media_block_size);
+ if (media_block >= dd->size)
+ {
rtems_disk_release(dd);
return RTEMS_INVALID_NUMBER;
}
@@ -1705,12 +1852,13 @@ rtems_bdbuf_read (dev_t device,
return RTEMS_INVALID_NUMBER;
}
-#if RTEMS_BDBUF_TRACE
- /* Print the block index relative to the physical disk */
- rtems_bdbuf_printf ("read: %d (dev = %08x)\n", block + dd->start, device);
-#endif
-
- req->bufnum = 0;
+ /*
+ * Print the block index relative to the physical disk and the user block
+ * number
+ */
+ if (rtems_bdbuf_tracer)
+ printf ("bdbuf:read: %lu (%lu) (dev = %08x)\n",
+ media_block + dd->start, block, (unsigned int) device);
/*
* Read the block plus the required number of blocks ahead. The number of
@@ -1719,10 +1867,14 @@ rtems_bdbuf_read (dev_t device,
*
* Limit the blocks read by the size of the disk.
*/
- if ((rtems_bdbuf_configuration.max_read_ahead_blocks + block) < dd->size)
+ if ((rtems_bdbuf_configuration.max_read_ahead_blocks + media_block) < dd->size)
read_ahead_count = rtems_bdbuf_configuration.max_read_ahead_blocks;
else
- read_ahead_count = dd->size - block;
+ read_ahead_count = dd->size - media_block;
+
+ media_block_count = dd->block_size / dd->media_block_size;
+
+ req->bufnum = 0;
rtems_bdbuf_lock_cache ();
@@ -1736,8 +1888,7 @@ rtems_bdbuf_read (dev_t device,
* We need to clean up any buffers allocated and not passed back to the
* caller.
*/
- bd = rtems_bdbuf_get_buffer (dd, bds_per_group,
- block + dd->start + req->bufnum,
+ bd = rtems_bdbuf_get_buffer (dd, bds_per_group, media_block + dd->start,
req->bufnum == 0 ? false : true);
/*
@@ -1761,6 +1912,9 @@ rtems_bdbuf_read (dev_t device,
* The buffer will be passed to the driver so this buffer has a user.
*/
bd->group->users++;
+
+ if (rtems_bdbuf_tracer)
+ rtems_bdbuf_show_users ("reading", bd);
/*
* @todo The use of these req blocks is not a great design. The req is a
@@ -1771,10 +1925,16 @@ rtems_bdbuf_read (dev_t device,
* node that can be used.
*/
req->bufs[req->bufnum].user = bd;
- req->bufs[req->bufnum].block = bd->block;
+ req->bufs[req->bufnum].block = media_block + dd->start;
req->bufs[req->bufnum].length = dd->block_size;
req->bufs[req->bufnum].buffer = bd->buffer;
req->bufnum++;
+
+ /*
+ * Move the media block count by the number of media blocks in the
+ * disk device's set block size.
+ */
+ media_block += media_block_count;
}
/*
@@ -1797,6 +1957,7 @@ rtems_bdbuf_read (dev_t device,
rtems_event_set out;
int result;
uint32_t b;
+ bool wake_transfer;
/*
* Flush any events.
@@ -1837,20 +1998,27 @@ rtems_bdbuf_read (dev_t device,
rtems_fatal_error_occurred (BLKDEV_FATAL_BDBUF_SWAPOUT_RE);
}
+ wake_transfer = false;
+
rtems_bdbuf_lock_cache ();
for (b = 1; b < req->bufnum; b++)
{
bd = req->bufs[b].user;
- bd->error = req->error;
+ if (!bd->error)
+ bd->error = req->error;
bd->state = RTEMS_BDBUF_STATE_READ_AHEAD;
bd->group->users--;
+
+ if (rtems_bdbuf_tracer)
+ rtems_bdbuf_show_users ("read-ahead", bd);
+
rtems_chain_prepend (&bdbuf_cache.ready, &bd->link);
/*
- * If there is an error remove the BD from the AVL tree as it does is
- * invalid, then wake any threads that may be waiting. A thread may have
- * been waiting for this block and assumed it was in the tree.
+ * If there is an error remove the BD from the AVL tree as it is invalid,
+ * then wake any threads that may be waiting. A thread may have been
+ * waiting for this block and assumed it was in the tree.
*/
if (bd->error)
{
@@ -1860,22 +2028,26 @@ rtems_bdbuf_read (dev_t device,
}
if (bd->waiters)
- rtems_bdbuf_wake (bdbuf_cache.access, &bdbuf_cache.access_waiters);
- else
- {
- if (rtems_chain_has_only_one_node (&bdbuf_cache.ready))
- rtems_bdbuf_wake (bdbuf_cache.waiting, &bdbuf_cache.wait_waiters);
- }
+ wake_transfer = true;
}
+ if (wake_transfer)
+ rtems_bdbuf_wake (bdbuf_cache.transfer, &bdbuf_cache.transfer_waiters);
+ else
+ rtems_bdbuf_wake (bdbuf_cache.waiting, &bdbuf_cache.wait_waiters);
+
bd = req->bufs[0].user;
/*
- * One less user. We do this here then increment again so the case of the
- * buffer in the the cache and no read leaves the user counts at the
- * correct level.
+ * One less user for the BD we return. The loop above is only for the read
+ * head buffers. We do this here then increment again so the case of the
+ * buffer in the cache or modified and no read leaves the user counts at
+ * the correct level.
*/
bd->group->users--;
+
+ if (rtems_bdbuf_tracer)
+ rtems_bdbuf_show_users ("read-done", bd);
}
/*
@@ -1892,6 +2064,12 @@ rtems_bdbuf_read (dev_t device,
bd->state = RTEMS_BDBUF_STATE_ACCESS;
}
+ if (rtems_bdbuf_tracer)
+ {
+ rtems_bdbuf_show_users ("read", bd);
+ rtems_bdbuf_show_usage ();
+ }
+
rtems_bdbuf_unlock_cache ();
rtems_disk_release (dd);
@@ -1911,9 +2089,8 @@ rtems_bdbuf_release (rtems_bdbuf_buffer* bd)
rtems_bdbuf_lock_cache ();
-#if RTEMS_BDBUF_TRACE
- rtems_bdbuf_printf ("release: %d\n", bd->block);
-#endif
+ if (rtems_bdbuf_tracer)
+ printf ("bdbuf:release: %lu\n", bd->block);
if (bd->state == RTEMS_BDBUF_STATE_ACCESS_MODIFIED)
{
@@ -1921,18 +2098,8 @@ rtems_bdbuf_release (rtems_bdbuf_buffer* bd)
}
else
{
- /*
- * If this is a read ahead buffer place the ready queue. Buffers are taken
- * from here first. If we prepend then get from the queue the buffers
- * furthermost from the read buffer will be used.
- */
- if (bd->state == RTEMS_BDBUF_STATE_READ_AHEAD)
- rtems_chain_prepend (&bdbuf_cache.ready, &bd->link);
- else
- {
- bd->state = RTEMS_BDBUF_STATE_CACHED;
- rtems_chain_append (&bdbuf_cache.lru, &bd->link);
- }
+ bd->state = RTEMS_BDBUF_STATE_CACHED;
+ rtems_chain_append (&bdbuf_cache.lru, &bd->link);
/*
* One less user for the group of bds.
@@ -1940,25 +2107,20 @@ rtems_bdbuf_release (rtems_bdbuf_buffer* bd)
bd->group->users--;
}
+ if (rtems_bdbuf_tracer)
+ rtems_bdbuf_show_users ("release", bd);
+
/*
* If there are threads waiting to access the buffer wake them. Wake any
- * waiters if this is the first buffer to placed back onto the queue.
+ * waiters if this buffer is placed back onto the LRU queue.
*/
if (bd->waiters)
rtems_bdbuf_wake (bdbuf_cache.access, &bdbuf_cache.access_waiters);
else
- {
- if (bd->state == RTEMS_BDBUF_STATE_READ_AHEAD)
- {
- if (rtems_chain_has_only_one_node (&bdbuf_cache.ready))
- rtems_bdbuf_wake (bdbuf_cache.waiting, &bdbuf_cache.wait_waiters);
- }
- else
- {
- if (rtems_chain_has_only_one_node (&bdbuf_cache.lru))
- rtems_bdbuf_wake (bdbuf_cache.waiting, &bdbuf_cache.wait_waiters);
- }
- }
+ rtems_bdbuf_wake (bdbuf_cache.waiting, &bdbuf_cache.wait_waiters);
+
+ if (rtems_bdbuf_tracer)
+ rtems_bdbuf_show_usage ();
rtems_bdbuf_unlock_cache ();
@@ -1976,17 +2138,22 @@ rtems_bdbuf_release_modified (rtems_bdbuf_buffer* bd)
rtems_bdbuf_lock_cache ();
-#if RTEMS_BDBUF_TRACE
- rtems_bdbuf_printf ("release modified: %d\n", bd->block);
-#endif
+ if (rtems_bdbuf_tracer)
+ printf ("bdbuf:release modified: %lu\n", bd->block);
bd->hold_timer = rtems_bdbuf_configuration.swap_block_hold;
+ if (rtems_bdbuf_tracer)
+ rtems_bdbuf_show_users ("release-modified", bd);
+
rtems_bdbuf_append_modified (bd);
if (bd->waiters)
rtems_bdbuf_wake (bdbuf_cache.access, &bdbuf_cache.access_waiters);
+ if (rtems_bdbuf_tracer)
+ rtems_bdbuf_show_usage ();
+
rtems_bdbuf_unlock_cache ();
return RTEMS_SUCCESSFUL;
@@ -1997,9 +2164,8 @@ rtems_bdbuf_sync (rtems_bdbuf_buffer* bd)
{
bool available;
-#if RTEMS_BDBUF_TRACE
- rtems_bdbuf_printf ("sync: %d\n", bd->block);
-#endif
+ if (rtems_bdbuf_tracer)
+ printf ("bdbuf:sync: %lu\n", bd->block);
if (!bdbuf_cache.initialised)
return RTEMS_NOT_CONFIGURED;
@@ -2031,8 +2197,7 @@ rtems_bdbuf_sync (rtems_bdbuf_buffer* bd)
case RTEMS_BDBUF_STATE_SYNC:
case RTEMS_BDBUF_STATE_TRANSFER:
bd->waiters++;
- rtems_bdbuf_wait (&bdbuf_cache.transfer,
- &bdbuf_cache.transfer_waiters);
+ rtems_bdbuf_wait (&bdbuf_cache.transfer, &bdbuf_cache.transfer_waiters);
bd->waiters--;
break;
@@ -2053,9 +2218,8 @@ rtems_bdbuf_syncdev (dev_t dev)
rtems_status_code sc;
rtems_event_set out;
-#if RTEMS_BDBUF_TRACE
- rtems_bdbuf_printf ("syncdev: %08x\n", dev);
-#endif
+ if (rtems_bdbuf_tracer)
+ printf ("bdbuf:syncdev: %08x\n", (unsigned int) dev);
if (!bdbuf_cache.initialised)
return RTEMS_NOT_CONFIGURED;
@@ -2105,7 +2269,7 @@ rtems_bdbuf_syncdev (dev_t dev)
/**
* Call back handler called by the low level driver when the transfer has
- * completed. This function may be invoked from interrupt handler.
+ * completed. This function may be invoked from interrupt handlers.
*
* @param arg Arbitrary argument specified in block device request
* structure (in this case - pointer to the appropriate
@@ -2134,11 +2298,10 @@ rtems_bdbuf_write_done(void *arg, rtems_status_code status, int error)
static void
rtems_bdbuf_swapout_write (rtems_bdbuf_swapout_transfer* transfer)
{
- rtems_disk_device* dd;
+ rtems_disk_device* dd;
-#if RTEMS_BDBUF_TRACE
- rtems_bdbuf_printf ("swapout transfer: %08x\n", transfer->dev);
-#endif
+ if (rtems_bdbuf_tracer)
+ printf ("bdbuf:swapout transfer: %08x\n", (unsigned int) transfer->dev);
/*
* If there are buffers to transfer to the media transfer them.
@@ -2157,6 +2320,12 @@ rtems_bdbuf_swapout_write (rtems_bdbuf_swapout_transfer* transfer)
* continuous blocks in a single request.
*/
uint32_t last_block = 0;
+
+ /*
+ * Number of buffers per bd. This is used to detect the next
+ * block.
+ */
+ uint32_t bufs_per_bd = dd->block_size / bdbuf_config.buffer_min;
/*
* Take as many buffers as configured and pass to the driver. Note, the
@@ -2185,16 +2354,15 @@ rtems_bdbuf_swapout_write (rtems_bdbuf_swapout_transfer* transfer)
* the committed buffers.
*/
-#if RTEMS_BDBUF_TRACE
- rtems_bdbuf_printf ("swapout write: bd:%d, bufnum:%d mode:%s\n",
- bd->block, transfer->write_req->bufnum,
- dd->phys_dev->capabilities &
- RTEMS_BLKDEV_CAP_MULTISECTOR_CONT ? "MULIT" : "SCAT");
-#endif
-
+ if (rtems_bdbuf_tracer)
+ printf ("bdbuf:swapout write: bd:%lu, bufnum:%lu mode:%s\n",
+ bd->block, transfer->write_req->bufnum,
+ dd->phys_dev->capabilities &
+ RTEMS_BLKDEV_CAP_MULTISECTOR_CONT ? "MULIT" : "SCAT");
+
if ((dd->phys_dev->capabilities & RTEMS_BLKDEV_CAP_MULTISECTOR_CONT) &&
transfer->write_req->bufnum &&
- (bd->block != (last_block + 1)))
+ (bd->block != (last_block + bufs_per_bd)))
{
rtems_chain_prepend (&transfer->bds, &bd->link);
write = true;
@@ -2225,10 +2393,10 @@ rtems_bdbuf_swapout_write (rtems_bdbuf_swapout_transfer* transfer)
int result;
uint32_t b;
-#if RTEMS_BDBUF_TRACE
- rtems_bdbuf_printf ("swapout write: writing bufnum:%d\n",
- transfer->write_req->bufnum);
-#endif
+ if (rtems_bdbuf_tracer)
+ printf ("bdbuf:swapout write: writing bufnum:%lu\n",
+ transfer->write_req->bufnum);
+
/*
* Perform the transfer. No cache locks, no preemption, only the disk
* device is being held.
@@ -2279,19 +2447,22 @@ rtems_bdbuf_swapout_write (rtems_bdbuf_swapout_transfer* transfer)
* The buffer is now not modified so lower the user count for the group.
*/
bd->group->users--;
-
+
+ if (rtems_bdbuf_tracer)
+ rtems_bdbuf_show_users ("write", bd);
+
rtems_chain_append (&bdbuf_cache.lru, &bd->link);
if (bd->waiters)
rtems_bdbuf_wake (bdbuf_cache.transfer, &bdbuf_cache.transfer_waiters);
else
- {
- if (rtems_chain_has_only_one_node (&bdbuf_cache.lru))
- rtems_bdbuf_wake (bdbuf_cache.waiting, &bdbuf_cache.wait_waiters);
- }
+ rtems_bdbuf_wake (bdbuf_cache.waiting, &bdbuf_cache.wait_waiters);
}
}
-
+
+ if (rtems_bdbuf_tracer)
+ rtems_bdbuf_show_usage ();
+
rtems_bdbuf_unlock_cache ();
transfer->write_req->status = RTEMS_RESOURCE_IN_USE;
@@ -2451,11 +2622,11 @@ rtems_bdbuf_swapout_processing (unsigned long timer_delta,
/*
* If a sync is active do not use a worker because the current code does not
* cleaning up after. We need to know the buffers have been written when
- * syncing to release sync lock and currently worker threads do not return to
- * here. We do not know the worker is the last in a sequence of sync writes
- * until after we have it running so we do not know to tell it to release the
- * lock. The simplest solution is to get the main swap out task perform all
- * sync operations.
+ * syncing to the release sync lock and currently worker threads do not
+ * return to here. We do not know the worker is the last in a sequence of
+ * sync writes until after we have it running so we do not know to tell it to
+ * release the lock. The simplest solution is to get the main swap out task
+ * perform all sync operations.
*/
if (bdbuf_cache.sync_active)
worker = NULL;
diff --git a/cpukit/libblock/src/blkdev.c b/cpukit/libblock/src/blkdev.c
index 0411d47dba..8f0ceb6e7a 100644
--- a/cpukit/libblock/src/blkdev.c
+++ b/cpukit/libblock/src/blkdev.c
@@ -263,6 +263,7 @@ rtems_blkdev_ioctl(dev_t dev, uint32_t req, void *argp)
{
rtems_disk_device *dd;
size_t *arg_size = argp;
+ int rc = 0;
dd = rtems_disk_obtain(dev);
if (dd == NULL)
@@ -291,11 +292,11 @@ rtems_blkdev_ioctl(dev_t dev, uint32_t req, void *argp)
default:
errno = EINVAL;
- return -1;
+ rc = -1;
break;
}
rtems_disk_release(dd);
- return 0;
+ return rc;
}
diff --git a/cpukit/libblock/src/diskdevs.c b/cpukit/libblock/src/diskdevs.c
index 9d044bec69..c5599e873c 100644
--- a/cpukit/libblock/src/diskdevs.c
+++ b/cpukit/libblock/src/diskdevs.c
@@ -314,7 +314,7 @@ rtems_status_code rtems_disk_create_log(
dd->uses = 0;
dd->start = start;
dd->size = size;
- dd->block_size = pdd->block_size;
+ dd->block_size = dd->media_block_size = pdd->block_size;
dd->ioctl = pdd->ioctl;
rc = rtems_io_register_name(name, major, minor);
diff --git a/cpukit/libblock/src/flashdisk.c b/cpukit/libblock/src/flashdisk.c
index 56077f4d45..743de32432 100644
--- a/cpukit/libblock/src/flashdisk.c
+++ b/cpukit/libblock/src/flashdisk.c
@@ -2053,26 +2053,22 @@ static int
rtems_fdisk_read (rtems_flashdisk* fd, rtems_blkdev_request* req)
{
rtems_blkdev_sg_buffer* sg = req->bufs;
- uint32_t b;
+ uint32_t buf;
int ret = 0;
- for (b = 0; b < req->bufnum; b++, sg++)
+ for (buf = 0; (ret == 0) && (buf < req->bufnum); buf++, sg++)
{
- uint32_t length = sg->length;
-
- if (sg->length != fd->block_size)
+ uint8_t* data;
+ uint32_t fb;
+ uint32_t b;
+ fb = sg->length / fd->block_size;
+ data = sg->buffer;
+ for (b = 0; b < fb; b++, data += fd->block_size)
{
- rtems_fdisk_error ("fdisk-read: length is not the block size: "\
- "bd:%d fd:%d", sg->length, fd->block_size);
-
- if (length > fd->block_size)
- length = fd->block_size;
+ ret = rtems_fdisk_read_block (fd, sg->block + b, data);
+ if (ret)
+ break;
}
-
- ret = rtems_fdisk_read_block (fd, sg->block, sg->buffer);
-
- if (ret)
- break;
}
req->req_done (req->done_arg,
@@ -2093,21 +2089,22 @@ static int
rtems_fdisk_write (rtems_flashdisk* fd, rtems_blkdev_request* req)
{
rtems_blkdev_sg_buffer* sg = req->bufs;
- uint32_t b;
+ uint32_t buf;
int ret = 0;
- for (b = 0; b < req->bufnum; b++, sg++)
+ for (buf = 0; (ret == 0) && (buf < req->bufnum); buf++, sg++)
{
- if (sg->length != fd->block_size)
+ uint8_t* data;
+ uint32_t fb;
+ uint32_t b;
+ fb = sg->length / fd->block_size;
+ data = sg->buffer;
+ for (b = 0; b < fb; b++, data += fd->block_size)
{
- rtems_fdisk_error ("fdisk-write: length is not the block size: " \
- "bd:%d fd:%d", sg->length, fd->block_size);
+ ret = rtems_fdisk_write_block (fd, sg->block + b, data);
+ if (ret)
+ break;
}
-
- ret = rtems_fdisk_write_block (fd, sg->block, sg->buffer);
-
- if (ret)
- break;
}
req->req_done (req->done_arg,
@@ -2357,6 +2354,7 @@ rtems_fdisk_ioctl (dev_t dev, uint32_t req, void* argp)
errno = EIO;
else
{
+ errno = 0;
switch (req)
{
case RTEMS_BLKIO_REQUEST:
@@ -2410,7 +2408,7 @@ rtems_fdisk_ioctl (dev_t dev, uint32_t req, void* argp)
break;
default:
- return rtems_blkdev_ioctl (dev, req, argp);
+ rtems_blkdev_ioctl (dev, req, argp);
break;
}
diff --git a/cpukit/libblock/src/nvdisk.c b/cpukit/libblock/src/nvdisk.c
index 3776e92d29..005e846746 100644
--- a/cpukit/libblock/src/nvdisk.c
+++ b/cpukit/libblock/src/nvdisk.c
@@ -573,38 +573,26 @@ static int
rtems_nvdisk_read (rtems_nvdisk* nvd, rtems_blkdev_request* req)
{
rtems_blkdev_sg_buffer* sg = req->bufs;
- uint32_t b;
- int32_t remains;
+ uint32_t bufs;
int ret = 0;
#if RTEMS_NVDISK_TRACE
rtems_nvdisk_info (nvd, "read: blocks=%d", req->bufnum);
#endif
- remains = req->bufnum * nvd->block_size;
-
- for (b = 0; b < req->bufnum; b++, sg++)
+ for (bufs = 0; (ret == 0) && (bufs < req->bufnum); bufs++, sg++)
{
- uint32_t length = sg->length;
-
- if (remains <= 0)
- rtems_nvdisk_error ("nvdisk-read: remains size <= 0");
-
- if (sg->length != nvd->block_size)
+ uint8_t* data;
+ uint32_t nvb;
+ uint32_t b;
+ nvb = sg->length / nvd->block_size;
+ data = sg->buffer;
+ for (b = 0; b < nvb; b++, data += nvd->block_size)
{
- rtems_nvdisk_error ("nvdisk-read: length is not the block size: "\
- "bd:%d nvd:%d", sg->length, nvd->block_size);
-
- if (length > nvd->block_size)
- length = nvd->block_size;
+ ret = rtems_nvdisk_read_block (nvd, sg->block + b, data);
+ if (ret)
+ break;
}
-
- ret = rtems_nvdisk_read_block (nvd, sg->block, sg->buffer);
-
- if (ret)
- break;
-
- remains -= length;
}
req->req_done (req->done_arg,
@@ -625,25 +613,26 @@ static int
rtems_nvdisk_write (rtems_nvdisk* nvd, rtems_blkdev_request* req)
{
rtems_blkdev_sg_buffer* sg = req->bufs;
- uint32_t b;
+ uint32_t bufs;
int ret = 0;
#if RTEMS_NVDISK_TRACE
rtems_nvdisk_info (nvd, "write: blocks=%d", req->bufnum);
#endif
- for (b = 0; b < req->bufnum; b++, sg++)
+ for (bufs = 0; (ret == 0) && (bufs < req->bufnum); bufs++, sg++)
{
- if (sg->length != nvd->block_size)
+ uint8_t* data;
+ uint32_t nvb;
+ uint32_t b;
+ nvb = sg->length / nvd->block_size;
+ data = sg->buffer;
+ for (b = 0; b < nvb; b++, data += nvd->block_size)
{
- rtems_nvdisk_error ("nvdisk-write: length is not the block size: " \
- "bd:%d nvd:%d", sg->length, nvd->block_size);
+ ret = rtems_nvdisk_write_block (nvd, sg->block + b, data);
+ if (ret)
+ break;
}
-
- ret = rtems_nvdisk_write_block (nvd, sg->block, sg->buffer);
-
- if (ret)
- break;
}
req->req_done (req->done_arg,
@@ -716,6 +705,7 @@ rtems_nvdisk_ioctl (dev_t dev, uint32_t req, void* argp)
errno = EIO;
else
{
+ errno = 0;
switch (req)
{
case RTEMS_BLKIO_REQUEST:
@@ -744,7 +734,7 @@ rtems_nvdisk_ioctl (dev_t dev, uint32_t req, void* argp)
break;
default:
- return rtems_blkdev_ioctl (dev, req, argp);
+ rtems_blkdev_ioctl (dev, req, argp);
break;
}
diff --git a/cpukit/libblock/src/ramdisk.c b/cpukit/libblock/src/ramdisk.c
index faa5fef57b..98180923a7 100644
--- a/cpukit/libblock/src/ramdisk.c
+++ b/cpukit/libblock/src/ramdisk.c
@@ -41,7 +41,7 @@
/* Internal RAM disk descriptor */
struct ramdisk {
- uint32_t block_size; /* RAM disk block size */
+ uint32_t block_size; /* RAM disk block size, the media size */
rtems_blkdev_bnum block_num; /* Number of blocks on this RAM disk */
void *area; /* RAM disk memory area */
bool initialized; /* RAM disk is initialized */
@@ -94,28 +94,23 @@ rtems_ramdisk_printf (struct ramdisk *rd, const char *format, ...)
static int
ramdisk_read(struct ramdisk *rd, rtems_blkdev_request *req)
{
- char *from;
+ uint8_t *from = rd->area;
uint32_t i;
rtems_blkdev_sg_buffer *sg;
- uint32_t remains;
#if RTEMS_RAMDISK_TRACE
- rtems_ramdisk_printf (rd, "ramdisk read: start=%d, blocks=%d remains=%d",
- req->bufs[0].block, req->bufnum,
- rd->block_size * req->count);
+ rtems_ramdisk_printf (rd, "ramdisk read: start=%d, blocks=%d",
+ req->bufs[0].block, req->bufnum);
#endif
- remains = rd->block_size * req->bufnum;
- sg = req->bufs;
- for (i = 0; (remains > 0) && (i < req->bufnum); i++, sg++)
+ for (i = 0, sg = req->bufs; i < req->bufnum; i++, sg++)
{
- uint32_t count = sg->length;
- from = ((char *)rd->area + (sg->block * rd->block_size));
- if (count > remains)
- count = remains;
- memcpy(sg->buffer, from, count);
- remains -= count;
- from += count;
+#if RTEMS_RAMDISK_TRACE
+ rtems_ramdisk_printf (rd, "ramdisk read: buf=%d block=%d length=%d off=%d addr=%p",
+ i, sg->block, sg->length, sg->block * rd->block_size,
+ from + (sg->block * rd->block_size));
+#endif
+ memcpy(sg->buffer, from + (sg->block * rd->block_size), sg->length);
}
req->req_done(req->done_arg, RTEMS_SUCCESSFUL, 0);
return 0;
@@ -135,27 +130,22 @@ ramdisk_read(struct ramdisk *rd, rtems_blkdev_request *req)
static int
ramdisk_write(struct ramdisk *rd, rtems_blkdev_request *req)
{
- char *to;
+ uint8_t *to = rd->area;
uint32_t i;
rtems_blkdev_sg_buffer *sg;
- uint32_t remains;
#if RTEMS_RAMDISK_TRACE
- rtems_ramdisk_printf (rd, "ramdisk write: start=%d, blocks=%d remains=%d",
- req->bufs[0].block, req->bufnum,
- rd->block_size * req->bufnum);
+ rtems_ramdisk_printf (rd, "ramdisk write: start=%d, blocks=%d",
+ req->bufs[0].block, req->bufnum);
#endif
- remains = rd->block_size * req->bufnum;
- sg = req->bufs;
- for (i = 0; (remains > 0) && (i < req->bufnum); i++, sg++)
+ for (i = 0, sg = req->bufs; i < req->bufnum; i++, sg++)
{
- uint32_t count = sg->length;
- to = ((char *)rd->area + (sg->block * rd->block_size));
- if (count > remains)
- count = remains;
- memcpy(to, sg->buffer, count);
- remains -= count;
- to += count;
+#if RTEMS_RAMDISK_TRACE
+ rtems_ramdisk_printf (rd, "ramdisk write: buf=%d block=%d length=%d off=%d addr=%p",
+ i, sg->block, sg->length, sg->block * rd->block_size,
+ to + (sg->block * rd->block_size));
+#endif
+ memcpy(to + (sg->block * rd->block_size), sg->buffer, sg->length);
}
req->req_done(req->done_arg, RTEMS_SUCCESSFUL, 0);
return 0;
diff --git a/cpukit/libcsupport/Makefile.am b/cpukit/libcsupport/Makefile.am
index 40c46f0847..ef66d121ae 100644
--- a/cpukit/libcsupport/Makefile.am
+++ b/cpukit/libcsupport/Makefile.am
@@ -62,7 +62,7 @@ SYSTEM_CALL_C_FILES = src/open.c src/close.c src/read.c src/write.c \
src/link.c src/unlink.c src/umask.c src/ftruncate.c src/utime.c src/fstat.c \
src/fcntl.c src/fpathconf.c src/getdents.c src/fsync.c src/fdatasync.c \
src/pipe.c src/dup.c src/dup2.c src/symlink.c src/readlink.c src/creat.c \
- src/chroot.c src/sync.c src/_rename_r.c
+ src/chroot.c src/sync.c src/_rename_r.c src/statvfs.c
## Until sys/uio.h is moved to libcsupport, we have to have networking
## enabled to compile these. Hopefully this is a temporary situation.
diff --git a/cpukit/libcsupport/include/rtems/libio.h b/cpukit/libcsupport/include/rtems/libio.h
index 44e8b59267..e89427fa2e 100644
--- a/cpukit/libcsupport/include/rtems/libio.h
+++ b/cpukit/libcsupport/include/rtems/libio.h
@@ -28,6 +28,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
+#include <sys/statvfs.h>
/*
* Define data types which must be constructed using forward references.
@@ -250,6 +251,11 @@ typedef int (*rtems_filesystem_readlink_t)(
size_t bufsize
);
+typedef int (*rtems_filesystem_statvfs_t)(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ struct statvfs *buf /* OUT */
+);
+
/*
* operations table that must be defined for every file system.
*/
@@ -274,6 +280,7 @@ struct _rtems_filesystem_operations_table {
rtems_filesystem_evaluate_link_t eval_link_h;
rtems_filesystem_symlink_t symlink_h;
rtems_filesystem_readlink_t readlink_h;
+ rtems_filesystem_statvfs_t statvfs_h;
};
#if 0
diff --git a/cpukit/libcsupport/include/sys/statvfs.h b/cpukit/libcsupport/include/sys/statvfs.h
new file mode 100644
index 0000000000..1ef210a702
--- /dev/null
+++ b/cpukit/libcsupport/include/sys/statvfs.h
@@ -0,0 +1,45 @@
+/*
+ * COPYRIGHT (c) 2009 Chris Johns <chrisj@rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+/*
+ * The statvfs as defined by the SUS:
+ * http://www.opengroup.org/onlinepubs/009695399/basedefs/sys/statvfs.h.html
+ */
+
+#ifndef _SYS_STATVFS_H_
+#define _SYS_STATVFS_H_
+
+#include <sys/cdefs.h>
+#include <stdint.h>
+
+typedef uint64_t fsblkcnt_t;
+typedef uint32_t fsfilcnt_t;
+
+struct statvfs
+{
+ unsigned long f_bsize; /**< File system block size. */
+ unsigned long f_frsize; /**< Fundamental file system block size. */
+ fsblkcnt_t f_blocks; /**< Total number of blocks on file system in units
+ * of f_frsize. */
+ fsblkcnt_t f_bfree; /**< Total number of free blocks. */
+ fsblkcnt_t f_bavail; /**< Number of free blocks available to
+ * non-privileged process. */
+ fsfilcnt_t f_files; /**< Total number of file serial numbers. */
+ fsfilcnt_t f_ffree; /**< Total number of free file serial numbers. */
+ fsfilcnt_t f_favail; /**< Number of file serial numbers available to
+ * non-privileged process. */
+ unsigned long f_fsid; /**< File system ID. */
+ unsigned long f_flag; /**< Bit mask of f_flag values. */
+ unsigned long f_namemax; /**< Maximum filename length. */
+};
+
+int statvfs(const char *, struct statvfs *);
+int fstatvfs(int, struct statvfs *);
+
+#endif
diff --git a/cpukit/libcsupport/src/statvfs.c b/cpukit/libcsupport/src/statvfs.c
new file mode 100644
index 0000000000..bd6827fe76
--- /dev/null
+++ b/cpukit/libcsupport/src/statvfs.c
@@ -0,0 +1,60 @@
+/*
+ * COPYRIGHT (c) 2009 Chris Johns <chrisj@rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+/*
+ * The statvfs as defined by the SUS:
+ * http://www.opengroup.org/onlinepubs/009695399/basedefs/sys/statvfs.h.html
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+#include <sys/statvfs.h>
+
+/*
+ * Data structures and routines private to mount/unmount pair.
+ */
+extern rtems_chain_control rtems_filesystem_mount_table_control;
+
+int
+statvfs (const char *path, struct statvfs *sb)
+{
+ rtems_filesystem_location_info_t loc;
+ rtems_filesystem_location_info_t *fs_mount_root;
+ rtems_filesystem_mount_table_entry_t *mt_entry;
+ int result;
+
+ /*
+ * Get
+ * The root node of the mounted filesytem.
+ * The node for the directory that the fileystem is mounted on.
+ * The mount entry that is being refered to.
+ */
+
+ if ( rtems_filesystem_evaluate_path( path, strlen( path ), 0x0, &loc, true ) )
+ return -1;
+
+ mt_entry = loc.mt_entry;
+ fs_mount_root = &mt_entry->mt_fs_root;
+
+ if ( !fs_mount_root->ops->statvfs_h )
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+
+ memset (sb, 0, sizeof (struct statvfs));
+
+ result = ( fs_mount_root->ops->statvfs_h )( fs_mount_root, sb );
+
+ rtems_filesystem_freenode( &loc );
+
+ return result;
+}
diff --git a/cpukit/libfs/src/devfs/devfs_init.c b/cpukit/libfs/src/devfs/devfs_init.c
index c98ac113cb..b0ebcf803a 100644
--- a/cpukit/libfs/src/devfs/devfs_init.c
+++ b/cpukit/libfs/src/devfs/devfs_init.c
@@ -33,6 +33,7 @@ rtems_filesystem_operations_table devFS_ops =
NULL,
NULL,
NULL,
+ NULL,
NULL
};
diff --git a/cpukit/libfs/src/dosfs/fat.c b/cpukit/libfs/src/dosfs/fat.c
index 26682dc6dd..0c30053a72 100644
--- a/cpukit/libfs/src/dosfs/fat.c
+++ b/cpukit/libfs/src/dosfs/fat.c
@@ -264,6 +264,24 @@ _fat_block_write(
return cmpltd;
}
+/* _fat_block_release --
+ * This function works around the hack that hold a bdbuf and does
+ * not release it.
+ *
+ * PARAMETERS:
+ * mt_entry - mount table entry
+ *
+ * RETURNS:
+ * 0 on success, or -1 if error occured and errno set appropriately
+ */
+int
+_fat_block_release(
+ rtems_filesystem_mount_table_entry_t *mt_entry)
+{
+ fat_fs_info_t *fs_info = mt_entry->fs_info;
+ return fat_buf_release(fs_info);
+}
+
/* fat_cluster_read --
* wrapper for reading a whole cluster at once
*
@@ -504,6 +522,7 @@ fat_init_volume_info(rtems_filesystem_mount_table_entry_t *mt_entry)
if (FAT_GET_FSINFO_LEAD_SIGNATURE(fs_info_sector) !=
FAT_FSINFO_LEAD_SIGNATURE_VALUE)
{
+ _fat_block_release(mt_entry);
rtems_disk_release(vol->dd);
rtems_set_errno_and_return_minus_one( EINVAL );
}
@@ -513,6 +532,7 @@ fat_init_volume_info(rtems_filesystem_mount_table_entry_t *mt_entry)
FAT_USEFUL_INFO_SIZE, fs_info_sector);
if ( ret < 0 )
{
+ _fat_block_release(mt_entry);
rtems_disk_release(vol->dd);
return -1;
}
@@ -523,6 +543,7 @@ fat_init_volume_info(rtems_filesystem_mount_table_entry_t *mt_entry)
0xFFFFFFFF);
if ( rc != RC_OK )
{
+ _fat_block_release(mt_entry);
rtems_disk_release(vol->dd);
return rc;
}
@@ -537,6 +558,9 @@ fat_init_volume_info(rtems_filesystem_mount_table_entry_t *mt_entry)
vol->free_cls = 0xFFFFFFFF;
vol->next_cl = 0xFFFFFFFF;
}
+
+ _fat_block_release(mt_entry);
+
vol->afat_loc = vol->fat_loc + vol->fat_length * vol->afat;
/* set up collection of fat-files fd */
diff --git a/cpukit/libfs/src/dosfs/fat.h b/cpukit/libfs/src/dosfs/fat.h
index 74d0512fe5..61eb8c758c 100644
--- a/cpukit/libfs/src/dosfs/fat.h
+++ b/cpukit/libfs/src/dosfs/fat.h
@@ -464,6 +464,9 @@ _fat_block_write(rtems_filesystem_mount_table_entry_t *mt_entry,
uint32_t count,
const void *buff);
+int
+_fat_block_release(rtems_filesystem_mount_table_entry_t *mt_entry);
+
ssize_t
fat_cluster_read(rtems_filesystem_mount_table_entry_t *mt_entry,
uint32_t cln,
diff --git a/cpukit/libfs/src/dosfs/msdos_init.c b/cpukit/libfs/src/dosfs/msdos_init.c
index 1af639c286..89a3dac274 100644
--- a/cpukit/libfs/src/dosfs/msdos_init.c
+++ b/cpukit/libfs/src/dosfs/msdos_init.c
@@ -38,6 +38,7 @@ const rtems_filesystem_operations_table msdos_ops = {
NULL, /* msdos_utime */
NULL,
NULL,
+ NULL,
NULL
};
diff --git a/cpukit/libfs/src/imfs/imfs_init.c b/cpukit/libfs/src/imfs/imfs_init.c
index 81091bc936..d1b2d44fcf 100644
--- a/cpukit/libfs/src/imfs/imfs_init.c
+++ b/cpukit/libfs/src/imfs/imfs_init.c
@@ -49,7 +49,8 @@ const rtems_filesystem_operations_table IMFS_ops = {
IMFS_utime,
IMFS_evaluate_link,
IMFS_symlink,
- IMFS_readlink
+ IMFS_readlink,
+ NULL
};
/*
diff --git a/cpukit/libfs/src/nfsclient/src/nfs.c b/cpukit/libfs/src/nfsclient/src/nfs.c
index 50c125ad28..cce17a5c7c 100644
--- a/cpukit/libfs/src/nfsclient/src/nfs.c
+++ b/cpukit/libfs/src/nfsclient/src/nfs.c
@@ -2456,6 +2456,7 @@ struct _rtems_filesystem_operations_table nfs_fs_ops = {
nfs_eval_link, /* OPTIONAL; may be NULL */
nfs_symlink, /* OPTIONAL; may be NULL */
nfs_readlink, /* OPTIONAL; may be NULL */
+ NULL /* OPTIONAL; may be NULL */
};
/*****************************************
diff --git a/cpukit/libmisc/Makefile.am b/cpukit/libmisc/Makefile.am
index a17b8041ab..cd0988921c 100644
--- a/cpukit/libmisc/Makefile.am
+++ b/cpukit/libmisc/Makefile.am
@@ -73,7 +73,7 @@ libshell_a_SOURCES = shell/cat_file.c shell/cmds.c shell/internal.h \
shell/main_chdir.c shell/main_chmod.c shell/main_chroot.c \
shell/main_cp.c shell/main_cpuuse.c shell/main_date.c shell/main_dir.c \
shell/main_echo.c shell/main_exit.c shell/main_halt.c shell/main_help.c \
- shell/main_id.c shell/main_logoff.c shell/main_ls.c \
+ shell/main_id.c shell/main_logoff.c shell/main_ln.c shell/main_ls.c \
shell/main_mallocinfo.c shell/main_mdump.c shell/main_medit.c \
shell/main_mfill.c shell/main_mkdir.c shell/main_mount.c \
shell/main_mount_msdos.c shell/main_mmove.c shell/main_msdosfmt.c \
@@ -95,7 +95,7 @@ libshell_a_SOURCES = shell/cat_file.c shell/cmds.c shell/internal.h \
shell/dd-misc.c shell/dd-position.c \
shell/main_hexdump.c shell/hexdump-conv.c shell/hexdump-display.c \
shell/hexdump-odsyntax.c shell/hexdump-parse.c shell/hexsyntax.c \
- shell/main_time.c
+ shell/main_time.c shell/main_mknod.c
if LIBNETWORKING
libshell_a_SOURCES += shell/main_mount_ftp.c shell/main_mount_tftp.c \
diff --git a/cpukit/libmisc/shell/hexdump-display.c b/cpukit/libmisc/shell/hexdump-display.c
index 61499e7c57..b5886c5b02 100644
--- a/cpukit/libmisc/shell/hexdump-display.c
+++ b/cpukit/libmisc/shell/hexdump-display.c
@@ -365,8 +365,9 @@ next(rtems_shell_hexdump_globals* globals, char **argv)
errno = ENOMEM;
err(exit_jump, 1, "file name allocation");
}
+ memset (hdstdin, 0, sizeof(FILE));
}
- if (!(hdstdin = fopen(*_argv, "r"))) {
+ if (!(hdstdin = freopen(*_argv, "r", hdstdin))) {
warn("%s", *_argv);
exitval = 1;
++_argv;
@@ -399,22 +400,23 @@ doskip(rtems_shell_hexdump_globals* globals, const char *fname, int statok)
if (statok) {
if (fstat(fileno(hdstdin), &sb))
err(exit_jump, 1, "%s", fname);
- if (S_ISREG(sb.st_mode) && skip >= sb.st_size) {
+ /* can seek block devices on RTEMS */
+ if (0 && S_ISREG(sb.st_mode) && skip >= sb.st_size) {
address += sb.st_size;
skip -= sb.st_size;
return;
}
- }
- if (S_ISREG(sb.st_mode)) {
- if (fseeko(hdstdin, skip, SEEK_SET))
- err(exit_jump, 1, "%s", fname);
- address += skip;
- skip = 0;
- } else {
- for (cnt = 0; cnt < skip; ++cnt)
- if (getchar() == EOF)
- break;
- address += cnt;
- skip -= cnt;
+ if (1 || S_ISREG(sb.st_mode)) {
+ if (fseeko(hdstdin, skip, SEEK_SET))
+ err(exit_jump, 1, "%s", fname);
+ address += skip;
+ skip = 0;
+ } else {
+ for (cnt = 0; cnt < skip; ++cnt)
+ if (getchar() == EOF)
+ break;
+ address += cnt;
+ skip -= cnt;
+ }
}
}
diff --git a/cpukit/libmisc/shell/main_ln.c b/cpukit/libmisc/shell/main_ln.c
new file mode 100644
index 0000000000..871aa9551b
--- /dev/null
+++ b/cpukit/libmisc/shell/main_ln.c
@@ -0,0 +1,305 @@
+/* $NetBSD: ln.c,v 1.34 2008/07/20 00:52:40 lukem Exp $ */
+
+/*
+ * Copyright (c) 1987, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+__COPYRIGHT("@(#) Copyright (c) 1987, 1993, 1994\
+ The Regents of the University of California. All rights reserved.");
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)ln.c 8.2 (Berkeley) 3/31/94";
+#else
+__RCSID("$NetBSD: ln.c,v 1.34 2008/07/20 00:52:40 lukem Exp $");
+#endif
+#endif /* not lint */
+#endif
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include <rtems/shellconfig.h>
+#define __need_getopt_newlib
+#include <getopt.h>
+
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <errno.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <setjmp.h>
+
+typedef struct {
+ int fflag; /* Unlink existing files. */
+ int hflag; /* Check new name for symlink first. */
+ int iflag; /* Interactive mode. */
+ int sflag; /* Symbolic, not hard, link. */
+ int vflag; /* Verbose output */
+ char linkch;
+
+ int exit_code;
+ jmp_buf exit_jmp;
+} rtems_shell_ln_globals;
+
+#define fflag globals->fflag
+#define hflag globals->hflag
+#define iflag globals->iflag
+#define sflag globals->sflag
+#define vflag globals->vflag
+#define linkch globals->linkch
+
+#define exit_jump &(globals->exit_jmp)
+
+#define exit(ec) rtems_shell_ln_exit(globals, ec)
+
+static int main_ln(rtems_shell_ln_globals* , int, char *[]);
+
+static void
+rtems_shell_ln_exit (rtems_shell_ln_globals* globals, int code)
+{
+ globals->exit_code = code;
+ longjmp (globals->exit_jmp, 1);
+}
+
+static int main_ln(rtems_shell_ln_globals* globals, int argc, char *argv[]);
+
+int
+rtems_shell_main_ln(int argc, char *argv[])
+{
+ rtems_shell_ln_globals ln_globals;
+ rtems_shell_ln_globals* globals = &ln_globals;
+ memset (globals, 0, sizeof (ln_globals));
+ ln_globals.exit_code = 1;
+ if (setjmp (ln_globals.exit_jmp) == 0)
+ return main_ln (globals, argc, argv);
+ return ln_globals.exit_code;
+}
+
+#if RTEMS_REMOVED
+int fflag; /* Unlink existing files. */
+int hflag; /* Check new name for symlink first. */
+int iflag; /* Interactive mode. */
+int sflag; /* Symbolic, not hard, link. */
+int vflag; /* Verbose output */
+
+ /* System link call. */
+int (*linkf)(const char *, const char *);
+char linkch;
+#endif
+
+int (*linkf)(const char *, const char *);
+
+static int linkit(rtems_shell_ln_globals* , const char *, const char *, int);
+static void usage(rtems_shell_ln_globals* );
+
+static int
+main_ln(rtems_shell_ln_globals* globals, int argc, char *argv[])
+{
+ struct stat sb;
+ int ch, exitval;
+ char *sourcedir;
+
+ struct getopt_data getopt_reent;
+ memset(&getopt_reent, 0, sizeof(getopt_data));
+
+#if RTEMS_REMOVED
+ setprogname(argv[0]);
+ (void)setlocale(LC_ALL, "");
+#endif
+
+ while ((ch = getopt_r(argc, argv, "fhinsv", &getopt_reent)) != -1)
+ switch (ch) {
+ case 'f':
+ fflag = 1;
+ iflag = 0;
+ break;
+ case 'h':
+ case 'n':
+ hflag = 1;
+ break;
+ case 'i':
+ iflag = 1;
+ fflag = 0;
+ break;
+ case 's':
+ sflag = 1;
+ break;
+ case 'v':
+ vflag = 1;
+ break;
+ case '?':
+ default:
+ usage(globals);
+ /* NOTREACHED */
+ }
+
+ argv += getopt_reent.optind;
+ argc -= getopt_reent.optind;
+
+ if (sflag) {
+ linkf = symlink;
+ linkch = '-';
+ } else {
+ linkf = link;
+ linkch = '=';
+ }
+
+ switch(argc) {
+ case 0:
+ usage(globals);
+ /* NOTREACHED */
+ case 1: /* ln target */
+ exit(linkit(globals, argv[0], ".", 1));
+ /* NOTREACHED */
+ case 2: /* ln target source */
+ exit(linkit(globals, argv[0], argv[1], 0));
+ /* NOTREACHED */
+ }
+
+ /* ln target1 target2 directory */
+ sourcedir = argv[argc - 1];
+ if (hflag && lstat(sourcedir, &sb) == 0 && S_ISLNK(sb.st_mode)) {
+ /* we were asked not to follow symlinks, but found one at
+ the target--simulate "not a directory" error */
+ errno = ENOTDIR;
+ err(exit_jump, EXIT_FAILURE, "%s", sourcedir);
+ /* NOTREACHED */
+ }
+ if (stat(sourcedir, &sb)) {
+ err(exit_jump, EXIT_FAILURE, "%s", sourcedir);
+ /* NOTREACHED */
+ }
+ if (!S_ISDIR(sb.st_mode)) {
+ usage(globals);
+ /* NOTREACHED */
+ }
+ for (exitval = 0; *argv != sourcedir; ++argv)
+ exitval |= linkit(globals, *argv, sourcedir, 1);
+ exit(exitval);
+ /* NOTREACHED */
+ return 0;
+}
+
+int
+linkit(rtems_shell_ln_globals* globals, const char *source, const char *target, int isdir)
+{
+ struct stat sb;
+ const char *p;
+ char path[MAXPATHLEN];
+ int ch, exists, first;
+
+ if (!sflag) {
+ /* If target doesn't exist, quit now. */
+ if (stat(target, &sb)) {
+ warn("%s", target);
+ return (1);
+ }
+ }
+
+ /* If the source is a directory (and not a symlink if hflag),
+ append the target's name. */
+ if (isdir ||
+ (!lstat(source, &sb) && S_ISDIR(sb.st_mode)) ||
+ (!hflag && !stat(source, &sb) && S_ISDIR(sb.st_mode))) {
+ if ((p = strrchr(target, '/')) == NULL)
+ p = target;
+ else
+ ++p;
+ (void)snprintf(path, sizeof(path), "%s/%s", source, p);
+ source = path;
+ }
+
+ exists = !lstat(source, &sb);
+
+ /*
+ * If the file exists, then unlink it forcibly if -f was specified
+ * and interactively if -i was specified.
+ */
+ if (fflag && exists) {
+ if (unlink(source)) {
+ warn("%s", source);
+ return (1);
+ }
+ } else if (iflag && exists) {
+ fflush(stdout);
+ (void)fprintf(stderr, "replace %s? ", source);
+
+ first = ch = getchar();
+ while (ch != '\n' && ch != EOF)
+ ch = getchar();
+ if (first != 'y' && first != 'Y') {
+ (void)fprintf(stderr, "not replaced\n");
+ return (1);
+ }
+
+ if (unlink(source)) {
+ warn("%s", source);
+ return (1);
+ }
+ }
+
+ /* Attempt the link. */
+ if ((*linkf)(target, source)) {
+ warn("%s", source);
+ return (1);
+ }
+ if (vflag)
+ (void)printf("%s %c> %s\n", source, linkch, target);
+
+ return (0);
+}
+
+void
+usage(rtems_shell_ln_globals* globals)
+{
+#define getprogname() "ln"
+ (void)fprintf(stderr,
+ "usage:\t%s [-fhinsv] file1 file2\n\t%s [-fhinsv] file ... directory\n",
+ getprogname(), getprogname());
+ exit(1);
+ /* NOTREACHED */
+}
+
+rtems_shell_cmd_t rtems_shell_LN_Command = {
+ "ln", /* name */
+ "ln ln [-fhinsv] source_file [target_file]", /* usage */
+ "files", /* topic */
+ rtems_shell_main_ln, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_mknod.c b/cpukit/libmisc/shell/main_mknod.c
new file mode 100644
index 0000000000..3a9d0465d1
--- /dev/null
+++ b/cpukit/libmisc/shell/main_mknod.c
@@ -0,0 +1,459 @@
+/* $NetBSD: mknod.c,v 1.39 2009/02/13 01:37:23 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#if 0
+#ifndef lint
+__COPYRIGHT("@(#) Copyright (c) 1998\
+ The NetBSD Foundation, Inc. All rights reserved.");
+__RCSID("$NetBSD: mknod.c,v 1.39 2009/02/13 01:37:23 lukem Exp $");
+#endif /* not lint */
+#endif
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include <rtems/shellconfig.h>
+#define __need_getopt_newlib
+#include <getopt.h>
+
+#include <sys/cdefs.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#if !HAVE_NBTOOL_CONFIG_H
+#include <sys/sysctl.h>
+#endif
+
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "mknod-pack_dev.h"
+
+#include <setjmp.h>
+
+typedef struct {
+ int exit_code;
+ jmp_buf exit_jmp;
+} rtems_shell_mknod_globals;
+
+#define exit_jump &(globals->exit_jmp)
+
+#define exit(ec) rtems_shell_mknod_exit(globals, ec)
+
+static int gid_name(const char *, gid_t *);
+static portdev_t callPack(rtems_shell_mknod_globals* globals,
+ pack_t *, int, u_long *);
+
+static int main_mknod(rtems_shell_mknod_globals*, int, char *[]);
+static void usage(rtems_shell_mknod_globals* );
+
+static void
+rtems_shell_mknod_exit (rtems_shell_mknod_globals* globals, int code)
+{
+ globals->exit_code = code;
+ longjmp (globals->exit_jmp, 1);
+}
+
+#include "mknod-pack_dev.c"
+
+int
+rtems_shell_main_mknod(int argc, char *argv[])
+{
+ rtems_shell_mknod_globals mknod_globals;
+ rtems_shell_mknod_globals* globals = &mknod_globals;
+ memset (globals, 0, sizeof (mknod_globals));
+ mknod_globals.exit_code = 1;
+ if (setjmp (mknod_globals.exit_jmp) == 0)
+ return main_mknod (globals, argc, argv);
+ return mknod_globals.exit_code;
+}
+
+#define getprogname() "mknod"
+
+#ifdef KERN_DRIVERS
+#error invalid for RTEMS
+static struct kinfo_drivers *kern_drivers;
+static int num_drivers;
+
+static void get_device_info(void);
+static void print_device_info(char **);
+static int major_from_name(const char *, mode_t);
+#endif
+
+#define MAXARGS 3 /* 3 for bsdos, 2 for rest */
+
+int
+main_mknod(rtems_shell_mknod_globals* globals, int argc, char **argv)
+{
+ char *name, *p;
+ mode_t mode;
+ portdev_t dev;
+ pack_t *pack;
+ u_long numbers[MAXARGS];
+ int n, ch, fifo, hasformat;
+ int r_flag = 0; /* force: delete existing entry */
+#ifdef KERN_DRIVERS
+ int l_flag = 0; /* list device names and numbers */
+ int major;
+#endif
+#if RTEMS_REMOVED
+ void *modes = 0;
+#endif
+ uid_t uid = -1;
+ gid_t gid = -1;
+ int rval;
+
+ struct getopt_data getopt_reent;
+ memset(&getopt_reent, 0, sizeof(getopt_data));
+
+ dev = 0;
+ fifo = hasformat = 0;
+ pack = pack_native;
+
+#ifdef KERN_DRIVERS
+ while ((ch = getopt(argc, argv, "lrRF:g:m:u:")) != -1) {
+#else
+ while ((ch = getopt_r(argc, argv, "rRF:g:m:u:", &getopt_reent)) != -1) {
+#endif
+ switch (ch) {
+
+#ifdef KERN_DRIVERS
+ case 'l':
+ l_flag = 1;
+ break;
+#endif
+
+ case 'r':
+ r_flag = 1;
+ break;
+
+ case 'R':
+ r_flag = 2;
+ break;
+
+ case 'F':
+ pack = pack_find(getopt_reent.optarg);
+ if (pack == NULL)
+ errx(exit_jump, 1, "invalid format: %s", getopt_reent.optarg);
+ hasformat++;
+ break;
+
+ case 'g':
+ if (getopt_reent.optarg[0] == '#') {
+ gid = strtol(getopt_reent.optarg + 1, &p, 10);
+ if (*p == 0)
+ break;
+ }
+ if (gid_name(getopt_reent.optarg, &gid) == 0)
+ break;
+ gid = strtol(getopt_reent.optarg, &p, 10);
+ if (*p == 0)
+ break;
+ errx(exit_jump, 1, "%s: invalid group name", getopt_reent.optarg);
+
+ case 'm':
+#if RTEMS_REMOVED
+ modes = setmode(getopt_reent.optarg);
+ if (modes == NULL)
+#endif
+ err(exit_jump, 1, "Cannot set file mode `%s'", getopt_reent.optarg);
+ break;
+
+ case 'u':
+ if (getopt_reent.optarg[0] == '#') {
+ uid = strtol(getopt_reent.optarg + 1, &p, 10);
+ if (*p == 0)
+ break;
+ }
+#if RTEMS_REMOVED
+ if (uid_from_user(getopt_reent.optarg, &uid) == 0)
+ break;
+#endif
+ uid = strtol(getopt_reent.optarg, &p, 10);
+ if (*p == 0)
+ break;
+ errx(exit_jump, 1, "%s: invalid user name", getopt_reent.optarg);
+
+ default:
+ case '?':
+ usage(globals);
+ }
+ }
+ argc -= getopt_reent.optind;
+ argv += getopt_reent.optind;
+
+#ifdef KERN_DRIVERS
+ if (l_flag) {
+ print_device_info(argv);
+ return 0;
+ }
+#endif
+
+ if (argc < 2 || argc > 10)
+ usage(globals);
+
+ name = *argv;
+ argc--;
+ argv++;
+
+ umask(mode = umask(0));
+ mode = (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) & ~mode;
+
+ if (argv[0][1] != '\0')
+ goto badtype;
+ switch (*argv[0]) {
+ case 'c':
+ mode |= S_IFCHR;
+ break;
+
+ case 'b':
+ mode |= S_IFBLK;
+ break;
+
+ case 'p':
+ if (hasformat)
+ errx(exit_jump, 1, "format is meaningless for fifos");
+ mode |= S_IFIFO;
+ fifo = 1;
+ break;
+
+ default:
+ badtype:
+ errx(exit_jump, 1, "node type must be 'b', 'c' or 'p'.");
+ }
+ argc--;
+ argv++;
+
+ if (fifo) {
+ if (argc != 0)
+ usage(globals);
+ } else {
+ if (argc < 1 || argc > MAXARGS)
+ usage(globals);
+ }
+
+ for (n = 0; n < argc; n++) {
+ errno = 0;
+ numbers[n] = strtoul(argv[n], &p, 0);
+ if (*p == 0 && errno == 0)
+ continue;
+#ifdef KERN_DRIVERS
+ if (n == 0) {
+ major = major_from_name(argv[0], mode);
+ if (major != -1) {
+ numbers[0] = major;
+ continue;
+ }
+ if (!isdigit(*(unsigned char *)argv[0]))
+ errx(1, "unknown driver: %s", argv[0]);
+ }
+#endif
+ errx(exit_jump, 1, "invalid number: %s", argv[n]);
+ }
+
+ switch (argc) {
+ case 0:
+ dev = 0;
+ break;
+
+ case 1:
+ dev = numbers[0];
+ break;
+
+ default:
+ dev = callPack(globals, pack, argc, numbers);
+ break;
+ }
+
+#if RTEMS_REMOVED
+ if (modes != NULL)
+ mode = getmode(modes, mode);
+#endif
+ umask(0);
+ rval = fifo ? mkfifo(name, mode) : mknod(name, mode, dev);
+ if (rval < 0 && errno == EEXIST && r_flag) {
+ struct stat sb;
+ if (lstat(name, &sb) != 0 || (!fifo && sb.st_rdev != dev))
+ sb.st_mode = 0;
+
+ if ((sb.st_mode & S_IFMT) == (mode & S_IFMT)) {
+ if (r_flag == 1)
+ /* Ignore permissions and user/group */
+ return 0;
+ if (sb.st_mode != mode)
+ rval = chmod(name, mode);
+ else
+ rval = 0;
+ } else {
+ unlink(name);
+ rval = fifo ? mkfifo(name, mode)
+ : mknod(name, mode, dev);
+ }
+ }
+ if (rval < 0)
+ err(exit_jump, 1, "%s", name);
+ if ((uid != (uid_t)-1 || gid != (uid_t)-1) && chown(name, uid, gid) == -1)
+ /* XXX Should we unlink the files here? */
+ warn("%s: uid/gid not changed", name);
+
+ return 0;
+}
+
+static void
+usage(rtems_shell_mknod_globals* globals)
+{
+ const char *progname = getprogname();
+
+ (void)fprintf(stderr,
+ "usage: %s [-rR] [-F format] [-m mode] [-u user] [-g group]\n",
+ progname);
+ (void)fprintf(stderr,
+#ifdef KERN_DRIVERS
+ " [ name [b | c] [major | driver] minor\n"
+#else
+ " [ name [b | c] major minor\n"
+#endif
+ " | name [b | c] major unit subunit\n"
+ " | name [b | c] number\n"
+ " | name p ]\n");
+#ifdef KERN_DRIVERS
+ (void)fprintf(stderr, " %s -l [driver] ...\n", progname);
+#endif
+ exit(1);
+}
+
+static int
+gid_name(const char *name, gid_t *gid)
+{
+ struct group *g;
+
+ g = getgrnam(name);
+ if (!g)
+ return -1;
+ *gid = g->gr_gid;
+ return 0;
+}
+
+static portdev_t
+callPack(rtems_shell_mknod_globals* globals, pack_t *f, int n, u_long *numbers)
+{
+ portdev_t d;
+ const char *error = NULL;
+
+ d = (*f)(n, numbers, &error);
+ if (error != NULL)
+ errx(exit_jump, 1, "%s", error);
+ return d;
+}
+
+#ifdef KERN_DRIVERS
+static void
+get_device_info(void)
+{
+ static int mib[2] = {CTL_KERN, KERN_DRIVERS};
+ size_t len;
+
+ if (sysctl(mib, 2, NULL, &len, NULL, 0) != 0)
+ err(1, "kern.drivers" );
+ kern_drivers = malloc(len);
+ if (kern_drivers == NULL)
+ err(1, "malloc");
+ if (sysctl(mib, 2, kern_drivers, &len, NULL, 0) != 0)
+ err(1, "kern.drivers" );
+
+ num_drivers = len / sizeof *kern_drivers;
+}
+
+static void
+print_device_info(char **names)
+{
+ int i;
+ struct kinfo_drivers *kd;
+
+ if (kern_drivers == NULL)
+ get_device_info();
+
+ do {
+ kd = kern_drivers;
+ for (i = 0; i < num_drivers; kd++, i++) {
+ if (*names && strcmp(*names, kd->d_name))
+ continue;
+ printf("%s", kd->d_name);
+ if (kd->d_cmajor != -1)
+ printf(" character major %d", kd->d_cmajor);
+ if (kd->d_bmajor != -1)
+ printf(" block major %d", kd->d_bmajor);
+ printf("\n");
+ }
+ } while (*names && *++names);
+}
+
+static int
+major_from_name(const char *name, mode_t mode)
+{
+ int i;
+ struct kinfo_drivers *kd;
+
+ if (kern_drivers == NULL)
+ get_device_info();
+
+ kd = kern_drivers;
+ for (i = 0; i < num_drivers; kd++, i++) {
+ if (strcmp(name, kd->d_name))
+ continue;
+ if (S_ISCHR(mode))
+ return kd->d_cmajor;
+ return kd->d_bmajor;
+ }
+ return -1;
+}
+#endif
+
+rtems_shell_cmd_t rtems_shell_MKNOD_Command = {
+ "mknod", /* name */
+ "mknod mknod [-rR] [-F fmt] [-m mode] name [c | b] minor", /* usage */
+ "files", /* topic */
+ rtems_shell_main_mknod, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_mount.c b/cpukit/libmisc/shell/main_mount.c
index 824f9d70b8..89fafa5e12 100644
--- a/cpukit/libmisc/shell/main_mount.c
+++ b/cpukit/libmisc/shell/main_mount.c
@@ -128,6 +128,14 @@ int rtems_shell_main_mount(
for (a = rtems_shell_Mount_filesystems; *a; a++)
if (*a)
fprintf (stderr, "%s ", (*a)->name);
+ if (!rtems_chain_is_empty(&filesystems)) {
+ rtems_chain_node* node = filesystems.first;
+ while (!rtems_chain_is_tail (&filesystems, node)) {
+ rtems_shell_filesystems_t* f = (rtems_shell_filesystems_t*)node;
+ fprintf (stderr, "%s ", f->name);
+ node = node->next;
+ }
+ }
fprintf (stderr, "\n");
return 1;
} else {
diff --git a/cpukit/libmisc/shell/mknod-pack_dev.c b/cpukit/libmisc/shell/mknod-pack_dev.c
new file mode 100644
index 0000000000..c02a12a7bc
--- /dev/null
+++ b/cpukit/libmisc/shell/mknod-pack_dev.c
@@ -0,0 +1,296 @@
+/* $NetBSD: pack_dev.c,v 1.10 2009/02/13 01:37:23 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#if 0
+#include <sys/cdefs.h>
+#if !defined(lint)
+__RCSID("$NetBSD: pack_dev.c,v 1.10 2009/02/13 01:37:23 lukem Exp $");
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pack_dev.h"
+#endif
+
+static pack_t pack_netbsd;
+static pack_t pack_freebsd;
+static pack_t pack_8_8;
+static pack_t pack_12_20;
+static pack_t pack_14_18;
+static pack_t pack_8_24;
+static pack_t pack_bsdos;
+static int compare_format(const void *, const void *);
+
+static const char iMajorError[] = "invalid major number";
+static const char iMinorError[] = "invalid minor number";
+static const char tooManyFields[] = "too many fields for format";
+
+#define makedev(x,y) rtems_filesystem_make_dev_t(x,y)
+#define major(d) rtems_filesystem_dev_major_t(d)
+#define minor(d) rtems_filesystem_dev_minor_t(d)
+
+ /* exported */
+portdev_t
+pack_native(int n, u_long numbers[], const char **error)
+{
+ portdev_t dev = 0;
+
+ if (n == 2) {
+ dev = makedev(numbers[0], numbers[1]);
+ if ((u_long)major(dev) != numbers[0])
+ *error = iMajorError;
+ else if ((u_long)minor(dev) != numbers[1])
+ *error = iMinorError;
+ } else
+ *error = tooManyFields;
+ return (dev);
+}
+
+
+static portdev_t
+pack_netbsd(int n, u_long numbers[], const char **error)
+{
+ portdev_t dev = 0;
+
+ if (n == 2) {
+ dev = makedev_netbsd(numbers[0], numbers[1]);
+ if ((u_long)major_netbsd(dev) != numbers[0])
+ *error = iMajorError;
+ else if ((u_long)minor_netbsd(dev) != numbers[1])
+ *error = iMinorError;
+ } else
+ *error = tooManyFields;
+ return (dev);
+}
+
+
+#define major_freebsd(x) ((int32_t)(((x) & 0x0000ff00) >> 8))
+#define minor_freebsd(x) ((int32_t)(((x) & 0xffff00ff) >> 0))
+#define makedev_freebsd(x,y) ((portdev_t)((((x) << 8) & 0x0000ff00) | \
+ (((y) << 0) & 0xffff00ff)))
+
+static portdev_t
+pack_freebsd(int n, u_long numbers[], const char **error)
+{
+ portdev_t dev = 0;
+
+ if (n == 2) {
+ dev = makedev_freebsd(numbers[0], numbers[1]);
+ if ((u_long)major_freebsd(dev) != numbers[0])
+ *error = iMajorError;
+ if ((u_long)minor_freebsd(dev) != numbers[1])
+ *error = iMinorError;
+ } else
+ *error = tooManyFields;
+ return (dev);
+}
+
+
+#define major_8_8(x) ((int32_t)(((x) & 0x0000ff00) >> 8))
+#define minor_8_8(x) ((int32_t)(((x) & 0x000000ff) >> 0))
+#define makedev_8_8(x,y) ((portdev_t)((((x) << 8) & 0x0000ff00) | \
+ (((y) << 0) & 0x000000ff)))
+
+static portdev_t
+pack_8_8(int n, u_long numbers[], const char **error)
+{
+ portdev_t dev = 0;
+
+ if (n == 2) {
+ dev = makedev_8_8(numbers[0], numbers[1]);
+ if ((u_long)major_8_8(dev) != numbers[0])
+ *error = iMajorError;
+ if ((u_long)minor_8_8(dev) != numbers[1])
+ *error = iMinorError;
+ } else
+ *error = tooManyFields;
+ return (dev);
+}
+
+
+#define major_12_20(x) ((int32_t)(((x) & 0xfff00000) >> 20))
+#define minor_12_20(x) ((int32_t)(((x) & 0x000fffff) >> 0))
+#define makedev_12_20(x,y) ((portdev_t)((((x) << 20) & 0xfff00000) | \
+ (((y) << 0) & 0x000fffff)))
+
+static portdev_t
+pack_12_20(int n, u_long numbers[], const char **error)
+{
+ portdev_t dev = 0;
+
+ if (n == 2) {
+ dev = makedev_12_20(numbers[0], numbers[1]);
+ if ((u_long)major_12_20(dev) != numbers[0])
+ *error = iMajorError;
+ if ((u_long)minor_12_20(dev) != numbers[1])
+ *error = iMinorError;
+ } else
+ *error = tooManyFields;
+ return (dev);
+}
+
+
+#define major_14_18(x) ((int32_t)(((x) & 0xfffc0000) >> 18))
+#define minor_14_18(x) ((int32_t)(((x) & 0x0003ffff) >> 0))
+#define makedev_14_18(x,y) ((portdev_t)((((x) << 18) & 0xfffc0000) | \
+ (((y) << 0) & 0x0003ffff)))
+
+static portdev_t
+pack_14_18(int n, u_long numbers[], const char **error)
+{
+ portdev_t dev = 0;
+
+ if (n == 2) {
+ dev = makedev_14_18(numbers[0], numbers[1]);
+ if ((u_long)major_14_18(dev) != numbers[0])
+ *error = iMajorError;
+ if ((u_long)minor_14_18(dev) != numbers[1])
+ *error = iMinorError;
+ } else
+ *error = tooManyFields;
+ return (dev);
+}
+
+
+#define major_8_24(x) ((int32_t)(((x) & 0xff000000) >> 24))
+#define minor_8_24(x) ((int32_t)(((x) & 0x00ffffff) >> 0))
+#define makedev_8_24(x,y) ((portdev_t)((((x) << 24) & 0xff000000) | \
+ (((y) << 0) & 0x00ffffff)))
+
+static portdev_t
+pack_8_24(int n, u_long numbers[], const char **error)
+{
+ portdev_t dev = 0;
+
+ if (n == 2) {
+ dev = makedev_8_24(numbers[0], numbers[1]);
+ if ((u_long)major_8_24(dev) != numbers[0])
+ *error = iMajorError;
+ if ((u_long)minor_8_24(dev) != numbers[1])
+ *error = iMinorError;
+ } else
+ *error = tooManyFields;
+ return (dev);
+}
+
+
+#define major_12_12_8(x) ((int32_t)(((x) & 0xfff00000) >> 20))
+#define unit_12_12_8(x) ((int32_t)(((x) & 0x000fff00) >> 8))
+#define subunit_12_12_8(x) ((int32_t)(((x) & 0x000000ff) >> 0))
+#define makedev_12_12_8(x,y,z) ((portdev_t)((((x) << 20) & 0xfff00000) | \
+ (((y) << 8) & 0x000fff00) | \
+ (((z) << 0) & 0x000000ff)))
+
+static portdev_t
+pack_bsdos(int n, u_long numbers[], const char **error)
+{
+ portdev_t dev = 0;
+
+ if (n == 2) {
+ dev = makedev_12_20(numbers[0], numbers[1]);
+ if ((u_long)major_12_20(dev) != numbers[0])
+ *error = iMajorError;
+ if ((u_long)minor_12_20(dev) != numbers[1])
+ *error = iMinorError;
+ } else if (n == 3) {
+ dev = makedev_12_12_8(numbers[0], numbers[1], numbers[2]);
+ if ((u_long)major_12_12_8(dev) != numbers[0])
+ *error = iMajorError;
+ if ((u_long)unit_12_12_8(dev) != numbers[1])
+ *error = "invalid unit number";
+ if ((u_long)subunit_12_12_8(dev) != numbers[2])
+ *error = "invalid subunit number";
+ } else
+ *error = tooManyFields;
+ return (dev);
+}
+
+
+ /* list of formats and pack functions */
+ /* this list must be sorted lexically */
+struct format {
+ const char *name;
+ pack_t *pack;
+} formats[] = {
+ {"386bsd", pack_8_8},
+ {"4bsd", pack_8_8},
+ {"bsdos", pack_bsdos},
+ {"freebsd", pack_freebsd},
+ {"hpux", pack_8_24},
+ {"isc", pack_8_8},
+ {"linux", pack_8_8},
+ {"native", pack_native},
+ {"netbsd", pack_netbsd},
+ {"osf1", pack_12_20},
+ {"sco", pack_8_8},
+ {"solaris", pack_14_18},
+ {"sunos", pack_8_8},
+ {"svr3", pack_8_8},
+ {"svr4", pack_14_18},
+ {"ultrix", pack_8_8},
+};
+
+static int
+compare_format(const void *key, const void *element)
+{
+ const char *name;
+ const struct format *format;
+
+ name = key;
+ format = element;
+
+ return (strcmp(name, format->name));
+}
+
+
+pack_t *
+pack_find(const char *name)
+{
+ struct format *format;
+
+ format = bsearch(name, formats,
+ sizeof(formats)/sizeof(formats[0]),
+ sizeof(formats[0]), compare_format);
+ if (format == 0)
+ return (NULL);
+ return (format->pack);
+}
diff --git a/cpukit/libmisc/shell/mknod-pack_dev.h b/cpukit/libmisc/shell/mknod-pack_dev.h
new file mode 100644
index 0000000000..5c6d78af8b
--- /dev/null
+++ b/cpukit/libmisc/shell/mknod-pack_dev.h
@@ -0,0 +1,52 @@
+/* $NetBSD: pack_dev.h,v 1.7 2008/04/28 20:23:09 martin Exp $ */
+
+/*-
+ * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _PACK_DEV_H
+#define _PACK_DEV_H
+
+#ifdef __CYGWIN__
+typedef __dev32_t portdev_t;
+#else
+typedef dev_t portdev_t;
+#endif
+typedef portdev_t pack_t(int, u_long [], const char **);
+
+static pack_t *pack_find(const char *);
+static pack_t pack_native;
+
+#define major_netbsd(x) ((int32_t)((((x) & 0x000fff00) >> 8)))
+#define minor_netbsd(x) ((int32_t)((((x) & 0xfff00000) >> 12) | \
+ (((x) & 0x000000ff) >> 0)))
+#define makedev_netbsd(x,y) ((dev_t)((((x) << 8) & 0x000fff00) | \
+ (((y) << 12) & 0xfff00000) | \
+ (((y) << 0) & 0x000000ff)))
+
+#endif /* _PACK_DEV_H */
diff --git a/cpukit/libmisc/shell/shellconfig.h b/cpukit/libmisc/shell/shellconfig.h
index c9f9d4e9b7..1410430440 100644
--- a/cpukit/libmisc/shell/shellconfig.h
+++ b/cpukit/libmisc/shell/shellconfig.h
@@ -50,6 +50,8 @@ extern rtems_shell_cmd_t rtems_shell_CAT_Command;
extern rtems_shell_cmd_t rtems_shell_MSDOSFMT_Command;
extern rtems_shell_cmd_t rtems_shell_MV_Command;
extern rtems_shell_cmd_t rtems_shell_RM_Command;
+extern rtems_shell_cmd_t rtems_shell_LN_Command;
+extern rtems_shell_cmd_t rtems_shell_MKNOD_Command;
extern rtems_shell_cmd_t rtems_shell_UMASK_Command;
extern rtems_shell_cmd_t rtems_shell_MOUNT_Command;
extern rtems_shell_cmd_t rtems_shell_UNMOUNT_Command;
@@ -287,6 +289,16 @@ extern rtems_shell_filesystems_t *rtems_shell_Mount_filesystems[];
&rtems_shell_RM_Command,
#endif
#if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_LN)) || \
+ defined(CONFIGURE_SHELL_COMMAND_LN)
+ &rtems_shell_LN_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_MKNOD)) || \
+ defined(CONFIGURE_SHELL_COMMAND_MKNOD)
+ &rtems_shell_MKNOD_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
!defined(CONFIGURE_SHELL_NO_COMMAND_UMASK)) || \
defined(CONFIGURE_SHELL_COMMAND_UMASK)
&rtems_shell_UMASK_Command,
diff --git a/cpukit/libmisc/shell/utils-cp.c b/cpukit/libmisc/shell/utils-cp.c
index 65a27e6b5a..6ce71aa599 100644
--- a/cpukit/libmisc/shell/utils-cp.c
+++ b/cpukit/libmisc/shell/utils-cp.c
@@ -69,9 +69,6 @@ __RCSID("$NetBSD: utils.c,v 1.29 2005/10/15 18:22:18 christos Exp $");
#define cp_pct(x, y) ((y == 0) ? 0 : (int)(100.0 * (x) / (y)))
-/* original was MAXBSIZE which results in 64K on the stack */
-#define MAX_READ 1024
-
int
set_utimes(const char *file, struct stat *fs)
{
@@ -90,7 +87,9 @@ set_utimes(const char *file, struct stat *fs)
int
copy_file(rtems_shell_cp_globals* cp_globals __attribute__((unused)), FTSENT *entp, int dne)
{
- static char buf[MAX_READ];
+#define MAX_READ max_read
+ int max_read;
+ char* buf;
struct stat *fs;
ssize_t wcount;
size_t wresid;
@@ -101,13 +100,24 @@ copy_file(rtems_shell_cp_globals* cp_globals __attribute__((unused)), FTSENT *en
char *p;
#endif
+ fs = entp->fts_statp;
+
+ max_read = fs->st_blksize;
+ if (max_read < (8 * 1024))
+ max_read = 8 * 1024;
+ buf = malloc (max_read);
+ if (!buf)
+ {
+ warn("no memory");
+ return (1);
+ }
+
if ((from_fd = open(entp->fts_path, O_RDONLY, 0)) == -1) {
warn("%s", entp->fts_path);
+ (void)free(buf);
return (1);
}
- fs = entp->fts_statp;
-
/*
* If the file exists and we're interactive, verify with the user.
* If the file DNE, set the mode to be the from file, minus setuid
@@ -122,6 +132,7 @@ copy_file(rtems_shell_cp_globals* cp_globals __attribute__((unused)), FTSENT *en
if (vflag)
printf("%s not overwritten\n", to.p_path);
(void)close(from_fd);
+ (void)free(buf);
return (0);
} else if (iflag) {
(void)fprintf(stderr, "overwrite %s? %s",
@@ -131,6 +142,7 @@ copy_file(rtems_shell_cp_globals* cp_globals __attribute__((unused)), FTSENT *en
ch = getchar();
if (checkch != 'y' && checkch != 'Y') {
(void)close(from_fd);
+ (void)free(buf);
(void)fprintf(stderr, "not overwritten\n");
return (1);
}
@@ -157,6 +169,7 @@ copy_file(rtems_shell_cp_globals* cp_globals __attribute__((unused)), FTSENT *en
if (to_fd == -1) {
warn("%s", to.p_path);
(void)close(from_fd);
+ (void)free(buf);
return (1);
}
@@ -261,6 +274,7 @@ copy_file(rtems_shell_cp_globals* cp_globals __attribute__((unused)), FTSENT *en
rval = 1;
}
}
+ (void)free(buf);
return (rval);
}
diff --git a/cpukit/preinstall.am b/cpukit/preinstall.am
index 8a26282eb0..4dfcd12891 100644
--- a/cpukit/preinstall.am
+++ b/cpukit/preinstall.am
@@ -72,6 +72,10 @@ $(PROJECT_INCLUDE)/sys/ioctl.h: libcsupport/include/sys/ioctl.h $(PROJECT_INCLUD
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/ioctl.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/ioctl.h
+$(PROJECT_INCLUDE)/sys/statvfs.h: libcsupport/include/sys/statvfs.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/statvfs.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/statvfs.h
+
$(PROJECT_INCLUDE)/sys/sockio.h: libcsupport/include/sys/sockio.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/sockio.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/sockio.h
diff --git a/cpukit/sapi/inline/rtems/chain.inl b/cpukit/sapi/inline/rtems/chain.inl
index 7230eb032e..2a97b23124 100644
--- a/cpukit/sapi/inline/rtems/chain.inl
+++ b/cpukit/sapi/inline/rtems/chain.inl
@@ -74,6 +74,38 @@ RTEMS_INLINE_ROUTINE void rtems_chain_initialize_empty(
}
/**
+ * @brief Set off chain
+ *
+ * This function sets the next and previous fields of the @a node to NULL
+ * indicating the @a node is not part of a chain.
+ *
+ * @param[in] node the node set to off chain.
+ */
+RTEMS_INLINE_ROUTINE void rtems_chain_set_off_chain(
+ rtems_chain_node *node
+)
+{
+ _Chain_Set_off_chain( node );
+}
+
+/**
+ * @brief Is the Node off Chain
+ *
+ * This function returns true if the @a node is not on a chain. A @a node is
+ * off chain if the next and previous fields are set to NULL.
+ *
+ * @param[in] node is the node off chain.
+ *
+ * @return This function returns true if the @a node is off chain.
+ */
+RTEMS_INLINE_ROUTINE bool rtems_chain_is_node_off_chain(
+ const rtems_chain_node *node
+)
+{
+ return _Chain_Is_node_off_chain( node );
+}
+
+/**
* @brief Is the Chain Node Pointer NULL
*
* This function returns true if the_node is NULL and false otherwise.
@@ -172,6 +204,22 @@ RTEMS_INLINE_ROUTINE rtems_chain_node *rtems_chain_next(
}
/**
+ * @brief Return pointer the previous node from this node
+ *
+ * This function returns a pointer to the previous node on this chain.
+ *
+ * @param[in] the_node is the node to be operated upon.
+ *
+ * @return This method returns the previous node on the chain.
+ */
+RTEMS_INLINE_ROUTINE rtems_chain_node *rtems_chain_previous(
+ rtems_chain_node *the_node
+)
+{
+ return _Chain_Previous( the_node );
+}
+
+/**
* @brief Are Two Nodes Equal
*
* This function returns true if @a left and @a right are equal,
diff --git a/cpukit/score/inline/rtems/score/address.inl b/cpukit/score/inline/rtems/score/address.inl
index 417c069648..6a1fd3e9a3 100644
--- a/cpukit/score/inline/rtems/score/address.inl
+++ b/cpukit/score/inline/rtems/score/address.inl
@@ -42,10 +42,10 @@
#include <rtems/bspIo.h>
RTEMS_INLINE_ROUTINE void *_Addresses_Add_offset (
const void *base,
- intptr_t offset
+ uintptr_t offset
)
{
- return (void *)((intptr_t)base + offset);
+ return (void *)((uintptr_t)base + offset);
}
/** @brief Subtract Offset from Offset
@@ -62,10 +62,10 @@ RTEMS_INLINE_ROUTINE void *_Addresses_Add_offset (
RTEMS_INLINE_ROUTINE void *_Addresses_Subtract_offset (
const void *base,
- intptr_t offset
+ uintptr_t offset
)
{
- return (void *)((intptr_t)base - offset);
+ return (void *)((uintptr_t)base - offset);
}
/** @brief Subtract Two Offsets
diff --git a/cpukit/score/inline/rtems/score/chain.inl b/cpukit/score/inline/rtems/score/chain.inl
index ca60aa94f5..3bde7fb229 100644
--- a/cpukit/score/inline/rtems/score/chain.inl
+++ b/cpukit/score/inline/rtems/score/chain.inl
@@ -32,6 +32,36 @@
* @{
*/
+/** @brief Set off chain
+ *
+ * This function sets the next and previous fields of the @a node to NULL
+ * indicating the @a node is not part of a chain.
+ *
+ * @param[in] node the node set to off chain.
+ */
+RTEMS_INLINE_ROUTINE void _Chain_Set_off_chain(
+ Chain_Node *node
+)
+{
+ node->next = node->previous = NULL;
+}
+
+/** @brief Is the Node off Chain
+ *
+ * This function returns true if the @a node is not on a chain. A @a node is
+ * off chain if the next and previous fields are set to NULL.
+ *
+ * @param[in] node is the node off chain.
+ *
+ * @return This function returns true if the @a node is off chain.
+ */
+RTEMS_INLINE_ROUTINE bool _Chain_Is_node_off_chain(
+ const Chain_Node *node
+)
+{
+ return (node->next == NULL) && (node->previous == NULL);
+}
+
/** @brief Are Two Nodes Equal
*
* This function returns true if @a left and @a right are equal,
diff --git a/cpukit/score/src/coremsgsubmit.c b/cpukit/score/src/coremsgsubmit.c
index 23f9f10256..a1cdae84ea 100644
--- a/cpukit/score/src/coremsgsubmit.c
+++ b/cpukit/score/src/coremsgsubmit.c
@@ -88,7 +88,7 @@ CORE_message_queue_Status _CORE_message_queue_Submit(
size
);
*(size_t *) the_thread->Wait.return_argument = size;
- the_thread->Wait.count = submit_type;
+ the_thread->Wait.count = (uint32_t) submit_type;
#if defined(RTEMS_MULTIPROCESSING)
if ( !_Objects_Is_local_id( the_thread->Object.id ) )
diff --git a/cpukit/score/src/objectallocate.c b/cpukit/score/src/objectallocate.c
index c924f39453..3a4e329ab6 100644
--- a/cpukit/score/src/objectallocate.c
+++ b/cpukit/score/src/objectallocate.c
@@ -73,7 +73,7 @@ Objects_Control *_Objects_Allocate(
if ( the_object ) {
uint32_t block;
- block = _Objects_Get_index( the_object->id ) -
+ block = (uint32_t) _Objects_Get_index( the_object->id ) -
_Objects_Get_index( information->minimum_id );
block /= information->allocation_size;
diff --git a/cpukit/score/src/objectfree.c b/cpukit/score/src/objectfree.c
index af12a0fe8b..f74394d0fa 100644
--- a/cpukit/score/src/objectfree.c
+++ b/cpukit/score/src/objectfree.c
@@ -50,8 +50,8 @@ void _Objects_Free(
if ( information->auto_extend ) {
uint32_t block;
- block =
- _Objects_Get_index( the_object->id ) - _Objects_Get_index( information->minimum_id );
+ block = (uint32_t) (_Objects_Get_index( the_object->id ) -
+ _Objects_Get_index( information->minimum_id ));
block /= information->allocation_size;
information->inactive_per_block[ block ]++;