ext2_inode_cnv.c revision 296992
160786Sps/*-
260786Sps * Copyright (c) 1995 The University of Utah and
360786Sps * the Computer Systems Laboratory at the University of Utah (CSL).
460786Sps * All rights reserved.
560786Sps *
660786Sps * Permission to use, copy, modify and distribute this software is hereby
789019Sps * granted provided that (1) source code retains these copyright, permission,
860786Sps * and disclaimer notices, and (2) redistributions including binaries
960786Sps * reproduce the notices in supporting documentation, and (3) all advertising
10170256Sdelphij * materials mentioning features or use of this software display the following
11170256Sdelphij * acknowledgement: ``This product includes software developed by the
1260786Sps * Computer Systems Laboratory at the University of Utah.''
1360786Sps *
1460786Sps * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
15195941Sdelphij * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
16195941Sdelphij * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17195941Sdelphij *
18195941Sdelphij * CSL requests users of this software to return to csl-dist@cs.utah.edu any
19195941Sdelphij * improvements that they make and grant CSL redistribution rights.
20195941Sdelphij *
21195941Sdelphij *      Utah $Hdr$
22195941Sdelphij * $FreeBSD: stable/10/sys/fs/ext2fs/ext2_inode_cnv.c 296992 2016-03-17 19:28:15Z pfg $
23195941Sdelphij */
24195941Sdelphij
25195941Sdelphij/*
26195941Sdelphij * routines to convert on disk ext2 inodes into inodes and back
27191930Sdelphij */
2860786Sps#include <sys/param.h>
29191930Sdelphij#include <sys/systm.h>
30191930Sdelphij#include <sys/endian.h>
31191930Sdelphij#include <sys/lock.h>
32191930Sdelphij#include <sys/stat.h>
33191930Sdelphij#include <sys/vnode.h>
34191930Sdelphij
35191930Sdelphij#include <fs/ext2fs/fs.h>
36191930Sdelphij#include <fs/ext2fs/inode.h>
37191930Sdelphij#include <fs/ext2fs/ext2fs.h>
38191930Sdelphij#include <fs/ext2fs/ext2_dinode.h>
39191930Sdelphij#include <fs/ext2fs/ext2_extern.h>
40191930Sdelphij
41191930Sdelphij#define XTIME_TO_NSEC(x)	((x & EXT3_NSEC_MASK) >> 2)
42191930Sdelphij#define NSEC_TO_XTIME(t)	(le32toh(t << 2) & EXT3_NSEC_MASK)
43191930Sdelphij
44191930Sdelphij#ifdef EXT2FS_DEBUG
45191930Sdelphijvoid
46191930Sdelphijext2_print_inode(struct inode *in)
47191930Sdelphij{
48191930Sdelphij	int i;
49191930Sdelphij	struct ext4_extent_header *ehp;
50191930Sdelphij	struct ext4_extent *ep;
51191930Sdelphij
52191930Sdelphij	printf( "Inode: %5ju", (uintmax_t)in->i_number);
53191930Sdelphij	printf( /* "Inode: %5d" */
54191930Sdelphij		" Type: %10s Mode: 0x%o Flags: 0x%x  Version: %d\n",
55191930Sdelphij		"n/a", in->i_mode, in->i_flags, in->i_gen);
56191930Sdelphij	printf("User: %5u Group: %5u  Size: %ju\n",
57191930Sdelphij	    in->i_uid, in->i_gid, (uintmax_t)in->i_size);
58191930Sdelphij	printf("Links: %3d Blockcount: %ju\n",
59191930Sdelphij	    in->i_nlink, (uintmax_t)in->i_blocks);
60191930Sdelphij	printf( "ctime: 0x%x", in->i_ctime);
61191930Sdelphij	printf( "atime: 0x%x", in->i_atime);
62191930Sdelphij	printf( "mtime: 0x%x", in->i_mtime);
63191930Sdelphij	if (E2DI_HAS_XTIME(in))
64191930Sdelphij		printf("crtime %#x ", in->i_birthtime);
65191930Sdelphij	printf("BLOCKS:");
66191930Sdelphij	for (i = 0; i < (in->i_blocks <= 24 ? (in->i_blocks + 1) / 2 : 12); i++)
67191930Sdelphij		printf("  %d", in->i_db[i]);
68191930Sdelphij	printf("\n");
69191930Sdelphij	printf("Extents:\n");
70191930Sdelphij	ehp = (struct ext4_extent_header *)in->i_db;
71191930Sdelphij	printf("Header (magic 0x%x entries %d max %d depth %d gen %d)\n",
72191930Sdelphij	    ehp->eh_magic, ehp->eh_ecount, ehp->eh_max, ehp->eh_depth,
73191930Sdelphij	    ehp->eh_gen);
74191930Sdelphij	ep = (struct ext4_extent *)(char *)(ehp + 1);
75191930Sdelphij	printf("Index (blk %d len %d start_lo %d start_hi %d)\n", ep->e_blk,
76191930Sdelphij	    ep->e_len, ep->e_start_lo, ep->e_start_hi);
77191930Sdelphij	printf("\n");
78191930Sdelphij}
79191930Sdelphij#endif	/* EXT2FS_DEBUG */
80191930Sdelphij
81191930Sdelphij/*
82191930Sdelphij *	raw ext2 inode to inode
83191930Sdelphij */
84173932Sdelphijvoid
85173682Sdelphijext2_ei2i(struct ext2fs_dinode *ei, struct inode *ip)
86173682Sdelphij{
87173682Sdelphij	int i;
88173682Sdelphij
89173682Sdelphij	ip->i_nlink = ei->e2di_nlink;
90173682Sdelphij	/* Godmar thinks - if the link count is zero, then the inode is
91173682Sdelphij	   unused - according to ext2 standards. Ufs marks this fact
92173682Sdelphij	   by setting i_mode to zero - why ?
93173682Sdelphij	   I can see that this might lead to problems in an undelete.
94173682Sdelphij	*/
95172597Sdelphij	ip->i_mode = ei->e2di_nlink ? ei->e2di_mode : 0;
96172468Sdelphij	ip->i_size = ei->e2di_size;
97172468Sdelphij	if (S_ISREG(ip->i_mode))
98172468Sdelphij		ip->i_size |= ((u_int64_t)ei->e2di_size_high) << 32;
99172468Sdelphij	ip->i_atime = ei->e2di_atime;
100172468Sdelphij	ip->i_mtime = ei->e2di_mtime;
101172468Sdelphij	ip->i_ctime = ei->e2di_ctime;
102172468Sdelphij	if (E2DI_HAS_XTIME(ip)) {
103172468Sdelphij		ip->i_atimensec = XTIME_TO_NSEC(ei->e2di_atime_extra);
104172468Sdelphij		ip->i_mtimensec = XTIME_TO_NSEC(ei->e2di_mtime_extra);
105172597Sdelphij		ip->i_ctimensec = XTIME_TO_NSEC(ei->e2di_ctime_extra);
106172597Sdelphij		ip->i_birthtime = ei->e2di_crtime;
107172468Sdelphij		ip->i_birthnsec = XTIME_TO_NSEC(ei->e2di_crtime_extra);
108172468Sdelphij	}
109170964Sdelphij	ip->i_flags = 0;
110170256Sdelphij	ip->i_flags |= (ei->e2di_flags & EXT2_APPEND) ? SF_APPEND : 0;
111170256Sdelphij	ip->i_flags |= (ei->e2di_flags & EXT2_IMMUTABLE) ? SF_IMMUTABLE : 0;
112170256Sdelphij	ip->i_flags |= (ei->e2di_flags & EXT2_NODUMP) ? UF_NODUMP : 0;
113170256Sdelphij	ip->i_flag |= (ei->e2di_flags & EXT3_INDEX) ? IN_E3INDEX : 0;
114170256Sdelphij	ip->i_flag |= (ei->e2di_flags & EXT4_EXTENTS) ? IN_E4EXTENTS : 0;
115170256Sdelphij	ip->i_blocks = ei->e2di_nblock;
116170256Sdelphij	if (E2DI_HAS_HUGE_FILE(ip)) {
117170256Sdelphij		ip->i_blocks |= (uint64_t)ei->e2di_nblock_high << 32;
118170256Sdelphij		if (ei->e2di_flags & EXT4_HUGE_FILE)
119170256Sdelphij		      ip->i_blocks = fsbtodb(ip->i_e2fs, ip->i_blocks);
120170256Sdelphij	}
121170256Sdelphij	ip->i_gen = ei->e2di_gen;
122170256Sdelphij	ip->i_uid = ei->e2di_uid;
123170256Sdelphij	ip->i_gid = ei->e2di_gid;
124170256Sdelphij	/* XXX use memcpy */
125170256Sdelphij	for(i = 0; i < NDADDR; i++)
126170256Sdelphij		ip->i_db[i] = ei->e2di_blocks[i];
127170256Sdelphij	for(i = 0; i < NIADDR; i++)
128170256Sdelphij		ip->i_ib[i] = ei->e2di_blocks[EXT2_NDIR_BLOCKS + i];
129170256Sdelphij}
130170256Sdelphij
131170256Sdelphij/*
132170256Sdelphij *	inode to raw ext2 inode
133170256Sdelphij */
134170256Sdelphijvoid
135170256Sdelphijext2_i2ei(struct inode *ip, struct ext2fs_dinode *ei)
136170256Sdelphij{
137170256Sdelphij	int i;
138170256Sdelphij
139170256Sdelphij	ei->e2di_mode = ip->i_mode;
140170256Sdelphij	ei->e2di_nlink = ip->i_nlink;
141170256Sdelphij	/*
142170256Sdelphij	   Godmar thinks: if dtime is nonzero, ext2 says this inode
143170256Sdelphij	   has been deleted, this would correspond to a zero link count
144170256Sdelphij	 */
145170256Sdelphij	ei->e2di_dtime = ei->e2di_nlink ? 0 : ip->i_mtime;
146170256Sdelphij	ei->e2di_size = ip->i_size;
147170256Sdelphij	if (S_ISREG(ip->i_mode))
148170256Sdelphij		ei->e2di_size_high = ip->i_size >> 32;
149170256Sdelphij	ei->e2di_atime = ip->i_atime;
150170256Sdelphij	ei->e2di_mtime = ip->i_mtime;
151170256Sdelphij	ei->e2di_ctime = ip->i_ctime;
152170256Sdelphij	if (E2DI_HAS_XTIME(ip)) {
153170256Sdelphij		ei->e2di_ctime_extra = NSEC_TO_XTIME(ip->i_ctimensec);
154170256Sdelphij		ei->e2di_mtime_extra = NSEC_TO_XTIME(ip->i_mtimensec);
155170256Sdelphij		ei->e2di_atime_extra = NSEC_TO_XTIME(ip->i_atimensec);
156161475Sdelphij		ei->e2di_crtime = ip->i_birthtime;
157161475Sdelphij		ei->e2di_crtime_extra = NSEC_TO_XTIME(ip->i_birthnsec);
158161475Sdelphij	}
159161475Sdelphij	ei->e2di_flags = 0;
160161475Sdelphij	ei->e2di_flags |= (ip->i_flags & SF_APPEND) ? EXT2_APPEND: 0;
161161475Sdelphij	ei->e2di_flags |= (ip->i_flags & SF_IMMUTABLE) ? EXT2_IMMUTABLE: 0;
162161475Sdelphij	ei->e2di_flags |= (ip->i_flags & UF_NODUMP) ? EXT2_NODUMP: 0;
163161475Sdelphij	ei->e2di_flags |= (ip->i_flag & IN_E3INDEX) ? EXT3_INDEX: 0;
164161475Sdelphij	ei->e2di_flags |= (ip->i_flag & IN_E4EXTENTS) ? EXT4_EXTENTS: 0;
165161475Sdelphij	ei->e2di_nblock = ip->i_blocks & 0xffffffff;
166161475Sdelphij	ei->e2di_nblock_high = ip->i_blocks >> 32 & 0xffff;
167161475Sdelphij	ei->e2di_gen = ip->i_gen;
168161475Sdelphij	ei->e2di_uid = ip->i_uid;
169161475Sdelphij	ei->e2di_gid = ip->i_gid;
170161475Sdelphij	/* XXX use memcpy */
171161475Sdelphij	for(i = 0; i < NDADDR; i++)
172161475Sdelphij		ei->e2di_blocks[i] = ip->i_db[i];
173161475Sdelphij	for(i = 0; i < NIADDR; i++)
174161475Sdelphij		ei->e2di_blocks[EXT2_NDIR_BLOCKS + i] = ip->i_ib[i];
175161475Sdelphij}
176161475Sdelphij