make_ext4fs: insert lost+found directory into filled filesystems

Insert a lost+found directory if necessary when creating a filesystem
based on a directory structure.  This will make the resulting image
clean when tested with e2fsck, allowing e2fsck to be run on all images
as a validity test.

Change-Id: I81d0b6b4a802713270d3469e5a3bc555b680ec7e
diff --git a/ext4_utils/make_ext4fs.c b/ext4_utils/make_ext4fs.c
index be63e27..85dad4e 100644
--- a/ext4_utils/make_ext4fs.c
+++ b/ext4_utils/make_ext4fs.c
@@ -104,18 +104,30 @@
 {
 	int entries = 0;
 	struct dentry *dentries;
-	struct dirent **namelist;
+	struct dirent **namelist = NULL;
 	struct stat stat;
 	int ret;
 	int i;
 	u32 inode;
 	u32 entry_inode;
 	u32 dirs = 0;
+	bool needs_lost_and_found = false;
 
-	entries = scandir(full_path, &namelist, filter_dot, (void*)alphasort);
-	if (entries < 0) {
-		error_errno("scandir");
-		return EXT4_ALLOCATE_FAILED;
+	if (full_path) {
+		entries = scandir(full_path, &namelist, filter_dot, (void*)alphasort);
+		if (entries < 0) {
+			error_errno("scandir");
+			return EXT4_ALLOCATE_FAILED;
+		}
+	}
+
+	if (dir_inode == 0) {
+		/* root directory, check if lost+found already exists */
+		for (i = 0; i < entries; i++)
+			if (strcmp(namelist[i]->d_name, "lost+found") == 0)
+				break;
+		if (i == entries)
+			needs_lost_and_found = true;
 	}
 
 	dentries = calloc(entries, sizeof(struct dentry));
@@ -195,6 +207,30 @@
 	}
 	free(namelist);
 
+	if (needs_lost_and_found) {
+		/* insert a lost+found directory at the beginning of the dentries */
+		struct dentry *tmp = calloc(entries + 1, sizeof(struct dentry));
+		memset(tmp, 0, sizeof(struct dentry));
+		memcpy(tmp + 1, dentries, entries * sizeof(struct dentry));
+		dentries = tmp;
+
+		dentries[0].filename = strdup("lost+found");
+		dentries[0].path = strdup("/lost+found");
+		dentries[0].full_path = NULL;
+		dentries[0].size = 0;
+		dentries[0].mode = S_IRWXU;
+		dentries[0].file_type = EXT4_FT_DIR;
+		dentries[0].uid = 0;
+		dentries[0].gid = 0;
+#ifdef HAVE_SELINUX
+		if (sehnd)
+			if (selabel_lookup(sehnd, &dentries[0].secon, "lost+found", dentries[0].mode) < 0)
+				error("cannot lookup security context for /lost+found");
+#endif
+		entries++;
+		dirs++;
+	}
+
 	inode = make_directory(dir_inode, entries, dentries, dirs);
 
 	for (i = 0; i < entries; i++) {