the only issue I've encountered with this so far is that 'dd' will fail some of
its tests because it's not using of= but instead using the redir operator and
then it assumes it's NOT open in append mode ;)) so then it tries to seek past
EOF (which doesn't work in append mode) to make holes(of zeroes).
to illustrate:
$ rm /tmp/out;echo abcdefghijklm | dd bs=5 seek=8 oflag=seek_bytes > /tmp/out ;
stat --format=%s /tmp/out
2+1 records in
2+1 records out
14 bytes copied, 0.0001584 s, 88.4 kB/s
Actually written to disk: '14' bytes (100.00%).
14
the normal output should be(ie. file size 22 bytes not 14):
$ rm /tmp/out;echo abcdefghijklm | dd bs=5 seek=8 oflag=seek_bytes > /tmp/out ;
stat --format=%s /tmp/out
2+1 records in
2+1 records out
14 bytes copied, 0.000112444 s, 125 kB/s
Actually written to disk: '14' bytes (100.00%).
22
Not to worry though, I'm "sure" I pulled a Curly in Three Stooges episode
titled "A Plumbing We Will Go." when I added a kernel patch for this (attached)
which ensures `cannot seek: Illegal seek` when trying to go beyond EOF in
O_APPEND mode.
In a completely unrelated note, this cool Exolon theme/music, listening to it
right now: https://www.youtube.com/watch?v=Gfw-CIEM6Zs
ah memories:)
newer:
now using kernel patch deny_lseek_past_EOF_when_O_APPEND.patch
with this bash patch, testing to see how 'dd' reacts... better:
$ rm /tmp/out;echo abcdefghijklm | dd bs=5 seek=8 oflag=seek_bytes > /tmp/out ; stat --format=%s /tmp/out
dd: 'standard output': cannot seek: Illegal seek
0+0 records in
0+0 records out
0 bytes copied, 0.000102177 s, 0.0 kB/s
Actually written to disk: '0' bytes (-nan%).
0
new:
ok this is bad:
because it makes this fail:
$ rm /tmp/out;echo abcdefghijklm | dd bs=5 seek=8 oflag=seek_bytes > /tmp/out ; stat --format=%s /tmp/out
2+1 records in
2+1 records out
14 bytes copied, 0.0001584 s, 88.4 kB/s
Actually written to disk: '14' bytes (100.00%).
14
the normal output should be(ie. file size 22 bytes not 14):
$ rm /tmp/out;echo abcdefghijklm | dd bs=5 seek=8 oflag=seek_bytes > /tmp/out ; stat --format=%s /tmp/out
2+1 records in
2+1 records out
14 bytes copied, 0.000112444 s, 125 kB/s
Actually written to disk: '14' bytes (100.00%).
22
ok so because it's append only, dd cann't seek past the EOF, and thus lseek won't do it's job of skipping past EOF and the subsequent 'write' won't make those \0-es pop up in that gap! ie. dd assumes outfile is never opened in O_APPEND mode.
meanwhile this will always work(the redirect became of=):
$ rm /tmp/out;echo abcdefghijklm | dd bs=5 seek=8 oflag=seek_bytes of=/tmp/out ; stat --format=%s /tmp/out
2+1 records in
2+1 records out
14 bytes copied, 0.000137867 s, 102 kB/s
Actually written to disk: '14' bytes (100.00%).
22
old info:
https://github.com/libcheck/check/issues/188
diff --git a/make_cmd.c b/make_cmd.c
index ecbbfd6e..5db799f2 100644
--- a/make_cmd.c
+++ b/make_cmd.c
@@ -700,7 +700,7 @@ make_redirection (source, instruction, dest_and_filename, flags)
case r_output_direction: /* >foo */
case r_output_force: /* >| foo */
case r_err_and_out: /* &>filename */
- temp->flags = O_TRUNC | O_WRONLY | O_CREAT;
+ temp->flags = O_APPEND | O_TRUNC | O_WRONLY | O_CREAT;
break;
case r_appending_to: /* >>foo */
use this patch with bash patch always_append_on_redirection.patch
this will fix 'dd' trying to seek past EOF into the file used for redirection while that file is open in O_APPEND mode
now(with this patch and bash patch!) it's this:
$ rm /tmp/out;echo abcdefghijklm | dd bs=5 seek=8 oflag=seek_bytes > /tmp/out ; stat --format=%s /tmp/out
dd: 'standard output': cannot seek: Illegal seek
0+0 records in
0+0 records out
0 bytes copied, 0.000102177 s, 0.0 kB/s
Actually written to disk: '0' bytes (-nan%).
0
before patch:
$ rm /tmp/out;echo abcdefghijklm | dd bs=5 seek=8 oflag=seek_bytes > /tmp/out ; stat --format=%s /tmp/out
2+1 records in
2+1 records out
14 bytes copied, 0.0001584 s, 88.4 kB/s
Actually written to disk: '14' bytes (100.00%).
14
should be(if no bash patch was used):
$ rm /tmp/out;echo abcdefghijklm | dd bs=5 seek=8 oflag=seek_bytes > /tmp/out ; stat --format=%s /tmp/out
2+1 records in
2+1 records out
14 bytes copied, 0.000112444 s, 125 kB/s
Actually written to disk: '14' bytes (100.00%).
22
diff --git a/fs/read_write.c b/fs/read_write.c
index 7458fccc59e1..e46c2997a158 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -88,6 +88,10 @@ generic_file_llseek_size(struct file *file, loff_t offset, int whence,
{
switch (whence) {
case SEEK_END:
+ if ((file->f_flags & O_APPEND) && (offset > 0)) {
+ //tried to seek past EOF in O_APPEND mode will have no effect! so, this 'dd' will fail: echo abcdefghijklm | dd bs=5 seek=8 oflag=seek_bytes > /tmp/out ; stat --format=%s /tmp/out ie. 14 written 14 bytes file size, instead of 22 bytes file size, if applied O_APPEND patch to bash's redirect operator, thus /tmp/out is O_APPEND mode! ok but actually it's not SEEK_END that's in effect here but SEEK_CUR instead!
+ return -ESPIPE; // ESPIPE 29 Illegal seek
+ }
offset += eof;
break;
case SEEK_CUR:
@@ -105,6 +109,13 @@ generic_file_llseek_size(struct file *file, loff_t offset, int whence,
* like SEEK_SET.
*/
spin_lock(&file->f_lock);
+
+ if ((file->f_flags & O_APPEND) && (offset + file->f_pos > eof)) {
+ //tried to seek past EOF in O_APPEND mode will have no effect! so, this 'dd' will fail: echo abcdefghijklm | dd bs=5 seek=8 oflag=seek_bytes > /tmp/out ; stat --format=%s /tmp/out ie. 14 written 14 bytes file size, instead of 22 bytes file size, if applied O_APPEND patch to bash's redirect operator, thus /tmp/out is O_APPEND mode! ok but actually it's not SEEK_END that's in effect here but SEEK_CUR instead!
+ spin_unlock(&file->f_lock);
+ return -ESPIPE; // ESPIPE 29 Illegal seek
+ }
+
offset = vfs_setpos(file, file->f_pos + offset, maxsize);
spin_unlock(&file->f_lock);
return offset;
@@ -127,6 +138,10 @@ generic_file_llseek_size(struct file *file, loff_t offset, int whence,
break;
}
+ if ((file->f_flags & O_APPEND) && (offset > eof)) {
+ //tried to seek past EOF in O_APPEND mode will have no effect! so, this 'dd' will fail: echo abcdefghijklm | dd bs=5 seek=8 oflag=seek_bytes > /tmp/out ; stat --format=%s /tmp/out ie. 14 written 14 bytes file size, instead of 22 bytes file size, if applied O_APPEND patch to bash's redirect operator, thus /tmp/out is O_APPEND mode! ok but actually it's not SEEK_END that's in effect here but SEEK_CUR instead!
+ return -ESPIPE; // ESPIPE 29 Illegal seek
+ }
return vfs_setpos(file, offset, maxsize);
}
EXPORT_SYMBOL(generic_file_llseek_size);