Skip to content

mv and cp builtins cannot move or copy directories into /tmp or /dev/shm #871

@JohnoKing

Description

@JohnoKing

This gave me grief after a script failed when prepending PATH=/opt/ast/bin:$PATH. Reproducer:

# run on Linux at ksh repo root; /tmp and /dev/shm are both mounted to tmpfs
$ /opt/ast/bin/mv bin /dev/shm
mv: bin: /dev/shm/bin read error [Is a directory]
$ /opt/ast/bin/cp -r bin /dev/shm
cp: /dev/shm/bin: not a directory -- bin ignored
cp: /dev/shm/bin/package: cannot write [Not a directory]
cp: /dev/shm/bin/shtests: cannot write [Not a directory]
$ /opt/ast/bin/mv bin /tmp    
mv: bin: /tmp/bin read error [Is a directory]

Code where the error occurs:

ksh/src/lib/libcmd/cp.c

Lines 603 to 615 in 68fe82b

if (sfmove(ip, op, (Sfoff_t)SFIO_UNBOUND, -1) < 0)
n |= 3;
if (!sfeof(ip))
n |= 1;
if (sfsync(op) || state->sync && fsync(wfd) || sfclose(op))
n |= 2;
if (sfclose(ip))
n |= 1;
if (n)
{
error(ERROR_SYSTEM|2, "%s: %s %s error", ent->fts_path, state->path, n == 1 ? ERROR_translate(0, 0, 0, "read") : n == 2 ? ERROR_translate(0, 0, 0, "write") : ERROR_translate(0, 0, 0, "io"));
return 0;
}

I was able to trace the error as occurring after sfmove() fails. I haven't been able to debug it any further.

ksh93v- has some sort of bugfix applied to this area. I tried backporting that but it didn't help.

ksh93v-cp-mv-backport.patch
diff --git a/src/lib/libcmd/cp.c b/src/lib/libcmd/cp.c
index 2087baef4..69a368738 100644
--- a/src/lib/libcmd/cp.c
+++ b/src/lib/libcmd/cp.c
@@ -573,7 +573,7 @@ visit(State_t* state, FTSENT* ent)
 		{
 			int	rfd = -1;
 			int	wfd = -1;
-			if (ent->fts_statp->st_size > 0 && (rfd = open(ent->fts_path, O_RDONLY|O_BINARY|O_cloexec)) < 0)
+			if ((!S_ISREG(ent->fts_statp->st_mode) || ent->fts_statp->st_size > 0) && (rfd = open(ent->fts_path, O_RDONLY|O_BINARY|O_cloexec)) < 0)
 			{
 				error(ERROR_SYSTEM|2, "%s: cannot read", ent->fts_path);
 				return 0;
@@ -581,11 +581,11 @@ visit(State_t* state, FTSENT* ent)
 			else if ((wfd = open(state->path, (st.st_mode ? (state->wflags & ~O_EXCL) : state->wflags)|O_cloexec, ent->fts_statp->st_mode & state->perm)) < 0)
 			{
 				error(ERROR_SYSTEM|2, "%s: cannot write", state->path);
-				if (ent->fts_statp->st_size > 0)
+				if (rfd >= 0)
 					close(rfd);
 				return 0;
 			}
-			else if (ent->fts_statp->st_size > 0)
+			else if (rfd >= 0)
 			{
 				if (!(ip = sfnew(NULL, NULL, (size_t)SFIO_UNBOUND, rfd, SFIO_READ)))
 				{

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions