cpu: handle "os: invalid use of WriteAt on file opened with O_APPEND"
cpu: handle "os: invalid use of WriteAt on file opened with O_APPEND"

The 9p Twrite message is equivalent to WriteAt, i.e. it takes data and offset.

Files can be opened as O_APPEND. On Plan 9, all servers use O_APPEND to indicate
"ignore offset, just write at end." 9P Twrite and Plan 9 system call
are thus self-consistent: servers ignore offset on files opened O_APPEND,
honor offset otherwise; clients open files with or without O_APPEND.

Linux, other Unix-like systems, and Windows do not seem to share this
consistency. Mixing write at offset and O_APPEND writes does not work
at all, and will corrupt the file.

In c7f7f5, in March 2019, the Go runtime changed to not allow mixed
pwrite and append writes.

This is likely because Linux and other sytems allow pwrite on files
opened with O_APPEND, which will make a large mess of things. The author of that
commit comments:

    Making WriteAt returns an error if file is opened in append mode, we
    guarantee to get consistent behavior between platforms, also prevent
    user from accidently corrupting their data.

Hence the Go runtime, since 2019, returns an error for something that used
to work, even though on, e.g., Plan 9, there is no problem. This change
will likely not work for Plan 9 users, but few people care :-)

Fortunately, this change is easy to work around, and cheap. It rarely
occurs; it is generated in the Go runtime by a test of a (non exported)
member of a struct; no system calls are involved.

Hence, we need only call WriteAt and, in the rare event of an error,
see if err.Error() contains the string (the error value is not exported,
unfortunately). If it does contain the string, do a Write and return
what Write returns.

Fixes #64.

Signed-off-by: Ronald G. Minnich <f569d0af9a3481c4007b95c7180d6c41009f2513@gmail.com>

u-root/cpu,u-root/cpu,u-root/cpu