/* Store I/O Copyright (C) 1995, 1996 Free Software Foundation, Inc. Written by Miles Bader This file is part of the GNU Hurd. The GNU Hurd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. The GNU Hurd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 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. */ #ifndef __STORE_H__ #define __STORE_H__ #include #include #include #include /* A portion of a store. If START == -1, it's a hole. */ struct store_run { off_t start, length; }; struct store { /* If this store was created using store_create, the file from which we got our store. */ file_t source; /* Address ranges in the underlying storage which make up our contiguous address space. In units of BLOCK_SIZE, below. */ struct store_run *runs; /* Malloced */ size_t num_runs; /* Length of RUNS. */ /* Maximum valid offset. This is the same as SIZE, but in blocks. */ off_t end; /* WRAP_SRC is the sum of the run lengths in RUNS. If this is less than END, then RUNS describes a repeating pattern, of length WRAP_SRC -- each successive iteration having an additional offset of WRAP_DST. */ off_t wrap_src; off_t wrap_dst; /* Only meaningful if WRAP_SRC < END */ /* Handles for the underlying storage. */ char *name; /* Malloced */ mach_port_t port; /* Send right */ /* The size of a `block' on this storage. */ size_t block_size; /* The number of blocks (of size BLOCK_SIZE) in this storage. */ size_t blocks; /* The number of bytes in this storage, including holes. */ size_t size; /* Log_2 (BLOCK_SIZE) or 0 if not a power of 2. */ int log2_block_size; /* Log_2 (VM_PAGE_SIZE / BLOCK_SIZE); only valid if LOG2_BLOCK_SIZE is. */ int log2_blocks_per_page; /* Random flags. */ int flags; void *misc; /* malloced */ size_t misc_len; struct store_class *class; /* A list of sub-stores. The interpretation of this is type-specific. */ struct store **children; size_t num_children; void *hook; /* Type specific noise. */ }; /* Store flags. These are in addition to the STORAGE_ flags defined in . XXX synchronize these values. */ /* Flags that reflect something immutable about the object. */ #define STORE_IMMUTABLE_FLAGS 0xFF /* Flags implemented by generic store code. */ #define STORE_READONLY 0x100 /* No writing allowed. */ #define STORE_GENERIC_FLAGS STORE_READONLY /* Flags implemented by each backend. */ #define STORE_HARD_READONLY 0x200 /* Can't be made writable. */ #define STORE_ENFORCED 0x400 /* Range is enforced by device. */ #define STORE_BACKEND_SPEC_BASE 0x1000 /* Here up are backend-specific */ #define STORE_BACKEND_FLAGS (STORE_HARD_READONLY | STORE_ENFORCED \ | ~(STORE_BACKEND_SPEC_BASE - 1)) typedef error_t (*store_write_meth_t)(struct store *store, off_t addr, size_t index, char *buf, mach_msg_type_number_t len, mach_msg_type_number_t *amount); typedef error_t (*store_read_meth_t)(struct store *store, off_t addr, size_t index, mach_msg_type_number_t amount, char **buf, mach_msg_type_number_t *len); struct store_enc; /* fwd decl */ struct store_class { /* The type of storage this is (see STORAGE_ in hurd/hurd_types.h). */ enum file_storage_class id; /* Name of the class. */ char *name; /* Read up to AMOUNT bytes at the underlying address ADDR from the storage into BUF and LEN. INDEX varies from 0 to the number of runs in STORE. */ store_read_meth_t read; /* Write up to LEN bytes from BUF to the storage at the underlying address ADDR. INDEX varies from 0 to the number of runs in STORE. */ store_write_meth_t write; /* To the lengths of each for the four arrays in ENC, add how much STORE would need to be encoded. */ error_t (*allocate_encoding)(const struct store *store, struct store_enc *enc); /* Append the encoding for STORE to ENC. */ error_t (*encode) (const struct store *store, struct store_enc *enc); /* Decode from ENC a new store, which return in STORE. CLASSES is used to lookup child classes. */ error_t (*decode) (struct store_enc *enc, struct store_class *classes, struct store **store); /* Modify flags that reflect backend state, such as STORE_HARD_READONLY and STORE_ENFORCED. */ error_t (*set_flags) (struct store *store, int flags); error_t (*clear_flags) (struct store *store, int flags); /* Called just before deallocating STORE. */ void (*cleanup) (struct store *store); /* Copy any format-dependent fields in FROM to TO; if there's some reason why the copy can't be made, an error should be returned. This call is made after all format-indendependent fields have been cloned. */ error_t (*clone) (const struct store *from, struct store *to); /* For making a list of classes to pass to e.g. store_create. */ struct store_class *next; }; /* Return a new store in STORE, which refers to the storage underlying SOURCE. CLASSES is used to select classes specified by the provider; if it is 0, STORE_STD_CLASSES is used. FLAGS is set with store_set_flags. A reference to SOURCE is created (but may be destroyed with store_close_source). */ error_t store_create (file_t source, int flags, struct store_class *classes, struct store **store); void store_free (struct store *store); /* Allocate a new store structure with class CLASS, and the various other fields initialized to the given parameters. */ struct store * _make_store (struct store_class *class, mach_port_t port, int flags, size_t block_size, const struct store_run *runs, size_t num_runs, off_t end); /* Set STORE's current runs list to (a copy of) RUNS and NUM_RUNS. */ error_t store_set_runs (struct store *store, const struct store_run *runs, size_t num_runs); /* Set STORE's current children to (a copy of) CHILDREN and NUM_CHILDREN (note that just the vector CHILDREN is copied, not the actual children). */ error_t store_set_children (struct store *store, struct store *const *children, size_t num_children); /* Sets the name associated with STORE to a copy of NAME. */ error_t store_set_name (struct store *store, const char *name); /* Add FLAGS to STORE's currently set flags. */ error_t store_set_flags (struct store *store, int flags); /* Remove FLAGS from STORE's currently set flags. */ error_t store_clear_flags (struct store *store, int flags); /* Fills in the values of the various fields in STORE that are derivable from the set of runs & the block size. */ void _store_derive (struct store *store); /* Return in TO a copy of FROM. */ error_t store_clone (struct store *from, struct store **to); /* Write LEN bytes from BUF to STORE at ADDR. Returns the amount written in AMOUNT (in bytes). ADDR is in BLOCKS (as defined by STORE->block_size). */ error_t store_write (struct store *store, off_t addr, char *buf, size_t len, size_t *amount); /* Read AMOUNT bytes from STORE at ADDR into BUF & LEN (which following the usual mach buffer-return semantics) to STORE at ADDR. ADDR is in BLOCKS (as defined by STORE->block_size). Note that LEN is in bytes. */ error_t store_read (struct store *store, off_t addr, size_t amount, char **buf, size_t *len); /* If STORE was created using store_create, remove the reference to the source from which it was created. */ void store_close_source (struct store *store); #if 0 /* Return a memory object paging on STORE. [among other reasons,] this may fail because store contains non-contiguous regions on the underlying object. In such a case you can try calling some of the routines below to get a pager. */ error_t store_map (struct store *store, vm_prot_t prot, ..., mach_port_t *pager); /* Returns a memory object paging on the file from which STORE was created. If STORE wasn't created using store_create, or the source was destroyed using store_close_source, this will fail. */ error_t store_map_source (struct store *store, vm_prot_t prot, ..., mach_port_t *pager) /* Create a new pager and paging threads paging on STORE, and return the resulting memory object in PAGER. */ error_t store_create_pager (struct store *store, vm_prot_t prot, ..., mach_port_t *pager) #endif /* Creating specific types of stores. */ /* Return a new store in STORE referring to the mach device DEVICE. Consumes the send right DEVICE. */ error_t store_device_create (device_t device, int flags, struct store **store); /* Like store_device_create, but doesn't query the device for information. */ error_t _store_device_create (device_t device, int flags, size_t block_size, const struct store_run *runs, size_t num_runs, struct store **store); /* Open the device NAME, and return the corresponding store in STORE. */ error_t store_device_open (const char *name, int flags, struct store **store); /* Return a new store in STORE referring to the file FILE. Unlike store_create, this will always use file i/o, even it would be possible to be more direct. This may work in more cases, for instance if the file has holes. Consumes the send right FILE. */ error_t store_file_create (file_t file, int flags, struct store **store); /* Like store_file_create, but doesn't query the file for information. */ error_t _store_file_create (file_t file, int flags, size_t block_size, const struct store_run *runs, size_t num_runs, struct store **store); /* Open the file NAME, and return the corresponding store in STORE. */ error_t store_file_open (const char *name, int flags, struct store **store); /* Return a new store in STORE that interleaves all the stores in STRIPES (NUM_STRIPES of them) every INTERLEAVE bytes; INTERLEAVE must be an integer multiple of each stripe's block size. The stores in STRIPES are consumed -- that is, will be freed when this store is (however, the *array* STRIPES is copied, and so should be freed by the caller). */ error_t store_ileave_create (struct store * const *stripes, size_t num_stripes, off_t interleave, int flags, struct store **store); /* Return a new store in STORE that concatenates all the stores in STORES (NUM_STORES of them). The stores in STRIPES are consumed -- that is, will be freed when this store is (however, the *array* STRIPES is copied, and so should be freed by the caller). */ error_t store_concat_create (struct store * const *stores, size_t num_stores, int flags, struct store **store); /* Return a new null store SIZE bytes long in STORE. */ error_t store_null_create (size_t size, int flags, struct store **store); /* Standard store classes implemented by libstore. */ extern struct store_class *store_std_classes; /* Add CLASS to the list of standard classes. It must not already be in the list, or in any other, as its next field is simply written over. */ void _store_add_std_class (struct store_class *class); /* Use this macro to automagically add a class to STORE_STD_CLASSES at startup. */ #define _STORE_STD_CLASS(class_struct) \ static void _store_init_std_##class_struct () __attribute__ ((constructor));\ static void _store_init_std_##class_struct () \ { \ _store_add_std_class (&class_struct); \ } /* Used to hold the various bits that make up the representation of a store for transmission via rpc. See for an explanation of the encodings for the various storage types. */ struct store_enc { /* Each of the four vectors used. All are vm_allocated. */ mach_port_t *ports; int *ints; off_t *offsets; char *data; /* The sizes of the vectors. */ mach_msg_type_number_t num_ports, num_ints, num_offsets, data_len; /* Offsets into the above vectors, for an encoding/decoding in progress. */ size_t cur_port, cur_int, cur_offset, cur_data; /* Each of these is an `initial' version of the associated vector. When store_enc_dealloc is called, any vector that is the same as its `init_' version won't be deallocated. */ mach_port_t *init_ports; int *init_ints; off_t *init_offsets; char *init_data; }; /* Initialize ENC. The given vector and sizes will be used for the encoding if they are big enough (otherwise new ones will be automatically allocated). */ void store_enc_init (struct store_enc *enc, 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); /* Deallocate storage used by the fields in ENC (but nothing is done with ENC itself). */ void store_enc_dealloc (struct store_enc *enc); /* Encode STORE into ENC, which should have been prepared with store_enc_init, or return an error. The contents of ENC may then be return as the value of file_get_storage_info; if for some reason this can't be done, store_enc_dealloc may be used to deallocate the mmemory used by the unsent vectors. */ error_t store_encode (const struct store *store, struct store_enc *enc); /* Decode ENC, either returning a new store in STORE, or an error. CLASSES defines the mapping from hurd storage class ids to store classes; if it is 0, STORE_STD_CLASSES is used. If nothing else is to be done with ENC, its contents may then be freed using store_enc_dealloc. */ error_t store_decode (struct store_enc *enc, struct store_class *classes, struct store **store); /* Calls the allocate_encoding method in each child store of STORE, propagating any errors. If any child does not hae such a method, EOPNOTSUPP is returned. */ error_t store_allocate_child_encodings (const struct store *store, struct store_enc *enc); /* Calls the encode method in each child store of STORE, propagating any errors. If any child does not hae such a method, EOPNOTSUPP is returned. */ error_t store_encode_children (const struct store *store, struct store_enc *enc); /* Decodes NUM_CHILDREN from ENC, storing the results into successive positions in CHILDREN. */ error_t store_decode_children (struct store_enc *enc, int num_children, struct store_class *classes, struct store **children); /* Standard encoding used for most leaf store types. */ error_t store_std_leaf_allocate_encoding (const struct store *store, struct store_enc *enc); error_t store_std_leaf_encode (const struct store *store, struct store_enc *enc); /* Creation function signature used by store_std_leaf_decode. */ typedef error_t (*store_std_leaf_create_t)(mach_port_t port, int flags, size_t block_size, const struct store_run *runs, size_t num_runs, struct store **store); /* Decodes the standard leaf encoding that's common to various builtin formats, and calls CREATE to actually create the store. */ error_t store_std_leaf_decode (struct store_enc *enc, store_std_leaf_create_t create, struct store **store); /* An argument parser that may be used for parsing a simple command line specification for stores. The accompanying input parameter must be a pointer to a structure of type struct store_argp_param. */ extern struct argp store_argp; /* Structure used to pass in arguments and return the result from STORE_ARGP. */ struct store_argp_params { /* An initial set of flags desired to be set. */ int flags; /* If true, don't attempt use store_file_create to create a store on files upon which store_create has failed. */ int no_file_io : 1; /* Parsed store returned here. */ struct store *result; }; #endif /* __STORE_H__ */