labgrid-project / labgrid

Embedded systems control library for development, testing and installation
https://labgrid.readthedocs.io/
Other
327 stars 164 forks source link

AndroidFastboot: discrepancy between relative and absolute paths #433

Open a3f opened 5 years ago

a3f commented 5 years ago

Initial situation

I got 2 systems: client and exporter, client has labgrid-client running and exporter, labgrid-exporter. I am in directory /build, which on client is a symlink to local file system /mnt/something, which is also exported via NFS. On exporter, /build is a symlink to that NFS share.

Steps to reproduce

Fastboot upload with absolute path works as expected:

$ labgrid-client -d -v fastboot flash rootfs $PWD/rootfs.img

DEBUG: Sending command: ['ssh', '-x', '-o', 'LogLevel=ERROR', '-o', 'PasswordAuthentication=no', '-o', 'ControlMaster=no', '-o', 'ControlPath=/tmp/labgrid-connection-xxxxx/control-exporter', 'exporter', "stat --format 'inode=%i,size=%s,birth=%W,modified=%Y' /build/rootfs.img"]

ManagedFile applies its heuristic and detects that both files are the same, so it foregoes a rsync from client to exporter.

While using a relative path doesn't:

$ labgrid-client fastboot flash rootfs ./rootfs.img

DEBUG: Sending command: ['ssh', '-x', '-o', 'LogLevel=ERROR', '-o', 'PasswordAuthentication=no', '-o', 'ControlMaster=no', '-o', 'ControlPath=/tmp/labgrid-connection-xxxxx/control-exporter', 'exporter', "stat --format 'inode=%i,size=%s,birth=%W,modified=%Y' /mnt/something/rootfs.img"] DEBUG: remote: stat: unsuccessful error code 1

Here labgrid does a rsync between the systems.

Expected Behavior

Whether a relative or absolute path is used shouldn't change the behavior if both refer to the same file. They both should result in stat suceeding and no rsync.

I assume there's an erroneous path canonization somewhere.

a3f commented 5 years ago

The culprit is the os.path.abspath in remote/client.py here: https://github.com/labgrid-project/labgrid/blob/133b5b7886f0b76a56216100d480e5905604fe0e/labgrid/remote/client.py#L727-L730

os.path.abspath uses os.getcwd to get the current working directory, which returns /mnt/something instead of /build. os.getcwd seems to be just a wrapper around getcwd(2), which returns /mnt/something as well...

a3f commented 5 years ago

I looked some more into it and it seems the only way to get /build is to manually prefix $PWD to the path. I talked this over with @jluebbe and we should probably be using os.path.realpath everywhere to get canonical paths without symlinks.

I've settled for creating some symlinks on the exporter to reflect that structure on the client system, which works for me.