{"id":44325,"date":"2024-08-02T16:45:23","date_gmt":"2024-08-02T20:45:23","guid":{"rendered":"https:\/\/mjtsai.com\/blog\/?p=44325"},"modified":"2024-11-25T15:14:16","modified_gmt":"2024-11-25T20:14:16","slug":"the-switch-from-file-paths-to-urls","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2024\/08\/02\/the-switch-from-file-paths-to-urls\/","title":{"rendered":"The Switch From File Paths to URLs"},"content":{"rendered":"<p><a href=\"https:\/\/forums.swift.org\/t\/get-folders-number-of-elements\/30674\/12\">Quinn<\/a>:<\/p>\n<blockquote cite=\"https:\/\/forums.swift.org\/t\/get-folders-number-of-elements\/30674\/12\"><p>I don&rsquo;t think we ever documented this officially, but to understand this choice you have to look at the history of macOS. Traditional Mac OS did not use paths a lot. Rather, files were identified by an <code>FSSpec<\/code>, which contains a volume identifier, a directory ID, and a name. The directory ID was an HFS [Plus] catalogue node ID (CNID), which is kinda like an inode number.<\/p><p>Additionally, starting with System 7 it was possible to track a file with a volume identifier and the file ID, that is, the CNID of the file itself.<\/p><p>This was quite tricky to support on a Unix-y platform like Mac OS X.  At the lowest levels of the system you needed the ability to manipulate files based on CNIDs rather than paths.  For an explanation of how this was done, see QA1113 <a href=\"https:\/\/developer.apple.com\/library\/archive\/qa\/qa2001\/qa1113.html\">The &ldquo;\/.vol&rdquo; directory and &ldquo;volfs&rdquo;<\/a> (note, however, that <code>volfs<\/code> is no longer a thing and the same functionality is now implemented in a very different way).<\/p><p>[&#8230;]<\/p><p>So far, so much obscure backward compatibility. However, since we made the decision to use file URLs we&rsquo;ve exploited that to significant advantage[&#8230;]<\/p><\/blockquote>\n\n<p>Via <a href=\"https:\/\/mastodon.social\/@cocoawithlove\/112737261294397919\">Matt Gallagher<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@cocoawithlove\/112737261294397919\"><p>There&rsquo;s a lesson about attaching data (like security attributes) to an opaque interface (like <code>NSURL<\/code>). Because my mental model of <code>NSURL<\/code> is as plain RFC-3986 storage, these attributes are easy to lose and the security behaviours are easy to forget, when moving data around an app (I wish we received a bookmark type that made this explicit).<\/p><\/blockquote>\n\n<p><a href=\"https:\/\/techhub.social\/@jimluther\/112743590993588397\">Jim Luther<\/a>:<\/p>\n<blockquote cite=\"https:\/\/techhub.social\/@jimluther\/112743590993588397\">\n<p>The original proposal was not to use a <code>NS<\/code>\/<code>CFString<\/code> object encapsulating the path or a <code>NS<\/code>\/<code>CFURL<\/code> object, and instead use a new object type to identify a file&rsquo;s location, to cache properties, etc. That idea was vetoed in early API reviews because there were already API that took file locations as paths or URLs. We were told to pick path or URL. We chose URL objects over string objects.<\/p>\n<p>I still think a new object type would have been cleaner and better in the long run. &#x1F937;&#x200D;&#x2642;&#xFE0F;<\/p>\n<p>[&#8230;]<\/p>\n<p><code>FSRef<\/code>s were not objects so they didn&rsquo;t fit into the Cocoa (or CoreFoundation)API memory model. They were also a fixed size glob of memory so expanding their functionality was very difficult. One of the things I did in my last year at Apple was to make the old Carbon File Manager work well with APFS and its 64-bit inode numbers. That meant making shoehorning 64-bit file and folder ids into <code>FSRef<\/code>s and translating them to 32-bit ids for the old File Manager API. Fun hacking &#x1F600;<\/p>\n<\/blockquote>\n\n<p>Previously:<\/p>\n<ul>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2022\/06\/30\/swift-url-improvements-at-wwdc-2022\/\">Swift URL Improvements at WWDC 2022<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2019\/10\/24\/modern-appkit-file-permissions\/\">Modern AppKit File Permissions<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2019\/03\/29\/the-weirdness-of-nsurls-isdirectory-flag\/\">The Weirdness of NSURL&rsquo;s isDirectory Flag<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2005\/09\/13\/path_max-blackholing\/\">PATH_MAX Blackholing<\/a><\/li>\n<\/ul>\n\n<p id=\"the-switch-from-file-paths-to-urls-update-2024-11-25\">Update (2024-11-25): <a href=\"https:\/\/chaos.social\/@uliwitness\/113534163034019251\">Uli Kusterer<\/a>:<\/p>\n<blockquote cite=\"https:\/\/chaos.social\/@uliwitness\/113534163034019251\"><p>I&rsquo;m still kinda confused <code>(NS)Stream<\/code> was so late to arrive and has so little support for serializing objects. I guess PowerPlant spoiled me.<\/p><\/blockquote>\n\n<p>I was and remain surprised that the stream APIs are comparatively awkward and rarely used throughout Apple&rsquo;s frameworks.<\/p>\n\n<p><a href=\"https:\/\/techhub.social\/@jimluther\/113544410721022182\">Jim Luther<\/a>:<\/p>\n<blockquote cite=\"https:\/\/techhub.social\/@jimluther\/113544410721022182\">\n<p>How bad was the URL performance? Using the new &ldquo;efficient&rdquo; Snow Leopard URL file system property API: getattrlist (the Apple extended lstat function that gets more file system data) was only around 5% of the time. Caching that data in newly created CF\/Cocoa objects and returning those objects  was another 25% of the time. The rest of the time was spent creating the URL from the file system path and getting the file system path back from the URL.<\/p>\n<p>After fixing the URL performance issues, Apple found lots of other things to change that helped the performance of those API, and thus other parts of the system: like tagged pointers (file system properties are mostly numbers), and optimizing  all-ASCII CF\/NSStrings (like URL strings).<\/p>\n<p>Better performance tools really helped us easily determine what was causing performance issues.<\/p>\n<p>Until Lion or maybe Mountain Lion, the new &ldquo;efficient&rdquo; URL file system API was a lot slower than using the old Carbon File Manager API.<\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/mastodon.social\/@jimluther@techhub.social\/113544504826528287\">Jim Luther<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@jimluther@techhub.social\/113544504826528287\">\n<p>Those are the two primary reasons Apple did  not add a URL property to get a directory&rsquo;s valence (like was available in the deprecated Carbon File Manager API).<\/p>\n<\/blockquote>","protected":false},"excerpt":{"rendered":"<p>Quinn: I don&rsquo;t think we ever documented this officially, but to understand this choice you have to look at the history of macOS. Traditional Mac OS did not use paths a lot. Rather, files were identified by an FSSpec, which contains a volume identifier, a directory ID, and a name. The directory ID was an [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"apple_news_api_created_at":"2024-08-02T20:45:29Z","apple_news_api_id":"03d0e6a0-3e8d-4c5b-9c5c-3a27fe66f16c","apple_news_api_modified_at":"2024-11-25T20:14:19Z","apple_news_api_revision":"AAAAAAAAAAAAAAAAAAAAAQ==","apple_news_api_share_url":"https:\/\/apple.news\/AA9DmoD6NTFucXDon_mbxbA","apple_news_coverimage":0,"apple_news_coverimage_caption":"","apple_news_is_hidden":false,"apple_news_is_paid":false,"apple_news_is_preview":false,"apple_news_is_sponsored":false,"apple_news_maturity_rating":"","apple_news_metadata":"\"\"","apple_news_pullquote":"","apple_news_pullquote_position":"","apple_news_slug":"","apple_news_sections":"\"\"","apple_news_suppress_video_url":false,"apple_news_use_image_component":false,"footnotes":""},"categories":[4],"tags":[1395,755,69,537,295,30,2385,922,489],"class_list":["post-44325","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-apple-file-system-apfs","tag-carbon","tag-cocoa","tag-filesystem","tag-history","tag-mac","tag-macos-14-sonoma","tag-system-7","tag-url"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/44325","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/comments?post=44325"}],"version-history":[{"count":3,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/44325\/revisions"}],"predecessor-version":[{"id":45919,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/44325\/revisions\/45919"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=44325"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=44325"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=44325"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}