dupfs.c revision 816d2c9cf7fb17fe808a081e076cb558f44ec30d
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * dupfs.c --- duplicate a ext2 filesystem handle
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (C) 1997, 1998, 2001, 2003, 2005 by Theodore Ts'o.
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * %Begin-Header%
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This file may be redistributed under the terms of the GNU Library
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * General Public License, version 2.
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * %End-Header%
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "config.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h>
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if HAVE_UNISTD_H
156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include <unistd.h>
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <time.h>
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string.h>
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include "ext2_fs.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ext2fsP.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)errcode_t ext2fs_dup_handle(ext2_filsys src, ext2_filsys *dest)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ext2_filsys	fs;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	errcode_t	retval;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	EXT2_CHECK_MAGIC(src, EXT2_ET_MAGIC_EXT2FS_FILSYS);
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs);
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (retval)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return retval;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*fs = *src;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	fs->device_name = 0;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	fs->super = 0;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	fs->orig_super = 0;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	fs->group_desc = 0;
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	fs->inode_map = 0;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	fs->block_map = 0;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	fs->badblocks = 0;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	fs->dblist = 0;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	fs->mmp_buf = 0;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	fs->mmp_cmp = 0;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	fs->mmp_fd = -1;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	io_channel_bumpcount(fs->io);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (fs->icache)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		fs->icache->refcount++;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	retval = ext2fs_get_mem(strlen(src->device_name)+1, &fs->device_name);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (retval)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		goto errout;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	strcpy(fs->device_name, src->device_name);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->super);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (retval)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		goto errout;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	memcpy(fs->super, src->super, SUPERBLOCK_SIZE);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->orig_super);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (retval)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		goto errout;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	memcpy(fs->orig_super, src->orig_super, SUPERBLOCK_SIZE);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize,
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				&fs->group_desc);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (retval)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		goto errout;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	memcpy(fs->group_desc, src->group_desc,
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       (size_t) fs->desc_blocks * fs->blocksize);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (src->inode_map) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		retval = ext2fs_copy_bitmap(src->inode_map, &fs->inode_map);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (retval)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			goto errout;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (src->block_map) {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		retval = ext2fs_copy_bitmap(src->block_map, &fs->block_map);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (retval)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			goto errout;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch	if (src->badblocks) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		retval = ext2fs_badblocks_copy(src->badblocks, &fs->badblocks);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (retval)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			goto errout;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (src->dblist) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		retval = ext2fs_copy_dblist(src->dblist, &fs->dblist);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (retval)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			goto errout;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (src->mmp_buf) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		retval = ext2fs_get_mem(src->blocksize, &fs->mmp_buf);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (retval)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			goto errout;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		memcpy(fs->mmp_buf, src->mmp_buf, src->blocksize);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (src->mmp_fd >= 0) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		fs->mmp_fd = dup(src->mmp_fd);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (fs->mmp_fd < 0) {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			retval = EXT2_ET_MMP_OPEN_DIRECT;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			goto errout;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (src->mmp_cmp) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		int align = ext2fs_get_dio_alignment(src->mmp_fd);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		retval = ext2fs_get_memalign(src->blocksize, align,
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					     &fs->mmp_cmp);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (retval)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			goto errout;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		memcpy(fs->mmp_cmp, src->mmp_cmp, src->blocksize);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*dest = fs;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return 0;
117errout:
118	ext2fs_free(fs);
119	return retval;
120
121}
122
123