diff options
Diffstat (limited to 'libstore/encode.c')
-rw-r--r-- | libstore/encode.c | 87 |
1 files changed, 69 insertions, 18 deletions
diff --git a/libstore/encode.c b/libstore/encode.c index 38490cc0..df27250d 100644 --- a/libstore/encode.c +++ b/libstore/encode.c @@ -1,9 +1,7 @@ /* Store wire encoding - Copyright (C) 1996 Free Software Foundation, Inc. - - Written by Miles Bader <miles@gnu.ai.mit.edu> - + Copyright (C) 1996,97,99,2001,02 Free Software Foundation, Inc. + Written by Miles Bader <miles@gnu.org> This file is part of the GNU Hurd. The GNU Hurd is free software; you can redistribute it and/or @@ -18,9 +16,10 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ #include <string.h> +#include <sys/mman.h> #include "store.h" @@ -32,13 +31,20 @@ store_std_leaf_allocate_encoding (const struct store *store, { enc->num_ports++; enc->num_ints += 6; - enc->num_offsets += store->num_runs; + enc->num_offsets += store->num_runs * 2; if (store->name) enc->data_len += strlen (store->name) + 1; enc->data_len += store->misc_len; return 0; } +/* The RPC protocol uses 32-bit off_t's, but store_offset_t is now 64 bits. */ +static inline int too_big (store_offset_t ofs) +{ + off_t o = (off_t) ofs; + return o < 0 || ((store_offset_t) o != ofs); +} + error_t store_std_leaf_encode (const struct store *store, struct store_enc *enc) { @@ -56,6 +62,10 @@ store_std_leaf_encode (const struct store *store, struct store_enc *enc) for (i = 0; i < store->num_runs; i++) { + if (sizeof (*enc->offsets) != sizeof (store->runs[i].start) + && (too_big (store->runs[i].start) + || too_big (store->runs[i].start + store->runs[i].length))) + return EOVERFLOW; enc->offsets[enc->cur_offset++] = store->runs[i].start; enc->offsets[enc->cur_offset++] = store->runs[i].length; } @@ -82,8 +92,9 @@ store_std_leaf_encode (const struct store *store, struct store_enc *enc) error_t store_encode (const struct store *store, struct store_enc *enc) { + void *buf; error_t err; - struct store_class *class = store->class; + const struct store_class *class = store->class; /* We zero each vector length for the allocate_encoding method to work, so save the old values. */ mach_msg_type_number_t init_num_ports = enc->num_ports; @@ -102,19 +113,36 @@ store_encode (const struct store *store, struct store_enc *enc) if (err) return err; + errno = 0; if (enc->num_ports > init_num_ports) - err = vm_allocate (mach_task_self (), - (vm_address_t *)&enc->ports, enc->num_ports, 1); - if (!err && enc->num_ints > init_num_ints) - err = vm_allocate (mach_task_self (), - (vm_address_t *)&enc->ints, enc->num_ints, 1); - if (!err && enc->num_offsets > init_num_offsets) - err = vm_allocate (mach_task_self (), - (vm_address_t *)&enc->offsets, enc->num_offsets, 1); - if (!err && enc->data_len > init_data_len) - err = vm_allocate (mach_task_self (), - (vm_address_t *)&enc->data, enc->data_len, 1); + { + buf = mmap (0, enc->num_ports * sizeof *enc->ports, + PROT_READ|PROT_WRITE, MAP_ANON, 0, 0); + if (buf != (void *) -1) + enc->ports = buf; + } + if (!errno && enc->num_ints > init_num_ints) + { + buf = mmap (0, enc->num_ints * sizeof *enc->ints, + PROT_READ|PROT_WRITE, MAP_ANON, 0, 0); + if (buf != (void *) -1) + enc->ints = buf; + } + if (!errno && enc->num_offsets > init_num_offsets) + { + buf = mmap (0, enc->num_offsets * sizeof *enc->offsets, + PROT_READ|PROT_WRITE, MAP_ANON, 0, 0); + if (buf != (void *) -1) + enc->offsets = buf; + } + if (!errno && enc->data_len > init_data_len) + { + buf = mmap (0, enc->data_len, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0); + if (buf != (void *) -1) + enc->data = buf; + } + err = errno; if (! err) err = (*class->encode) (store, enc); @@ -125,3 +153,26 @@ store_encode (const struct store *store, struct store_enc *enc) return err; } + +/* Encode STORE into the given return variables, suitably for returning from a + file_get_storage_info rpc. */ +error_t +store_return (const struct store *store, + mach_port_t **ports, mach_msg_type_number_t *num_ports, + int **ints, mach_msg_type_number_t *num_ints, + off_t **offsets, mach_msg_type_number_t *num_offsets, + char **data, mach_msg_type_number_t *data_len) +{ + error_t err; + struct store_enc enc; + + store_enc_init (&enc, *ports, *num_ports, *ints, *num_ints, + *offsets, *num_offsets, *data, *data_len); + err = store_encode (store, &enc); + if (err) + store_enc_dealloc (&enc); + else + store_enc_return (&enc, ports, num_ports, ints, num_ints, + offsets, num_offsets, data, data_len); + return err; +} |