1*6a54128fSAndroid Build Coastguard Worker /*
2*6a54128fSAndroid Build Coastguard Worker * create_inode.c --- create an inode
3*6a54128fSAndroid Build Coastguard Worker *
4*6a54128fSAndroid Build Coastguard Worker * Copyright (C) 2014 Robert Yang <[email protected]>
5*6a54128fSAndroid Build Coastguard Worker *
6*6a54128fSAndroid Build Coastguard Worker * %Begin-Header%
7*6a54128fSAndroid Build Coastguard Worker * This file may be redistributed under the terms of the GNU library
8*6a54128fSAndroid Build Coastguard Worker * General Public License, version 2.
9*6a54128fSAndroid Build Coastguard Worker * %End-Header%
10*6a54128fSAndroid Build Coastguard Worker */
11*6a54128fSAndroid Build Coastguard Worker
12*6a54128fSAndroid Build Coastguard Worker #define _FILE_OFFSET_BITS 64
13*6a54128fSAndroid Build Coastguard Worker #define _LARGEFILE64_SOURCE 1
14*6a54128fSAndroid Build Coastguard Worker #define _GNU_SOURCE 1
15*6a54128fSAndroid Build Coastguard Worker
16*6a54128fSAndroid Build Coastguard Worker #include "config.h"
17*6a54128fSAndroid Build Coastguard Worker #include <time.h>
18*6a54128fSAndroid Build Coastguard Worker #include <sys/stat.h>
19*6a54128fSAndroid Build Coastguard Worker #include <sys/types.h>
20*6a54128fSAndroid Build Coastguard Worker #include <unistd.h>
21*6a54128fSAndroid Build Coastguard Worker #include <limits.h> /* for PATH_MAX */
22*6a54128fSAndroid Build Coastguard Worker #include <dirent.h> /* for scandir() and alphasort() */
23*6a54128fSAndroid Build Coastguard Worker #if defined HAVE_SYS_XATTR_H
24*6a54128fSAndroid Build Coastguard Worker #include <sys/xattr.h>
25*6a54128fSAndroid Build Coastguard Worker #elif defined HAVE_ATTR_XATTR_H
26*6a54128fSAndroid Build Coastguard Worker #include <attr/xattr.h>
27*6a54128fSAndroid Build Coastguard Worker #endif
28*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_SYS_IOCTL_H
29*6a54128fSAndroid Build Coastguard Worker #include <sys/ioctl.h>
30*6a54128fSAndroid Build Coastguard Worker #endif
31*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_SYS_SYSMACROS_H
32*6a54128fSAndroid Build Coastguard Worker #include <sys/sysmacros.h>
33*6a54128fSAndroid Build Coastguard Worker #endif
34*6a54128fSAndroid Build Coastguard Worker
35*6a54128fSAndroid Build Coastguard Worker #include <ext2fs/ext2fs.h>
36*6a54128fSAndroid Build Coastguard Worker #include <ext2fs/ext2_types.h>
37*6a54128fSAndroid Build Coastguard Worker #include <ext2fs/fiemap.h>
38*6a54128fSAndroid Build Coastguard Worker
39*6a54128fSAndroid Build Coastguard Worker #include "create_inode.h"
40*6a54128fSAndroid Build Coastguard Worker #include "support/nls-enable.h"
41*6a54128fSAndroid Build Coastguard Worker
42*6a54128fSAndroid Build Coastguard Worker /* 64KiB is the minimum blksize to best minimize system call overhead. */
43*6a54128fSAndroid Build Coastguard Worker #define COPY_FILE_BUFLEN 65536
44*6a54128fSAndroid Build Coastguard Worker
ext2_file_type(unsigned int mode)45*6a54128fSAndroid Build Coastguard Worker static int ext2_file_type(unsigned int mode)
46*6a54128fSAndroid Build Coastguard Worker {
47*6a54128fSAndroid Build Coastguard Worker if (LINUX_S_ISREG(mode))
48*6a54128fSAndroid Build Coastguard Worker return EXT2_FT_REG_FILE;
49*6a54128fSAndroid Build Coastguard Worker
50*6a54128fSAndroid Build Coastguard Worker if (LINUX_S_ISDIR(mode))
51*6a54128fSAndroid Build Coastguard Worker return EXT2_FT_DIR;
52*6a54128fSAndroid Build Coastguard Worker
53*6a54128fSAndroid Build Coastguard Worker if (LINUX_S_ISCHR(mode))
54*6a54128fSAndroid Build Coastguard Worker return EXT2_FT_CHRDEV;
55*6a54128fSAndroid Build Coastguard Worker
56*6a54128fSAndroid Build Coastguard Worker if (LINUX_S_ISBLK(mode))
57*6a54128fSAndroid Build Coastguard Worker return EXT2_FT_BLKDEV;
58*6a54128fSAndroid Build Coastguard Worker
59*6a54128fSAndroid Build Coastguard Worker if (LINUX_S_ISLNK(mode))
60*6a54128fSAndroid Build Coastguard Worker return EXT2_FT_SYMLINK;
61*6a54128fSAndroid Build Coastguard Worker
62*6a54128fSAndroid Build Coastguard Worker if (LINUX_S_ISFIFO(mode))
63*6a54128fSAndroid Build Coastguard Worker return EXT2_FT_FIFO;
64*6a54128fSAndroid Build Coastguard Worker
65*6a54128fSAndroid Build Coastguard Worker if (LINUX_S_ISSOCK(mode))
66*6a54128fSAndroid Build Coastguard Worker return EXT2_FT_SOCK;
67*6a54128fSAndroid Build Coastguard Worker
68*6a54128fSAndroid Build Coastguard Worker return 0;
69*6a54128fSAndroid Build Coastguard Worker }
70*6a54128fSAndroid Build Coastguard Worker
71*6a54128fSAndroid Build Coastguard Worker /* Link an inode number to a directory */
add_link(ext2_filsys fs,ext2_ino_t parent_ino,ext2_ino_t ino,const char * name)72*6a54128fSAndroid Build Coastguard Worker static errcode_t add_link(ext2_filsys fs, ext2_ino_t parent_ino,
73*6a54128fSAndroid Build Coastguard Worker ext2_ino_t ino, const char *name)
74*6a54128fSAndroid Build Coastguard Worker {
75*6a54128fSAndroid Build Coastguard Worker struct ext2_inode inode;
76*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
77*6a54128fSAndroid Build Coastguard Worker
78*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_read_inode(fs, ino, &inode);
79*6a54128fSAndroid Build Coastguard Worker if (retval) {
80*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval, _("while reading inode %u"), ino);
81*6a54128fSAndroid Build Coastguard Worker return retval;
82*6a54128fSAndroid Build Coastguard Worker }
83*6a54128fSAndroid Build Coastguard Worker
84*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_link(fs, parent_ino, name, ino,
85*6a54128fSAndroid Build Coastguard Worker ext2_file_type(inode.i_mode));
86*6a54128fSAndroid Build Coastguard Worker if (retval == EXT2_ET_DIR_NO_SPACE) {
87*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_expand_dir(fs, parent_ino);
88*6a54128fSAndroid Build Coastguard Worker if (retval) {
89*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval,
90*6a54128fSAndroid Build Coastguard Worker _("while expanding directory"));
91*6a54128fSAndroid Build Coastguard Worker return retval;
92*6a54128fSAndroid Build Coastguard Worker }
93*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_link(fs, parent_ino, name, ino,
94*6a54128fSAndroid Build Coastguard Worker ext2_file_type(inode.i_mode));
95*6a54128fSAndroid Build Coastguard Worker }
96*6a54128fSAndroid Build Coastguard Worker if (retval) {
97*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval, _("while linking \"%s\""), name);
98*6a54128fSAndroid Build Coastguard Worker return retval;
99*6a54128fSAndroid Build Coastguard Worker }
100*6a54128fSAndroid Build Coastguard Worker
101*6a54128fSAndroid Build Coastguard Worker inode.i_links_count++;
102*6a54128fSAndroid Build Coastguard Worker
103*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_write_inode(fs, ino, &inode);
104*6a54128fSAndroid Build Coastguard Worker if (retval)
105*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval, _("while writing inode %u"), ino);
106*6a54128fSAndroid Build Coastguard Worker
107*6a54128fSAndroid Build Coastguard Worker return retval;
108*6a54128fSAndroid Build Coastguard Worker }
109*6a54128fSAndroid Build Coastguard Worker
110*6a54128fSAndroid Build Coastguard Worker /* Set the uid, gid, mode and time for the inode */
set_inode_extra(ext2_filsys fs,ext2_ino_t ino,struct stat * st)111*6a54128fSAndroid Build Coastguard Worker static errcode_t set_inode_extra(ext2_filsys fs, ext2_ino_t ino,
112*6a54128fSAndroid Build Coastguard Worker struct stat *st)
113*6a54128fSAndroid Build Coastguard Worker {
114*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
115*6a54128fSAndroid Build Coastguard Worker struct ext2_inode inode;
116*6a54128fSAndroid Build Coastguard Worker
117*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_read_inode(fs, ino, &inode);
118*6a54128fSAndroid Build Coastguard Worker if (retval) {
119*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval, _("while reading inode %u"), ino);
120*6a54128fSAndroid Build Coastguard Worker return retval;
121*6a54128fSAndroid Build Coastguard Worker }
122*6a54128fSAndroid Build Coastguard Worker
123*6a54128fSAndroid Build Coastguard Worker inode.i_uid = st->st_uid;
124*6a54128fSAndroid Build Coastguard Worker ext2fs_set_i_uid_high(inode, st->st_uid >> 16);
125*6a54128fSAndroid Build Coastguard Worker inode.i_gid = st->st_gid;
126*6a54128fSAndroid Build Coastguard Worker ext2fs_set_i_gid_high(inode, st->st_gid >> 16);
127*6a54128fSAndroid Build Coastguard Worker inode.i_mode = (LINUX_S_IFMT & inode.i_mode) | (~S_IFMT & st->st_mode);
128*6a54128fSAndroid Build Coastguard Worker inode.i_atime = st->st_atime;
129*6a54128fSAndroid Build Coastguard Worker inode.i_mtime = st->st_mtime;
130*6a54128fSAndroid Build Coastguard Worker inode.i_ctime = st->st_ctime;
131*6a54128fSAndroid Build Coastguard Worker
132*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_write_inode(fs, ino, &inode);
133*6a54128fSAndroid Build Coastguard Worker if (retval)
134*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval, _("while writing inode %u"), ino);
135*6a54128fSAndroid Build Coastguard Worker return retval;
136*6a54128fSAndroid Build Coastguard Worker }
137*6a54128fSAndroid Build Coastguard Worker
138*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_LLISTXATTR
set_inode_xattr(ext2_filsys fs,ext2_ino_t ino,const char * filename)139*6a54128fSAndroid Build Coastguard Worker static errcode_t set_inode_xattr(ext2_filsys fs, ext2_ino_t ino,
140*6a54128fSAndroid Build Coastguard Worker const char *filename)
141*6a54128fSAndroid Build Coastguard Worker {
142*6a54128fSAndroid Build Coastguard Worker errcode_t retval, close_retval;
143*6a54128fSAndroid Build Coastguard Worker struct ext2_xattr_handle *handle;
144*6a54128fSAndroid Build Coastguard Worker ssize_t size, value_size;
145*6a54128fSAndroid Build Coastguard Worker char *list = NULL;
146*6a54128fSAndroid Build Coastguard Worker int i;
147*6a54128fSAndroid Build Coastguard Worker
148*6a54128fSAndroid Build Coastguard Worker if (no_copy_xattrs)
149*6a54128fSAndroid Build Coastguard Worker return 0;
150*6a54128fSAndroid Build Coastguard Worker
151*6a54128fSAndroid Build Coastguard Worker size = llistxattr(filename, NULL, 0);
152*6a54128fSAndroid Build Coastguard Worker if (size == -1) {
153*6a54128fSAndroid Build Coastguard Worker if (errno == ENOTSUP)
154*6a54128fSAndroid Build Coastguard Worker return 0;
155*6a54128fSAndroid Build Coastguard Worker retval = errno;
156*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval, _("while listing attributes of \"%s\""),
157*6a54128fSAndroid Build Coastguard Worker filename);
158*6a54128fSAndroid Build Coastguard Worker return retval;
159*6a54128fSAndroid Build Coastguard Worker } else if (size == 0) {
160*6a54128fSAndroid Build Coastguard Worker return 0;
161*6a54128fSAndroid Build Coastguard Worker }
162*6a54128fSAndroid Build Coastguard Worker
163*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_xattrs_open(fs, ino, &handle);
164*6a54128fSAndroid Build Coastguard Worker if (retval) {
165*6a54128fSAndroid Build Coastguard Worker if (retval == EXT2_ET_MISSING_EA_FEATURE)
166*6a54128fSAndroid Build Coastguard Worker return 0;
167*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval, _("while opening inode %u"), ino);
168*6a54128fSAndroid Build Coastguard Worker return retval;
169*6a54128fSAndroid Build Coastguard Worker }
170*6a54128fSAndroid Build Coastguard Worker
171*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_xattrs_read(handle);
172*6a54128fSAndroid Build Coastguard Worker if (retval) {
173*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval,
174*6a54128fSAndroid Build Coastguard Worker _("while reading xattrs for inode %u"), ino);
175*6a54128fSAndroid Build Coastguard Worker goto out;
176*6a54128fSAndroid Build Coastguard Worker }
177*6a54128fSAndroid Build Coastguard Worker
178*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_get_mem(size, &list);
179*6a54128fSAndroid Build Coastguard Worker if (retval) {
180*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval, _("while allocating memory"));
181*6a54128fSAndroid Build Coastguard Worker goto out;
182*6a54128fSAndroid Build Coastguard Worker }
183*6a54128fSAndroid Build Coastguard Worker
184*6a54128fSAndroid Build Coastguard Worker size = llistxattr(filename, list, size);
185*6a54128fSAndroid Build Coastguard Worker if (size == -1) {
186*6a54128fSAndroid Build Coastguard Worker retval = errno;
187*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval, _("while listing attributes of \"%s\""),
188*6a54128fSAndroid Build Coastguard Worker filename);
189*6a54128fSAndroid Build Coastguard Worker goto out;
190*6a54128fSAndroid Build Coastguard Worker }
191*6a54128fSAndroid Build Coastguard Worker
192*6a54128fSAndroid Build Coastguard Worker for (i = 0; i < size; i += strlen(&list[i]) + 1) {
193*6a54128fSAndroid Build Coastguard Worker const char *name = &list[i];
194*6a54128fSAndroid Build Coastguard Worker char *value;
195*6a54128fSAndroid Build Coastguard Worker
196*6a54128fSAndroid Build Coastguard Worker value_size = lgetxattr(filename, name, NULL, 0);
197*6a54128fSAndroid Build Coastguard Worker if (value_size == -1) {
198*6a54128fSAndroid Build Coastguard Worker retval = errno;
199*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval,
200*6a54128fSAndroid Build Coastguard Worker _("while reading attribute \"%s\" of \"%s\""),
201*6a54128fSAndroid Build Coastguard Worker name, filename);
202*6a54128fSAndroid Build Coastguard Worker break;
203*6a54128fSAndroid Build Coastguard Worker }
204*6a54128fSAndroid Build Coastguard Worker
205*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_get_mem(value_size, &value);
206*6a54128fSAndroid Build Coastguard Worker if (retval) {
207*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval, _("while allocating memory"));
208*6a54128fSAndroid Build Coastguard Worker break;
209*6a54128fSAndroid Build Coastguard Worker }
210*6a54128fSAndroid Build Coastguard Worker
211*6a54128fSAndroid Build Coastguard Worker value_size = lgetxattr(filename, name, value, value_size);
212*6a54128fSAndroid Build Coastguard Worker if (value_size == -1) {
213*6a54128fSAndroid Build Coastguard Worker ext2fs_free_mem(&value);
214*6a54128fSAndroid Build Coastguard Worker retval = errno;
215*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval,
216*6a54128fSAndroid Build Coastguard Worker _("while reading attribute \"%s\" of \"%s\""),
217*6a54128fSAndroid Build Coastguard Worker name, filename);
218*6a54128fSAndroid Build Coastguard Worker break;
219*6a54128fSAndroid Build Coastguard Worker }
220*6a54128fSAndroid Build Coastguard Worker
221*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_xattr_set(handle, name, value, value_size);
222*6a54128fSAndroid Build Coastguard Worker ext2fs_free_mem(&value);
223*6a54128fSAndroid Build Coastguard Worker if (retval) {
224*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval,
225*6a54128fSAndroid Build Coastguard Worker _("while writing attribute \"%s\" to inode %u"),
226*6a54128fSAndroid Build Coastguard Worker name, ino);
227*6a54128fSAndroid Build Coastguard Worker break;
228*6a54128fSAndroid Build Coastguard Worker }
229*6a54128fSAndroid Build Coastguard Worker
230*6a54128fSAndroid Build Coastguard Worker }
231*6a54128fSAndroid Build Coastguard Worker out:
232*6a54128fSAndroid Build Coastguard Worker ext2fs_free_mem(&list);
233*6a54128fSAndroid Build Coastguard Worker close_retval = ext2fs_xattrs_close(&handle);
234*6a54128fSAndroid Build Coastguard Worker if (close_retval) {
235*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval, _("while closing inode %u"), ino);
236*6a54128fSAndroid Build Coastguard Worker retval = retval ? retval : close_retval;
237*6a54128fSAndroid Build Coastguard Worker }
238*6a54128fSAndroid Build Coastguard Worker return retval;
239*6a54128fSAndroid Build Coastguard Worker }
240*6a54128fSAndroid Build Coastguard Worker #else /* HAVE_LLISTXATTR */
set_inode_xattr(ext2_filsys fs EXT2FS_ATTR ((unused)),ext2_ino_t ino EXT2FS_ATTR ((unused)),const char * filename EXT2FS_ATTR ((unused)))241*6a54128fSAndroid Build Coastguard Worker static errcode_t set_inode_xattr(ext2_filsys fs EXT2FS_ATTR((unused)),
242*6a54128fSAndroid Build Coastguard Worker ext2_ino_t ino EXT2FS_ATTR((unused)),
243*6a54128fSAndroid Build Coastguard Worker const char *filename EXT2FS_ATTR((unused)))
244*6a54128fSAndroid Build Coastguard Worker {
245*6a54128fSAndroid Build Coastguard Worker return 0;
246*6a54128fSAndroid Build Coastguard Worker }
247*6a54128fSAndroid Build Coastguard Worker #endif /* HAVE_LLISTXATTR */
248*6a54128fSAndroid Build Coastguard Worker
249*6a54128fSAndroid Build Coastguard Worker #ifndef _WIN32
250*6a54128fSAndroid Build Coastguard Worker /* Make a special files (block and character devices), fifo's, and sockets */
do_mknod_internal(ext2_filsys fs,ext2_ino_t cwd,const char * name,unsigned int st_mode,unsigned int st_rdev)251*6a54128fSAndroid Build Coastguard Worker errcode_t do_mknod_internal(ext2_filsys fs, ext2_ino_t cwd, const char *name,
252*6a54128fSAndroid Build Coastguard Worker unsigned int st_mode, unsigned int st_rdev)
253*6a54128fSAndroid Build Coastguard Worker {
254*6a54128fSAndroid Build Coastguard Worker ext2_ino_t ino;
255*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
256*6a54128fSAndroid Build Coastguard Worker struct ext2_inode inode;
257*6a54128fSAndroid Build Coastguard Worker unsigned long devmajor, devminor, mode;
258*6a54128fSAndroid Build Coastguard Worker int filetype;
259*6a54128fSAndroid Build Coastguard Worker
260*6a54128fSAndroid Build Coastguard Worker switch(st_mode & S_IFMT) {
261*6a54128fSAndroid Build Coastguard Worker case S_IFCHR:
262*6a54128fSAndroid Build Coastguard Worker mode = LINUX_S_IFCHR;
263*6a54128fSAndroid Build Coastguard Worker filetype = EXT2_FT_CHRDEV;
264*6a54128fSAndroid Build Coastguard Worker break;
265*6a54128fSAndroid Build Coastguard Worker case S_IFBLK:
266*6a54128fSAndroid Build Coastguard Worker mode = LINUX_S_IFBLK;
267*6a54128fSAndroid Build Coastguard Worker filetype = EXT2_FT_BLKDEV;
268*6a54128fSAndroid Build Coastguard Worker break;
269*6a54128fSAndroid Build Coastguard Worker case S_IFIFO:
270*6a54128fSAndroid Build Coastguard Worker mode = LINUX_S_IFIFO;
271*6a54128fSAndroid Build Coastguard Worker filetype = EXT2_FT_FIFO;
272*6a54128fSAndroid Build Coastguard Worker break;
273*6a54128fSAndroid Build Coastguard Worker #ifndef _WIN32
274*6a54128fSAndroid Build Coastguard Worker case S_IFSOCK:
275*6a54128fSAndroid Build Coastguard Worker mode = LINUX_S_IFSOCK;
276*6a54128fSAndroid Build Coastguard Worker filetype = EXT2_FT_SOCK;
277*6a54128fSAndroid Build Coastguard Worker break;
278*6a54128fSAndroid Build Coastguard Worker #endif
279*6a54128fSAndroid Build Coastguard Worker default:
280*6a54128fSAndroid Build Coastguard Worker return EXT2_ET_INVALID_ARGUMENT;
281*6a54128fSAndroid Build Coastguard Worker }
282*6a54128fSAndroid Build Coastguard Worker
283*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_new_inode(fs, cwd, 010755, 0, &ino);
284*6a54128fSAndroid Build Coastguard Worker if (retval) {
285*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval, _("while allocating inode \"%s\""),
286*6a54128fSAndroid Build Coastguard Worker name);
287*6a54128fSAndroid Build Coastguard Worker return retval;
288*6a54128fSAndroid Build Coastguard Worker }
289*6a54128fSAndroid Build Coastguard Worker
290*6a54128fSAndroid Build Coastguard Worker #ifdef DEBUGFS
291*6a54128fSAndroid Build Coastguard Worker printf("Allocated inode: %u\n", ino);
292*6a54128fSAndroid Build Coastguard Worker #endif
293*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_link(fs, cwd, name, ino, filetype);
294*6a54128fSAndroid Build Coastguard Worker if (retval == EXT2_ET_DIR_NO_SPACE) {
295*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_expand_dir(fs, cwd);
296*6a54128fSAndroid Build Coastguard Worker if (retval) {
297*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval,
298*6a54128fSAndroid Build Coastguard Worker _("while expanding directory"));
299*6a54128fSAndroid Build Coastguard Worker return retval;
300*6a54128fSAndroid Build Coastguard Worker }
301*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_link(fs, cwd, name, ino, filetype);
302*6a54128fSAndroid Build Coastguard Worker }
303*6a54128fSAndroid Build Coastguard Worker if (retval) {
304*6a54128fSAndroid Build Coastguard Worker com_err(name, retval, _("while creating inode \"%s\""), name);
305*6a54128fSAndroid Build Coastguard Worker return retval;
306*6a54128fSAndroid Build Coastguard Worker }
307*6a54128fSAndroid Build Coastguard Worker if (ext2fs_test_inode_bitmap2(fs->inode_map, ino))
308*6a54128fSAndroid Build Coastguard Worker com_err(__func__, 0, "Warning: inode already set");
309*6a54128fSAndroid Build Coastguard Worker ext2fs_inode_alloc_stats2(fs, ino, +1, 0);
310*6a54128fSAndroid Build Coastguard Worker memset(&inode, 0, sizeof(inode));
311*6a54128fSAndroid Build Coastguard Worker inode.i_mode = mode;
312*6a54128fSAndroid Build Coastguard Worker inode.i_atime = inode.i_ctime = inode.i_mtime =
313*6a54128fSAndroid Build Coastguard Worker fs->now ? fs->now : time(0);
314*6a54128fSAndroid Build Coastguard Worker
315*6a54128fSAndroid Build Coastguard Worker if (filetype != S_IFIFO) {
316*6a54128fSAndroid Build Coastguard Worker devmajor = major(st_rdev);
317*6a54128fSAndroid Build Coastguard Worker devminor = minor(st_rdev);
318*6a54128fSAndroid Build Coastguard Worker
319*6a54128fSAndroid Build Coastguard Worker if ((devmajor < 256) && (devminor < 256)) {
320*6a54128fSAndroid Build Coastguard Worker inode.i_block[0] = devmajor * 256 + devminor;
321*6a54128fSAndroid Build Coastguard Worker inode.i_block[1] = 0;
322*6a54128fSAndroid Build Coastguard Worker } else {
323*6a54128fSAndroid Build Coastguard Worker inode.i_block[0] = 0;
324*6a54128fSAndroid Build Coastguard Worker inode.i_block[1] = (devminor & 0xff) | (devmajor << 8) |
325*6a54128fSAndroid Build Coastguard Worker ((devminor & ~0xff) << 12);
326*6a54128fSAndroid Build Coastguard Worker }
327*6a54128fSAndroid Build Coastguard Worker }
328*6a54128fSAndroid Build Coastguard Worker inode.i_links_count = 1;
329*6a54128fSAndroid Build Coastguard Worker
330*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_write_new_inode(fs, ino, &inode);
331*6a54128fSAndroid Build Coastguard Worker if (retval)
332*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval, _("while writing inode %u"), ino);
333*6a54128fSAndroid Build Coastguard Worker
334*6a54128fSAndroid Build Coastguard Worker return retval;
335*6a54128fSAndroid Build Coastguard Worker }
336*6a54128fSAndroid Build Coastguard Worker #endif
337*6a54128fSAndroid Build Coastguard Worker
338*6a54128fSAndroid Build Coastguard Worker /* Make a symlink name -> target */
do_symlink_internal(ext2_filsys fs,ext2_ino_t cwd,const char * name,char * target,ext2_ino_t root)339*6a54128fSAndroid Build Coastguard Worker errcode_t do_symlink_internal(ext2_filsys fs, ext2_ino_t cwd, const char *name,
340*6a54128fSAndroid Build Coastguard Worker char *target, ext2_ino_t root)
341*6a54128fSAndroid Build Coastguard Worker {
342*6a54128fSAndroid Build Coastguard Worker char *cp;
343*6a54128fSAndroid Build Coastguard Worker ext2_ino_t parent_ino;
344*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
345*6a54128fSAndroid Build Coastguard Worker
346*6a54128fSAndroid Build Coastguard Worker cp = strrchr(name, '/');
347*6a54128fSAndroid Build Coastguard Worker if (cp) {
348*6a54128fSAndroid Build Coastguard Worker *cp = 0;
349*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_namei(fs, root, cwd, name, &parent_ino);
350*6a54128fSAndroid Build Coastguard Worker if (retval) {
351*6a54128fSAndroid Build Coastguard Worker com_err(name, retval, 0);
352*6a54128fSAndroid Build Coastguard Worker return retval;
353*6a54128fSAndroid Build Coastguard Worker }
354*6a54128fSAndroid Build Coastguard Worker name = cp+1;
355*6a54128fSAndroid Build Coastguard Worker } else
356*6a54128fSAndroid Build Coastguard Worker parent_ino = cwd;
357*6a54128fSAndroid Build Coastguard Worker
358*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_symlink(fs, parent_ino, 0, name, target);
359*6a54128fSAndroid Build Coastguard Worker if (retval == EXT2_ET_DIR_NO_SPACE) {
360*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_expand_dir(fs, parent_ino);
361*6a54128fSAndroid Build Coastguard Worker if (retval) {
362*6a54128fSAndroid Build Coastguard Worker com_err("do_symlink_internal", retval,
363*6a54128fSAndroid Build Coastguard Worker _("while expanding directory"));
364*6a54128fSAndroid Build Coastguard Worker return retval;
365*6a54128fSAndroid Build Coastguard Worker }
366*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_symlink(fs, parent_ino, 0, name, target);
367*6a54128fSAndroid Build Coastguard Worker }
368*6a54128fSAndroid Build Coastguard Worker if (retval)
369*6a54128fSAndroid Build Coastguard Worker com_err("ext2fs_symlink", retval,
370*6a54128fSAndroid Build Coastguard Worker _("while creating symlink \"%s\""), name);
371*6a54128fSAndroid Build Coastguard Worker return retval;
372*6a54128fSAndroid Build Coastguard Worker }
373*6a54128fSAndroid Build Coastguard Worker
374*6a54128fSAndroid Build Coastguard Worker /* Make a directory in the fs */
do_mkdir_internal(ext2_filsys fs,ext2_ino_t cwd,const char * name,ext2_ino_t root)375*6a54128fSAndroid Build Coastguard Worker errcode_t do_mkdir_internal(ext2_filsys fs, ext2_ino_t cwd, const char *name,
376*6a54128fSAndroid Build Coastguard Worker ext2_ino_t root)
377*6a54128fSAndroid Build Coastguard Worker {
378*6a54128fSAndroid Build Coastguard Worker char *cp;
379*6a54128fSAndroid Build Coastguard Worker ext2_ino_t parent_ino;
380*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
381*6a54128fSAndroid Build Coastguard Worker
382*6a54128fSAndroid Build Coastguard Worker
383*6a54128fSAndroid Build Coastguard Worker cp = strrchr(name, '/');
384*6a54128fSAndroid Build Coastguard Worker if (cp) {
385*6a54128fSAndroid Build Coastguard Worker *cp = 0;
386*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_namei(fs, root, cwd, name, &parent_ino);
387*6a54128fSAndroid Build Coastguard Worker if (retval) {
388*6a54128fSAndroid Build Coastguard Worker com_err(name, retval, _("while looking up \"%s\""),
389*6a54128fSAndroid Build Coastguard Worker name);
390*6a54128fSAndroid Build Coastguard Worker return retval;
391*6a54128fSAndroid Build Coastguard Worker }
392*6a54128fSAndroid Build Coastguard Worker name = cp+1;
393*6a54128fSAndroid Build Coastguard Worker } else
394*6a54128fSAndroid Build Coastguard Worker parent_ino = cwd;
395*6a54128fSAndroid Build Coastguard Worker
396*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_mkdir(fs, parent_ino, 0, name);
397*6a54128fSAndroid Build Coastguard Worker if (retval == EXT2_ET_DIR_NO_SPACE) {
398*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_expand_dir(fs, parent_ino);
399*6a54128fSAndroid Build Coastguard Worker if (retval) {
400*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval,
401*6a54128fSAndroid Build Coastguard Worker _("while expanding directory"));
402*6a54128fSAndroid Build Coastguard Worker return retval;
403*6a54128fSAndroid Build Coastguard Worker }
404*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_mkdir(fs, parent_ino, 0, name);
405*6a54128fSAndroid Build Coastguard Worker }
406*6a54128fSAndroid Build Coastguard Worker if (retval)
407*6a54128fSAndroid Build Coastguard Worker com_err("ext2fs_mkdir", retval,
408*6a54128fSAndroid Build Coastguard Worker _("while creating directory \"%s\""), name);
409*6a54128fSAndroid Build Coastguard Worker return retval;
410*6a54128fSAndroid Build Coastguard Worker }
411*6a54128fSAndroid Build Coastguard Worker
412*6a54128fSAndroid Build Coastguard Worker #if !defined HAVE_PREAD64 && !defined HAVE_PREAD
my_pread(int fd,void * buf,size_t count,off_t offset)413*6a54128fSAndroid Build Coastguard Worker static ssize_t my_pread(int fd, void *buf, size_t count, off_t offset)
414*6a54128fSAndroid Build Coastguard Worker {
415*6a54128fSAndroid Build Coastguard Worker if (lseek(fd, offset, SEEK_SET) < 0)
416*6a54128fSAndroid Build Coastguard Worker return 0;
417*6a54128fSAndroid Build Coastguard Worker
418*6a54128fSAndroid Build Coastguard Worker return read(fd, buf, count);
419*6a54128fSAndroid Build Coastguard Worker }
420*6a54128fSAndroid Build Coastguard Worker #endif /* !defined HAVE_PREAD64 && !defined HAVE_PREAD */
421*6a54128fSAndroid Build Coastguard Worker
copy_file_chunk(ext2_filsys fs,int fd,ext2_file_t e2_file,off_t start,off_t end,char * buf,char * zerobuf)422*6a54128fSAndroid Build Coastguard Worker static errcode_t copy_file_chunk(ext2_filsys fs, int fd, ext2_file_t e2_file,
423*6a54128fSAndroid Build Coastguard Worker off_t start, off_t end, char *buf,
424*6a54128fSAndroid Build Coastguard Worker char *zerobuf)
425*6a54128fSAndroid Build Coastguard Worker {
426*6a54128fSAndroid Build Coastguard Worker off_t off, bpos;
427*6a54128fSAndroid Build Coastguard Worker ssize_t got, blen;
428*6a54128fSAndroid Build Coastguard Worker unsigned int written;
429*6a54128fSAndroid Build Coastguard Worker char *ptr;
430*6a54128fSAndroid Build Coastguard Worker errcode_t err = 0;
431*6a54128fSAndroid Build Coastguard Worker
432*6a54128fSAndroid Build Coastguard Worker for (off = start; off < end; off += COPY_FILE_BUFLEN) {
433*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_PREAD64
434*6a54128fSAndroid Build Coastguard Worker got = pread64(fd, buf, COPY_FILE_BUFLEN, off);
435*6a54128fSAndroid Build Coastguard Worker #elif HAVE_PREAD
436*6a54128fSAndroid Build Coastguard Worker got = pread(fd, buf, COPY_FILE_BUFLEN, off);
437*6a54128fSAndroid Build Coastguard Worker #else
438*6a54128fSAndroid Build Coastguard Worker got = my_pread(fd, buf, COPY_FILE_BUFLEN, off);
439*6a54128fSAndroid Build Coastguard Worker #endif
440*6a54128fSAndroid Build Coastguard Worker if (got < 0) {
441*6a54128fSAndroid Build Coastguard Worker err = errno;
442*6a54128fSAndroid Build Coastguard Worker goto fail;
443*6a54128fSAndroid Build Coastguard Worker }
444*6a54128fSAndroid Build Coastguard Worker for (bpos = 0, ptr = buf; bpos < got; bpos += fs->blocksize) {
445*6a54128fSAndroid Build Coastguard Worker blen = fs->blocksize;
446*6a54128fSAndroid Build Coastguard Worker if (blen > got - bpos)
447*6a54128fSAndroid Build Coastguard Worker blen = got - bpos;
448*6a54128fSAndroid Build Coastguard Worker if (memcmp(ptr, zerobuf, blen) == 0) {
449*6a54128fSAndroid Build Coastguard Worker ptr += blen;
450*6a54128fSAndroid Build Coastguard Worker continue;
451*6a54128fSAndroid Build Coastguard Worker }
452*6a54128fSAndroid Build Coastguard Worker err = ext2fs_file_llseek(e2_file, off + bpos,
453*6a54128fSAndroid Build Coastguard Worker EXT2_SEEK_SET, NULL);
454*6a54128fSAndroid Build Coastguard Worker if (err)
455*6a54128fSAndroid Build Coastguard Worker goto fail;
456*6a54128fSAndroid Build Coastguard Worker while (blen > 0) {
457*6a54128fSAndroid Build Coastguard Worker err = ext2fs_file_write(e2_file, ptr, blen,
458*6a54128fSAndroid Build Coastguard Worker &written);
459*6a54128fSAndroid Build Coastguard Worker if (err)
460*6a54128fSAndroid Build Coastguard Worker goto fail;
461*6a54128fSAndroid Build Coastguard Worker if (written == 0) {
462*6a54128fSAndroid Build Coastguard Worker err = EIO;
463*6a54128fSAndroid Build Coastguard Worker goto fail;
464*6a54128fSAndroid Build Coastguard Worker }
465*6a54128fSAndroid Build Coastguard Worker blen -= written;
466*6a54128fSAndroid Build Coastguard Worker ptr += written;
467*6a54128fSAndroid Build Coastguard Worker }
468*6a54128fSAndroid Build Coastguard Worker }
469*6a54128fSAndroid Build Coastguard Worker }
470*6a54128fSAndroid Build Coastguard Worker fail:
471*6a54128fSAndroid Build Coastguard Worker return err;
472*6a54128fSAndroid Build Coastguard Worker }
473*6a54128fSAndroid Build Coastguard Worker
474*6a54128fSAndroid Build Coastguard Worker #if defined(SEEK_DATA) && defined(SEEK_HOLE)
try_lseek_copy(ext2_filsys fs,int fd,struct stat * statbuf,ext2_file_t e2_file,char * buf,char * zerobuf)475*6a54128fSAndroid Build Coastguard Worker static errcode_t try_lseek_copy(ext2_filsys fs, int fd, struct stat *statbuf,
476*6a54128fSAndroid Build Coastguard Worker ext2_file_t e2_file, char *buf, char *zerobuf)
477*6a54128fSAndroid Build Coastguard Worker {
478*6a54128fSAndroid Build Coastguard Worker off_t data = 0, hole;
479*6a54128fSAndroid Build Coastguard Worker off_t data_blk, hole_blk;
480*6a54128fSAndroid Build Coastguard Worker errcode_t err = 0;
481*6a54128fSAndroid Build Coastguard Worker
482*6a54128fSAndroid Build Coastguard Worker /* Try to use SEEK_DATA and SEEK_HOLE */
483*6a54128fSAndroid Build Coastguard Worker while (data < statbuf->st_size) {
484*6a54128fSAndroid Build Coastguard Worker data = lseek(fd, data, SEEK_DATA);
485*6a54128fSAndroid Build Coastguard Worker if (data < 0) {
486*6a54128fSAndroid Build Coastguard Worker if (errno == ENXIO)
487*6a54128fSAndroid Build Coastguard Worker break;
488*6a54128fSAndroid Build Coastguard Worker return EXT2_ET_UNIMPLEMENTED;
489*6a54128fSAndroid Build Coastguard Worker }
490*6a54128fSAndroid Build Coastguard Worker hole = lseek(fd, data, SEEK_HOLE);
491*6a54128fSAndroid Build Coastguard Worker if (hole < 0)
492*6a54128fSAndroid Build Coastguard Worker return EXT2_ET_UNIMPLEMENTED;
493*6a54128fSAndroid Build Coastguard Worker
494*6a54128fSAndroid Build Coastguard Worker data_blk = data & ~(off_t)(fs->blocksize - 1);
495*6a54128fSAndroid Build Coastguard Worker hole_blk = ((hole + (off_t)(fs->blocksize - 1)) &
496*6a54128fSAndroid Build Coastguard Worker ~(off_t)(fs->blocksize - 1));
497*6a54128fSAndroid Build Coastguard Worker err = copy_file_chunk(fs, fd, e2_file, data_blk, hole_blk, buf,
498*6a54128fSAndroid Build Coastguard Worker zerobuf);
499*6a54128fSAndroid Build Coastguard Worker if (err)
500*6a54128fSAndroid Build Coastguard Worker return err;
501*6a54128fSAndroid Build Coastguard Worker
502*6a54128fSAndroid Build Coastguard Worker data = hole;
503*6a54128fSAndroid Build Coastguard Worker }
504*6a54128fSAndroid Build Coastguard Worker
505*6a54128fSAndroid Build Coastguard Worker return err;
506*6a54128fSAndroid Build Coastguard Worker }
507*6a54128fSAndroid Build Coastguard Worker #endif /* SEEK_DATA and SEEK_HOLE */
508*6a54128fSAndroid Build Coastguard Worker
509*6a54128fSAndroid Build Coastguard Worker #if defined(FS_IOC_FIEMAP)
try_fiemap_copy(ext2_filsys fs,int fd,ext2_file_t e2_file,char * buf,char * zerobuf)510*6a54128fSAndroid Build Coastguard Worker static errcode_t try_fiemap_copy(ext2_filsys fs, int fd, ext2_file_t e2_file,
511*6a54128fSAndroid Build Coastguard Worker char *buf, char *zerobuf)
512*6a54128fSAndroid Build Coastguard Worker {
513*6a54128fSAndroid Build Coastguard Worker #define EXTENT_MAX_COUNT 512
514*6a54128fSAndroid Build Coastguard Worker struct fiemap *fiemap_buf;
515*6a54128fSAndroid Build Coastguard Worker struct fiemap_extent *ext_buf, *ext;
516*6a54128fSAndroid Build Coastguard Worker int ext_buf_size, fie_buf_size;
517*6a54128fSAndroid Build Coastguard Worker off_t pos = 0;
518*6a54128fSAndroid Build Coastguard Worker unsigned int i;
519*6a54128fSAndroid Build Coastguard Worker errcode_t err;
520*6a54128fSAndroid Build Coastguard Worker
521*6a54128fSAndroid Build Coastguard Worker ext_buf_size = EXTENT_MAX_COUNT * sizeof(struct fiemap_extent);
522*6a54128fSAndroid Build Coastguard Worker fie_buf_size = sizeof(struct fiemap) + ext_buf_size;
523*6a54128fSAndroid Build Coastguard Worker
524*6a54128fSAndroid Build Coastguard Worker err = ext2fs_get_memzero(fie_buf_size, &fiemap_buf);
525*6a54128fSAndroid Build Coastguard Worker if (err)
526*6a54128fSAndroid Build Coastguard Worker return err;
527*6a54128fSAndroid Build Coastguard Worker
528*6a54128fSAndroid Build Coastguard Worker ext_buf = fiemap_buf->fm_extents;
529*6a54128fSAndroid Build Coastguard Worker memset(fiemap_buf, 0, fie_buf_size);
530*6a54128fSAndroid Build Coastguard Worker fiemap_buf->fm_length = FIEMAP_MAX_OFFSET;
531*6a54128fSAndroid Build Coastguard Worker fiemap_buf->fm_flags |= FIEMAP_FLAG_SYNC;
532*6a54128fSAndroid Build Coastguard Worker fiemap_buf->fm_extent_count = EXTENT_MAX_COUNT;
533*6a54128fSAndroid Build Coastguard Worker
534*6a54128fSAndroid Build Coastguard Worker do {
535*6a54128fSAndroid Build Coastguard Worker fiemap_buf->fm_start = pos;
536*6a54128fSAndroid Build Coastguard Worker memset(ext_buf, 0, ext_buf_size);
537*6a54128fSAndroid Build Coastguard Worker err = ioctl(fd, FS_IOC_FIEMAP, fiemap_buf);
538*6a54128fSAndroid Build Coastguard Worker if (err < 0 && (errno == EOPNOTSUPP || errno == ENOTTY)) {
539*6a54128fSAndroid Build Coastguard Worker err = EXT2_ET_UNIMPLEMENTED;
540*6a54128fSAndroid Build Coastguard Worker goto out;
541*6a54128fSAndroid Build Coastguard Worker } else if (err < 0) {
542*6a54128fSAndroid Build Coastguard Worker err = errno;
543*6a54128fSAndroid Build Coastguard Worker goto out;
544*6a54128fSAndroid Build Coastguard Worker } else if (fiemap_buf->fm_mapped_extents == 0)
545*6a54128fSAndroid Build Coastguard Worker goto out;
546*6a54128fSAndroid Build Coastguard Worker for (i = 0, ext = ext_buf; i < fiemap_buf->fm_mapped_extents;
547*6a54128fSAndroid Build Coastguard Worker i++, ext++) {
548*6a54128fSAndroid Build Coastguard Worker err = copy_file_chunk(fs, fd, e2_file, ext->fe_logical,
549*6a54128fSAndroid Build Coastguard Worker ext->fe_logical + ext->fe_length,
550*6a54128fSAndroid Build Coastguard Worker buf, zerobuf);
551*6a54128fSAndroid Build Coastguard Worker if (err)
552*6a54128fSAndroid Build Coastguard Worker goto out;
553*6a54128fSAndroid Build Coastguard Worker }
554*6a54128fSAndroid Build Coastguard Worker
555*6a54128fSAndroid Build Coastguard Worker ext--;
556*6a54128fSAndroid Build Coastguard Worker /* Record file's logical offset this time */
557*6a54128fSAndroid Build Coastguard Worker pos = ext->fe_logical + ext->fe_length;
558*6a54128fSAndroid Build Coastguard Worker /*
559*6a54128fSAndroid Build Coastguard Worker * If fm_extents array has been filled and
560*6a54128fSAndroid Build Coastguard Worker * there are extents left, continue to cycle.
561*6a54128fSAndroid Build Coastguard Worker */
562*6a54128fSAndroid Build Coastguard Worker } while (fiemap_buf->fm_mapped_extents == EXTENT_MAX_COUNT &&
563*6a54128fSAndroid Build Coastguard Worker !(ext->fe_flags & FIEMAP_EXTENT_LAST));
564*6a54128fSAndroid Build Coastguard Worker out:
565*6a54128fSAndroid Build Coastguard Worker ext2fs_free_mem(&fiemap_buf);
566*6a54128fSAndroid Build Coastguard Worker return err;
567*6a54128fSAndroid Build Coastguard Worker }
568*6a54128fSAndroid Build Coastguard Worker #endif /* FS_IOC_FIEMAP */
569*6a54128fSAndroid Build Coastguard Worker
copy_file(ext2_filsys fs,int fd,struct stat * statbuf,ext2_ino_t ino)570*6a54128fSAndroid Build Coastguard Worker static errcode_t copy_file(ext2_filsys fs, int fd, struct stat *statbuf,
571*6a54128fSAndroid Build Coastguard Worker ext2_ino_t ino)
572*6a54128fSAndroid Build Coastguard Worker {
573*6a54128fSAndroid Build Coastguard Worker ext2_file_t e2_file;
574*6a54128fSAndroid Build Coastguard Worker char *buf = NULL, *zerobuf = NULL;
575*6a54128fSAndroid Build Coastguard Worker errcode_t err, close_err;
576*6a54128fSAndroid Build Coastguard Worker
577*6a54128fSAndroid Build Coastguard Worker err = ext2fs_file_open(fs, ino, EXT2_FILE_WRITE, &e2_file);
578*6a54128fSAndroid Build Coastguard Worker if (err)
579*6a54128fSAndroid Build Coastguard Worker return err;
580*6a54128fSAndroid Build Coastguard Worker
581*6a54128fSAndroid Build Coastguard Worker err = ext2fs_get_mem(COPY_FILE_BUFLEN, &buf);
582*6a54128fSAndroid Build Coastguard Worker if (err)
583*6a54128fSAndroid Build Coastguard Worker goto out;
584*6a54128fSAndroid Build Coastguard Worker
585*6a54128fSAndroid Build Coastguard Worker err = ext2fs_get_memzero(fs->blocksize, &zerobuf);
586*6a54128fSAndroid Build Coastguard Worker if (err)
587*6a54128fSAndroid Build Coastguard Worker goto out;
588*6a54128fSAndroid Build Coastguard Worker
589*6a54128fSAndroid Build Coastguard Worker #if defined(SEEK_DATA) && defined(SEEK_HOLE)
590*6a54128fSAndroid Build Coastguard Worker err = try_lseek_copy(fs, fd, statbuf, e2_file, buf, zerobuf);
591*6a54128fSAndroid Build Coastguard Worker if (err != EXT2_ET_UNIMPLEMENTED)
592*6a54128fSAndroid Build Coastguard Worker goto out;
593*6a54128fSAndroid Build Coastguard Worker #endif
594*6a54128fSAndroid Build Coastguard Worker
595*6a54128fSAndroid Build Coastguard Worker #if defined(FS_IOC_FIEMAP)
596*6a54128fSAndroid Build Coastguard Worker err = try_fiemap_copy(fs, fd, e2_file, buf, zerobuf);
597*6a54128fSAndroid Build Coastguard Worker if (err != EXT2_ET_UNIMPLEMENTED)
598*6a54128fSAndroid Build Coastguard Worker goto out;
599*6a54128fSAndroid Build Coastguard Worker #endif
600*6a54128fSAndroid Build Coastguard Worker
601*6a54128fSAndroid Build Coastguard Worker err = copy_file_chunk(fs, fd, e2_file, 0, statbuf->st_size, buf,
602*6a54128fSAndroid Build Coastguard Worker zerobuf);
603*6a54128fSAndroid Build Coastguard Worker out:
604*6a54128fSAndroid Build Coastguard Worker ext2fs_free_mem(&zerobuf);
605*6a54128fSAndroid Build Coastguard Worker ext2fs_free_mem(&buf);
606*6a54128fSAndroid Build Coastguard Worker close_err = ext2fs_file_close(e2_file);
607*6a54128fSAndroid Build Coastguard Worker if (err == 0)
608*6a54128fSAndroid Build Coastguard Worker err = close_err;
609*6a54128fSAndroid Build Coastguard Worker return err;
610*6a54128fSAndroid Build Coastguard Worker }
611*6a54128fSAndroid Build Coastguard Worker
is_hardlink(struct hdlinks_s * hdlinks,dev_t dev,ino_t ino)612*6a54128fSAndroid Build Coastguard Worker static int is_hardlink(struct hdlinks_s *hdlinks, dev_t dev, ino_t ino)
613*6a54128fSAndroid Build Coastguard Worker {
614*6a54128fSAndroid Build Coastguard Worker int i;
615*6a54128fSAndroid Build Coastguard Worker
616*6a54128fSAndroid Build Coastguard Worker for (i = 0; i < hdlinks->count; i++) {
617*6a54128fSAndroid Build Coastguard Worker if (hdlinks->hdl[i].src_dev == dev &&
618*6a54128fSAndroid Build Coastguard Worker hdlinks->hdl[i].src_ino == ino)
619*6a54128fSAndroid Build Coastguard Worker return i;
620*6a54128fSAndroid Build Coastguard Worker }
621*6a54128fSAndroid Build Coastguard Worker return -1;
622*6a54128fSAndroid Build Coastguard Worker }
623*6a54128fSAndroid Build Coastguard Worker
624*6a54128fSAndroid Build Coastguard Worker /* Copy the native file to the fs */
do_write_internal(ext2_filsys fs,ext2_ino_t cwd,const char * src,const char * dest,ext2_ino_t root)625*6a54128fSAndroid Build Coastguard Worker errcode_t do_write_internal(ext2_filsys fs, ext2_ino_t cwd, const char *src,
626*6a54128fSAndroid Build Coastguard Worker const char *dest, ext2_ino_t root)
627*6a54128fSAndroid Build Coastguard Worker {
628*6a54128fSAndroid Build Coastguard Worker int fd;
629*6a54128fSAndroid Build Coastguard Worker struct stat statbuf;
630*6a54128fSAndroid Build Coastguard Worker ext2_ino_t newfile, parent_ino;
631*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
632*6a54128fSAndroid Build Coastguard Worker struct ext2_inode inode;
633*6a54128fSAndroid Build Coastguard Worker char *cp;
634*6a54128fSAndroid Build Coastguard Worker
635*6a54128fSAndroid Build Coastguard Worker fd = ext2fs_open_file(src, O_RDONLY, 0);
636*6a54128fSAndroid Build Coastguard Worker if (fd < 0) {
637*6a54128fSAndroid Build Coastguard Worker retval = errno;
638*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval, _("while opening \"%s\" to copy"),
639*6a54128fSAndroid Build Coastguard Worker src);
640*6a54128fSAndroid Build Coastguard Worker return retval;
641*6a54128fSAndroid Build Coastguard Worker }
642*6a54128fSAndroid Build Coastguard Worker if (fstat(fd, &statbuf) < 0) {
643*6a54128fSAndroid Build Coastguard Worker retval = errno;
644*6a54128fSAndroid Build Coastguard Worker goto out;
645*6a54128fSAndroid Build Coastguard Worker }
646*6a54128fSAndroid Build Coastguard Worker
647*6a54128fSAndroid Build Coastguard Worker cp = strrchr(dest, '/');
648*6a54128fSAndroid Build Coastguard Worker if (cp) {
649*6a54128fSAndroid Build Coastguard Worker *cp = 0;
650*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_namei(fs, root, cwd, dest, &parent_ino);
651*6a54128fSAndroid Build Coastguard Worker if (retval) {
652*6a54128fSAndroid Build Coastguard Worker com_err(dest, retval, _("while looking up \"%s\""),
653*6a54128fSAndroid Build Coastguard Worker dest);
654*6a54128fSAndroid Build Coastguard Worker goto out;
655*6a54128fSAndroid Build Coastguard Worker }
656*6a54128fSAndroid Build Coastguard Worker dest = cp+1;
657*6a54128fSAndroid Build Coastguard Worker } else
658*6a54128fSAndroid Build Coastguard Worker parent_ino = cwd;
659*6a54128fSAndroid Build Coastguard Worker
660*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_namei(fs, root, parent_ino, dest, &newfile);
661*6a54128fSAndroid Build Coastguard Worker if (retval == 0) {
662*6a54128fSAndroid Build Coastguard Worker retval = EXT2_ET_FILE_EXISTS;
663*6a54128fSAndroid Build Coastguard Worker goto out;
664*6a54128fSAndroid Build Coastguard Worker }
665*6a54128fSAndroid Build Coastguard Worker
666*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_new_inode(fs, parent_ino, 010755, 0, &newfile);
667*6a54128fSAndroid Build Coastguard Worker if (retval)
668*6a54128fSAndroid Build Coastguard Worker goto out;
669*6a54128fSAndroid Build Coastguard Worker #ifdef DEBUGFS
670*6a54128fSAndroid Build Coastguard Worker printf("Allocated inode: %u\n", newfile);
671*6a54128fSAndroid Build Coastguard Worker #endif
672*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_link(fs, parent_ino, dest, newfile, EXT2_FT_REG_FILE);
673*6a54128fSAndroid Build Coastguard Worker if (retval == EXT2_ET_DIR_NO_SPACE) {
674*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_expand_dir(fs, parent_ino);
675*6a54128fSAndroid Build Coastguard Worker if (retval)
676*6a54128fSAndroid Build Coastguard Worker goto out;
677*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_link(fs, parent_ino, dest, newfile,
678*6a54128fSAndroid Build Coastguard Worker EXT2_FT_REG_FILE);
679*6a54128fSAndroid Build Coastguard Worker }
680*6a54128fSAndroid Build Coastguard Worker if (retval)
681*6a54128fSAndroid Build Coastguard Worker goto out;
682*6a54128fSAndroid Build Coastguard Worker if (ext2fs_test_inode_bitmap2(fs->inode_map, newfile))
683*6a54128fSAndroid Build Coastguard Worker com_err(__func__, 0, "Warning: inode already set");
684*6a54128fSAndroid Build Coastguard Worker ext2fs_inode_alloc_stats2(fs, newfile, +1, 0);
685*6a54128fSAndroid Build Coastguard Worker memset(&inode, 0, sizeof(inode));
686*6a54128fSAndroid Build Coastguard Worker inode.i_mode = (statbuf.st_mode & ~S_IFMT) | LINUX_S_IFREG;
687*6a54128fSAndroid Build Coastguard Worker inode.i_atime = inode.i_ctime = inode.i_mtime =
688*6a54128fSAndroid Build Coastguard Worker fs->now ? fs->now : time(0);
689*6a54128fSAndroid Build Coastguard Worker inode.i_links_count = 1;
690*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_inode_size_set(fs, &inode, statbuf.st_size);
691*6a54128fSAndroid Build Coastguard Worker if (retval)
692*6a54128fSAndroid Build Coastguard Worker goto out;
693*6a54128fSAndroid Build Coastguard Worker if (ext2fs_has_feature_inline_data(fs->super)) {
694*6a54128fSAndroid Build Coastguard Worker inode.i_flags |= EXT4_INLINE_DATA_FL;
695*6a54128fSAndroid Build Coastguard Worker } else if (ext2fs_has_feature_extents(fs->super)) {
696*6a54128fSAndroid Build Coastguard Worker ext2_extent_handle_t handle;
697*6a54128fSAndroid Build Coastguard Worker
698*6a54128fSAndroid Build Coastguard Worker inode.i_flags &= ~EXT4_EXTENTS_FL;
699*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_extent_open2(fs, newfile, &inode, &handle);
700*6a54128fSAndroid Build Coastguard Worker if (retval)
701*6a54128fSAndroid Build Coastguard Worker goto out;
702*6a54128fSAndroid Build Coastguard Worker ext2fs_extent_free(handle);
703*6a54128fSAndroid Build Coastguard Worker }
704*6a54128fSAndroid Build Coastguard Worker
705*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_write_new_inode(fs, newfile, &inode);
706*6a54128fSAndroid Build Coastguard Worker if (retval)
707*6a54128fSAndroid Build Coastguard Worker goto out;
708*6a54128fSAndroid Build Coastguard Worker if (inode.i_flags & EXT4_INLINE_DATA_FL) {
709*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_inline_data_init(fs, newfile);
710*6a54128fSAndroid Build Coastguard Worker if (retval)
711*6a54128fSAndroid Build Coastguard Worker goto out;
712*6a54128fSAndroid Build Coastguard Worker }
713*6a54128fSAndroid Build Coastguard Worker if (LINUX_S_ISREG(inode.i_mode)) {
714*6a54128fSAndroid Build Coastguard Worker retval = copy_file(fs, fd, &statbuf, newfile);
715*6a54128fSAndroid Build Coastguard Worker if (retval)
716*6a54128fSAndroid Build Coastguard Worker goto out;
717*6a54128fSAndroid Build Coastguard Worker }
718*6a54128fSAndroid Build Coastguard Worker out:
719*6a54128fSAndroid Build Coastguard Worker close(fd);
720*6a54128fSAndroid Build Coastguard Worker return retval;
721*6a54128fSAndroid Build Coastguard Worker }
722*6a54128fSAndroid Build Coastguard Worker
723*6a54128fSAndroid Build Coastguard Worker struct file_info {
724*6a54128fSAndroid Build Coastguard Worker char *path;
725*6a54128fSAndroid Build Coastguard Worker size_t path_len;
726*6a54128fSAndroid Build Coastguard Worker size_t path_max_len;
727*6a54128fSAndroid Build Coastguard Worker };
728*6a54128fSAndroid Build Coastguard Worker
path_append(struct file_info * target,const char * file)729*6a54128fSAndroid Build Coastguard Worker static errcode_t path_append(struct file_info *target, const char *file)
730*6a54128fSAndroid Build Coastguard Worker {
731*6a54128fSAndroid Build Coastguard Worker if (strlen(file) + target->path_len + 1 > target->path_max_len) {
732*6a54128fSAndroid Build Coastguard Worker void *p;
733*6a54128fSAndroid Build Coastguard Worker target->path_max_len *= 2;
734*6a54128fSAndroid Build Coastguard Worker p = realloc(target->path, target->path_max_len);
735*6a54128fSAndroid Build Coastguard Worker if (p == NULL)
736*6a54128fSAndroid Build Coastguard Worker return EXT2_ET_NO_MEMORY;
737*6a54128fSAndroid Build Coastguard Worker target->path = p;
738*6a54128fSAndroid Build Coastguard Worker }
739*6a54128fSAndroid Build Coastguard Worker target->path_len += sprintf(target->path + target->path_len, "/%s",
740*6a54128fSAndroid Build Coastguard Worker file);
741*6a54128fSAndroid Build Coastguard Worker return 0;
742*6a54128fSAndroid Build Coastguard Worker }
743*6a54128fSAndroid Build Coastguard Worker
744*6a54128fSAndroid Build Coastguard Worker #ifdef _WIN32
scandir(const char * dir_name,struct dirent *** name_list,int (* filter)(const struct dirent *),int (* compar)(const struct dirent **,const struct dirent **))745*6a54128fSAndroid Build Coastguard Worker static int scandir(const char *dir_name, struct dirent ***name_list,
746*6a54128fSAndroid Build Coastguard Worker int (*filter)(const struct dirent*),
747*6a54128fSAndroid Build Coastguard Worker int (*compar)(const struct dirent**, const struct dirent**)) {
748*6a54128fSAndroid Build Coastguard Worker DIR *dir;
749*6a54128fSAndroid Build Coastguard Worker struct dirent *dent;
750*6a54128fSAndroid Build Coastguard Worker struct dirent **temp_list = NULL;
751*6a54128fSAndroid Build Coastguard Worker size_t temp_list_size = 0; // unit: num of dirent
752*6a54128fSAndroid Build Coastguard Worker size_t num_dent = 0;
753*6a54128fSAndroid Build Coastguard Worker
754*6a54128fSAndroid Build Coastguard Worker dir = opendir(dir_name);
755*6a54128fSAndroid Build Coastguard Worker if (dir == NULL) {
756*6a54128fSAndroid Build Coastguard Worker return -1;
757*6a54128fSAndroid Build Coastguard Worker }
758*6a54128fSAndroid Build Coastguard Worker
759*6a54128fSAndroid Build Coastguard Worker while ((dent = readdir(dir))) {
760*6a54128fSAndroid Build Coastguard Worker if (filter != NULL && !(*filter)(dent))
761*6a54128fSAndroid Build Coastguard Worker continue;
762*6a54128fSAndroid Build Coastguard Worker
763*6a54128fSAndroid Build Coastguard Worker // re-allocate the list
764*6a54128fSAndroid Build Coastguard Worker if (num_dent == temp_list_size) {
765*6a54128fSAndroid Build Coastguard Worker size_t new_list_size = temp_list_size + 32;
766*6a54128fSAndroid Build Coastguard Worker struct dirent **new_list = (struct dirent**)realloc(
767*6a54128fSAndroid Build Coastguard Worker temp_list, new_list_size * sizeof(struct dirent*));
768*6a54128fSAndroid Build Coastguard Worker if (new_list == NULL)
769*6a54128fSAndroid Build Coastguard Worker goto out_err;
770*6a54128fSAndroid Build Coastguard Worker temp_list_size = new_list_size;
771*6a54128fSAndroid Build Coastguard Worker temp_list = new_list;
772*6a54128fSAndroid Build Coastguard Worker }
773*6a54128fSAndroid Build Coastguard Worker // add the copy of dirent to the list
774*6a54128fSAndroid Build Coastguard Worker temp_list[num_dent] = (struct dirent*)malloc((dent->d_reclen + 3) & ~3);
775*6a54128fSAndroid Build Coastguard Worker if (!temp_list[num_dent])
776*6a54128fSAndroid Build Coastguard Worker goto out_err;
777*6a54128fSAndroid Build Coastguard Worker memcpy(temp_list[num_dent], dent, dent->d_reclen);
778*6a54128fSAndroid Build Coastguard Worker num_dent++;
779*6a54128fSAndroid Build Coastguard Worker }
780*6a54128fSAndroid Build Coastguard Worker closedir(dir);
781*6a54128fSAndroid Build Coastguard Worker
782*6a54128fSAndroid Build Coastguard Worker if (compar != NULL) {
783*6a54128fSAndroid Build Coastguard Worker qsort(temp_list, num_dent, sizeof(struct dirent*),
784*6a54128fSAndroid Build Coastguard Worker (int (*)(const void*, const void*))compar);
785*6a54128fSAndroid Build Coastguard Worker }
786*6a54128fSAndroid Build Coastguard Worker *name_list = temp_list;
787*6a54128fSAndroid Build Coastguard Worker return num_dent;
788*6a54128fSAndroid Build Coastguard Worker
789*6a54128fSAndroid Build Coastguard Worker out_err:
790*6a54128fSAndroid Build Coastguard Worker closedir(dir);
791*6a54128fSAndroid Build Coastguard Worker while (num_dent > 0)
792*6a54128fSAndroid Build Coastguard Worker free(temp_list[--num_dent]);
793*6a54128fSAndroid Build Coastguard Worker free(temp_list);
794*6a54128fSAndroid Build Coastguard Worker return -1;
795*6a54128fSAndroid Build Coastguard Worker }
796*6a54128fSAndroid Build Coastguard Worker
alphasort(const struct dirent ** a,const struct dirent ** b)797*6a54128fSAndroid Build Coastguard Worker static int alphasort(const struct dirent **a, const struct dirent **b) {
798*6a54128fSAndroid Build Coastguard Worker return strcoll((*a)->d_name, (*b)->d_name);
799*6a54128fSAndroid Build Coastguard Worker }
800*6a54128fSAndroid Build Coastguard Worker #endif
801*6a54128fSAndroid Build Coastguard Worker
802*6a54128fSAndroid Build Coastguard Worker /* Copy files from source_dir to fs in alphabetical order */
__populate_fs(ext2_filsys fs,ext2_ino_t parent_ino,const char * source_dir,ext2_ino_t root,struct hdlinks_s * hdlinks,struct file_info * target,struct fs_ops_callbacks * fs_callbacks)803*6a54128fSAndroid Build Coastguard Worker static errcode_t __populate_fs(ext2_filsys fs, ext2_ino_t parent_ino,
804*6a54128fSAndroid Build Coastguard Worker const char *source_dir, ext2_ino_t root,
805*6a54128fSAndroid Build Coastguard Worker struct hdlinks_s *hdlinks,
806*6a54128fSAndroid Build Coastguard Worker struct file_info *target,
807*6a54128fSAndroid Build Coastguard Worker struct fs_ops_callbacks *fs_callbacks)
808*6a54128fSAndroid Build Coastguard Worker {
809*6a54128fSAndroid Build Coastguard Worker const char *name;
810*6a54128fSAndroid Build Coastguard Worker struct dirent **dent;
811*6a54128fSAndroid Build Coastguard Worker struct stat st;
812*6a54128fSAndroid Build Coastguard Worker unsigned int save_inode;
813*6a54128fSAndroid Build Coastguard Worker ext2_ino_t ino;
814*6a54128fSAndroid Build Coastguard Worker errcode_t retval = 0;
815*6a54128fSAndroid Build Coastguard Worker int hdlink;
816*6a54128fSAndroid Build Coastguard Worker size_t cur_dir_path_len;
817*6a54128fSAndroid Build Coastguard Worker int i, num_dents;
818*6a54128fSAndroid Build Coastguard Worker
819*6a54128fSAndroid Build Coastguard Worker if (chdir(source_dir) < 0) {
820*6a54128fSAndroid Build Coastguard Worker retval = errno;
821*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval,
822*6a54128fSAndroid Build Coastguard Worker _("while changing working directory to \"%s\""),
823*6a54128fSAndroid Build Coastguard Worker source_dir);
824*6a54128fSAndroid Build Coastguard Worker return retval;
825*6a54128fSAndroid Build Coastguard Worker }
826*6a54128fSAndroid Build Coastguard Worker
827*6a54128fSAndroid Build Coastguard Worker num_dents = scandir(".", &dent, NULL, alphasort);
828*6a54128fSAndroid Build Coastguard Worker
829*6a54128fSAndroid Build Coastguard Worker if (num_dents < 0) {
830*6a54128fSAndroid Build Coastguard Worker retval = errno;
831*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval,
832*6a54128fSAndroid Build Coastguard Worker _("while scanning directory \"%s\""), source_dir);
833*6a54128fSAndroid Build Coastguard Worker return retval;
834*6a54128fSAndroid Build Coastguard Worker }
835*6a54128fSAndroid Build Coastguard Worker
836*6a54128fSAndroid Build Coastguard Worker for (i = 0; i < num_dents; free(dent[i]), i++) {
837*6a54128fSAndroid Build Coastguard Worker name = dent[i]->d_name;
838*6a54128fSAndroid Build Coastguard Worker if ((!strcmp(name, ".")) || (!strcmp(name, "..")))
839*6a54128fSAndroid Build Coastguard Worker continue;
840*6a54128fSAndroid Build Coastguard Worker if (lstat(name, &st)) {
841*6a54128fSAndroid Build Coastguard Worker retval = errno;
842*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval, _("while lstat \"%s\""),
843*6a54128fSAndroid Build Coastguard Worker name);
844*6a54128fSAndroid Build Coastguard Worker goto out;
845*6a54128fSAndroid Build Coastguard Worker }
846*6a54128fSAndroid Build Coastguard Worker
847*6a54128fSAndroid Build Coastguard Worker /* Check for hardlinks */
848*6a54128fSAndroid Build Coastguard Worker save_inode = 0;
849*6a54128fSAndroid Build Coastguard Worker if (!S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode) &&
850*6a54128fSAndroid Build Coastguard Worker st.st_nlink > 1) {
851*6a54128fSAndroid Build Coastguard Worker hdlink = is_hardlink(hdlinks, st.st_dev, st.st_ino);
852*6a54128fSAndroid Build Coastguard Worker if (hdlink >= 0) {
853*6a54128fSAndroid Build Coastguard Worker retval = add_link(fs, parent_ino,
854*6a54128fSAndroid Build Coastguard Worker hdlinks->hdl[hdlink].dst_ino,
855*6a54128fSAndroid Build Coastguard Worker name);
856*6a54128fSAndroid Build Coastguard Worker if (retval) {
857*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval,
858*6a54128fSAndroid Build Coastguard Worker "while linking %s", name);
859*6a54128fSAndroid Build Coastguard Worker goto out;
860*6a54128fSAndroid Build Coastguard Worker }
861*6a54128fSAndroid Build Coastguard Worker continue;
862*6a54128fSAndroid Build Coastguard Worker } else
863*6a54128fSAndroid Build Coastguard Worker save_inode = 1;
864*6a54128fSAndroid Build Coastguard Worker }
865*6a54128fSAndroid Build Coastguard Worker
866*6a54128fSAndroid Build Coastguard Worker cur_dir_path_len = target->path_len;
867*6a54128fSAndroid Build Coastguard Worker retval = path_append(target, name);
868*6a54128fSAndroid Build Coastguard Worker if (retval) {
869*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval,
870*6a54128fSAndroid Build Coastguard Worker "while appending %s", name);
871*6a54128fSAndroid Build Coastguard Worker goto out;
872*6a54128fSAndroid Build Coastguard Worker }
873*6a54128fSAndroid Build Coastguard Worker
874*6a54128fSAndroid Build Coastguard Worker if (fs_callbacks && fs_callbacks->create_new_inode) {
875*6a54128fSAndroid Build Coastguard Worker retval = fs_callbacks->create_new_inode(fs,
876*6a54128fSAndroid Build Coastguard Worker target->path, name, parent_ino, root,
877*6a54128fSAndroid Build Coastguard Worker st.st_mode & S_IFMT);
878*6a54128fSAndroid Build Coastguard Worker if (retval)
879*6a54128fSAndroid Build Coastguard Worker goto out;
880*6a54128fSAndroid Build Coastguard Worker }
881*6a54128fSAndroid Build Coastguard Worker
882*6a54128fSAndroid Build Coastguard Worker switch(st.st_mode & S_IFMT) {
883*6a54128fSAndroid Build Coastguard Worker case S_IFCHR:
884*6a54128fSAndroid Build Coastguard Worker case S_IFBLK:
885*6a54128fSAndroid Build Coastguard Worker case S_IFIFO:
886*6a54128fSAndroid Build Coastguard Worker #ifndef _WIN32
887*6a54128fSAndroid Build Coastguard Worker case S_IFSOCK:
888*6a54128fSAndroid Build Coastguard Worker retval = do_mknod_internal(fs, parent_ino, name,
889*6a54128fSAndroid Build Coastguard Worker st.st_mode, st.st_rdev);
890*6a54128fSAndroid Build Coastguard Worker if (retval) {
891*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval,
892*6a54128fSAndroid Build Coastguard Worker _("while creating special file "
893*6a54128fSAndroid Build Coastguard Worker "\"%s\""), name);
894*6a54128fSAndroid Build Coastguard Worker goto out;
895*6a54128fSAndroid Build Coastguard Worker }
896*6a54128fSAndroid Build Coastguard Worker break;
897*6a54128fSAndroid Build Coastguard Worker case S_IFLNK: {
898*6a54128fSAndroid Build Coastguard Worker char *ln_target;
899*6a54128fSAndroid Build Coastguard Worker int read_cnt;
900*6a54128fSAndroid Build Coastguard Worker
901*6a54128fSAndroid Build Coastguard Worker ln_target = malloc(st.st_size + 1);
902*6a54128fSAndroid Build Coastguard Worker if (ln_target == NULL) {
903*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval,
904*6a54128fSAndroid Build Coastguard Worker _("malloc failed"));
905*6a54128fSAndroid Build Coastguard Worker goto out;
906*6a54128fSAndroid Build Coastguard Worker }
907*6a54128fSAndroid Build Coastguard Worker read_cnt = readlink(name, ln_target,
908*6a54128fSAndroid Build Coastguard Worker st.st_size + 1);
909*6a54128fSAndroid Build Coastguard Worker if (read_cnt == -1) {
910*6a54128fSAndroid Build Coastguard Worker retval = errno;
911*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval,
912*6a54128fSAndroid Build Coastguard Worker _("while trying to read link \"%s\""),
913*6a54128fSAndroid Build Coastguard Worker name);
914*6a54128fSAndroid Build Coastguard Worker free(ln_target);
915*6a54128fSAndroid Build Coastguard Worker goto out;
916*6a54128fSAndroid Build Coastguard Worker }
917*6a54128fSAndroid Build Coastguard Worker if (read_cnt > st.st_size) {
918*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval,
919*6a54128fSAndroid Build Coastguard Worker _("symlink increased in size "
920*6a54128fSAndroid Build Coastguard Worker "between lstat() and readlink()"));
921*6a54128fSAndroid Build Coastguard Worker free(ln_target);
922*6a54128fSAndroid Build Coastguard Worker goto out;
923*6a54128fSAndroid Build Coastguard Worker }
924*6a54128fSAndroid Build Coastguard Worker ln_target[read_cnt] = '\0';
925*6a54128fSAndroid Build Coastguard Worker retval = do_symlink_internal(fs, parent_ino, name,
926*6a54128fSAndroid Build Coastguard Worker ln_target, root);
927*6a54128fSAndroid Build Coastguard Worker free(ln_target);
928*6a54128fSAndroid Build Coastguard Worker if (retval) {
929*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval,
930*6a54128fSAndroid Build Coastguard Worker _("while writing symlink\"%s\""),
931*6a54128fSAndroid Build Coastguard Worker name);
932*6a54128fSAndroid Build Coastguard Worker goto out;
933*6a54128fSAndroid Build Coastguard Worker }
934*6a54128fSAndroid Build Coastguard Worker break;
935*6a54128fSAndroid Build Coastguard Worker }
936*6a54128fSAndroid Build Coastguard Worker #endif /* !_WIN32 */
937*6a54128fSAndroid Build Coastguard Worker case S_IFREG:
938*6a54128fSAndroid Build Coastguard Worker retval = do_write_internal(fs, parent_ino, name, name,
939*6a54128fSAndroid Build Coastguard Worker root);
940*6a54128fSAndroid Build Coastguard Worker if (retval) {
941*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval,
942*6a54128fSAndroid Build Coastguard Worker _("while writing file \"%s\""), name);
943*6a54128fSAndroid Build Coastguard Worker goto out;
944*6a54128fSAndroid Build Coastguard Worker }
945*6a54128fSAndroid Build Coastguard Worker break;
946*6a54128fSAndroid Build Coastguard Worker case S_IFDIR:
947*6a54128fSAndroid Build Coastguard Worker /* Don't choke on /lost+found */
948*6a54128fSAndroid Build Coastguard Worker if (parent_ino == EXT2_ROOT_INO &&
949*6a54128fSAndroid Build Coastguard Worker strcmp(name, "lost+found") == 0)
950*6a54128fSAndroid Build Coastguard Worker goto find_lnf;
951*6a54128fSAndroid Build Coastguard Worker retval = do_mkdir_internal(fs, parent_ino, name,
952*6a54128fSAndroid Build Coastguard Worker root);
953*6a54128fSAndroid Build Coastguard Worker if (retval) {
954*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval,
955*6a54128fSAndroid Build Coastguard Worker _("while making dir \"%s\""), name);
956*6a54128fSAndroid Build Coastguard Worker goto out;
957*6a54128fSAndroid Build Coastguard Worker }
958*6a54128fSAndroid Build Coastguard Worker find_lnf:
959*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_namei(fs, root, parent_ino,
960*6a54128fSAndroid Build Coastguard Worker name, &ino);
961*6a54128fSAndroid Build Coastguard Worker if (retval) {
962*6a54128fSAndroid Build Coastguard Worker com_err(name, retval, 0);
963*6a54128fSAndroid Build Coastguard Worker goto out;
964*6a54128fSAndroid Build Coastguard Worker }
965*6a54128fSAndroid Build Coastguard Worker /* Populate the dir recursively*/
966*6a54128fSAndroid Build Coastguard Worker retval = __populate_fs(fs, ino, name, root, hdlinks,
967*6a54128fSAndroid Build Coastguard Worker target, fs_callbacks);
968*6a54128fSAndroid Build Coastguard Worker if (retval)
969*6a54128fSAndroid Build Coastguard Worker goto out;
970*6a54128fSAndroid Build Coastguard Worker if (chdir("..")) {
971*6a54128fSAndroid Build Coastguard Worker retval = errno;
972*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval,
973*6a54128fSAndroid Build Coastguard Worker _("while changing directory"));
974*6a54128fSAndroid Build Coastguard Worker goto out;
975*6a54128fSAndroid Build Coastguard Worker }
976*6a54128fSAndroid Build Coastguard Worker break;
977*6a54128fSAndroid Build Coastguard Worker default:
978*6a54128fSAndroid Build Coastguard Worker com_err(__func__, 0,
979*6a54128fSAndroid Build Coastguard Worker _("ignoring entry \"%s\""), name);
980*6a54128fSAndroid Build Coastguard Worker }
981*6a54128fSAndroid Build Coastguard Worker
982*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_namei(fs, root, parent_ino, name, &ino);
983*6a54128fSAndroid Build Coastguard Worker if (retval) {
984*6a54128fSAndroid Build Coastguard Worker com_err(name, retval, _("while looking up \"%s\""),
985*6a54128fSAndroid Build Coastguard Worker name);
986*6a54128fSAndroid Build Coastguard Worker goto out;
987*6a54128fSAndroid Build Coastguard Worker }
988*6a54128fSAndroid Build Coastguard Worker
989*6a54128fSAndroid Build Coastguard Worker retval = set_inode_extra(fs, ino, &st);
990*6a54128fSAndroid Build Coastguard Worker if (retval) {
991*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval,
992*6a54128fSAndroid Build Coastguard Worker _("while setting inode for \"%s\""), name);
993*6a54128fSAndroid Build Coastguard Worker goto out;
994*6a54128fSAndroid Build Coastguard Worker }
995*6a54128fSAndroid Build Coastguard Worker
996*6a54128fSAndroid Build Coastguard Worker retval = set_inode_xattr(fs, ino, name);
997*6a54128fSAndroid Build Coastguard Worker if (retval) {
998*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval,
999*6a54128fSAndroid Build Coastguard Worker _("while setting xattrs for \"%s\""), name);
1000*6a54128fSAndroid Build Coastguard Worker goto out;
1001*6a54128fSAndroid Build Coastguard Worker }
1002*6a54128fSAndroid Build Coastguard Worker
1003*6a54128fSAndroid Build Coastguard Worker if (fs_callbacks && fs_callbacks->end_create_new_inode) {
1004*6a54128fSAndroid Build Coastguard Worker retval = fs_callbacks->end_create_new_inode(fs,
1005*6a54128fSAndroid Build Coastguard Worker target->path, name, parent_ino, root,
1006*6a54128fSAndroid Build Coastguard Worker st.st_mode & S_IFMT);
1007*6a54128fSAndroid Build Coastguard Worker if (retval)
1008*6a54128fSAndroid Build Coastguard Worker goto out;
1009*6a54128fSAndroid Build Coastguard Worker }
1010*6a54128fSAndroid Build Coastguard Worker
1011*6a54128fSAndroid Build Coastguard Worker /* Save the hardlink ino */
1012*6a54128fSAndroid Build Coastguard Worker if (save_inode) {
1013*6a54128fSAndroid Build Coastguard Worker /*
1014*6a54128fSAndroid Build Coastguard Worker * Check whether need more memory, and we don't need
1015*6a54128fSAndroid Build Coastguard Worker * free() since the lifespan will be over after the fs
1016*6a54128fSAndroid Build Coastguard Worker * populated.
1017*6a54128fSAndroid Build Coastguard Worker */
1018*6a54128fSAndroid Build Coastguard Worker if (hdlinks->count == hdlinks->size) {
1019*6a54128fSAndroid Build Coastguard Worker void *p = realloc(hdlinks->hdl,
1020*6a54128fSAndroid Build Coastguard Worker (hdlinks->size + HDLINK_CNT) *
1021*6a54128fSAndroid Build Coastguard Worker sizeof(struct hdlink_s));
1022*6a54128fSAndroid Build Coastguard Worker if (p == NULL) {
1023*6a54128fSAndroid Build Coastguard Worker retval = EXT2_ET_NO_MEMORY;
1024*6a54128fSAndroid Build Coastguard Worker com_err(name, retval,
1025*6a54128fSAndroid Build Coastguard Worker _("while saving inode data"));
1026*6a54128fSAndroid Build Coastguard Worker goto out;
1027*6a54128fSAndroid Build Coastguard Worker }
1028*6a54128fSAndroid Build Coastguard Worker hdlinks->hdl = p;
1029*6a54128fSAndroid Build Coastguard Worker hdlinks->size += HDLINK_CNT;
1030*6a54128fSAndroid Build Coastguard Worker }
1031*6a54128fSAndroid Build Coastguard Worker hdlinks->hdl[hdlinks->count].src_dev = st.st_dev;
1032*6a54128fSAndroid Build Coastguard Worker hdlinks->hdl[hdlinks->count].src_ino = st.st_ino;
1033*6a54128fSAndroid Build Coastguard Worker hdlinks->hdl[hdlinks->count].dst_ino = ino;
1034*6a54128fSAndroid Build Coastguard Worker hdlinks->count++;
1035*6a54128fSAndroid Build Coastguard Worker }
1036*6a54128fSAndroid Build Coastguard Worker target->path_len = cur_dir_path_len;
1037*6a54128fSAndroid Build Coastguard Worker target->path[target->path_len] = 0;
1038*6a54128fSAndroid Build Coastguard Worker }
1039*6a54128fSAndroid Build Coastguard Worker
1040*6a54128fSAndroid Build Coastguard Worker out:
1041*6a54128fSAndroid Build Coastguard Worker for (; i < num_dents; free(dent[i]), i++);
1042*6a54128fSAndroid Build Coastguard Worker free(dent);
1043*6a54128fSAndroid Build Coastguard Worker return retval;
1044*6a54128fSAndroid Build Coastguard Worker }
1045*6a54128fSAndroid Build Coastguard Worker
populate_fs2(ext2_filsys fs,ext2_ino_t parent_ino,const char * source_dir,ext2_ino_t root,struct fs_ops_callbacks * fs_callbacks)1046*6a54128fSAndroid Build Coastguard Worker errcode_t populate_fs2(ext2_filsys fs, ext2_ino_t parent_ino,
1047*6a54128fSAndroid Build Coastguard Worker const char *source_dir, ext2_ino_t root,
1048*6a54128fSAndroid Build Coastguard Worker struct fs_ops_callbacks *fs_callbacks)
1049*6a54128fSAndroid Build Coastguard Worker {
1050*6a54128fSAndroid Build Coastguard Worker struct file_info file_info;
1051*6a54128fSAndroid Build Coastguard Worker struct hdlinks_s hdlinks;
1052*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
1053*6a54128fSAndroid Build Coastguard Worker
1054*6a54128fSAndroid Build Coastguard Worker if (!(fs->flags & EXT2_FLAG_RW)) {
1055*6a54128fSAndroid Build Coastguard Worker com_err(__func__, 0, "Filesystem opened readonly");
1056*6a54128fSAndroid Build Coastguard Worker return EROFS;
1057*6a54128fSAndroid Build Coastguard Worker }
1058*6a54128fSAndroid Build Coastguard Worker
1059*6a54128fSAndroid Build Coastguard Worker hdlinks.count = 0;
1060*6a54128fSAndroid Build Coastguard Worker hdlinks.size = HDLINK_CNT;
1061*6a54128fSAndroid Build Coastguard Worker hdlinks.hdl = realloc(NULL, hdlinks.size * sizeof(struct hdlink_s));
1062*6a54128fSAndroid Build Coastguard Worker if (hdlinks.hdl == NULL) {
1063*6a54128fSAndroid Build Coastguard Worker retval = errno;
1064*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval, _("while allocating memory"));
1065*6a54128fSAndroid Build Coastguard Worker return retval;
1066*6a54128fSAndroid Build Coastguard Worker }
1067*6a54128fSAndroid Build Coastguard Worker
1068*6a54128fSAndroid Build Coastguard Worker file_info.path_len = 0;
1069*6a54128fSAndroid Build Coastguard Worker file_info.path_max_len = 255;
1070*6a54128fSAndroid Build Coastguard Worker file_info.path = calloc(file_info.path_max_len, 1);
1071*6a54128fSAndroid Build Coastguard Worker
1072*6a54128fSAndroid Build Coastguard Worker retval = set_inode_xattr(fs, root, source_dir);
1073*6a54128fSAndroid Build Coastguard Worker if (retval) {
1074*6a54128fSAndroid Build Coastguard Worker com_err(__func__, retval,
1075*6a54128fSAndroid Build Coastguard Worker _("while copying xattrs on root directory"));
1076*6a54128fSAndroid Build Coastguard Worker goto out;
1077*6a54128fSAndroid Build Coastguard Worker }
1078*6a54128fSAndroid Build Coastguard Worker
1079*6a54128fSAndroid Build Coastguard Worker retval = __populate_fs(fs, parent_ino, source_dir, root, &hdlinks,
1080*6a54128fSAndroid Build Coastguard Worker &file_info, fs_callbacks);
1081*6a54128fSAndroid Build Coastguard Worker
1082*6a54128fSAndroid Build Coastguard Worker out:
1083*6a54128fSAndroid Build Coastguard Worker free(file_info.path);
1084*6a54128fSAndroid Build Coastguard Worker free(hdlinks.hdl);
1085*6a54128fSAndroid Build Coastguard Worker return retval;
1086*6a54128fSAndroid Build Coastguard Worker }
1087*6a54128fSAndroid Build Coastguard Worker
populate_fs(ext2_filsys fs,ext2_ino_t parent_ino,const char * source_dir,ext2_ino_t root)1088*6a54128fSAndroid Build Coastguard Worker errcode_t populate_fs(ext2_filsys fs, ext2_ino_t parent_ino,
1089*6a54128fSAndroid Build Coastguard Worker const char *source_dir, ext2_ino_t root)
1090*6a54128fSAndroid Build Coastguard Worker {
1091*6a54128fSAndroid Build Coastguard Worker return populate_fs2(fs, parent_ino, source_dir, root, NULL);
1092*6a54128fSAndroid Build Coastguard Worker }
1093