Rixstep
 About | ACP | Buy | Industry Watch | Learning Curve | News | Products | Search | Substack
Home » Learning Curve

PATH_MAX Revisited

For the rest of us.


Get It

Try It

This is a bit of an exercise - a 'lab', a 'hands on'. You're supposed to follow along. Treats await at the end of the rainbow. If you're ready for a laugh or two.

Ready?

OK! So go find Terminal.app (in your 'Utilities' folder) and launch it. Make the window a decent size, something like 80x60 (Preferences → Profiles → Window).

Now type in this (and yes you hit 'enter' afterwards, don't ask again).

cd /private/tmp

That was supposed to change your directory to /private/tmp. Verify that you got there with this command:

pwd

(Stands for print working directory - yes they actually printed things back then.)

You should get back '/private/tmp'. If you didn't: try again.

Now, when you're ready, the real fun starts. Paste this into Terminal (just triple-click it and copypasta in). Then run it.

mkdir 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789

Do the same with this.

cd 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789

And then this, to round things off.

pwd; echo; echo

What you've just done (don't copypasta from here) is the following.

mkdir
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
0123456789012345678901234567890123456789012345678901234567890123456789

cd
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
0123456789012345678901234567890123456789012345678901234567890123456789

pwd; echo; echo

You 1) made a directory (mkdir) then 2) changed into that directory (cd) then 3) printed out your new working directory (pwd) with a few blank lines (echo).

Now try pasting all of that in at once. From here. (A triple click should do it.)

mkdir 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789; cd 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789; pwd;echo;echo

And do it again. And again. And again.

Keep doing that until your 'pwd' returns something ginormous. Like this.

/private/tmp/0123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789

(That's a path of 3263 bytes.)

Step II

Don't close your Terminal window just yet.

Take any image file you have on disk and duplicate it.

Open the duplicated image file in Preview. Go to the File menu, hold down option (⌥) and choose 'Save As' (shortcut: ⌥⇧⌘S).

Try to 'save as' at the bottom (far right) of the new hive you created in /private/tmp.



Oops! As you scroll towards the end of that path (you won't make it all the way) your 'Save' button should dim out.

So you'd seem to have two fails going on at the same time. First: you can't get all the way down that path you created; and second: you can't save the file anyway.

What went wrong?

PATH_MAX Revisited

This is a lot harder to explain that it seems. Your Unix underbody (the Rock Solid Foundation™) uses static character buffers to denote your current directory, but the old Apple 'MacOS' doesn't. Your Unix deals in inodes but the old Apple 'MacOS' deals in CNIDs.

And your Terminal.app, despite its name and declared intention, is actually a crazy mixture of both operating systems.

(You can sometimes see this when you remove a directory, then replace it: Terminal won't know where it is. Run 'cd .' to help it out.)

Your file system has nothing against against paths of any length you want. A test run here recently produced a path of 14,081 bytes, and that wasn't a limit the people hit, that's just when they got tired of testing the danged thing. You can, in theory, go on forever.

No, the limit isn't in your file system. Or on your disk. It's in your operating system - in this case: Unix.

PATH_MAX is a value baked in everywhere on your system. For Apple Unix, this value is set at 1,024. Many other systems use a far greater value. Sometimes 5,120 or so, some systems go up to 8,192, and so forth. But there's always a limit. For that limit sets the size of buffers that are going to internally hold your current working directory (the thing you see when you run the 'pwd' command).

It's just that 'old' 'Mac OS' didn't have such a limit. 'Old' 'Mac OS' didn't have the concept of the 'current working directory'. 'Old' 'Mac OS' didn't have a command line. And that wasn't just a 'pretend' as it was with Windows. It was real: no command line.

So you didn't have 'relative paths' ('../foo') contra 'full paths' ('/private/tmp'). All paths, to the extent they were used, were full paths.

Yo Yer Paths

This was noticed a long time ago - back in 2007.



It was noticed even earlier at the Apple forums and here. It doesn't matter much which side of the fence you happen to be on: things are going to crash.

And finding some fancy way (eg with NSMutableString) to store your paths and your current working directory won't help much either: your code will crash somewhere in the frameworks (in the kernel).

'Cocoa apps: You cannot open any such document or save a document to such a place. No user feedback apart from dimmed Open/Save buttons in Open/Save dialogs. Carbon apps: You can double-click them to open them, but attempting to use Nav Services to open or save them will crash the app whilst trying to update the Recent Documents.'

But 'Carbon' doesn't exist anymore, right? Because Carbon is only 32-bit at best, and it wasn't upgraded to 64-bit, and it was only a transition thing anyway, right?

Here's where 'PATH_MAX' (and 'MAXPATHLEN') can be found in versions 10.7 and 10.14.

10.7:


10.14:

So What To Do?

So what to do? Good question. Because, as things stand, your Rock Solid Foundation™ is going to crash. (No, you shouldn't damage anything, but still and all.)

There would seem to be two ways to solve this.

  1. Fix the Terminal. So it can't create paths that are too long (greater than PATH_MAX bytes).

  2. Retool all of the Rock Solid Foundation™. So it deals in paths of any length.

The latter alternative should prove to be very daunting (albeit very attractive).

Cleaning Up

You still have that Terminal window open?

Good. Now run this command and you should be good to go.

rm -r 0123456789*

About Rixstep

Stockholm/London-based Rixstep are a constellation of programmers and support staff from Radsoft Laboratories who tired of Windows vulnerabilities, Linux driver issues, and cursing x86 hardware all day long. Rixstep have many years of experience behind their efforts, with teaching and consulting credentials from the likes of British Aerospace, General Electric, Lockheed Martin, Lloyds TSB, SAAB Defence Systems, British Broadcasting Corporation, Barclays Bank, IBM, Microsoft, and Sony/Ericsson.

Rixstep and Radsoft products are or have been in use by Sweden's Royal Mail, Sony/Ericsson, the US Department of Defense, the offices of the US Supreme Court, the Government of Western Australia, the German Federal Police, Verizon Wireless, Los Alamos National Laboratory, Microsoft Corporation, the New York Times, Apple Inc, Oxford University, and hundreds of research institutes around the globe. See here.

All Content and Software Copyright © Rixstep. All Rights Reserved.

CONTACT INFO:
John Cattelin
Media Contact
contact@rixstep.com
PURCHASE INFO:
ACP/Xfile licences
User/Family/Business
http://rixstep.com/buy
About | ACP | Buy | Industry Watch | Learning Curve | News | Products | Search | Substack
Copyright © Rixstep. All rights reserved.