5

In the code I maintain I run across:

from ctypes.wintypes import MAX_PATH

I would like to change it to something like:

try:
    from ctypes.wintypes import MAX_PATH
except ValueError: # raises on linux
    MAX_PATH = 4096 # see comments

but I can't find any way to get the value of max filesystem path from python (os, os.path, sys...) - is there a standard way or do I need an external lib ?

Or there is no analogous as MAX_PATH in linux, at least not a standard among distributions ?


Answer

try:
    MAX_PATH = int(subprocess.check_output(['getconf', 'PATH_MAX', '/']))
except (ValueError, subprocess.CalledProcessError, OSError):
    deprint('calling getconf failed - error:', traceback=True)
    MAX_PATH = 4096
Community
  • 1
  • 1
Mr_and_Mrs_D
  • 32,208
  • 39
  • 178
  • 361

2 Answers2

15

The way to do it correctly is to use the os.pathconf or os.fpathconf with PC_ prefixed names:

>>> os.pathconf('/', 'PC_PATH_MAX')
4096
>>> os.pathconf('/', 'PC_NAME_MAX')
255

Notice that the maximum length of a path component may vary from directory to another, as it is filesystem dependent, so you might have os.pathconf('/', 'PC_NAME_MAX') as 255 and os.pathconf('/', 'PC_NAME_MAX') as 12, say.

4

You can read this values from files:

* PATH_MAX (defined in limits.h)
* FILENAME_MAX (defined in stdio.h)

Or use subprocess.check_output() with getconf function:

$ getconf NAME_MAX /
$ getconf PATH_MAX /

as in the following example:

name_max = subprocess.check_output("getconf NAME_MAX /", shell=True)
path_max = subprocess.check_output("getconf PATH_MAX /", shell=True)

to get values and fpath to set different values for files.

WojtekCh
  • 90
  • 3
  • First things first - is `shell=True` used to avoid passing absolute paths ? And is this getconf call portable ? May I need root rights using it ? – Mr_and_Mrs_D Sep 28 '15 at 14:16
  • 1. `shell=True` makes that the specified command will be executed through the shell 2. getconf call is portable in unix/linux systems, not in windows 3. root is not required – WojtekCh Sep 29 '15 at 07:54
  • Alright +1 for additional effort - 1. shell=True - I know what it does but what difference does it make here (I tested without - I get `OSError: [Errno 2] No such file or directory` - why?)? In other words could you rewrite this with Popen ? 4. Apparently I should catch CalledProcessError __and__ OSError __and__ ....? – Mr_and_Mrs_D Sep 29 '15 at 16:11
  • 1. Here you are: `name_max = subprocess.check_output(["getconf", "NAME_MAX", "/"], shell=False)` = `name_max = subprocess.Popen("getconf NAME_MAX /", stdout=subprocess.PIPE, shell=True)` = `name_max = subprocess.Popen(["getconf", "NAME_MAX", "/"], stdout=subprocess.PIPE, shell=False)` When you pass shell=True, Popen expects a single string argument, not a list. And if args is a sequence['1', , ], the first item specifies the command string, and any additional items will be treated as additional arguments to the shell itself. – WojtekCh Sep 30 '15 at 23:12
  • 4. The minor difference is that check_output will raise a Python error if the subprocess returns a non-zero exit status. With Popen you can control that: `name_max = subprocess.Popen("getconf NAME_MAX /", stdout=subprocess.PIPE, shell=True) output, error = process.communicate() retcode = process.poll()` – WojtekCh Sep 30 '15 at 23:13