]> git.ipfire.org Git - thirdparty/e2fsprogs.git/blob - lib/ext2fs/closefs.c
e24b6b6972644e72068d067b2cd66a5666eac826
[thirdparty/e2fsprogs.git] / lib / ext2fs / closefs.c
1 /*
2 * closefs.c --- close an ext2 filesystem
3 *
4 * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
5 *
6 * %Begin-Header%
7 * This file may be redistributed under the terms of the GNU Public
8 * License.
9 * %End-Header%
10 */
11
12 #include <stdio.h>
13 #include <unistd.h>
14 #include <stdlib.h>
15 #include <time.h>
16 #include <string.h>
17 #ifdef HAVE_ERRNO_H
18 #include <errno.h>
19 #endif
20
21 #include <linux/ext2_fs.h>
22
23 #include "ext2fsP.h"
24
25 errcode_t ext2fs_flush(ext2_filsys fs)
26 {
27 int i,j,maxgroup;
28 int group_block;
29 errcode_t retval;
30 char *group_ptr;
31 unsigned long fs_state;
32 struct ext2_super_block *super_shadow = 0;
33 struct ext2_group_desc *group_shadow = 0;
34 struct ext2_group_desc *s, *t;
35
36 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
37
38 fs_state = fs->super->s_state;
39
40 fs->super->s_wtime = time(NULL);
41 if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
42 retval = ENOMEM;
43 if (!(super_shadow = malloc(SUPERBLOCK_SIZE)))
44 goto errout;
45 if (!(group_shadow = malloc(fs->blocksize*fs->desc_blocks)))
46 goto errout;
47 memset(group_shadow, 0, fs->blocksize*fs->desc_blocks);
48
49 /* swap the superblock */
50 *super_shadow = *fs->super;
51 ext2fs_swap_super(super_shadow);
52
53 /* swap the group descriptors */
54 for (j=0, s=fs->group_desc, t=group_shadow;
55 j < fs->group_desc_count; j++, t++, s++) {
56 *t = *s;
57 ext2fs_swap_group_desc(t);
58 }
59 } else {
60 super_shadow = fs->super;
61 group_shadow = fs->group_desc;
62 }
63
64 /*
65 * Write out master superblock. This has to be done
66 * separately, since it is located at a fixed location
67 * (SUPERBLOCK_OFFSET).
68 */
69 io_channel_set_blksize(fs->io, SUPERBLOCK_OFFSET);
70 retval = io_channel_write_blk(fs->io, 1, -SUPERBLOCK_SIZE,
71 super_shadow);
72 if (retval)
73 goto errout;
74 io_channel_set_blksize(fs->io, fs->blocksize);
75
76 /*
77 * Set the state of the FS to be non-valid. (The state has
78 * already been backed up earlier, and will be restored when
79 * we exit.)
80 */
81 fs->super->s_state &= ~EXT2_VALID_FS;
82 if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
83 *super_shadow = *fs->super;
84 ext2fs_swap_super(super_shadow);
85 }
86
87 /*
88 * Write out the master group descriptors, and the backup
89 * superblocks and group descriptors.
90 */
91 group_block = fs->super->s_first_data_block;
92 maxgroup = (fs->flags & EXT2_FLAG_MASTER_SB_ONLY) ? 1 :
93 fs->group_desc_count;
94 for (i = 0; i < maxgroup; i++) {
95 if (i !=0 ) {
96 retval = io_channel_write_blk(fs->io, group_block,
97 -SUPERBLOCK_SIZE,
98 super_shadow);
99 if (retval)
100 goto errout;
101 }
102 group_ptr = (char *) group_shadow;
103 for (j=0; j < fs->desc_blocks; j++) {
104 retval = io_channel_write_blk(fs->io,
105 group_block+1+j, 1,
106 group_ptr);
107 if (retval)
108 goto errout;
109 group_ptr += fs->blocksize;
110 }
111 group_block += EXT2_BLOCKS_PER_GROUP(fs->super);
112 }
113
114 /*
115 * If the write_bitmaps() function is present, call it to
116 * flush the bitmaps. This is done this way so that a simple
117 * program that doesn't mess with the bitmaps doesn't need to
118 * drag in the bitmaps.c code.
119 */
120 if (fs->write_bitmaps) {
121 retval = fs->write_bitmaps(fs);
122 if (retval)
123 goto errout;
124 }
125 retval = 0;
126 errout:
127 fs->super->s_state = fs_state;
128 if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
129 if (super_shadow)
130 free(super_shadow);
131 if (group_shadow)
132 free(group_shadow);
133 }
134 return retval;
135 }
136
137 errcode_t ext2fs_close(ext2_filsys fs)
138 {
139 errcode_t retval;
140
141 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
142
143 if (fs->flags & EXT2_FLAG_DIRTY) {
144 retval = ext2fs_flush(fs);
145 if (retval)
146 return retval;
147 }
148 if (fs->write_bitmaps) {
149 retval = fs->write_bitmaps(fs);
150 if (retval)
151 return retval;
152 }
153 ext2fs_free(fs);
154 return 0;
155 }
156
157 /*
158 * This procedure frees a badblocks list.
159 */
160 void ext2fs_badblocks_list_free(ext2_badblocks_list bb)
161 {
162 if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
163 return;
164
165 if (bb->list)
166 free(bb->list);
167 bb->list = 0;
168 free(bb);
169 }
170
171 /*
172 * Close a directory block list
173 */
174 void ext2fs_free_dblist(ext2_dblist dblist)
175 {
176 if (!dblist || (dblist->magic != EXT2_ET_MAGIC_DBLIST))
177 return;
178
179 if (dblist->list)
180 free(dblist->list);
181 dblist->list = 0;
182 if (dblist->fs && dblist->fs->dblist == dblist)
183 dblist->fs->dblist = 0;
184 dblist->magic = 0;
185 free(dblist);
186 }