ext2_inode_cnv.c revision 320841
150472Speter/*-
21823Sphk * Copyright (c) 1995 The University of Utah and
345763Sobrien * the Computer Systems Laboratory at the University of Utah (CSL).
445763Sobrien * All rights reserved.
518390Speter *
695294Sobrien * Permission to use, copy, modify and distribute this software is hereby
795294Sobrien * granted provided that (1) source code retains these copyright, permission,
895294Sobrien * and disclaimer notices, and (2) redistributions including binaries
9207995Sobrien * reproduce the notices in supporting documentation, and (3) all advertising
1096340Sobrien * materials mentioning features or use of this software display the following
11169718Skan * acknowledgement: ``This product includes software developed by the
122375Sbde * Computer Systems Laboratory at the University of Utah.''
1396340Sobrien *
1445943Sobrien * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
1518390Speter * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
1696340Sobrien * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17167471Skan *
1845299Sobrien * CSL requests users of this software to return to csl-dist@cs.utah.edu any
19207995Sobrien * improvements that they make and grant CSL redistribution rights.
2073306Sobrien *
2155220Sobrien *      Utah $Hdr$
2296340Sobrien * $FreeBSD: stable/10/sys/fs/ext2fs/ext2_inode_cnv.c 320841 2017-07-09 15:14:22Z pfg $
23189834Sdas */
2468572Sobrien
2555220Sobrien/*
26259563Spfg * routines to convert on disk ext2 inodes into inodes and back
2745943Sobrien */
2845943Sobrien#include <sys/param.h>
29245539Sandrew#include <sys/systm.h>
30245539Sandrew#include <sys/endian.h>
31245539Sandrew#include <sys/lock.h>
32245539Sandrew#include <sys/stat.h>
33239272Sgonzo#include <sys/vnode.h>
34215082Simp
35215082Simp#include <fs/ext2fs/fs.h>
36239272Sgonzo#include <fs/ext2fs/inode.h>
37239272Sgonzo#include <fs/ext2fs/ext2fs.h>
38239272Sgonzo#include <fs/ext2fs/ext2_dinode.h>
39215082Simp#include <fs/ext2fs/ext2_extern.h>
40215082Simp
41217123Simp#define XTIME_TO_NSEC(x)	((x & EXT3_NSEC_MASK) >> 2)
42204771Simp#define NSEC_TO_XTIME(t)	(le32toh(t << 2) & EXT3_NSEC_MASK)
43204771Simp
44204771Simp#ifdef EXT2FS_DEBUG
45217123Simpvoid
46217123Simpext2_print_inode(struct inode *in)
47217123Simp{
48208737Sjmallett	int i;
49217123Simp	struct ext4_extent_header *ehp;
50217123Simp	struct ext4_extent *ep;
51208737Sjmallett
52208737Sjmallett	printf("Inode: %5ju", (uintmax_t)in->i_number);
53208737Sjmallett	printf(	/* "Inode: %5d" */
54208758Sjmallett	    " Type: %10s Mode: 0x%o Flags: 0x%x  Version: %d\n",
55208758Sjmallett	    "n/a", in->i_mode, in->i_flags, in->i_gen);
56208758Sjmallett	printf("User: %5u Group: %5u  Size: %ju\n",
57208758Sjmallett	    in->i_uid, in->i_gid, (uintmax_t)in->i_size);
58208758Sjmallett	printf("Links: %3d Blockcount: %ju\n",
59208758Sjmallett	    in->i_nlink, (uintmax_t)in->i_blocks);
60208758Sjmallett	printf("ctime: 0x%x", in->i_ctime);
61208758Sjmallett	printf("atime: 0x%x", in->i_atime);
62208737Sjmallett	printf("mtime: 0x%x", in->i_mtime);
63208737Sjmallett	if (E2DI_HAS_XTIME(in))
64208737Sjmallett		printf("crtime %#x ", in->i_birthtime);
65208737Sjmallett	printf("BLOCKS:");
66208737Sjmallett	for (i = 0; i < (in->i_blocks <= 24 ? (in->i_blocks + 1) / 2 : 12); i++)
67208737Sjmallett		printf("  %d", in->i_db[i]);
68208737Sjmallett	printf("\n");
69208737Sjmallett	printf("Extents:\n");
7081749Sobrien	ehp = (struct ext4_extent_header *)in->i_db;
7181749Sobrien	printf("Header (magic 0x%x entries %d max %d depth %d gen %d)\n",
7281749Sobrien	    ehp->eh_magic, ehp->eh_ecount, ehp->eh_max, ehp->eh_depth,
7381749Sobrien	    ehp->eh_gen);
7418390Speter	ep = (struct ext4_extent *)(char *)(ehp + 1);
7518390Speter	printf("Index (blk %d len %d start_lo %d start_hi %d)\n", ep->e_blk,
7645301Sobrien	    ep->e_len, ep->e_start_lo, ep->e_start_hi);
7718390Speter	printf("\n");
7854987Sobrien}
7954987Sobrien#endif	/* EXT2FS_DEBUG */
8052170Sobrien
8118390Speter/*
82169718Skan *	raw ext2 inode to inode
83169718Skan */
84169718Skanvoid
85169718Skanext2_ei2i(struct ext2fs_dinode *ei, struct inode *ip)
8616663Sjkh{
87169718Skan	int i;
882375Sbde
89169718Skan	ip->i_nlink = ei->e2di_nlink;
902375Sbde	/*
912375Sbde	 * Godmar thinks - if the link count is zero, then the inode is
92169718Skan	 * unused - according to ext2 standards. Ufs marks this fact by
93169718Skan	 * setting i_mode to zero - why ? I can see that this might lead to
94169718Skan	 * problems in an undelete.
95169718Skan	 */
96169718Skan	ip->i_mode = ei->e2di_nlink ? ei->e2di_mode : 0;
97169718Skan	ip->i_size = ei->e2di_size;
98169718Skan	if (S_ISREG(ip->i_mode))
99169718Skan		ip->i_size |= ((u_int64_t)ei->e2di_size_high) << 32;
100169718Skan	ip->i_atime = ei->e2di_atime;
101169718Skan	ip->i_mtime = ei->e2di_mtime;
102169718Skan	ip->i_ctime = ei->e2di_ctime;
103169718Skan	if (E2DI_HAS_XTIME(ip)) {
104169718Skan		ip->i_atimensec = XTIME_TO_NSEC(ei->e2di_atime_extra);
105169718Skan		ip->i_mtimensec = XTIME_TO_NSEC(ei->e2di_mtime_extra);
106169718Skan		ip->i_ctimensec = XTIME_TO_NSEC(ei->e2di_ctime_extra);
107169718Skan		ip->i_birthtime = ei->e2di_crtime;
108169718Skan		ip->i_birthnsec = XTIME_TO_NSEC(ei->e2di_crtime_extra);
109169718Skan	}
11095294Sobrien	ip->i_flags = 0;
111	ip->i_flags |= (ei->e2di_flags & EXT2_APPEND) ? SF_APPEND : 0;
112	ip->i_flags |= (ei->e2di_flags & EXT2_IMMUTABLE) ? SF_IMMUTABLE : 0;
113	ip->i_flags |= (ei->e2di_flags & EXT2_NODUMP) ? UF_NODUMP : 0;
114	ip->i_flag |= (ei->e2di_flags & EXT3_INDEX) ? IN_E3INDEX : 0;
115	ip->i_flag |= (ei->e2di_flags & EXT4_EXTENTS) ? IN_E4EXTENTS : 0;
116	ip->i_blocks = ei->e2di_nblock;
117	if (E2DI_HAS_HUGE_FILE(ip)) {
118		ip->i_blocks |= (uint64_t)ei->e2di_nblock_high << 32;
119		if (ei->e2di_flags & EXT4_HUGE_FILE)
120			ip->i_blocks = fsbtodb(ip->i_e2fs, ip->i_blocks);
121	}
122	ip->i_gen = ei->e2di_gen;
123	ip->i_uid = ei->e2di_uid;
124	ip->i_gid = ei->e2di_gid;
125	ip->i_uid |= (uint32_t)ei->e2di_uid_high << 16;
126	ip->i_gid |= (uint32_t)ei->e2di_gid_high << 16;
127	/* XXX use memcpy */
128	for (i = 0; i < NDADDR; i++)
129		ip->i_db[i] = ei->e2di_blocks[i];
130	for (i = 0; i < NIADDR; i++)
131		ip->i_ib[i] = ei->e2di_blocks[EXT2_NDIR_BLOCKS + i];
132}
133
134/*
135 *	inode to raw ext2 inode
136 */
137void
138ext2_i2ei(struct inode *ip, struct ext2fs_dinode *ei)
139{
140	int i;
141
142	ei->e2di_mode = ip->i_mode;
143	ei->e2di_nlink = ip->i_nlink;
144	/*
145	 * Godmar thinks: if dtime is nonzero, ext2 says this inode has been
146	 * deleted, this would correspond to a zero link count
147	 */
148	ei->e2di_dtime = ei->e2di_nlink ? 0 : ip->i_mtime;
149	ei->e2di_size = ip->i_size;
150	if (S_ISREG(ip->i_mode))
151		ei->e2di_size_high = ip->i_size >> 32;
152	ei->e2di_atime = ip->i_atime;
153	ei->e2di_mtime = ip->i_mtime;
154	ei->e2di_ctime = ip->i_ctime;
155	if (E2DI_HAS_XTIME(ip)) {
156		ei->e2di_ctime_extra = NSEC_TO_XTIME(ip->i_ctimensec);
157		ei->e2di_mtime_extra = NSEC_TO_XTIME(ip->i_mtimensec);
158		ei->e2di_atime_extra = NSEC_TO_XTIME(ip->i_atimensec);
159		ei->e2di_crtime = ip->i_birthtime;
160		ei->e2di_crtime_extra = NSEC_TO_XTIME(ip->i_birthnsec);
161	}
162	ei->e2di_flags = 0;
163	ei->e2di_flags |= (ip->i_flags & SF_APPEND) ? EXT2_APPEND : 0;
164	ei->e2di_flags |= (ip->i_flags & SF_IMMUTABLE) ? EXT2_IMMUTABLE : 0;
165	ei->e2di_flags |= (ip->i_flags & UF_NODUMP) ? EXT2_NODUMP : 0;
166	ei->e2di_flags |= (ip->i_flag & IN_E3INDEX) ? EXT3_INDEX : 0;
167	ei->e2di_flags |= (ip->i_flag & IN_E4EXTENTS) ? EXT4_EXTENTS : 0;
168	ei->e2di_nblock = ip->i_blocks & 0xffffffff;
169	ei->e2di_nblock_high = ip->i_blocks >> 32 & 0xffff;
170	ei->e2di_gen = ip->i_gen;
171	ei->e2di_uid = ip->i_uid & 0xffff;
172	ei->e2di_uid_high = ip->i_uid >> 16 & 0xffff;
173	ei->e2di_gid = ip->i_gid & 0xffff;
174	ei->e2di_gid_high = ip->i_gid >> 16 & 0xffff;
175	/* XXX use memcpy */
176	for (i = 0; i < NDADDR; i++)
177		ei->e2di_blocks[i] = ip->i_db[i];
178	for (i = 0; i < NIADDR; i++)
179		ei->e2di_blocks[EXT2_NDIR_BLOCKS + i] = ip->i_ib[i];
180}
181