Package: busybox
Version: v1.31.1
Severity: wishlist

This implementation assumes that iflag/oflag=direct will be used only on
block devices and files that are multiples of pagesize, and makes no
effort to solve issues with unaligned or partial reads (unlike gnu
coreutils dd)

Using iflag/oflag=direct will also limit usage block sizes, which must
also be a multiple of pagesize
-- 
Akash Hadke

800-7474-400
diff --git a/coreutils/dd.c b/coreutils/dd.c
index b5f3cbe..b4fb71a 100644
--- a/coreutils/dd.c
+++ b/coreutils/dd.c
@@ -59,7 +59,7 @@
 //usage:       "[if=FILE] [of=FILE] [" IF_FEATURE_DD_IBS_OBS("ibs=N obs=N/") "bs=N] [count=N] [skip=N] [seek=N]\n"
 //usage:	IF_FEATURE_DD_IBS_OBS(
 //usage:       "	[conv=notrunc|noerror|sync|fsync]\n"
-//usage:       "	[iflag=skip_bytes|fullblock] [oflag=seek_bytes|append]"
+//usage:       "	[iflag=skip_bytes|fullblock|direct] [oflag=seek_bytes|append|direct]"
 //usage:	)
 //usage:#define dd_full_usage "\n\n"
 //usage:       "Copy a file with converting and formatting\n"
@@ -83,8 +83,10 @@
 //usage:     "\n	conv=swab	Swap every pair of bytes"
 //usage:     "\n	iflag=skip_bytes	skip=N is in bytes"
 //usage:     "\n	iflag=fullblock	Read full blocks"
+//usage:     "\n	iflag=direct	use direct I/O for data (limited support, file and bs must be a pagesize multiple)"
 //usage:     "\n	oflag=seek_bytes	seek=N is in bytes"
 //usage:     "\n	oflag=append	Open output file in append mode"
+//usage:     "\n	oflag=direct	use direct I/O for data (limited support, file and bs must be a pagesize multiple)"
 //usage:	)
 //usage:	IF_FEATURE_DD_STATUS(
 //usage:     "\n	status=noxfer	Suppress rate output"
@@ -137,16 +139,18 @@ enum {
 	FLAG_IFLAG_SHIFT = 5,
 	FLAG_SKIP_BYTES = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS,
 	FLAG_FULLBLOCK = (1 << 6) * ENABLE_FEATURE_DD_IBS_OBS,
+	FLAG_IDIRECT = (1 << 7) * ENABLE_FEATURE_DD_IBS_OBS,
 	/* end of input flags */
 	/* start of output flags */
-	FLAG_OFLAG_SHIFT = 7,
-	FLAG_SEEK_BYTES = (1 << 7) * ENABLE_FEATURE_DD_IBS_OBS,
-	FLAG_APPEND = (1 << 8) * ENABLE_FEATURE_DD_IBS_OBS,
+	FLAG_OFLAG_SHIFT = 8,
+	FLAG_SEEK_BYTES = (1 << 8) * ENABLE_FEATURE_DD_IBS_OBS,
+	FLAG_APPEND = (1 << 9) * ENABLE_FEATURE_DD_IBS_OBS,
+	FLAG_ODIRECT = (1 << 10) * ENABLE_FEATURE_DD_IBS_OBS,
 	/* end of output flags */
-	FLAG_TWOBUFS = (1 << 9) * ENABLE_FEATURE_DD_IBS_OBS,
-	FLAG_COUNT   = 1 << 10,
-	FLAG_STATUS_NONE = 1 << 11,
-	FLAG_STATUS_NOXFER = 1 << 12,
+	FLAG_TWOBUFS = (1 << 11) * ENABLE_FEATURE_DD_IBS_OBS,
+	FLAG_COUNT   = 1 << 12,
+	FLAG_STATUS_NONE = 1 << 13,
+	FLAG_STATUS_NOXFER = 1 << 14,
 };
 
 static void dd_output_status(int UNUSED_PARAM cur_signal)
@@ -252,6 +256,13 @@ static int parse_comma_flags(char *val, const char *words, const char *error_in)
 	}
 	return flags;
 }
+
+static char *ptr_align(char *ptr, size_t alignment)
+{
+  char *p0 = ptr;
+  char *p1 = p0 + alignment - 1;
+  return p1 - (size_t) p1 % alignment;
+}
 #endif
 
 int dd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
@@ -267,9 +278,9 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
 	static const char conv_words[] ALIGN1 =
 		"notrunc\0""sync\0""noerror\0""fsync\0""swab\0";
 	static const char iflag_words[] ALIGN1 =
-		"skip_bytes\0""fullblock\0";
+		"skip_bytes\0""fullblock\0""direct\0";
 	static const char oflag_words[] ALIGN1 =
-		"seek_bytes\0append\0";
+		"seek_bytes\0append\0""direct\0";
 #endif
 #if ENABLE_FEATURE_DD_STATUS
 	static const char status_words[] ALIGN1 =
@@ -310,7 +321,9 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
 	//swab          swap every pair of input bytes: will abort on non-even reads
 		OP_iflag_skip_bytes,
 		OP_iflag_fullblock,
+		OP_iflag_direct,
 		OP_oflag_seek_bytes,
+		OP_oflag_direct,
 #endif
 	};
 	smallint exitcode = EXIT_FAILURE;
@@ -320,9 +333,13 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
 #if ENABLE_FEATURE_DD_IBS_OBS
 	size_t obs = 512;
 	char *obuf;
+	char *ibufptr, *obufptr;
+	int pagesize;
 #else
 # define obs  ibs
 # define obuf ibuf
+# define ibufptr ibuf
+# define obufptr ibuf
 #endif
 	/* These are all zeroed at once! */
 	struct {
@@ -427,13 +444,33 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
 	} /* end of "for (argv[i])" */
 
 //XXX:FIXME for huge ibs or obs, malloc'ing them isn't the brightest idea ever
-	ibuf = xmalloc(ibs);
-	obuf = ibuf;
 #if ENABLE_FEATURE_DD_IBS_OBS
+	/* because of O_DIRECT, block needs to be page-aligned */
+	pagesize = getpagesize();
+	ibufptr = xmalloc(ibs + pagesize);
+	obufptr = ibufptr;
 	if (ibs != obs) {
 		G.flags |= FLAG_TWOBUFS;
-		obuf = xmalloc(obs);
+		obufptr = xmalloc(obs + pagesize);
 	}
+
+	/* most filesystems will refuse O_DIRECT if read/writes aren't pagesize aligned */
+	if ((G.flags & FLAG_IDIRECT) && (ibs % pagesize)) {
+		bb_error_msg_and_die("iflag=direct needs bs %lu to be a multiple of pagesize %d",
+			ibs, pagesize);
+	}
+	if ((G.flags & FLAG_ODIRECT) && (obs % pagesize)) {
+		bb_error_msg_and_die("oflag=direct needs bs %lu to be a multiple of pagesize %d",
+			ibs, pagesize);
+	}
+
+	ibuf = ptr_align(ibufptr, pagesize);
+	obuf = ptr_align(obufptr, pagesize);
+#else
+	ibufptr = xmalloc(ibs);
+	obufptr = ibufptr;
+	ibuf = ibufptr;
+	obuf = obufptr;
 #endif
 
 #if ENABLE_FEATURE_DD_SIGNAL_HANDLING
@@ -444,7 +481,14 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
 #endif
 
 	if (infile) {
-		xmove_fd(xopen(infile, O_RDONLY), ifd);
+		int iflag = O_RDONLY;
+
+#if ENABLE_FEATURE_DD_IBS_OBS
+		if (G.flags & FLAG_IDIRECT)
+			iflag |= O_DIRECT;
+#endif
+
+		xmove_fd(xopen(infile, iflag), ifd);
 	} else {
 		infile = bb_msg_standard_input;
 	}
@@ -455,6 +499,10 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
 			oflag |= O_TRUNC;
 		if (G.flags & FLAG_APPEND)
 			oflag |= O_APPEND;
+#if ENABLE_FEATURE_DD_IBS_OBS
+		if (G.flags & FLAG_ODIRECT)
+			oflag |= O_DIRECT;
+#endif
 
 		xmove_fd(xopen(outfile, oflag), ofd);
 
@@ -601,9 +649,9 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
 		dd_output_status(0);
 
 	if (ENABLE_FEATURE_CLEAN_UP) {
-		free(obuf);
+		free(obufptr);
 		if (G.flags & FLAG_TWOBUFS)
-			free(ibuf);
+			free(ibufptr);
 	}
 
 	return exitcode;
_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to