What component do all KDE applications call that prevents them opening directories and files whose absolute paths are > `PATH_MAX`'s value?

Context

If one creates a directory whose absolute path is > [1] PATH_MAX’s 4096 default: [2]

  1. Creation

    #!/usr/bin/env python3
    import os
    import subprocess
    import shutil
    from datetime import datetime
    
    # Configuration
    base = os.path.expanduser('~/pathmax_tool_test')
    name = 'd' * 255
    log_path = os.path.join(base, 'tool_results.log')
    content = 'This file is deeper than PATH_MAX.\nIt contains real content.\n'
    tools = [
        ['ls', '-ld'],
        ['realpath'],
        ['file'],
        ['readlink', '-f'],
        ['stat'],
        ['du', '-sh'],
        ['cat'],
        ['rm']
    ]
    
    def log(msg):
        timestamp = datetime.now().strftime("[%Y-%m-%d %H:%M:%S]")
        with open(log_path, 'a') as f:
            f.write(f"{timestamp} {msg}\n")
    
    def run_tool(tool, path):
        try:
            subprocess.run(tool + [path], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
            log(f"{' '.join(tool)}: success")
        except subprocess.CalledProcessError as e:
            result = subprocess.run(tool + [path], stderr=subprocess.PIPE, text=True)
            log(f"{' '.join(tool)}: failed")
            log(f"    stderr: {result.stderr.strip()}")
    
    # Cleanup and setup
    shutil.rmtree(base, ignore_errors=True)
    os.makedirs(base)
    with open(log_path, 'w') as f:
        f.write("# Tool Results Log\n\n")
    
    log("Starting deep path creation...")
    
    # Create deep directory using file descriptors
    fd = os.open(base, os.O_RDONLY)
    components = []
    path_len = len(base)
    
    while path_len <= 4096:
        os.mkdir(name, dir_fd=fd)
        fd = os.open(name, os.O_RDONLY, dir_fd=fd)
        components.append(name)
        path_len += len(name) + 1  # account for slash
    
    full_path = os.path.join(base, *components, 'deepfile.txt')
    
    log(f"Created path: {full_path}")
    log(f"Path length: {len(full_path)}")
    
    # Create and write to the deep file
    file_fd = os.open("deepfile.txt", os.O_CREAT | os.O_WRONLY, 0o600, dir_fd=fd)
    os.write(file_fd, content.encode('utf-8'))
    os.close(file_fd)
    
    log("Wrote content to deepfile.txt")
    
    # Read back the content using file descriptor
    fd_read = os.open("deepfile.txt", os.O_RDONLY, dir_fd=fd)
    read_content = os.read(fd_read, 1024).decode('utf-8')
    os.close(fd_read)
    
    log("Read back content:")
    for line in read_content.strip().splitlines():
        log(f"    {line}")
    
    # Run tools and log results
    log("\n=== Tool Compatibility Check ===")
    for tool in tools:
        run_tool(tool, full_path)
    
    # Save full path for external reference
    with open(os.path.join(base, 'full_path.txt'), 'w') as f:
        f.write(full_path + '\n')
    
    log("Finished all checks.")
    print(f"\nDone. See log at: {log_path}")
    

    [3]

    Something in that calls file, which returns:

    deepfile.txt: ERROR: Output buffer space exceeded 4186+0

    Ignore it. IDK what’s calling it. It’s separate to MAX_PATH anyway, since it appears to indicate that a buffer internal to file is overflown.

  2. Confirmation

    I’ve confirmed that this actually works:

    1. I wrote to it:

      #!/usr/bin/env python3
      import os
      
      base = os.path.expanduser('~/pathmax_tool_test')
      segment = 'd' * 255
      target_file = 'deepfile.txt'
      content = b'Hello from the deep!\n'
      
      # Start from the base directory
      fd = os.open(base, os.O_RDONLY)
      
      try:
          for _ in range(100):  # reasonable max depth cap
              try:
                  # Try to descend into next subdirectory
                  next_fd = os.open(segment, os.O_RDONLY, dir_fd=fd)
                  os.close(fd)
                  fd = next_fd
              except FileNotFoundError:
                  break  # No more levels
      
          # Now we're at the deepest level, write the file here
          file_fd = os.open(target_file, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o644, dir_fd=fd)
          os.write(file_fd, content)
          os.close(file_fd)
      
          print("Wrote to deepfile.txt at deepest level.")
      finally:
          try: os.close(fd)
          except: pass
      
    2. I read from it:

      #!/usr/bin/env python3
      import os
      
      base = os.path.expanduser('~/pathmax_tool_test')
      segment = 'd' * 255
      target_file = 'deepfile.txt'
      
      def walk_fd_to_file(base_dir, segment_name, target_file):
          """
          Walks down segment_name subdirectories using file descriptors until target_file is found.
          Returns the file content as a string.
          """
          print(f"Starting from base: {base_dir}")
          fd = os.open(base_dir, os.O_RDONLY)
      
          try:
              for depth in range(100):  # Limit to prevent infinite loops
                  try:
                      file_fd = os.open(target_file, os.O_RDONLY, dir_fd=fd)
                      print(f"Found '{target_file}' at depth {depth}")
                      content = os.read(file_fd, 4096).decode('utf-8', errors='replace')
                      os.close(file_fd)
                      return content
                  except FileNotFoundError:
                      # Not here yet, try next subdirectory
                      try:
                          next_fd = os.open(segment_name, os.O_RDONLY, dir_fd=fd)
                          os.close(fd)
                          fd = next_fd
                      except FileNotFoundError:
                          raise FileNotFoundError(f"Directory segment '{segment_name}' not found at depth {depth}")
              raise RuntimeError(f"Reached max depth without finding '{target_file}'")
          finally:
              try: os.close(fd)
              except: pass
      
      # ---- Main usage ----
      
      if __name__ == '__main__':
          try:
              file_content = walk_fd_to_file(base, segment, target_file)
              print("\nFile content:\n")
              print(file_content)
          except Exception as e:
              print(f"Error: {e}")
      

…Dolphin merely pretends that it has no children, and fails to open its child directory if it is manually entered:

This reminds me of what occurs when Windows’s MAX_PATH is exceeded:

This is, unfortunately, the best behaviour of any KDE application.

If, inside that directory, is a file of text/plain, when passed as an argument, Kate considers invokes a small “New file” notification in its GUI. Additionally, it fails to save it, with an erroneous message that the file may be corrupt:

Gwenview and Okular fail even to open it:

  1. Gwenview

  2. Okular

Question

What library and/or function do all these applications call to open and save these? Perhaps, better yet, might I be able to easily ascertain with something like strace?


  1. stackoverflow.com/revisions/6216960/1 ↩︎

  2. serverfault.com/revisions/306726/3 ↩︎

  3. chatgpt.com/s/t_6864162c13448191b80a87a529138696 [4] ↩︎

  4. chatgpt.com/c/6863fd27-b8cc-8006-862c-765cb1b6e975 ↩︎

Perhaps, some references shall assist in ascertaining this:

In creating my solution to that question, I have ascertained that the common component appears to be QFileSystemModel.

I’ve filed bugreports.qt.io/browse/QTBUG-138251 upstream. If any dolphin developers are interested in how you could bypass PATH_MAX, I’ve provided a CPP example.

Oh well. That was swiftly rejected, for good reason: multiple code paths would be difficult to maintain. If anyone can weigh in whether this would be at least theoretically acceptible in KDE Frameworks, I’ll file an FR. Otherwise, I’ve done as much as I can:

KDE uses a different code path for handling files than Qt does, so I think it would be easier. IMO you should file a feature request on Bugzilla.

1 Like

@bernardogn, thank you! I’ll do so, so do you know what component? It helps to save Nate a bit of triage time, and make a better report. I’m estimating frameworks-kio.

@bernardogn, filed at bugs.kde.org/show_bug.cgi?id=506659.