10ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey/* 20ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey * create_inode.c --- create an inode 30ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey * 40ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey * Copyright (C) 2014 Robert Yang <liezhi.yang@windriver.com> 50ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey * 60ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey * %Begin-Header% 70ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey * This file may be redistributed under the terms of the GNU library 80ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey * General Public License, version 2. 90ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey * %End-Header% 100ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey */ 110ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 120ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#define _FILE_OFFSET_BITS 64 130ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#define _LARGEFILE64_SOURCE 1 140ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#define _GNU_SOURCE 1 150ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 160ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#include "config.h" 170ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#include <time.h> 180ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#include <sys/types.h> 190ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#include <unistd.h> 200ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#include <limits.h> /* for PATH_MAX */ 210ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#ifdef HAVE_ATTR_XATTR_H 220ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#include <attr/xattr.h> 230ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#endif 240ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#include <sys/ioctl.h> 250ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#include <ext2fs/ext2fs.h> 260ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#include <ext2fs/ext2_types.h> 270ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#include <ext2fs/fiemap.h> 280ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 290ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#include "create_inode.h" 300ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#include "support/nls-enable.h" 310ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 320ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey/* 64KiB is the minimium blksize to best minimize system call overhead. */ 330ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#define COPY_FILE_BUFLEN 65536 340ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 350ce8844d681b935caad893db8ff740400262ec8bJeff Sharkeystatic int ext2_file_type(unsigned int mode) 360ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey{ 370ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (LINUX_S_ISREG(mode)) 380ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return EXT2_FT_REG_FILE; 390ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 400ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (LINUX_S_ISDIR(mode)) 410ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return EXT2_FT_DIR; 420ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 430ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (LINUX_S_ISCHR(mode)) 440ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return EXT2_FT_CHRDEV; 450ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 460ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (LINUX_S_ISBLK(mode)) 470ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return EXT2_FT_BLKDEV; 480ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 490ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (LINUX_S_ISLNK(mode)) 500ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return EXT2_FT_SYMLINK; 510ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 520ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (LINUX_S_ISFIFO(mode)) 530ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return EXT2_FT_FIFO; 540ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 550ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (LINUX_S_ISSOCK(mode)) 560ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return EXT2_FT_SOCK; 570ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 580ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return 0; 590ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey} 600ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 610ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey/* Link an inode number to a directory */ 620ce8844d681b935caad893db8ff740400262ec8bJeff Sharkeystatic errcode_t add_link(ext2_filsys fs, ext2_ino_t parent_ino, 630ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ext2_ino_t ino, const char *name) 640ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey{ 650ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey struct ext2_inode inode; 660ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey errcode_t retval; 670ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 680ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_read_inode(fs, ino, &inode); 690ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) { 700ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, _("while reading inode %u"), ino); 710ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return retval; 720ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 730ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 740ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_link(fs, parent_ino, name, ino, 750ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ext2_file_type(inode.i_mode)); 760ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval == EXT2_ET_DIR_NO_SPACE) { 770ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_expand_dir(fs, parent_ino); 780ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) { 790ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, 800ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey _("while expanding directory")); 810ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return retval; 820ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 830ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_link(fs, parent_ino, name, ino, 840ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ext2_file_type(inode.i_mode)); 850ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 860ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) { 870ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, _("while linking \"%s\""), name); 880ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return retval; 890ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 900ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 910ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey inode.i_links_count++; 920ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 930ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_write_inode(fs, ino, &inode); 940ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) 950ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, _("while writing inode %u"), ino); 960ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 970ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return retval; 980ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey} 990ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 1000ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey/* Set the uid, gid, mode and time for the inode */ 1010ce8844d681b935caad893db8ff740400262ec8bJeff Sharkeystatic errcode_t set_inode_extra(ext2_filsys fs, ext2_ino_t ino, 1020ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey struct stat *st) 1030ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey{ 1040ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey errcode_t retval; 1050ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey struct ext2_inode inode; 1060ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 1070ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_read_inode(fs, ino, &inode); 1080ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) { 1090ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, _("while reading inode %u"), ino); 1100ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return retval; 1110ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 1120ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 1130ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey inode.i_uid = st->st_uid; 1140ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey inode.i_gid = st->st_gid; 1150ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey inode.i_mode |= st->st_mode; 1160ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey inode.i_atime = st->st_atime; 1170ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey inode.i_mtime = st->st_mtime; 1180ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey inode.i_ctime = st->st_ctime; 1190ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 1200ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_write_inode(fs, ino, &inode); 1210ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) 1220ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, _("while writing inode %u"), ino); 1230ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return retval; 1240ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey} 1250ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 1260ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#ifdef HAVE_LLISTXATTR 1270ce8844d681b935caad893db8ff740400262ec8bJeff Sharkeystatic errcode_t set_inode_xattr(ext2_filsys fs, ext2_ino_t ino, 1280ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey const char *filename) 1290ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey{ 1300ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey errcode_t retval, close_retval; 1310ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey struct ext2_xattr_handle *handle; 1320ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ssize_t size, value_size; 1330ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey char *list = NULL; 1340ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey int i; 1350ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 1360ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey size = llistxattr(filename, NULL, 0); 1370ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (size == -1) { 1380ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = errno; 1390ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, _("while listing attributes of \"%s\""), 1400ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey filename); 1410ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return retval; 1420ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } else if (size == 0) { 1430ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return 0; 1440ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 1450ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 1460ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_xattrs_open(fs, ino, &handle); 1470ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) { 1480ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval == EXT2_ET_MISSING_EA_FEATURE) 1490ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return 0; 1500ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, _("while opening inode %u"), ino); 1510ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return retval; 1520ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 1530ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 1540ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_get_mem(size, &list); 1550ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) { 1560ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, _("while allocating memory")); 1570ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 1580ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 1590ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 1600ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey size = llistxattr(filename, list, size); 1610ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (size == -1) { 1620ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = errno; 1630ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, _("while listing attributes of \"%s\""), 1640ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey filename); 1650ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 1660ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 1670ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 1680ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey for (i = 0; i < size; i += strlen(&list[i]) + 1) { 1690ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey const char *name = &list[i]; 1700ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey char *value; 1710ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 1720ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey value_size = lgetxattr(filename, name, NULL, 0); 1730ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (value_size == -1) { 1740ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = errno; 1750ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, 1760ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey _("while reading attribute \"%s\" of \"%s\""), 1770ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey name, filename); 1780ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey break; 1790ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 1800ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 1810ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_get_mem(value_size, &value); 1820ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) { 1830ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, _("while allocating memory")); 1840ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey break; 1850ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 1860ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 1870ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey value_size = lgetxattr(filename, name, value, value_size); 1880ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (value_size == -1) { 1890ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ext2fs_free_mem(&value); 1900ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = errno; 1910ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, 1920ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey _("while reading attribute \"%s\" of \"%s\""), 1930ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey name, filename); 1940ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey break; 1950ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 1960ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 1970ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_xattr_set(handle, name, value, value_size); 1980ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ext2fs_free_mem(&value); 1990ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) { 2000ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, 2010ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey _("while writing attribute \"%s\" to inode %u"), 2020ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey name, ino); 2030ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey break; 2040ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 2050ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 2060ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 2070ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey out: 2080ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ext2fs_free_mem(&list); 2090ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey close_retval = ext2fs_xattrs_close(&handle); 2100ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (close_retval) { 2110ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, _("while closing inode %u"), ino); 2120ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = retval ? retval : close_retval; 2130ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 2140ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return retval; 2150ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return 0; 2160ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey} 2170ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#else /* HAVE_LLISTXATTR */ 2180ce8844d681b935caad893db8ff740400262ec8bJeff Sharkeystatic errcode_t set_inode_xattr(ext2_filsys fs EXT2FS_ATTR((unused)), 2190ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ext2_ino_t ino EXT2FS_ATTR((unused)), 2200ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey const char *filename EXT2FS_ATTR((unused))) 2210ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey{ 2220ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return 0; 2230ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey} 2240ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#endif /* HAVE_LLISTXATTR */ 2250ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 2260ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey/* Make a special files (block and character devices), fifo's, and sockets */ 2270ce8844d681b935caad893db8ff740400262ec8bJeff Sharkeyerrcode_t do_mknod_internal(ext2_filsys fs, ext2_ino_t cwd, const char *name, 2280ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey struct stat *st) 2290ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey{ 2300ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ext2_ino_t ino; 2310ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey errcode_t retval; 2320ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey struct ext2_inode inode; 2330ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey unsigned long devmajor, devminor, mode; 2340ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey int filetype; 2350ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 2360ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey switch(st->st_mode & S_IFMT) { 2370ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey case S_IFCHR: 2380ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey mode = LINUX_S_IFCHR; 2390ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey filetype = EXT2_FT_CHRDEV; 2400ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey break; 2410ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey case S_IFBLK: 2420ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey mode = LINUX_S_IFBLK; 2430ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey filetype = EXT2_FT_BLKDEV; 2440ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey break; 2450ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey case S_IFIFO: 2460ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey mode = LINUX_S_IFIFO; 2470ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey filetype = EXT2_FT_FIFO; 2480ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey break; 2490ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey case S_IFSOCK: 2500ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey mode = LINUX_S_IFSOCK; 2510ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey filetype = EXT2_FT_SOCK; 2520ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey break; 2530ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey default: 2540ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return EXT2_ET_INVALID_ARGUMENT; 2550ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 2560ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 2570ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_new_inode(fs, cwd, 010755, 0, &ino); 2580ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) { 2590ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, _("while allocating inode \"%s\""), 2600ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey name); 2610ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return retval; 2620ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 2630ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 2640ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#ifdef DEBUGFS 2650ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey printf("Allocated inode: %u\n", ino); 2660ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#endif 2670ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_link(fs, cwd, name, ino, filetype); 2680ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval == EXT2_ET_DIR_NO_SPACE) { 2690ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_expand_dir(fs, cwd); 2700ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) { 2710ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, 2720ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey _("while expanding directory")); 2730ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return retval; 2740ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 2750ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_link(fs, cwd, name, ino, filetype); 2760ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 2770ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) { 2780ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(name, retval, _("while creating inode \"%s\""), name); 2790ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return retval; 2800ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 2810ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (ext2fs_test_inode_bitmap2(fs->inode_map, ino)) 2820ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, 0, "Warning: inode already set"); 2830ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ext2fs_inode_alloc_stats2(fs, ino, +1, 0); 2840ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey memset(&inode, 0, sizeof(inode)); 2850ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey inode.i_mode = mode; 2860ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey inode.i_atime = inode.i_ctime = inode.i_mtime = 2870ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey fs->now ? fs->now : time(0); 2880ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 2890ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (filetype != S_IFIFO) { 2900ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey devmajor = major(st->st_rdev); 2910ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey devminor = minor(st->st_rdev); 2920ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 2930ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if ((devmajor < 256) && (devminor < 256)) { 2940ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey inode.i_block[0] = devmajor * 256 + devminor; 2950ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey inode.i_block[1] = 0; 2960ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } else { 2970ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey inode.i_block[0] = 0; 2980ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey inode.i_block[1] = (devminor & 0xff) | (devmajor << 8) | 2990ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ((devminor & ~0xff) << 12); 3000ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 3010ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 3020ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey inode.i_links_count = 1; 3030ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 3040ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_write_new_inode(fs, ino, &inode); 3050ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) 3060ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, _("while writing inode %u"), ino); 3070ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 3080ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return retval; 3090ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey} 3100ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 3110ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey/* Make a symlink name -> target */ 3120ce8844d681b935caad893db8ff740400262ec8bJeff Sharkeyerrcode_t do_symlink_internal(ext2_filsys fs, ext2_ino_t cwd, const char *name, 3130ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey char *target, ext2_ino_t root) 3140ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey{ 3150ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey char *cp; 3160ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ext2_ino_t parent_ino; 3170ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey errcode_t retval; 3180ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 3190ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey cp = strrchr(name, '/'); 3200ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (cp) { 3210ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey *cp = 0; 3220ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_namei(fs, root, cwd, name, &parent_ino); 3230ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) { 3240ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(name, retval, 0); 3250ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return retval; 3260ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 3270ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey name = cp+1; 3280ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } else 3290ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey parent_ino = cwd; 3300ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 3310ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_symlink(fs, parent_ino, 0, name, target); 3320ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval == EXT2_ET_DIR_NO_SPACE) { 3330ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_expand_dir(fs, parent_ino); 3340ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) { 3350ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err("do_symlink_internal", retval, 3360ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey _("while expanding directory")); 3370ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return retval; 3380ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 3390ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_symlink(fs, parent_ino, 0, name, target); 3400ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 3410ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) 3420ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err("ext2fs_symlink", retval, 3430ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey _("while creating symlink \"%s\""), name); 3440ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return retval; 3450ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey} 3460ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 3470ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey/* Make a directory in the fs */ 3480ce8844d681b935caad893db8ff740400262ec8bJeff Sharkeyerrcode_t do_mkdir_internal(ext2_filsys fs, ext2_ino_t cwd, const char *name, 3490ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ext2_ino_t root) 3500ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey{ 3510ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey char *cp; 3520ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ext2_ino_t parent_ino; 3530ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey errcode_t retval; 3540ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 3550ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 3560ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey cp = strrchr(name, '/'); 3570ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (cp) { 3580ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey *cp = 0; 3590ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_namei(fs, root, cwd, name, &parent_ino); 3600ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) { 3610ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(name, retval, _("while looking up \"%s\""), 3620ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey name); 3630ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return retval; 3640ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 3650ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey name = cp+1; 3660ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } else 3670ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey parent_ino = cwd; 3680ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 3690ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_mkdir(fs, parent_ino, 0, name); 3700ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval == EXT2_ET_DIR_NO_SPACE) { 3710ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_expand_dir(fs, parent_ino); 3720ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) { 3730ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, 3740ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey _("while expanding directory")); 3750ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return retval; 3760ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 3770ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_mkdir(fs, parent_ino, 0, name); 3780ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 3790ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) 3800ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err("ext2fs_mkdir", retval, 3810ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey _("while creating directory \"%s\""), name); 3820ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return retval; 3830ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey} 3840ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 3850ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#if !defined HAVE_PREAD64 && !defined HAVE_PREAD 3860ce8844d681b935caad893db8ff740400262ec8bJeff Sharkeystatic ssize_t my_pread(int fd, void *buf, size_t count, off_t offset) 3870ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey{ 3880ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (lseek(fd, offset, SEEK_SET) < 0) 3890ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return 0; 3900ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 3910ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return read(fd, buf, count); 3920ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey} 3930ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#endif /* !defined HAVE_PREAD64 && !defined HAVE_PREAD */ 3940ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 3950ce8844d681b935caad893db8ff740400262ec8bJeff Sharkeystatic errcode_t copy_file_range(ext2_filsys fs, int fd, ext2_file_t e2_file, 3960ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey off_t start, off_t end, char *buf, 3970ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey char *zerobuf) 3980ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey{ 3990ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey off_t off, bpos; 4000ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ssize_t got, blen; 4010ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey unsigned int written; 4020ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey char *ptr; 4030ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey errcode_t err = 0; 4040ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 4050ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey for (off = start; off < end; off += COPY_FILE_BUFLEN) { 4060ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#ifdef HAVE_PREAD64 4070ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey got = pread64(fd, buf, COPY_FILE_BUFLEN, off); 4080ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#elif HAVE_PREAD 4090ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey got = pread(fd, buf, COPY_FILE_BUFLEN, off); 4100ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#else 4110ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey got = my_pread(fd, buf, COPY_FILE_BUFLEN, off); 4120ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#endif 4130ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (got < 0) { 4140ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey err = errno; 4150ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto fail; 4160ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 4170ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey for (bpos = 0, ptr = buf; bpos < got; bpos += fs->blocksize) { 4180ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey blen = fs->blocksize; 4190ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (blen > got - bpos) 4200ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey blen = got - bpos; 4210ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (memcmp(ptr, zerobuf, blen) == 0) { 4220ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ptr += blen; 4230ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey continue; 4240ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 4250ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey err = ext2fs_file_lseek(e2_file, off + bpos, 4260ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey EXT2_SEEK_SET, NULL); 4270ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (err) 4280ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto fail; 4290ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey while (blen > 0) { 4300ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey err = ext2fs_file_write(e2_file, ptr, blen, 4310ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey &written); 4320ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (err) 4330ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto fail; 4340ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (written == 0) { 4350ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey err = EIO; 4360ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto fail; 4370ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 4380ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey blen -= written; 4390ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ptr += written; 4400ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 4410ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 4420ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 4430ce8844d681b935caad893db8ff740400262ec8bJeff Sharkeyfail: 4440ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return err; 4450ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey} 4460ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 4470ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#if defined(SEEK_DATA) && defined(SEEK_HOLE) 4480ce8844d681b935caad893db8ff740400262ec8bJeff Sharkeystatic errcode_t try_lseek_copy(ext2_filsys fs, int fd, struct stat *statbuf, 4490ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ext2_file_t e2_file, char *buf, char *zerobuf) 4500ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey{ 4510ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey off_t data = 0, hole; 4520ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey off_t data_blk, hole_blk; 4530ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey errcode_t err = 0; 4540ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 4550ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey /* Try to use SEEK_DATA and SEEK_HOLE */ 4560ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey while (data < statbuf->st_size) { 4570ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey data = lseek(fd, data, SEEK_DATA); 4580ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (data < 0) { 4590ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (errno == ENXIO) 4600ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey break; 4610ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return EXT2_ET_UNIMPLEMENTED; 4620ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 4630ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey hole = lseek(fd, data, SEEK_HOLE); 4640ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (hole < 0) 4650ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return EXT2_ET_UNIMPLEMENTED; 4660ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 4670ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey data_blk = data & ~(fs->blocksize - 1); 4680ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey hole_blk = (hole + (fs->blocksize - 1)) & ~(fs->blocksize - 1); 4690ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey err = copy_file_range(fs, fd, e2_file, data_blk, hole_blk, buf, 4700ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey zerobuf); 4710ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (err) 4720ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return err; 4730ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 4740ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey data = hole; 4750ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 4760ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 4770ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return err; 4780ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey} 4790ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#endif /* SEEK_DATA and SEEK_HOLE */ 4800ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 4810ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#if defined(FS_IOC_FIEMAP) 4820ce8844d681b935caad893db8ff740400262ec8bJeff Sharkeystatic errcode_t try_fiemap_copy(ext2_filsys fs, int fd, ext2_file_t e2_file, 4830ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey char *buf, char *zerobuf) 4840ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey{ 4850ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#define EXTENT_MAX_COUNT 512 4860ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey struct fiemap *fiemap_buf; 4870ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey struct fiemap_extent *ext_buf, *ext; 4880ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey int ext_buf_size, fie_buf_size; 4890ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey off_t pos = 0; 4900ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey unsigned int i; 4910ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey errcode_t err; 4920ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 4930ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ext_buf_size = EXTENT_MAX_COUNT * sizeof(struct fiemap_extent); 4940ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey fie_buf_size = sizeof(struct fiemap) + ext_buf_size; 4950ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 4960ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey err = ext2fs_get_memzero(fie_buf_size, &fiemap_buf); 4970ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (err) 4980ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return err; 4990ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 5000ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ext_buf = fiemap_buf->fm_extents; 5010ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey memset(fiemap_buf, 0, fie_buf_size); 5020ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey fiemap_buf->fm_length = FIEMAP_MAX_OFFSET; 5030ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey fiemap_buf->fm_flags |= FIEMAP_FLAG_SYNC; 5040ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey fiemap_buf->fm_extent_count = EXTENT_MAX_COUNT; 5050ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 5060ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey do { 5070ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey fiemap_buf->fm_start = pos; 5080ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey memset(ext_buf, 0, ext_buf_size); 5090ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey err = ioctl(fd, FS_IOC_FIEMAP, fiemap_buf); 5100ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (err < 0 && (errno == EOPNOTSUPP || errno == ENOTTY)) { 5110ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey err = EXT2_ET_UNIMPLEMENTED; 5120ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 5130ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } else if (err < 0 || fiemap_buf->fm_mapped_extents == 0) { 5140ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey err = errno; 5150ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 5160ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 5170ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey for (i = 0, ext = ext_buf; i < fiemap_buf->fm_mapped_extents; 5180ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey i++, ext++) { 5190ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey err = copy_file_range(fs, fd, e2_file, ext->fe_logical, 5200ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ext->fe_logical + ext->fe_length, 5210ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey buf, zerobuf); 5220ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (err) 5230ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 5240ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 5250ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 5260ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ext--; 5270ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey /* Record file's logical offset this time */ 5280ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey pos = ext->fe_logical + ext->fe_length; 5290ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey /* 5300ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey * If fm_extents array has been filled and 5310ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey * there are extents left, continue to cycle. 5320ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey */ 5330ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } while (fiemap_buf->fm_mapped_extents == EXTENT_MAX_COUNT && 5340ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey !(ext->fe_flags & FIEMAP_EXTENT_LAST)); 5350ce8844d681b935caad893db8ff740400262ec8bJeff Sharkeyout: 5360ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ext2fs_free_mem(&fiemap_buf); 5370ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return err; 5380ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey} 5390ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#endif /* FS_IOC_FIEMAP */ 5400ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 5410ce8844d681b935caad893db8ff740400262ec8bJeff Sharkeystatic errcode_t copy_file(ext2_filsys fs, int fd, struct stat *statbuf, 5420ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ext2_ino_t ino) 5430ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey{ 5440ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ext2_file_t e2_file; 5450ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey char *buf = NULL, *zerobuf = NULL; 5460ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey errcode_t err, close_err; 5470ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 5480ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey err = ext2fs_file_open(fs, ino, EXT2_FILE_WRITE, &e2_file); 5490ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (err) 5500ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return err; 5510ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 5520ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey err = ext2fs_get_mem(COPY_FILE_BUFLEN, &buf); 5530ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (err) 5540ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 5550ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 5560ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey err = ext2fs_get_memzero(fs->blocksize, &zerobuf); 5570ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (err) 5580ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 5590ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 5600ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#if defined(SEEK_DATA) && defined(SEEK_HOLE) 5610ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey err = try_lseek_copy(fs, fd, statbuf, e2_file, buf, zerobuf); 5620ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (err != EXT2_ET_UNIMPLEMENTED) 5630ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 5640ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#endif 5650ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 5660ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#if defined(FS_IOC_FIEMAP) 5670ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey err = try_fiemap_copy(fs, fd, e2_file, buf, zerobuf); 5680ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (err != EXT2_ET_UNIMPLEMENTED) 5690ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 5700ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#endif 5710ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 5720ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey err = copy_file_range(fs, fd, e2_file, 0, statbuf->st_size, buf, 5730ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey zerobuf); 5740ce8844d681b935caad893db8ff740400262ec8bJeff Sharkeyout: 5750ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ext2fs_free_mem(&zerobuf); 5760ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ext2fs_free_mem(&buf); 5770ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey close_err = ext2fs_file_close(e2_file); 5780ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (err == 0) 5790ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey err = close_err; 5800ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return err; 5810ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey} 5820ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 5830ce8844d681b935caad893db8ff740400262ec8bJeff Sharkeystatic int is_hardlink(struct hdlinks_s *hdlinks, dev_t dev, ino_t ino) 5840ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey{ 5850ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey int i; 5860ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 5870ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey for (i = 0; i < hdlinks->count; i++) { 5880ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (hdlinks->hdl[i].src_dev == dev && 5890ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey hdlinks->hdl[i].src_ino == ino) 5900ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return i; 5910ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 5920ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return -1; 5930ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey} 5940ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 5950ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey/* Copy the native file to the fs */ 5960ce8844d681b935caad893db8ff740400262ec8bJeff Sharkeyerrcode_t do_write_internal(ext2_filsys fs, ext2_ino_t cwd, const char *src, 5970ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey const char *dest, ext2_ino_t root) 5980ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey{ 5990ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey int fd; 6000ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey struct stat statbuf; 6010ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ext2_ino_t newfile; 6020ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey errcode_t retval; 6030ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey struct ext2_inode inode; 6040ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 6050ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey fd = ext2fs_open_file(src, O_RDONLY, 0); 6060ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (fd < 0) { 6070ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = errno; 6080ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, _("while opening \"%s\" to copy"), 6090ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey src); 6100ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return retval; 6110ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 6120ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (fstat(fd, &statbuf) < 0) { 6130ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = errno; 6140ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 6150ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 6160ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 6170ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_namei(fs, root, cwd, dest, &newfile); 6180ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval == 0) { 6190ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = EXT2_ET_FILE_EXISTS; 6200ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 6210ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 6220ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 6230ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_new_inode(fs, cwd, 010755, 0, &newfile); 6240ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) 6250ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 6260ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#ifdef DEBUGFS 6270ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey printf("Allocated inode: %u\n", newfile); 6280ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey#endif 6290ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_link(fs, cwd, dest, newfile, 6300ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey EXT2_FT_REG_FILE); 6310ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval == EXT2_ET_DIR_NO_SPACE) { 6320ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_expand_dir(fs, cwd); 6330ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) 6340ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 6350ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_link(fs, cwd, dest, newfile, 6360ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey EXT2_FT_REG_FILE); 6370ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 6380ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) 6390ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 6400ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (ext2fs_test_inode_bitmap2(fs->inode_map, newfile)) 6410ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, 0, "Warning: inode already set"); 6420ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ext2fs_inode_alloc_stats2(fs, newfile, +1, 0); 6430ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey memset(&inode, 0, sizeof(inode)); 6440ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey inode.i_mode = (statbuf.st_mode & ~LINUX_S_IFMT) | LINUX_S_IFREG; 6450ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey inode.i_atime = inode.i_ctime = inode.i_mtime = 6460ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey fs->now ? fs->now : time(0); 6470ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey inode.i_links_count = 1; 6480ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_inode_size_set(fs, &inode, statbuf.st_size); 6490ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) 6500ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 6510ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (ext2fs_has_feature_inline_data(fs->super)) { 6520ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey inode.i_flags |= EXT4_INLINE_DATA_FL; 6530ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } else if (ext2fs_has_feature_extents(fs->super)) { 6540ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ext2_extent_handle_t handle; 6550ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 6560ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey inode.i_flags &= ~EXT4_EXTENTS_FL; 6570ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_extent_open2(fs, newfile, &inode, &handle); 6580ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) 6590ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 6600ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ext2fs_extent_free(handle); 6610ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 6620ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 6630ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_write_new_inode(fs, newfile, &inode); 6640ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) 6650ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 6660ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (inode.i_flags & EXT4_INLINE_DATA_FL) { 6670ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_inline_data_init(fs, newfile); 6680ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) 6690ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 6700ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 6710ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (LINUX_S_ISREG(inode.i_mode)) { 6720ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = copy_file(fs, fd, &statbuf, newfile); 6730ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) 6740ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 6750ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 6760ce8844d681b935caad893db8ff740400262ec8bJeff Sharkeyout: 6770ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey close(fd); 6780ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return retval; 6790ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey} 6800ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 681b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknechtstruct file_info { 682b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht char *path; 683b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht size_t path_len; 684b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht size_t path_max_len; 685b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht}; 686b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht 687b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknechtstatic errcode_t path_append(struct file_info *target, const char *file) 688b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht{ 689b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht if (strlen(file) + target->path_len + 1 > target->path_max_len) { 690b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht target->path_max_len *= 2; 691b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht target->path = realloc(target->path, target->path_max_len); 692b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht if (!target->path) 693b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht return EXT2_ET_NO_MEMORY; 694b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht } 695b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht target->path_len += sprintf(target->path + target->path_len, "/%s", 696b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht file); 697b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht return 0; 698b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht} 699b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht 7000ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey/* Copy files from source_dir to fs */ 7010ce8844d681b935caad893db8ff740400262ec8bJeff Sharkeystatic errcode_t __populate_fs(ext2_filsys fs, ext2_ino_t parent_ino, 7020ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey const char *source_dir, ext2_ino_t root, 703b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht struct hdlinks_s *hdlinks, 704b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht struct file_info *target, 705b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht struct fs_ops_callbacks *fs_callbacks) 7060ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey{ 7070ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey const char *name; 7080ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey DIR *dh; 7090ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey struct dirent *dent; 7100ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey struct stat st; 7110ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey char *ln_target = NULL; 7120ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey unsigned int save_inode; 7130ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ext2_ino_t ino; 7140ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey errcode_t retval = 0; 7150ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey int read_cnt; 7160ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey int hdlink; 717b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht size_t cur_dir_path_len; 7180ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 7190ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (chdir(source_dir) < 0) { 7200ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = errno; 7210ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, 7220ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey _("while changing working directory to \"%s\""), 7230ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey source_dir); 7240ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return retval; 7250ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 7260ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 7270ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (!(dh = opendir("."))) { 7280ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = errno; 7290ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, 7300ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey _("while opening directory \"%s\""), source_dir); 7310ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return retval; 7320ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 7330ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 7340ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey while ((dent = readdir(dh))) { 7350ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if ((!strcmp(dent->d_name, ".")) || 7360ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey (!strcmp(dent->d_name, ".."))) 7370ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey continue; 7380ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (lstat(dent->d_name, &st)) { 7390ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = errno; 7400ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, _("while lstat \"%s\""), 7410ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey dent->d_name); 7420ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 7430ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 7440ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey name = dent->d_name; 7450ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 7460ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey /* Check for hardlinks */ 7470ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey save_inode = 0; 7480ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (!S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode) && 7490ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey st.st_nlink > 1) { 7500ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey hdlink = is_hardlink(hdlinks, st.st_dev, st.st_ino); 7510ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (hdlink >= 0) { 7520ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = add_link(fs, parent_ino, 7530ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey hdlinks->hdl[hdlink].dst_ino, 7540ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey name); 7550ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) { 7560ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, 7570ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey "while linking %s", name); 7580ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 7590ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 7600ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey continue; 7610ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } else 7620ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey save_inode = 1; 7630ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 7640ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 765b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht cur_dir_path_len = target->path_len; 766b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht retval = path_append(target, name); 767b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht if (retval) 768b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht return retval; 769b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht 770b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht if (fs_callbacks && fs_callbacks->create_new_inode) { 771b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht retval = fs_callbacks->create_new_inode(fs, 772b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht target->path, name, parent_ino, root, 773b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht st.st_mode & S_IFMT); 774b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht if (retval) 775b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht goto out; 776b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht } 777b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht 7780ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey switch(st.st_mode & S_IFMT) { 7790ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey case S_IFCHR: 7800ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey case S_IFBLK: 7810ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey case S_IFIFO: 7820ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey case S_IFSOCK: 7830ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = do_mknod_internal(fs, parent_ino, name, &st); 7840ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) { 7850ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, 7860ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey _("while creating special file " 7870ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey "\"%s\""), name); 7880ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 7890ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 7900ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey break; 7910ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey case S_IFLNK: 7920ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ln_target = malloc(st.st_size + 1); 7930ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (ln_target == NULL) { 7940ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, 7950ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey _("malloc failed")); 7960ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 7970ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 7980ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey read_cnt = readlink(name, ln_target, 7990ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey st.st_size + 1); 8000ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (read_cnt == -1) { 8010ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = errno; 8020ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, 8030ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey _("while trying to read link \"%s\""), 8040ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey name); 8050ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey free(ln_target); 8060ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 8070ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 8080ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (read_cnt > st.st_size) { 8090ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, 8100ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey _("symlink increased in size " 8110ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey "between lstat() and readlink()")); 8120ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey free(ln_target); 8130ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 8140ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 8150ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ln_target[read_cnt] = '\0'; 8160ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = do_symlink_internal(fs, parent_ino, name, 8170ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey ln_target, root); 8180ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey free(ln_target); 8190ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) { 8200ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, 8210ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey _("while writing symlink\"%s\""), 8220ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey name); 8230ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 8240ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 8250ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey break; 8260ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey case S_IFREG: 8270ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = do_write_internal(fs, parent_ino, name, name, 8280ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey root); 8290ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) { 8300ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, 8310ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey _("while writing file \"%s\""), name); 8320ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 8330ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 8340ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey break; 8350ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey case S_IFDIR: 8360ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey /* Don't choke on /lost+found */ 8370ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (parent_ino == EXT2_ROOT_INO && 8380ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey strcmp(name, "lost+found") == 0) 8390ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto find_lnf; 8400ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = do_mkdir_internal(fs, parent_ino, name, 8410ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey root); 8420ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) { 8430ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, 8440ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey _("while making dir \"%s\""), name); 8450ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 8460ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 8470ce8844d681b935caad893db8ff740400262ec8bJeff Sharkeyfind_lnf: 8480ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_namei(fs, root, parent_ino, 8490ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey name, &ino); 8500ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) { 8510ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(name, retval, 0); 8520ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 8530ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 8540ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey /* Populate the dir recursively*/ 855b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht retval = __populate_fs(fs, ino, name, root, hdlinks, 856b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht target, fs_callbacks); 8570ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) 8580ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 8590ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (chdir("..")) { 8600ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = errno; 8610ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, 8620ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey _("while changing directory")); 8630ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 8640ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 8650ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey break; 8660ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey default: 8670ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, 0, 8680ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey _("ignoring entry \"%s\""), name); 8690ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 8700ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 8710ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = ext2fs_namei(fs, root, parent_ino, name, &ino); 8720ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) { 8730ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(name, retval, _("while looking up \"%s\""), 8740ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey name); 8750ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 8760ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 8770ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 8780ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = set_inode_extra(fs, ino, &st); 8790ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) { 8800ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, 8810ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey _("while setting inode for \"%s\""), name); 8820ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 8830ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 8840ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 8850ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = set_inode_xattr(fs, ino, name); 8860ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (retval) { 8870ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, 8880ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey _("while setting xattrs for \"%s\""), name); 8890ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 8900ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 8910ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 892b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht if (fs_callbacks && fs_callbacks->end_create_new_inode) { 893b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht retval = fs_callbacks->end_create_new_inode(fs, 894b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht target->path, name, parent_ino, root, 895b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht st.st_mode & S_IFMT); 896b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht if (retval) 897b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht goto out; 898b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht } 899b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht 9000ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey /* Save the hardlink ino */ 9010ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (save_inode) { 9020ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey /* 9030ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey * Check whether need more memory, and we don't need 9040ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey * free() since the lifespan will be over after the fs 9050ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey * populated. 9060ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey */ 9070ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (hdlinks->count == hdlinks->size) { 9080ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey void *p = realloc(hdlinks->hdl, 9090ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey (hdlinks->size + HDLINK_CNT) * 9100ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey sizeof(struct hdlink_s)); 9110ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (p == NULL) { 9120ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = EXT2_ET_NO_MEMORY; 9130ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(name, retval, 9140ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey _("while saving inode data")); 9150ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey goto out; 9160ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 9170ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey hdlinks->hdl = p; 9180ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey hdlinks->size += HDLINK_CNT; 9190ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 9200ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey hdlinks->hdl[hdlinks->count].src_dev = st.st_dev; 9210ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey hdlinks->hdl[hdlinks->count].src_ino = st.st_ino; 9220ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey hdlinks->hdl[hdlinks->count].dst_ino = ino; 9230ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey hdlinks->count++; 9240ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 925b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht target->path_len = cur_dir_path_len; 926b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht target->path[target->path_len] = 0; 9270ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 9280ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 9290ce8844d681b935caad893db8ff740400262ec8bJeff Sharkeyout: 9300ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey closedir(dh); 9310ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return retval; 9320ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey} 9330ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 934b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknechterrcode_t populate_fs2(ext2_filsys fs, ext2_ino_t parent_ino, 935b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht const char *source_dir, ext2_ino_t root, 936b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht struct fs_ops_callbacks *fs_callbacks) 9370ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey{ 938b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht struct file_info file_info; 9390ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey struct hdlinks_s hdlinks; 9400ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey errcode_t retval; 9410ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 9420ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (!(fs->flags & EXT2_FLAG_RW)) { 9430ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, 0, "Filesystem opened readonly"); 9440ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return EROFS; 9450ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 9460ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 9470ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey hdlinks.count = 0; 9480ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey hdlinks.size = HDLINK_CNT; 9490ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey hdlinks.hdl = realloc(NULL, hdlinks.size * sizeof(struct hdlink_s)); 9500ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey if (hdlinks.hdl == NULL) { 9510ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey retval = errno; 9520ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey com_err(__func__, retval, _("while allocating memory")); 9530ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return retval; 9540ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey } 9550ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 956b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht file_info.path_len = 0; 957b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht file_info.path_max_len = 255; 958b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht file_info.path = calloc(file_info.path_max_len, 1); 9590ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey 960b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht retval = __populate_fs(fs, parent_ino, source_dir, root, &hdlinks, 961b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht &file_info, fs_callbacks); 962b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht 963b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht free(file_info.path); 9640ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey free(hdlinks.hdl); 9650ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey return retval; 9660ce8844d681b935caad893db8ff740400262ec8bJeff Sharkey} 967b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht 968b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknechterrcode_t populate_fs(ext2_filsys fs, ext2_ino_t parent_ino, 969b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht const char *source_dir, ext2_ino_t root) 970b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht{ 971b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht return populate_fs2(fs, parent_ino, source_dir, root, NULL); 972b298f7e8a30775943ec21c2ad1c7fbe30bb8fd09Adrien Schildknecht} 973