diff options
Diffstat (limited to 'libdiskfs/filedev.c')
-rw-r--r-- | libdiskfs/filedev.c | 111 |
1 files changed, 69 insertions, 42 deletions
diff --git a/libdiskfs/filedev.c b/libdiskfs/filedev.c index 5a3e752d..ab600e8c 100644 --- a/libdiskfs/filedev.c +++ b/libdiskfs/filedev.c @@ -1,6 +1,6 @@ /* Get the mach device underlying a file - Copyright (C) 1995 Free Software Foundation, Inc. + Copyright (C) 1995, 1996 Free Software Foundation, Inc. Written by Miles Bader <miles@gnu.ai.mit.edu> @@ -25,8 +25,6 @@ #include "priv.h" -typedef int run_elem_t; - /* Returns the name and a send right for the mach device on which the file NAME is stored, and returns it in DEV_NAME (which is malloced) and PORT. Other values returned are START, the first valid offset, SIZE, the the @@ -40,12 +38,14 @@ diskfs_get_file_device (char *name, char **dev_name, mach_port_t *port, off_t *start, off_t *size, size_t *block_size) { + int i; error_t err; - int class, flags; - char *misc = 0; - off_t *runs = 0; - mach_msg_type_number_t misc_len = 0, runs_len = 0; - string_t dev_name_buf; + mach_msg_type_number_t data_len = 100; + mach_msg_type_number_t num_ints = 10, num_ports = 10, num_offsets = 10; + int _ints[num_ints], *ints = _ints; + mach_port_t _ports[num_ports], *ports = _ports; + off_t _offsets[num_offsets], *offsets = _offsets; + char *_data[data_len], **data = _data; file_t node = file_name_lookup (name, diskfs_readonly ? O_RDONLY : O_RDWR, 0); @@ -54,54 +54,81 @@ diskfs_get_file_device (char *name, *port = MACH_PORT_NULL; - err = file_get_storage_info (node, &class, &runs, &runs_len, block_size, - dev_name_buf, port, &misc, &misc_len, &flags); + err = file_get_storage_info (node, &ports, &num_ports, &ints, &num_ints, + &offsets, &num_offsets, &data, &data_len); if (err) - goto done; + return err; + + /* See <hurd/store.h> for an explanation of what's in the vectors returned + by file_get_storage_info. */ + + if (num_ints < 6) + err = EGRATUITOUS; + else if (ints[0] != STORAGE_DEVICE) + err = ENODEV; + + if (!err && blocksize) + *block_size = ints[2]; - if (class != STORAGE_DEVICE) + if (!err && port) + /* Extract the device port. */ + if (num_ports != 1) + err = EGRATUITOUS; + else + *port = ports[0]; + + if (!err && dev_name) + /* Extract the device name into DEV_NAME. */ { - err = ENODEV; - goto done; + size_t name_len = ints[4]; + if (data && name_len > 0) + if (data_len < name_len) + err = EGRATUITOUS; + else + { + *dev_name = malloc (name_len); + if (*dev_name) + strcpy (*dev_name, dev_name_buf); + else + err = ENOMEM; + } } - if (dev_name) + if (!err && (start || size)) + /* Extract the device block addresses. */ { - *dev_name = malloc (strlen (dev_name_buf) + 1); - if (*dev_name) - strcpy (*dev_name, dev_name_buf); + size_t runs_len = ints[3]; + if (runs_len != 2) + /* We can't handle anything but a contiguous set of blocks. */ + err = ENODEV; /* XXX */ else - err = ENOMEM; + { + if (start) + *start = offsets[0]; + if (size) + *size = offsets[1]; + } } - if (start || size) - if (runs_len > 2) - /* We can't handle anything but a contiguous set of blocks. */ - err = ENODEV; /* XXX */ - else - { - if (start) - *start = runs[0]; - if (size) - *size = runs[1]; - } - - /* Note that we don't deallocate NODE, which should prevent the information - returned by file_get_storage_info from changing. */ + /* Note that we don't deallocate NODE unless we're returning an error, + which should prevent the information returned by file_get_storage_info + from changing. */ - done: if (err) + /* We got an error, so deallocate everything we got back from the device. */ { + for (i = 0; i < num_ports; i++) + if (MACH_PORT_VALID (ports[i])) + mach_port_deallocate (mach_task_self (), ports[i]); +#define DISCARD_MEM(v, vl, b) \ + if (v != b) \ + vm_deallocate (mach_task_self (), (vm_address_t)v, vl * sizeof *v); + DISCARD_MEM (ports, num_ports, _ports); + DISCARD_MEM (ints, num_ints, _ints); + DISCARD_MEM (offsets, num_offsets, _offsets); + DISCARD_MEM (data, data_len, _data); mach_port_deallocate (mach_task_self (), node); - if (*port) - mach_port_deallocate (mach_task_self (), *port); } - if (misc_len > 0) - vm_deallocate (mach_task_self (), (vm_address_t)misc, misc_len); - if (runs_len > 0) - vm_deallocate (mach_task_self (), - (vm_address_t)runs, runs_len * sizeof (*runs)); - return err; } |