summaryrefslogtreecommitdiffstats
path: root/src/H5F.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5F.c')
-rw-r--r--src/H5F.c395
1 files changed, 395 insertions, 0 deletions
diff --git a/src/H5F.c b/src/H5F.c
index 937cf5e..fe3dfb6 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -94,6 +94,13 @@ const H5F_create_t H5F_create_dflt = {
*/
H5F_access_t H5F_access_dflt;
+/*
+ * Define the default mount property list.
+ */
+const H5F_mprop_t H5F_mount_dflt = {
+ FALSE, /* Absolute symlinks are wrt mount root */
+};
+
/* Interface initialization */
static intn interface_initialize_g = FALSE;
#define INTERFACE_INIT H5F_init_interface
@@ -1661,6 +1668,394 @@ H5Fclose(hid_t file_id)
done:
FUNC_LEAVE(ret_value < 0 ? FAIL : SUCCEED);
}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_mount
+ *
+ * Purpose: Mount file CHILD onto the group specified by LOC and NAME,
+ * using mount properties in PLIST. CHILD must not already be
+ * mouted and must not be a mount ancestor of the mount-point.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, October 6, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5F_mount(H5G_entry_t *loc, const char *name, H5F_t *child,
+ const H5F_mprop_t *plist)
+{
+ H5G_t *mount_point = NULL; /*mount point group */
+ H5G_entry_t *mp_ent = NULL; /*mount point symbol table entry*/
+ H5F_t *ancestor = NULL; /*ancestor files */
+ H5F_t *parent = NULL; /*file containing mount point */
+ intn lt, rt, md, cmp; /*binary search indices */
+ H5G_entry_t *ent = NULL; /*temporary symbol table entry */
+ herr_t ret_value = FAIL; /*return value */
+
+ FUNC_ENTER(H5F_mount, FAIL);
+ assert(loc);
+ assert(name && *name);
+ assert(child);
+ assert(plist);
+
+ /*
+ * Check that the child isn't mounted, that the mount point exists, and
+ * that the mount wouldn't introduce a cycle in the mount tree.
+ */
+ if (child->mtab.parent) {
+ HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "file is already mounted");
+ }
+ if (NULL==(mount_point=H5G_open(loc, name))) {
+ HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "mount point not found");
+ }
+ parent = H5G_fileof(mount_point);
+ mp_ent = H5G_entof(mount_point);
+ for (ancestor=parent; ancestor; ancestor=ancestor->mtab.parent) {
+ if (ancestor==child) {
+ HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL,
+ "mount would introduce a cycle");
+ }
+ }
+
+ /*
+ * Use a binary search to locate the position that the child should be
+ * inserted into the parent mount table. At the end of this paragraph
+ * `md' will be the index where the child should be inserted.
+ */
+ lt = md = 0;
+ rt = parent->mtab.nmounts;
+ cmp = -1;
+ while (lt<rt && cmp) {
+ md = (lt+rt)/2;
+ ent = H5G_entof(parent->mtab.child[md].group);
+ cmp = H5F_addr_cmp(&(mp_ent->header), &(ent->header));
+ if (cmp<0) {
+ rt = md;
+ } else if (cmp>0) {
+ lt = md+1;
+ }
+ }
+ if (cmp>0) md++;
+ if (!cmp) {
+ HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL,
+ "mount point is already in use");
+ }
+
+ /* Make room in the table */
+ if (parent->mtab.nmounts>=parent->mtab.nalloc) {
+ uintn n = MAX(16, 2*parent->mtab.nalloc);
+ H5F_mount_t *x = H5MM_realloc(parent->mtab.child,
+ n*sizeof(parent->mtab.child[0]));
+ if (!x) {
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
+ "memory allocation failed for mount table");
+ }
+ parent->mtab.child = x;
+ parent->mtab.nalloc = n;
+ }
+
+ /* Insert into table */
+ HDmemmove(parent->mtab.child+md+1,
+ parent->mtab.child+md,
+ (parent->mtab.nmounts-md)*sizeof(parent->mtab.child[0]));
+ parent->mtab.nmounts++;
+ parent->mtab.child[md].group = mount_point;
+ parent->mtab.child[md].file = child;
+ child->mtab.parent = parent;
+ ret_value = SUCCEED;
+
+ done:
+ if (ret_value<0 && mount_point) {
+ H5G_close(mount_point);
+ }
+ FUNC_LEAVE(ret_value);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_unmount
+ *
+ * Purpose: Unmount the child which is mounted at the group specified by
+ * LOC and NAME or fail if nothing is mounted there. Neither
+ * file is closed.
+ *
+ * Because the mount point is specified by name and opened as a
+ * group, the H5G_namei() will resolve it to the root of the
+ * mounted file, not the group where the file is mounted.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, October 6, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5F_unmount(H5G_entry_t *loc, const char *name)
+{
+ H5G_t *mounted = NULL; /*mount point group */
+ H5G_entry_t *mnt_ent = NULL; /*mounted symbol table entry */
+ H5F_t *child = NULL; /*mounted file */
+ H5F_t *parent = NULL; /*file where mounted */
+ H5G_entry_t *ent = NULL; /*temporary symbol table entry */
+ herr_t ret_value = FAIL; /*return value */
+ uintn i; /*coutners */
+ intn lt, rt, md, cmp; /*binary search indices */
+
+ FUNC_ENTER(H5F_unmount, FAIL);
+ assert(loc);
+ assert(name && *name);
+
+ /*
+ * Get the mount point, or more precisely the root of the mounted file.
+ * If we get the root group and the file has a parent in the mount tree,
+ * then we must have found the mount point.
+ */
+ if (NULL==(mounted=H5G_open(loc, name))) {
+ HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "mount point not found");
+ }
+ child = H5G_fileof(mounted);
+ mnt_ent = H5G_entof(mounted);
+ ent = H5G_entof(child->shared->root_grp);
+
+ if (child->mtab.parent &&
+ H5F_addr_eq(&(mnt_ent->header), &(ent->header))) {
+ /*
+ * We've been given the root group of the child. We do a reverse
+ * lookup in the parent's mount table to find the correct entry.
+ */
+ parent = child->mtab.parent;
+ for (i=0; i<parent->mtab.nmounts; i++) {
+ if (parent->mtab.child[i].file==child) {
+ /* Unmount the child */
+ parent->mtab.nmounts -= 1;
+ H5G_close(parent->mtab.child[i].group);
+ child->mtab.parent = NULL;
+ HDmemmove(parent->mtab.child+i,
+ parent->mtab.child+i+1,
+ ((parent->mtab.nmounts-i)*
+ sizeof(parent->mtab.child[0])));
+ ret_value = SUCCEED;
+ }
+ }
+ assert(ret_value>=0);
+
+ } else {
+ /*
+ * We've been given the mount point in the parent. We use a binary
+ * search in the parent to locate the mounted file, if any.
+ */
+ parent = child; /*we guessed wrong*/
+ lt = 0;
+ rt = parent->mtab.nmounts;
+ cmp = -1;
+ while (lt<rt && cmp) {
+ md = (lt+rt)/2;
+ ent = H5G_entof(parent->mtab.child[md].group);
+ cmp = H5F_addr_cmp(&(mnt_ent->header), &(ent->header));
+ if (cmp<0) {
+ rt = md;
+ } else {
+ lt = md+1;
+ }
+ }
+ if (cmp) {
+ HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "not a mount point");
+ }
+
+ /* Unmount the child */
+ parent->mtab.nmounts -= 1;
+ H5G_close(parent->mtab.child[md].group);
+ parent->mtab.child[md].file->mtab.parent = NULL;
+ HDmemmove(parent->mtab.child+md,
+ parent->mtab.child+md+1,
+ (parent->mtab.nmounts-md)*sizeof(parent->mtab.child[0]));
+ ret_value = SUCCEED;
+ }
+
+ done:
+ if (mounted) H5G_close(mounted);
+ FUNC_LEAVE(ret_value);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_mountpoint
+ *
+ * Purpose: If ENT is a mount point then copy the entry for the root
+ * group of the mounted file into ENT.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, October 6, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_mountpoint(H5G_entry_t *find/*in,out*/)
+{
+ H5F_t *parent = find->file;
+ intn lt, rt, md, cmp;
+ H5G_entry_t *ent = NULL;
+
+ FUNC_ENTER(H5F_mountpoint, FAIL);
+ assert(find);
+
+ /*
+ * The loop is necessary because we might have file1 mounted at the root
+ * of file2, which is mounted somewhere in file3.
+ */
+ do {
+ /*
+ * Use a binary search to find the potential mount point in the mount
+ * table for the parent
+ */
+ lt = 0;
+ rt = parent->mtab.nmounts;
+ cmp = -1;
+ while (lt<rt && cmp) {
+ md = (lt+rt)/2;
+ ent = H5G_entof(parent->mtab.child[md].group);
+ cmp = H5F_addr_cmp(&(find->header), &(ent->header));
+ if (cmp<0) {
+ rt = md;
+ } else {
+ lt = md+1;
+ }
+ }
+
+ /* Copy root info over to ENT */
+ if (0==cmp) {
+ ent = H5G_entof(parent->mtab.child[md].file->shared->root_grp);
+ *find = *ent;
+ }
+ } while (!cmp);
+
+ FUNC_LEAVE(SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Fmount
+ *
+ * Purpose: Mount file CHILD_ID onto the group specified by LOC_ID and
+ * NAME using mount properties PLIST_ID.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, October 6, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Fmount(hid_t loc_id, const char *name, hid_t child_id, hid_t plist_id)
+{
+ H5G_entry_t *loc = NULL;
+ const H5F_mprop_t *plist = NULL;
+ H5F_t *child = NULL;
+
+ FUNC_ENTER(H5Fmount, FAIL);
+ H5TRACE4("e","isii",loc_id,name,child_id,plist_id);
+
+ /* Check arguments */
+ if (NULL==(loc=H5G_loc(loc_id))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location");
+ }
+ if (!name || !*name) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name");
+ }
+ if (H5I_FILE!=H5I_get_type(child_id) ||
+ NULL==(child=H5I_object(child_id))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file");
+ }
+ if (H5P_DEFAULT==plist_id) {
+ plist = &H5F_mount_dflt;
+ } else if (H5P_MOUNT!=H5P_get_class(plist_id) ||
+ NULL==(plist=H5I_object(plist_id))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL,
+ "not a mount property list");
+ }
+
+ /* Do the mount */
+ if (H5F_mount(loc, name, child, plist)<0) {
+ HRETURN_ERROR(H5E_FILE, H5E_MOUNT, FAIL,
+ "unable to mount file");
+ }
+
+ FUNC_LEAVE(SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Funmount
+ *
+ * Purpose: Given a mount point, dissassociate the mount point's file
+ * from the file mounted there. Do not close either file.
+ *
+ * The mount point can either be the group in the parent or the
+ * root group of the mounted file (both groups have the same
+ * name). If the mount point was opened before the mount then
+ * it's the group in the parent, but if it was opened after the
+ * mount then it's the root group of the child.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, October 6, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5Funmount(hid_t loc_id, const char *name)
+{
+ H5G_entry_t *loc = NULL;
+
+ FUNC_ENTER(H5Funmount, FAIL);
+ H5TRACE2("i","is",loc_id,name);
+
+ /* Check args */
+ if (NULL==(loc=H5G_loc(loc_id))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location");
+ }
+ if (!name || !*name) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name");
+ }
+
+ /* Unmount */
+ if (H5F_unmount(loc, name)<0) {
+ HRETURN_ERROR(H5E_FILE, H5E_MOUNT, FAIL,
+ "unable to unmount file");
+ }
+
+ FUNC_LEAVE(SUCCEED);
+}
+
/*-------------------------------------------------------------------------
* Function: H5F_block_read