4.1.1. اشیاء سیستمفایل آدرسدهیشده بر اساس محتوا
برای بسیاری از عملیاتها، نیکس نیاز دارد تا آدرسهای محتوایی یک شیء سیستمفایل (FSO) را محاسبه کند. معمولاً این کار بهعنوان بخشی از اشیاء انبار آدرسدهیشده بر اساس محتوا مورد نیاز است، زیرا اشیاء انبار همیشه دارای یک شیء سیستمفایل ریشه هستند. اما برخی از ابزارهای خط فرمان نیز صرفاً روی اشیاء سیستمفایل «خام» که بخشی از هیچ شیء انباری نیستند، کار میکنند.
هر طرح آدرسدهی محتوایی که نیکس استفاده میکند، در نهایت شامل دادن دادهها به یک تابع هش و دریافت یک خلاصه (digest) مبهم با اندازه ثابت است که بهعنوان آدرس محتوا در نظر گرفته میشود. بنابراین، روشهای مختلف آدرسدهی محتوایی در نحوه انتقال دادههای انتزاعی (در اینجا، یک شیء سیستمفایل و فرزندان آن) به تابع هش با یکدیگر تفاوت دارند.
سریالسازی اشیاء سیستمفایل { #serial }
سادهترین روش این است که کل درخت شیء سیستمفایل را به یک رشته باینری واحد سریالسازی کنیم و سپس آن رشته باینری را هش کنیم تا آدرس محتوا به دست آید. در این بخش، روشهای پشتیبانیشده فعلی برای سریالسازی اشیاء سیستمفایل را شرح میدهیم.
مسطح (Flat) { #serial-flat }
یک شیء فایل منفرد را میتوان صرفاً بر اساس محتوای آن هش کرد. این اطلاعات برای رمزگذاری این حقیقت که شیء سیستمفایل یک فایل است کافی نیست، اما اگر از قبل از راههای دیگر بدانیم که FSO یک فایل منفرد غیرقابلاجرا است، همین مقدار کافی خواهد بود.
از آنجا که دادههای هششده دقیقاً همان فایل خام و دستنخورده هستند، این انتخاب برای سازگاری با سایر سیستمها مناسب است.
برای مثال، دستورات یونیکس مانند sha256sum یا sha1sum برای فایلهای منفرد هشهایی تولید میکنند که با این روش مطابقت دارد.
آرشیو نیکس (NAR) { #serial-nix-archive }
برای سایر موارد اشیاء سیستمفایل، بهویژه دایرکتوریها با فرزندان دلخواه، به یک فرمت سریالسازی پیچیدهتر نیاز داریم. نمونههایی از این نوع سریالسازیها، فرمتهای فایل ZIP و TAR هستند. با این حال، برای اهداف ما این فرمتها دو مشکل دارند:
آنها یک سریالسازی کاننیکال (معتبر و استاندارد) ندارند؛ به این معنا که با داشتن یک FSO، میتوانند سریالسازیهای مختلفی داشته باشند. برای مثال، فایلهای TAR میتوانند مقادیر متغیری از پدینگ (padding) بین اعضای آرشیو داشته باشند؛ و برخی از فرمتهای آرشیو، ترتیب ورودیهای دایرکتوری را نامشخص رها میکنند. این موضوع بد خواهد بود زیرا ما از سریالسازی برای محاسبه هشهای رمزنگاریشده روی اشیاء سیستمفایل استفاده میکنیم و برای اینکه آن هشها بهعنوان آدرس محتوا یا بررسی یکپارچگی مفید باشند، منحصربهفرد بودن بسیار حیاتی است. در غیر این صورت، هشهای صحیح گزارشهای نادرستی از عدم تطابق ارائه میدهند و انبار در یافتن محتوا ناکام خواهد ماند.
آنها اطلاعاتی فراتر از مفهوم ما از FSOها، مانند مهر زمانی (time stamps)، را ذخیره میکنند. این امر میتواند باعث شود FSOهایی که نیکس باید آنها را برابر در نظر بگیرد، صرفاً به دلیل متفاوت بودن تاریخها، در ماشینهای مختلف مقادیر هش متفاوتی تولید کنند.
به عنوان یک ملاحظه عملی، فرمت TAR تنها فرمت واقعاً جهانی در محیط یونیکس است. این فرمت مشکلات زیادی دارد، از جمله ناتوانی در مدیریت نامهای فایل طولانی و فایلهای بزرگتر از ۲ به توان ۳۳ بایت. پیادهسازیهای فعلی مانند GNU Tar به راههای مختلفی این محدودیتها را دور میزنند.
به همین دلیل، نیکس فرمت آرشیو مخصوص به خود را دارد؛ یعنی فرمت آرشیو نیکس (NAR)، که با دقت طراحی شده است تا از مشکلاتی که در بالا ذکر شد جلوگیری کند.
مشخصات دقیق فرمت آرشیو نیکس در اینجا مشخص شده است.
آدرسدهی محتوایی اشیاء سیستمفایل فراتر از یک مرحله سریالسازی منفرد
با این حال، سریالسازی کل درخت و سپس هش کردن آن رشتهٔ باینری، تنها گزینه برای آدرسدهی محتواپایه نیست. teknik دیگری که وجود دارد، گراف مرکل (Merkle graph) است که در آن هشهای محاسبهشدهٔ قبلی در رشتههای بایت بعدی که قرار است هش شوند، گنجانده میشوند.
بهطور ویژه، گرافهای مرکل میتوانند با ساختار گراف اصلی اشیاء سیستمفایل مطابقت داشته باشند: ما میتوانیم ابتدا اشیاء سیستمفایل فرزند (سریالشده) را هش کنیم و سپس با استفاده از هش فرزندان در سریالسازی (که قرار است هش شود) اشیاء سیستمفایل والد، اشیاء والد را هش کنیم.
در حال حاضر، یک روش آدرسدهی محتوای گراف جهتدار بدون دور (DAG) مرکل از این دست پشتیبانی میشود.
Git (تجربی) { #git }
هشدار
این روش بخشی از ویژگی تجربی
git-hashingاست.
مدل سیستمفایل Git بسیار شبیه به مدل Nix است، و به همین دلیل روش آدرسدهی محتوای Git تطابق بسیار خوبی دارد. دقیقاً مانند Git معمولی، فایلها و پیوندهای نمادین به عنوان «بارهای (blobs)» گیت و دایرکتوریها به عنوان «درختهای (trees)» گیت هش میشوند.
با این حال، یک تفاوت بین مدل سیستمفایل Nix و Git وجود دارد که نیازمند توجه ویژهای است. فایلهای ساده، فایلهای قابلاجرا و پیوندهای نمادین به عنوان اشیاء قابلادرسدهی مجزا متمایز نمیشوند، بلکه بر اساس زمینهٔ خود متمایز میشوند: یعنی توسط ورودی دایرکتوری که به آنها اشاره میکند. این بدان معناست که تا زمانی که شیء ریشه یک دایرکتوری باشد، مشکلی وجود ندارد: هر شیء غیردایرکتوری متعلق به یک دایرکتوری والد است و ورودیای که به آن اشاره میکند، اطلاعات مفقوده را فراهم میکند. با این حال، اگر شیء ریشه یک دایرکتوری نباشد، هیچ راهی برای دانستن اینکه قرار است کدامیک از یک فایل قابلاجرا، فایل غیرقابلاجرا یا پیوند نمادین باشد، نداریم.
در واکنش به این موضوع، تصمیم گرفتهایم که یک فایل ساده را به عنوان فایل غیرقابلاجرا در نظر بگیریم. این شبیه به کاری است که با سریالسازی تخت انجام میدهیم که آن هم فاقد این اطلاعات است. برای جلوگیری از تداخل آدرس، تلاش برای هش کردن یک فایل قابلاجرا یا پیوند نمادین ساده منجر به خطا خواهد شد (دقیقاً همان اتفاقی که برای سریالسازی تخت نیز رخ میدهد). بنابراین، Git میتواند برخی از «اشیاء سیستمفایل» Nix را رمزگذاری کند، اما نه همه آنها، و این نوع آدرسدهی محتوا به همین ترتیب جزئی است.
در آینده، ممکن است از یک هش شبیه به Git برای چنین اشیاء سیستمفایل پشتیبانی کنیم، یا ممکن است قالب گراف جهتدار بدون دور (DAG) مرکل دیگری را اتخاذ کنیم که قادر به نمایش تمام اشیاء سیستمفایل Nix باشد.
nix.dev/manual/nix/stable/store/file-system-object/content-address.html