http://linux-ntfs.sourceforge.net/snapshots/ntfsprogs-200307311516.tar.bz2
[ntfsprogs.git] / libntfs / inode.c
1 /*
2  * inode.c - Inode handling code. Part of the Linux-NTFS project.
3  *
4  * Copyright (c) 2002 Anton Altaparmakov
5  *
6  * This program/include file is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as published
8  * by the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program/include file is distributed in the hope that it will be
12  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program (in the main directory of the Linux-NTFS
18  * distribution in the file COPYING); if not, write to the Free Software
19  * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25
26 #include "compat.h"
27
28 #include "types.h"
29 #include "inode.h"
30 #include "debug.h"
31 #include "mft.h"
32 #include "attrib.h"
33 #include "runlist.h"
34
35 /**
36  * Internal:
37  *
38  * __ntfs_inode_allocate - desc
39  */
40 static __inline__ ntfs_inode *__ntfs_inode_allocate(ntfs_volume *vol)
41 {
42         ntfs_inode *ni;
43
44         ni = (ntfs_inode*)calloc(1, sizeof(ntfs_inode));
45         if (ni)
46                 ni->vol = vol;
47         return ni;
48 }
49
50 /**
51  * Internal:
52  *
53  * ntfs_inode_allocate - desc
54  */
55 ntfs_inode *ntfs_inode_allocate(ntfs_volume *vol)
56 {
57         return __ntfs_inode_allocate(vol);
58 }
59
60 /**
61  * Internal:
62  *
63  * __ntfs_inode_release - desc
64  */
65 static __inline__ int __ntfs_inode_release(ntfs_inode *ni)
66 {
67         if (NInoDirty(ni))
68                 Dputs("Eeek. Discarding dirty inode!");
69         if (NInoAttrList(ni) && ni->attr_list)
70                 free(ni->attr_list);
71         if (NInoAttrListNonResident(ni) && ni->attr_list_rl)
72                 free(ni->attr_list_rl);
73         if (ni->mrec)
74                 free(ni->mrec);
75         free(ni);
76         return 0;
77 }
78
79 /**
80  * ntfs_inode_open - open an inode ready for access
81  * @vol:        volume to get the inode from
82  * @mref:       inode number / mft record number to open
83  *
84  * Allocate an ntfs_inode structure and initialize it for the given inode
85  * specified by @mref. @mref specifies the inode number / mft record to read,
86  * including the sequence number, which can be 0 if no sequence number checking
87  * is to be performed.
88  *
89  * Then, allocate a buffer for the mft record, read the mft record from the
90  * volume @vol, and attach it to the ntfs_inode structure (->mrec). The
91  * mft record is mst deprotected and sanity checked for validity and we abort
92  * if deprotection or checks fail.
93  *
94  * Finally, search for an attribute list attribute in the mft record and if one
95  * is found, load the attribute list attribute value and attach it to the
96  * ntfs_inode structure (->attr_list). Also set the NI_AttrList bit to indicate
97  * this as well as the NI_AttrListNonResident bit if the the attribute list is
98  * non-resident. In that case, also attach the decompressed runlist to the
99  * ntfs_inode structure (->attr_list_rl).
100  *
101  * Return a pointer to the ntfs_inode structure on success or NULL on error,
102  * with errno set to the error code.
103  */
104 ntfs_inode *ntfs_inode_open(ntfs_volume *vol, const MFT_REF mref)
105 {
106         s64 l;
107         ntfs_inode *ni;
108         ntfs_attr_search_ctx *ctx;
109         int err = 0;
110
111         Dprintf("%s(): Entering for inode 0x%Lx.\n", __FUNCTION__, MREF(mref));
112         if (!vol) {
113                 errno = EINVAL;
114                 return NULL;
115         }
116         ni = __ntfs_inode_allocate(vol);
117         if (!ni)
118                 return NULL;
119         if (ntfs_file_record_read(vol, mref, &ni->mrec, NULL))
120                 goto err_out;
121         if (!(ni->mrec->flags & MFT_RECORD_IN_USE))
122                 goto err_out;
123         ni->mft_no = MREF(mref);
124         ctx = ntfs_attr_get_search_ctx(ni, NULL);
125         if (!ctx)
126                 goto err_out;
127         if (ntfs_attr_lookup(AT_ATTRIBUTE_LIST, AT_UNNAMED, 0, 0, 0, NULL, 0,
128                         ctx)) {
129                 if (errno != ENOENT)
130                         goto put_err_out;
131                 /* Attribute list attribute not present so we are done. */
132                 ntfs_attr_put_search_ctx(ctx);
133                 return ni;
134         }
135         NInoSetAttrList(ni);
136         l = ntfs_get_attribute_value_length(ctx->attr);
137         if (!l)
138                 goto put_err_out;
139         if (l > 0x40000) {
140                 err = EIO;
141                 goto put_err_out;
142         }
143         ni->attr_list_size = l;
144         ni->attr_list = malloc(ni->attr_list_size);
145         if (!ni->attr_list)
146                 goto put_err_out;
147         l = ntfs_get_attribute_value(vol, ni->mrec, ctx->attr, ni->attr_list);
148         if (!l)
149                 goto put_err_out;
150         if (l != ni->attr_list_size) {
151                 err = EIO;
152                 goto put_err_out;
153         }
154         if (!ctx->attr->non_resident) {
155                 /* Attribute list attribute is resident so we are done. */
156                 ntfs_attr_put_search_ctx(ctx);
157                 return ni;
158         }
159         NInoSetAttrListNonResident(ni);
160         // FIXME: We are duplicating work here! (AIA)
161         ni->attr_list_rl = ntfs_mapping_pairs_decompress(vol, ctx->attr, NULL);
162         if (ni->attr_list_rl) {
163                 /* We got the runlist, so we are done. */
164                 ntfs_attr_put_search_ctx(ctx);
165                 return ni;
166         }
167         err = EIO;
168 put_err_out:
169         if (!err)
170                 err = errno;
171         ntfs_attr_put_search_ctx(ctx);
172 err_out:
173         if (!err)
174                 err = errno;
175         __ntfs_inode_release(ni);
176         errno = err;
177         return NULL;
178 }
179
180 /**
181  * ntfs_inode_close - close an ntfs inode and free all associated memory
182  * @ni:         ntfs inode to close
183  *
184  * Make sure the ntfs inode @ni is clean.
185  *
186  * If the ntfs inode @ni is a base inode, close all associated extent inodes,
187  * then deallocate all memory attached to it, and finally free the ntfs inode
188  * structure itself.
189  *
190  * If it is an extent inode, we disconnect it from its base inode before we
191  * destroy it.
192  *
193  * Return 0 on success or -1 on error with errno set to the error code. On
194  * error, @ni has not been freed. The user should attempt to handle the error
195  * and call ntfs_inode_close() again. The following error codes are defined:
196  *
197  *      EBUSY   @ni and/or its attribute list runlist is/are dirty and the
198  *              attempt to write it/them to disk failed.
199  *      EINVAL  @ni is invalid (probably it is an extent inode).
200  *      EIO     I/O error while trying to write inode to disk.
201  */
202 int ntfs_inode_close(ntfs_inode *ni)
203 {
204         /* If we have dirty metadata, write it out. */
205         if (NInoDirty(ni) || NInoAttrListDirty(ni)) {
206                 if (ntfs_inode_sync(ni)) {
207                         if (errno != EIO)
208                                 errno = EBUSY;
209                         return -1;
210                 }
211         }
212         /* Is this a base inode with mapped extent inodes? */
213         if (ni->nr_extents > 0) {
214                 int i;
215
216                 // FIXME: Handle dirty case for each extent inode! (AIA)
217                 for (i = 0; i < ni->nr_extents; i++)
218                         __ntfs_inode_release(ni->extent_nis[i]);
219                 free(ni->extent_nis);
220         } else if (ni->nr_extents == -1) {
221                 ntfs_inode **tmp_nis;
222                 ntfs_inode *base_ni;
223                 s32 i;
224
225                 /*
226                  * If the inode is an extent inode, disconnect it from the
227                  * base inode before destroying it.
228                  */
229                 base_ni = ni->base_ni;
230                 for (i = 0; i < base_ni->nr_extents; ++i) {
231                         tmp_nis = base_ni->extent_nis;
232                         if (tmp_nis[i] != ni)
233                                 continue;
234                         /* Found it. Disconnect. */
235                         memmove(tmp_nis + i, tmp_nis + i + 1,
236                                         (base_ni->nr_extents - i - 1) *
237                                         sizeof(ntfs_inode *));
238                         base_ni->nr_extents--;
239                         /* Resize the memory buffer. */
240                         tmp_nis = realloc(tmp_nis, base_ni->nr_extents *
241                                         sizeof(ntfs_inode *));
242                         /* Ignore errors, they don't really matter. */
243                         if (tmp_nis)
244                                 base_ni->extent_nis = tmp_nis;
245                         /* Allow for error checking. */
246                         i = -1;
247                 }
248                 if (i != -1)
249                         Dputs("Extent inode was not attached to base inode! "
250                                         "Weird! Continuing regardless.");
251         }
252         return __ntfs_inode_release(ni);
253 }
254
255 /**
256  * ntfs_extent_inode_open - load an extent inode and attach it to its base
257  * @base_ni:    base ntfs inode
258  * @mref:       mft reference of the extent inode to load (in little endian)
259  *
260  * First check if the extent inode @mref is already attached to the base ntfs
261  * inode @base_ni, and if so, return a pointer to the attached extent inode.
262  *
263  * If the extent inode is not already attached to the base inode, allocate an
264  * ntfs_inode structure and initialize it for the given inode @mref. @mref
265  * specifies the inode number / mft record to read, including the sequence
266  * number, which can be 0 if no sequence number checking is to be performed.
267  *
268  * Then, allocate a buffer for the mft record, read the mft record from the
269  * volume @base_ni->vol, and attach it to the ntfs_inode structure (->mrec).
270  * The mft record is mst deprotected and sanity checked for validity and we
271  * abort if deprotection or checks fail.
272  *
273  * Finally attach the ntfs inode to its base inode @base_ni and return a
274  * pointer to the ntfs_inode structure on success or NULL on error, with errno
275  * set to the error code.
276  *
277  * Note, extent inodes are never closed directly. They are automatically
278  * disposed off by the closing of the base inode.
279  */
280 ntfs_inode *ntfs_extent_inode_open(ntfs_inode *base_ni, const MFT_REF mref)
281 {
282         u64 mft_no = MREF_LE(mref);
283         ntfs_inode *ni;
284         ntfs_inode **extent_nis;
285         int i;
286
287         if (!base_ni) {
288                 errno = EINVAL;
289                 return NULL;
290         }
291         Dprintf("Opening extent inode %Lu (base mft record 0x%Lu).\n",
292                         (unsigned long long)mft_no,
293                         (unsigned long long)base_ni->mft_no);
294         /* Is the extent inode already open and attached to the base inode? */
295         if (base_ni->nr_extents > 0) {
296                 extent_nis = base_ni->extent_nis;
297                 for (i = 0; i < base_ni->nr_extents; i++) {
298                         u16 seq_no;
299
300                         ni = extent_nis[i];
301                         if (mft_no != ni->mft_no)
302                                 continue;
303                         /* Verify the sequence number if given. */
304                         seq_no = MSEQNO_LE(mref);
305                         if (seq_no && seq_no != le16_to_cpu(
306                                         ni->mrec->sequence_number)) {
307                                 Dputs("Found stale extent mft reference! "
308                                                 "Corrupt file system. Run "
309                                                 "chkdsk.");
310                                 errno = EIO;
311                                 return NULL;
312                         }
313                         /* We are done, return the extent inode. */
314                         return ni;
315                 }
316         }
317         /* Wasn't there, we need to load the extent inode. */
318         ni = __ntfs_inode_allocate(base_ni->vol);
319         if (!ni)
320                 return NULL;
321         if (ntfs_file_record_read(base_ni->vol, le64_to_cpu(mref), &ni->mrec,
322                         NULL))
323                 goto err_out;
324         ni->mft_no = mft_no;
325         ni->nr_extents = -1;
326         ni->base_ni = base_ni;
327         /* Attach extent inode to base inode, reallocating memory if needed. */
328         if (!(base_ni->nr_extents & 3)) {
329                 i = (base_ni->nr_extents + 4) * sizeof(ntfs_inode *);
330
331                 extent_nis = (ntfs_inode**)malloc(i);
332                 if (!extent_nis)
333                         goto err_out;
334                 if (base_ni->extent_nis) {
335                         memcpy(extent_nis, base_ni->extent_nis,
336                                         i - 4 * sizeof(ntfs_inode *));
337                         free(base_ni->extent_nis);
338                 }
339                 base_ni->extent_nis = extent_nis;
340         }
341         base_ni->extent_nis[base_ni->nr_extents++] = ni;
342         return ni;
343 err_out:
344         i = errno;
345         __ntfs_inode_release(ni);
346         errno = i;
347         Dperror("Failed to open extent inode");
348         return NULL;
349 }
350
351 /**
352  * ntfs_inode_sync - write the inode (and its dirty extents) to disk
353  * @ni:         ntfs inode to write
354  *
355  * Write the inode @ni to disk as well as its dirty extent inodes if such
356  * exist and @ni is a base inode. If @ni is an extent inode, only @ni is
357  * written completely disregarding its base inode and any other extent inodes.
358  *
359  * For a base inode with dirty extent inodes if any writes fail for whatever
360  * reason, the failing inode is skipped and the sync process is continued. At
361  * the end the error condition that brought about the failure is returned. Thus
362  * the smallest amount of data loss possible occurs.
363  *
364  * Return 0 on success or -1 on error with errno set to the error code.
365  * The following error codes are defined:
366  *      EINVAL  - Invalid arguments were passed to the function.
367  *      ENOTSUP - Syncing requires code that has not been imlemented yet.
368  *      EBUSY   - Inode and/or one of its extents is busy, try again later.
369  *      EIO     - I/O error while writing the inode (or one of its extents).
370  */
371 int ntfs_inode_sync(ntfs_inode *ni)
372 {
373         int err = 0;
374
375         if (!ni) {
376                 errno = EINVAL;
377                 return -1;
378         }
379
380         // TODO: Implement writing out of attribute list attribute. (AIA)
381         if (NInoAttrListDirty(ni)) {
382                 errno = ENOTSUP;
383                 return -1;
384         }
385
386         /* Write this inode out to the $MFT (and $MFTMirr if applicable). */
387         if (NInoTestAndClearDirty(ni)) {
388                 if (ntfs_mft_record_write(ni->vol, ni->mft_no, ni->mrec)) {
389                         if (!err || errno == EIO) {
390                                 err = errno;
391                                 if (err != EIO)
392                                         err = EBUSY;
393                         }
394                 }
395         }
396
397         /* If this is a base inode with extents write all dirty extents, too. */
398         if (ni->nr_extents > 0) {
399                 s32 i;
400
401                 for (i = 0; i < ni->nr_extents; ++i) {
402                         ntfs_inode *eni;
403                         
404                         eni = ni->extent_nis[i];
405                         if (NInoTestAndClearDirty(eni)) {
406                                 if (ntfs_mft_record_write(eni->vol, eni->mft_no,
407                                                 eni->mrec)) {
408                                         if (!err || errno == EIO) {
409                                                 err = errno;
410                                                 if (err != EIO)
411                                                         err = EBUSY;
412                                         }
413                                 }
414                         }
415                 }
416         }
417
418         if (!err)
419                 return err;
420         errno = err;
421         return -1;
422 }
423