summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--trans/streamio.c149
1 files changed, 82 insertions, 67 deletions
diff --git a/trans/streamio.c b/trans/streamio.c
index 8fa03fa4..13714239 100644
--- a/trans/streamio.c
+++ b/trans/streamio.c
@@ -113,7 +113,7 @@ extern inline size_t
buffer_read (struct buffer *b, void *data, size_t len)
{
size_t max = buffer_size (b);
-
+
if (len > max)
len = max;
@@ -123,7 +123,7 @@ buffer_read (struct buffer *b, void *data, size_t len)
if (b->head > b->buf + b->size / 2)
{
size_t size = buffer_size (b);
-
+
memmove (b->buf, b->head, size);
b->head = b->buf;
b->tail = b->buf + size;
@@ -183,11 +183,17 @@ error_t dev_sync (int wait);
static struct argp_option options[] =
{
- {"readonly", 'r', 0, 0, "Disallow writing"},
- {"writable", 'w', 0, 0, "Allow writing"},
{"rdev", 'n', "ID", 0,
"The stat rdev number for this node; may be either a"
" single integer, or of the form MAJOR,MINOR"},
+ {"readonly", 'r', 0, 0, "Disallow writing"},
+ {"rdonly", 0, 0, OPTION_ALIAS | OPTION_HIDDEN},
+ {"ro", 0, 0, OPTION_ALIAS | OPTION_HIDDEN},
+ {"writable", 'w', 0, 0, "Allow writing"},
+ {"rdwr", 0, 0, OPTION_ALIAS | OPTION_HIDDEN},
+ {"rw", 0, 0, OPTION_ALIAS | OPTION_HIDDEN},
+ {"writeonly", 'W',0, 0, "Disallow reading"},
+ {"wronly", 0, 0, OPTION_ALIAS | OPTION_HIDDEN},
{0}
};
@@ -197,10 +203,9 @@ static const char doc[] = "Translator for stream devices";
const char *argp_program_version = STANDARD_HURD_VERSION (streamdev);
-static char *stream_name = 0;
-static int readonly = 0;
-static int rdev = 0;
-static int nperopens = 0;
+static char *stream_name;
+static int rdev;
+static int nperopens;
/* Parse a single option. */
static error_t
@@ -209,11 +214,13 @@ parse_opt (int key, char *arg, struct argp_state *state)
switch (key)
{
case 'r':
- readonly = 1;
+ trivfs_allow_open = O_READ;
break;
-
case 'w':
- readonly = 0;
+ trivfs_allow_open = O_RDWR;
+ break;
+ case 'W':
+ trivfs_allow_open = O_WRITE;
break;
case 'n':
@@ -245,7 +252,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
if (stream_name == 0)
argp_usage (state);
break;
-
+
default:
return ARGP_ERR_UNKNOWN;
}
@@ -263,7 +270,7 @@ demuxer (mach_msg_header_t *inp, mach_msg_header_t *outp)
return (trivfs_demuxer (inp, outp)
|| device_reply_server (inp, outp));
}
-
+
int
main (int argc, char *argv[])
{
@@ -273,15 +280,12 @@ main (int argc, char *argv[])
argp_parse (&argp, argc, argv, 0, 0, 0);
- if (readonly)
- trivfs_allow_open &= ~O_WRITE;
-
task_get_bootstrap_port (mach_task_self (), &bootstrap);
if (bootstrap == MACH_PORT_NULL)
error (2, 0, "Must be started as a translator");
streamdev_bucket = ports_create_bucket ();
-
+
err = trivfs_startup (bootstrap, 0,
0, streamdev_bucket, 0, streamdev_bucket,
&fsys);
@@ -289,16 +293,20 @@ main (int argc, char *argv[])
error (3, err, "trivfs_startup");
mutex_init (&global_lock);
-
- input_buffer = create_buffer (256);
- if (!readonly)
- output_buffer = create_buffer (256);
condition_init (&open_alert);
condition_init (&select_alert);
- condition_implies (input_buffer->wait, &select_alert);
- if (!readonly)
- condition_implies (output_buffer->wait, &select_alert);
+
+ if (trivfs_allow_open & O_READ)
+ {
+ input_buffer = create_buffer (256);
+ condition_implies (input_buffer->wait, &select_alert);
+ }
+ if (trivfs_allow_open & O_WRITE)
+ {
+ output_buffer = create_buffer (256);
+ condition_implies (output_buffer->wait, &select_alert);
+ }
/* Launch */
ports_manage_port_operations_multithread (streamdev_bucket, demuxer,
@@ -321,10 +329,12 @@ static error_t
open_hook (struct trivfs_control *cntl, struct iouser *user, int flags)
{
error_t err;
- dev_mode_t mode = D_READ;
+ dev_mode_t mode;
- if (readonly && (flags & O_WRITE))
+ if (flags & O_WRITE & ~trivfs_allow_open)
return EROFS;
+ if (flags & O_READ & ~trivfs_allow_open)
+ return EIO;
if ((flags & (O_READ|O_WRITE)) == 0)
return 0;
@@ -332,9 +342,12 @@ open_hook (struct trivfs_control *cntl, struct iouser *user, int flags)
/* XXX */
if (flags & O_ASYNC)
return EOPNOTSUPP;
-
+
mutex_lock (&global_lock);
+ mode = 0;
+ if (flags & O_READ)
+ mode |= D_READ;
if (flags & O_WRITE)
mode |= D_WRITE;
@@ -411,7 +424,9 @@ trivfs_modify_stat (struct trivfs_protid *cred, struct stat *st)
st->st_mode &= ~S_IFMT;
st->st_mode |= S_IFCHR;
st->st_rdev = rdev;
- if (readonly)
+ if (trivfs_allow_open & O_READ)
+ st->st_mode &= ~(S_IRUSR | S_IRGRP | S_IROTH);
+ if (trivfs_allow_open & O_WRITE)
st->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
}
@@ -437,7 +452,7 @@ trivfs_goaway (struct trivfs_control *fsys, int flags)
if (force && nosync)
exit (0);
-
+
if (!force && ports_count_class (root_port_class) > 0)
goto busy;
@@ -449,7 +464,7 @@ trivfs_goaway (struct trivfs_control *fsys, int flags)
ports_enable_class (root_port_class);
ports_resume_class_rpcs (root_port_class);
mutex_unlock (&global_lock);
-
+
return EBUSY;
}
@@ -461,10 +476,10 @@ trivfs_S_io_read (struct trivfs_protid *cred,
off_t offs, mach_msg_type_number_t amount)
{
error_t err;
-
+
if (!cred)
return EOPNOTSUPP;
-
+
if (!(cred->po->openmodes & O_READ))
return EBADF;
@@ -480,10 +495,10 @@ trivfs_S_io_readable (struct trivfs_protid *cred,
mach_msg_type_number_t *amount)
{
error_t err;
-
+
if (!cred)
return EOPNOTSUPP;
-
+
if (!(cred->po->openmodes & O_READ))
return EBADF;
@@ -500,10 +515,10 @@ trivfs_S_io_write (struct trivfs_protid *cred,
off_t offs, mach_msg_type_number_t *amount)
{
error_t err;
-
+
if (!cred)
return EOPNOTSUPP;
-
+
if (!(cred->po->openmodes & O_WRITE))
return EBADF;
@@ -530,13 +545,13 @@ trivfs_S_io_select (struct trivfs_protid *cred,
int *type)
{
int available;
-
+
if (!cred)
return EOPNOTSUPP;
if (!(cred->po->openmodes & O_WRITE) && (*type & SELECT_WRITE))
return EBADF;
-
+
if (*type & ~(SELECT_READ | SELECT_WRITE))
return EINVAL;
@@ -648,7 +663,7 @@ trivfs_S_file_sync (struct trivfs_protid *cred,
int wait)
{
error_t err;
-
+
if (!cred)
return EOPNOTSUPP;
@@ -664,7 +679,7 @@ trivfs_S_file_syncfs (struct trivfs_protid *cred,
int wait, int dochildren)
{
error_t err;
-
+
if (!cred)
return EOPNOTSUPP;
@@ -721,7 +736,7 @@ dev_open (const char *name, dev_mode_t mode)
{
if (open_pending || (phys_device != MACH_PORT_NULL))
return 0;
-
+
err = get_privileged_ports (0, &device_master);
if (err)
return err;
@@ -738,7 +753,7 @@ dev_open (const char *name, dev_mode_t mode)
phys_reply = ports_get_right (phys_reply_pi);
mach_port_insert_right (mach_task_self (), phys_reply, phys_reply,
MACH_MSG_TYPE_MAKE_SEND);
-
+
if (output_buffer)
{
err = ports_create_port (phys_reply_class, streamdev_bucket,
@@ -758,7 +773,7 @@ dev_open (const char *name, dev_mode_t mode)
mach_port_insert_right (mach_task_self (), phys_reply_writes,
phys_reply_writes, MACH_MSG_TYPE_MAKE_SEND);
}
-
+
err = device_open_request (device_master, phys_reply, mode, name);
if (err)
{
@@ -787,7 +802,7 @@ device_open_reply (mach_port_t reply, int returncode, mach_port_t device)
size_t sizes[DEV_GET_SIZE_COUNT];
size_t sizes_len = DEV_GET_SIZE_COUNT;
int amount;
-
+
if (reply != phys_reply)
return EOPNOTSUPP;
@@ -795,7 +810,7 @@ device_open_reply (mach_port_t reply, int returncode, mach_port_t device)
open_pending = 0;
condition_broadcast (&open_alert);
-
+
if (returncode != 0)
{
dev_close ();
@@ -817,10 +832,10 @@ device_open_reply (mach_port_t reply, int returncode, mach_port_t device)
else if (err == 0)
{
assert (sizes_len == DEV_GET_SIZE_COUNT);
-
+
dev_blksize = sizes[DEV_GET_SIZE_RECORD_SIZE];
dev_size = sizes[DEV_GET_SIZE_DEVICE_SIZE];
-
+
assert (dev_blksize && dev_blksize <= IO_INBAND_MAX);
}
else
@@ -837,7 +852,7 @@ device_open_reply (mach_port_t reply, int returncode, mach_port_t device)
mutex_unlock (&global_lock);
return 0;
}
-
+
/* Check if the device is already opened. */
/* Be careful that the global lock is already locked. */
int
@@ -845,7 +860,7 @@ dev_already_opened (void)
{
return (phys_device != MACH_PORT_NULL);
}
-
+
/* Close the device. */
/* Be careful that the global lock is already locked. */
void
@@ -864,7 +879,7 @@ dev_close (void)
phys_reply_pi = 0;
clear_buffer (input_buffer);
input_pending = 0;
-
+
if (output_buffer)
{
mach_port_deallocate (mach_task_self (), phys_reply_writes);
@@ -884,7 +899,7 @@ start_input (int nowait)
int size;
error_t err;
size_t amount;
-
+
size = buffer_writable (input_buffer);
if (size < dev_blksize || input_pending)
@@ -893,7 +908,7 @@ start_input (int nowait)
amount = vm_page_size;
if (dev_blksize != 1)
amount = amount / dev_blksize * dev_blksize;
-
+
err = device_read_request_inband (phys_device, phys_reply,
nowait? D_NOWAIT : 0,
0, amount);
@@ -918,7 +933,7 @@ dev_read (size_t amount, void **buf, size_t *len, int nowait)
if (err)
return err;
-
+
while (!buffer_readable (input_buffer))
{
err = start_input (nowait);
@@ -930,7 +945,7 @@ dev_read (size_t amount, void **buf, size_t *len, int nowait)
*len = 0;
return 0;
}
-
+
if (nowait)
return EWOULDBLOCK;
@@ -970,11 +985,11 @@ device_read_reply_inband (mach_port_t reply, error_t errorcode,
mutex_unlock (&global_lock);
return 0;
}
-
+
while (datalen)
{
size_t nwritten;
-
+
while (!buffer_writable (input_buffer))
condition_wait (input_buffer->wait, &global_lock);
@@ -993,7 +1008,7 @@ device_read_reply_inband (mach_port_t reply, error_t errorcode,
mutex_unlock (&global_lock);
return 0;
}
-
+
/* Return current readable size in AMOUNT. If an error occurs, the error
code is returned, otherwise 0. */
/* Be careful that the global lock is already locked. */
@@ -1011,9 +1026,9 @@ start_output (int nowait)
int size;
assert (output_buffer);
-
+
size = buffer_size (output_buffer);
-
+
if (size < dev_blksize || output_pending)
return 0;
@@ -1049,23 +1064,23 @@ dev_write (void *buf, size_t len, size_t *amount, int nowait)
{
if (err)
return err;
-
+
while (!buffer_writable (output_buffer))
{
err = start_output (nowait);
if (err)
return err;
-
+
if (nowait)
return EWOULDBLOCK;
-
+
if (hurd_condition_wait (output_buffer->wait, &global_lock))
return EINTR;
}
*amount = buffer_write (output_buffer, buf, len);
err = start_output (nowait);
-
+
return err;
}
@@ -1078,7 +1093,7 @@ device_write_reply_inband (mach_port_t reply, error_t returncode, int amount)
mutex_lock (&global_lock);
output_pending = 0;
-
+
if (!returncode)
{
if (amount >= npending_output)
@@ -1107,16 +1122,16 @@ dev_sync (int wait)
{
if (err)
return err;
-
+
if (!output_buffer || phys_device == MACH_PORT_NULL)
return 0;
-
+
while (buffer_readable (output_buffer) >= dev_blksize)
{
err = start_output (! wait);
if (err)
return err;
-
+
if (!wait)
return 0;