Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inconsistent behavior between os.scandir and os.path for mfsymlinks #102503

Open
sdawson-nvidia opened this issue Mar 7, 2023 · 4 comments
Open
Labels
extension-modules C modules in the Modules dir type-bug An unexpected behavior, bug, or error

Comments

@sdawson-nvidia
Copy link

Bug report

With a network drive mounted with CIFS and using the mfsymlinks options, os.path.islink and os.path.isdir will return True for a symbolic link to a directory, whereas the corresponding DirEntry for the symlink will return False for both DirEntry.is_symlink() and DirEntry.is_dir().

Repro steps:

  1. Mount a CIFS drive with -o mfsymlinks to /mnt/scratch
  2. mkdir /mnt/scratch/dir
  3. ln -s /mnt/scratch/dir /mnt/scratch/link
  4. In python 3, run os.scandir('/mnt/scratch') and iterate to the link entry
  5. Validate is_symlink() and is_dir() return False
  6. Run os.path.islink('/mnt/scratch/link') and os.path.isdir('/mnt/scratch/link') and validate both return True

Your environment

Python version 3.8.10, Ubuntu 20.04

@sdawson-nvidia sdawson-nvidia added the type-bug An unexpected behavior, bug, or error label Mar 7, 2023
@eryksun eryksun added the extension-modules C modules in the Modules dir label Mar 7, 2023
@arhadthedev
Copy link
Member

@serhiy-storchaka (as an os.path module expert)

@eryksun
Copy link
Contributor

eryksun commented Apr 3, 2023

The "mfsymlinks" option of the Linux "cifs" filesystem emulates native POSIX symlinks on an SMB share. When lstat() is called on an emulated symlink, the stat result does have the correct S_IFLNK file type. However, the file type in the readdir() entry of an emulated symlink is DT_REG (regular file) instead of DT_LNK. That's a third-party bug that needs to be handled by the developers of the "cifs" filesystem driver.

I compiled a "listdir" program that calls opendir() and readdir() to list the name and type of each entry in a directory. Here's the result for an SMB share mounted in Linux with "mfsymlinks". The share contains a directory, a file, and an emulated symlink to each.

$ ./listdir /mnt/temp/linktest
dir: DT_DIR
dirlink: DT_REG
file: DT_REG
filelink: DT_REG

As you can see, the links are misreported as type DT_REG. It's apparent why emulated symlinks are reported as regular files in the low-level directory listing, because that's what they really are when accessed from Windows:

>>> open('dirlink', 'rb').read(47)
b'XSym\n0003\n736007832d2167baaae763fd3a3f3cf1\ndir\n'
>>> open('filelink', 'rb').read(48)
b'XSym\n0004\n8c7dd922ad47494fc02c388e12c00eac\nfile\n'

The developers forgot to maintain the pretense for readdir(). The GNU "ls" command happens to show these entries correctly as links, but that's only after calling lstat() on each entry, which I confirmed using "strace".

os.scandir() is designed to rely on the d_type of the directory entry if it's not DT_UNKNOWN. Having to call lstat() would defeat the purpose of using os.scandir().

@sdawson-nvidia
Copy link
Author

Thank you for the investigation @eryksun. I've sent an email to linux-cifs@vger.kernel.org to follow up on this issue.

@Sxderp
Copy link

Sxderp commented Apr 24, 2023

We just ran into this as well. Looks like the thread on the mailing list died. Though, even if it did get patched it would take a long time to trickle into distributions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
extension-modules C modules in the Modules dir type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

4 participants