64-बिट time_t ट्रांज़िशन के जोखिम
(blogs.gentoo.org)- 32-बिट glibc सिस्टम में 2038 के बाद वर्तमान समय प्राप्त करना या
stat()कॉल विफल हो सकती है, इसलिए Gentoo को 64-बिट time_t पर सुरक्षित रूप से जाने का रास्ता चाहिए - glibc का time64 Large File Support(LFS) के साथ ही इस्तेमाल होना चाहिए, और 32-बिट वातावरण में मौजूदा ABI, LFS ABI, और LFS+time64 ABI साथ-साथ मौजूद रहते हैं
- जब
time_tAPI, struct, या function arguments में आता है, तो type width में बदलाव ABI breakage बन जाता है, जिससे time32 और time64 binaries को मिलाने पर runtime malfunction और security risk पैदा होते हैं - source-based distribution होने के कारण Gentoo में
@worldrebuild के दौरान failure या circular dependency की वजह से आधा-परिवर्तित सिस्टम बच सकता है - 2024-09-30 के correction के बाद यह साफ हुआ कि सिर्फ libdir transition काफ़ी नहीं है, और dynamic loader व कई language toolchains तक फैला time64 marker एक मुख्य constraint बना हुआ है
2038 समस्या और time64 ट्रांज़िशन का दायरा
- 32-बिट
time_tइस्तेमाल करने वाले 32-बिट applications को 2038 में वर्तमान समय की जगह-1error मिल सकती है, या वे फ़ाइलों परstat()नहीं कर पाएँगे - ट्रांज़िशन की बुनियादी दिशा
time_tको 64-बिट type में बदलना है- musl यह बदलाव पहले ही कर चुका है
- glibc इसे एक option के रूप में support करता है
- Debian जैसी कुछ distributions यह बदलाव पहले ही कर चुकी हैं
- Gentoo जैसी source-based distributions में users सिस्टम को खुद rebuild करते हैं, इसलिए packages के अलग-अलग ABI state में रहने का समय कम करना ज़रूरी है
- सबसे बड़ा जोखिम यह है कि
time_tकी width बदलने से ABI टूटता है- अगर किसी library API में
time_tहै, तो उस library से link होने वाला सारा code वही type width इस्तेमाल करे - केवल कुछ हिस्सों को time64 में बदलना सुरक्षित नहीं है
- अगर किसी library API में
LFS और 32-बिट के तीन sub-ABI
- 32-बिट architectures में फ़ाइल-संबंधित type width की समस्या पहले से मौजूद थी
off_tफ़ाइल offset के लिए इस्तेमाल होता हैino_tinode number के लिए इस्तेमाल होता है- ये मूल रूप से 32-बिट थे, इसलिए 2GiB से बड़ी फ़ाइलें या 32-बिट range से बाहर inode numbers समस्या बनते थे
- इसे हल करने के लिए Large File Support(LFS) लाया गया
off_tऔरino_tको 64-बिट variants में बदला गया- glibc में यह आज भी optional है
- कई packages ने upstream में LFS enable करके ABI breakage संभाला, लेकिन समस्या पूरी तरह खत्म नहीं हुई
- glibc का time64 support LFS के उपयोग की मांग करता है, इसलिए फ़ाइल size और समय की समस्या एक साथ हल करने वाली संरचना बनती है
- 32-बिट सिस्टम में तीन sub-ABI मौजूद होते हैं
- मौजूदा ABI: 32-बिट types
- LFS: 64-बिट
off_t, 64-बिटino_t, 32-बिटtime_t - time64: LFS + 64-बिट
time_t
- एक glibc build इन तीनों variants के साथ compatible हो सकता है, लेकिन जो libraries इन types को API में इस्तेमाल करती हैं, वे इन variants को आपस में mix नहीं कर सकतीं
ABI बदलाव वास्तव में कैसे तोड़ता है
- जब
time_t32-बिट से 64-बिट होता है, तो struct layout बदल जाता है- उदाहरण के लिए अगर किसी struct में
int a,time_t b,int cइसी क्रम में हों, तोcका offset 32-बिटtime_tऔर 64-बिटtime_tमें अलग होगा - time32 और time64 binaries को मिलाने पर गलत fields पढ़े या लिखे जा सकते हैं, और out-of-bounds access भी संभव है
- उदाहरण के लिए अगर किसी struct में
struct statका size भी ABI के अनुसार बदलता है- 32-बिट x86 glibc default: 88 bytes
- LFS: 96 bytes
- LFS + time64: 108 bytes
- केवल structs ही नहीं, function arguments में भी समस्या आती है
- x86 में function arguments stack के जरिए pass होते हैं
- अगर किसी argument में
time_tहै, तो उसके बाद आने वाले arguments की stack position बदल जाती है
- एक example experiment में जब time32 program को time64 के साथ rebuild की गई library से link किया गया, तो values बिगड़ गईं
- मूल output था
a = 1, एक सामान्य time value,c = 3 - लेकिन सिर्फ library को
-D_FILE_OFFSET_BITS=64 -D_TIME_BITS=64के साथ rebuild करने परbऔरcगलत तरह से interpret हुए
- मूल output था
- अभी ऐसे ABI mixing को रोकने के लिए कोई ठोस protection mechanism नहीं है, इसलिए runtime breakage और security issues पैदा हो सकते हैं
Gentoo में ट्रांज़िशन ज़्यादा कठिन क्यों है
- binary distributions सभी packages को rebuild करने के बाद users को अपेक्षाकृत atomic step में upgrade कराती हैं
- third-party repositories या local-built programs हों तो समस्या आ सकती है, लेकिन कुल प्रक्रिया अपेक्षाकृत सुरक्षित रहती है
- Gentoo में
@worldrebuild करते समय ABI को उसी जगह पर बदलना पड़ता है- दो packages के अलग-अलग rebuild होने के बीच incompatible ABI मिल सकते हैं
- कुछ rebuild failures की वजह से सिस्टम आधा-परिवर्तित स्थिति में रह सकता है
- circular dependencies की वजह से dependency packages rebuild करते-करते build tools ही टूट सकते हैं, और उसके बाद आगे rebuild संभव नहीं रह सकता
विचाराधीन mitigation उपाय
- चर्चा में तीन दिशाएँ हैं
- नए ABI को मौजूदा 32-बिट ABI से अलग दिखाने के लिए platform tuple
CHOSTबदलना - नए ABI का libdir बदलकर rebuilt libraries को पुरानी libraries से अलग install करना
- अलग sub-ABI की binaries को link होने से रोकने के लिए binary-level ABI distinction लाना
- नए ABI को मौजूदा 32-बिट ABI से अलग दिखाने के लिए platform tuple
- इन तीनों तरीकों को कुछ हद तक स्वतंत्र रूप से लागू किया जा सकता है, लेकिन कुछ मामलों में वे एक-दूसरे पर निर्भर हो सकते हैं
- लेख में दिए गए example strings अंतिम समाधान के वास्तविक strings हों, यह ज़रूरी नहीं है
CHOST के ज़रिए ABI अलग करना
- platform tuple उस platform की पहचान करता है जिसे toolchain target करता है, और Gentoo में यह multilib support के लिए ABI को uniquely अलग करने में भी काम आता है
- tuple चार हिस्सों से बना होता है: architecture, vendor, operating system, libc
- उदाहरण:
i386-pc-linux-gnu - उदाहरण:
i686-pc-linux-gnu - उदाहरण:
i686-unknown-linux-gnu
- उदाहरण:
- नया ABI लाते समय vendor field बदलने या libc field में ABI notation जोड़ने का तरीका पहले इस्तेमाल हुआ है
- ARM hardfloat ABI में पहले
armv7a-hardfloat-linux-gnueabiऔरarmv7a-unknown-linux-gnueabihfजैसे रूप इस्तेमाल हुए थे
- ARM hardfloat ABI में पहले
- time64 ABI के लिए भी ऐसे विकल्प हैं
i686-gentoo_t64-linux-gnui686-pc-linux-gnut64armv7a-gentoo_t64-linux-gnueabihfarmv7a-unknown-linux-gnueabihft64
- tuple बदलने के लिए बहुत ज़्यादा patches की ज़रूरत नहीं लगती
- GNU toolchain और GNU build system, libc field में
gnuके बाद आने वाले हिस्से को ignore करते हैं - Clang को tuple के आधार पर सही ABI अपने-आप चुनने के लिए patch करना होगा
- GNU toolchain और GNU build system, libc field में
libdir बदलाव और preserved-libs
- libdir library installation directory का default नाम होता है
- सामान्य default
libहै - 64-बिट capable architectures में परंपरागत रूप से
lib64अक्सर इस्तेमाल होता है - x86 का x32 ABI
libx32और MIPS n32 ABIlib32इस्तेमाल करते हैं
- सामान्य default
- time64 वाले 32-बिट ABI के लिए libdir को
libसेlibt64जैसे नाम में बदलने का प्रस्ताव विचाराधीन है - अलग libdir ट्रांज़िशन के दौरान ABI mixing कम करने का एक उपाय बनता है
- इससे time64 executables के गलती से time32 libraries से link होने का जोखिम घटता है
- Portage की preserved-libs सुविधा time32 libraries को preserve कर सकती है
- विकल्प के रूप में time32 + time64 multilib profile देकर पुराने time32 prebuilt applications के साथ compatibility रखी जा सकती है
- preserved-libs होने पर पुराने executables rebuild होने तक time32 libraries इस्तेमाल करते रहेंगे, और time64 में rebuilt libraries नए libdir में install होंगी
- libdir बदलने के लिए toolchain patches चाहिए
- glibc को special handling दी जा सकती है, क्योंकि वही library set कई sub-ABI के लिए valid हो सकता है
- time64 executables की
.interpको time64 वालेld.soकी ओर point कराने के लिए अलगld.soकी ज़रूरत पड़ सकती है
- proper multilib support के लिए उस ABI का एक unique platform tuple भी चाहिए
binary स्तर पर incompatibility को चिह्नित करना
- अलग ABI की binaries को मिलाने पर सामान्यतः linker या dynamic loader को उसे रोकना चाहिए
- अगर 64-बिट program को 32-बिट library से link किया जाए, तो linker
file in wrong formatकहकर मना कर देता है - dynamic loader भी
wrong ELF class: ELFCLASS32जैसी error देकर मना कर देता है
- अगर 64-बिट program को 32-बिट library से link किया जाए, तो linker
- मौजूदा ABI distinction के लिए कई mechanisms इस्तेमाल होते हैं
ELFCLASS32औरELFCLASS64EM_386औरEM_X86_64जैसे machine identifier- ARM और MIPS के flags field
- architecture-specific attribute section
- time32 और time64 के लिए भी ऐसा ही mechanism चाहिए, लेकिन यह आसान नहीं है
- कोई reusable general mechanism दिखता नहीं है
- कई architectures के लिए काम करने वाला समाधान चाहिए
- नया ELF note section जोड़ना और उसके लिए toolchain support implement करना एक व्यावहारिक विकल्प लगता है
- यह भी ध्यान रखना होगा कि users इस protection को disable कर सकते हैं
- अगर source के बिना मिलने वाला prebuilt software
time_tइस्तेमाल करने वाले API को call नहीं करता, तो वह system libraries के साथ चलता रह सकता है - ऐसे में इसे हर हाल में रोकने वाला उपाय समस्या से भी बुरा साबित हो सकता है
- अगर source के बिना मिलने वाला prebuilt software
- अलग libdir का उपयोग करके अपेक्षाकृत आसान non-fatal QA checks बनाए जा सकते हैं
.interpसे time64 executables पहचाने जा सकते हैं- जाँचा जा सकता है कि time32 programs
libt64से libraries load तो नहीं कर रहे - और time64 programs सीधे
libसे libraries load तो नहीं कर रहे
prebuilt 32-बिट applications की सीमाएँ
- source से build होने वाले packages से अलग, x86 और PowerPC के लिए कुछ applications केवल पुराने prebuilt binaries के रूप में उपलब्ध हैं
- खासकर proprietary software और पुराने games इस श्रेणी में आते हैं
- इन्हें system libraries के साथ compatibility की समस्या भी होती है और 2038 समस्या भी
- compatibility समस्या के लिए मौजूदा multilib structure कुछ हद तक समाधान देता है
- amd64 पर 32-बिट software support के लिए पहले से multilib layout और कई library versions build करने की व्यवस्था मौजूद है
- इसे
abi_x86_32औरabi_x86_t64अलग करने तक बढ़ाया जा सकता है - दोनों ABI को support करने वाला नया multilib x86 profile बनाया जा सकता है
- लेकिन 2038 के बाद 32-बिट program के अपने failure की समस्या बनी रहती है
- faketime से system time को नियंत्रित करने का तरीका संभव है
- या समय को पीछे सेट किए हुए VM चलाने का तरीका भी संभव है
2024-09-30 correction: केवल libdir काफ़ी नहीं
- शुरुआती योजना ज़रूरत से ज़्यादा आशावादी थी, और केवल libdir बदलकर स्थिर separation पाना मुश्किल है
- क्योंकि सभी libdir
ld.so.confमें सूचीबद्ध होते हैं, इसलिएld.soके अंदर libdir path hardcode करने वाले तरीके पर निर्भर नहीं रहा जा सकता- custom LLVM prefix में पहले से path adjustments होते हैं, और इस मामले में भी special handling चाहिए
- इसके कारण libdir बदलाव को binary incompatibility distinction पर निर्भर होना पड़ सकता है
- तीन बुनियादी लक्ष्य पूरे करने होंगे
- dynamic loader को time32 और time64 binaries में फर्क करना चाहिए
- जिन binaries पर explicit time64 marker न हो, उन्हें backward compatibility के लिए time32 माना जाना चाहिए
- नई build होने वाली सभी binaries पर explicit time64 marker होना चाहिए, जिनमें Rust जैसे non-C environments में बनी binaries भी शामिल हैं
- यह कई भाषाओं के कई toolchains में patching माँगने वाला काम है
- Gentoo के लिए इसे केवल local patch set के रूप में बनाए रखना मुश्किल होगा, और कई पक्षों के सहयोग की ज़रूरत होगी
- target architectures को अक्सर legacy माना जाता है या उन्हें अब पर्याप्त support नहीं मिलता
- एक अलग समस्या यह भी है कि क्या दूसरे toolchains सही time64 executables बनाएँगे
- अगर उन्हें C programs की तरह
_TIME_BITSfollow करने के लिए adjust नहीं किया गया, तो वे किसी खासtime_twidth को hardcode करके टूट सकते हैं
- अगर उन्हें C programs की तरह
- जिन binaries पर explicit time64 marker नहीं होगा, वे सभी time32 libraries का उपयोग करेंगी, इसलिए Gentoo ऐसे third-party executables नहीं चला पाएगा जिन्हें सही marker देने के लिए patch नहीं किया गया है
- कम महत्वाकांक्षी विकल्पों पर भी विचार हो रहा है
- सभी time64 executables में RPATH inject करके time64 libdir को सीधे enforce किया जाए
- यह तरीका dynamic loader को time32 libraries उपयोग करने से पूरी तरह नहीं रोकेगा, लेकिन बड़े compatibility issues के बिना ट्रांज़िशन में मदद कर सकता है
- उल्टा तरीका भी संभव है, जिसमें time64 libdir को स्थायी रूप से नहीं बदला जाए बल्कि time32 libdir को अस्थायी रूप से बदला जाए
- पुराने programs में RPATH inject किया जाए और libdir का नाम बदला जाए
- नई time64 libraries मौजूदा libdir में install हों
- नए time64 programs में time32 libraries को force करने वाला RPATH न हो
- इसका फायदा यह है कि पहले से ट्रांज़िशन कर चुकी दूसरी distributions के साथ compatibility बनी रह सकती है
बाकी बची चुनौतियाँ
- अगर इन तीनों समाधानों को लागू किया जाए, तो glibc इस्तेमाल करने वाले 32-बिट Gentoo सिस्टम के लिए एक ज़्यादा साफ़ और अपेक्षाकृत सुरक्षित ट्रांज़िशन path दिया जा सकता है
- फिर भी ये समाधान मुख्यतः source से build होने वाले packages पर लागू होते हैं
- prebuilt 32-बिट applications में ABI compatibility बनी रहे, तब भी 2038 समस्या बनी रहती है
- पूरी design अभी draft में है, और experiments, discussions, और patch submissions के साथ बदलती रह सकती है
1 टिप्पणियां
Hacker News की राय
Gentoo में कुछ विकल्प हैं जिन पर लेख में बात नहीं की गई, और शायद Gentoo के सिस्टम डिज़ाइन के कारण काम की मात्रा बड़ी होने से वे छूट गए
.soversioning को बढ़ाकर dependent packages के ABI बदलावों को भी दर्शाना। आम तौर पर shared libraries मेंlibfoo.so.1.0.0जैसे filename और internal version में version number होता है, और package अपने ABI breakage को track करता है। 64-bittime_tको support करने के लिए हर.soके dependency ABI द्वारा नियंत्रित version element जोड़ना होगा। लेख में “अलग libdir इस्तेमाल करना” जैसा ही परिणाम होगा, लेकिन भविष्य के ABI बदलावों के लिए reusable आधार बन सकता है—हालांकि यह कहीं ज़्यादा invasive होने की संभावना रखता हैकई नए packages की build schedule करें, उन्हें sandbox में build करें, और फिर नई compilation को union के ज़रिए पहले sandbox देखने और फिर system पर fallback करने दें। सब build हो जाने पर परिणामों को package करके sandbox से real system में ले जाया जा सकता है। इससे Gentoo updates को transaction जैसा बनाया जा सकता है, जिससे अन्य पहलुओं में भी बड़े फायदे मिलेंगे
/पर set होने वालेROOTको बदलना होता है@systemऔर@worldपूरे को फिर से build करके निर्दिष्ट subdirectory में install किया जा सकता है, और फिर एक बार में sync किया जा सकता है। संभव हो तो यह live session में करना बेहतर है; सिद्धांत रूप में नए install किए गए स्थान की subdirectory में/को bind mount करके chroot में जाकर वास्तविक parent/में sync करना भी संभव हैhttps://devmanual.gentoo.org/ebuild-writing/variables/#root
Mac OS X ने
off_tऔरino_tको जिस तरह handle किया, वह एक hint हो सकता है। मौजूदा calls और structs का behavior बनाए रखा गया,64suffix वाली नई calls और types जोड़ी गईं, और preprocessor macros से actual reference target चुना जा सकता था, हालांकि सीधे ऐसा करना दुर्लभ थाइसके बजाय OS और SDK versioned थे, और build time पर यह specify किया जा सकता था कि binary को सबसे पुराने किस OS version पर चलना है। headers इसी के आधार पर उचित macros अपने-आप चुनते थे, और नए API/deprecated API annotations भी इसी mechanism से weak links या warnings बनाते थे। शुरू में यह preprocessor से किया गया था, लेकिन अब compiler Apple द्वारा कही जाने वाली API availability को और बारीकी से समझता है, इसलिए दूसरे platforms पर भी यही तरीका संभव दिखता है
OS v.B पर चल रहे होने पर भी, OS v.B को target करके घोषित application X, OS v.A को target करके घोषित application Y से link नहीं कर सकेगा। दरअसल यह तरीका लगभग वही है जो लगभग सभी platforms पहले से करते हैं, और अलग तरीके से करने पर existing binary compatibility तुरंत टूट जाएगी
off_tsize के हिसाब से functions के कई sets define नहीं करेंगी, और client program जिस type size को चाहता है उसके आधार पर सही function set को headers में transparently चुनने वाला कोई switch भी नहीं होगाफिर भी लेख ज़ोर देता है कि
time_t,off_tसे बड़ी समस्या है। इसकी संभावित वजह यह है किtime_tकहीं अधिक व्यापक रूप से फैला हुआ है।off_tअपेक्षाकृत कम interfaces में शामिल POSIX type है, जबकिtime_tISO C का हिस्सा है और जगह-जगह इस्तेमाल होता है। इसके अलावा बहुत-सा C code मानता है किtime_t,intजितनी ही width वाला integer type है, जबकिoff_tके बारे में ऐसी धारणा कम आम हैDebian के लिए भी यह बहुत दर्दनाक था। कुछ लोगों के burnout होने की संभावना है, और कई लोग source-based distribution की ओर इशारा करते हुए कहते थे, “उनके लिए तो यह बहुत आसान होगा”
/usrmerge से कहीं बेहतर दिखाजब भी लोगों को इस तरह की समस्या से जूझते देखता हूँ, तो लगता है कि FreeBSD के शुरुआती amd64 port के समय इस मुद्दे को आगे बढ़ाना वाकई अच्छा फैसला था। हम ABI के basic types तय कर सकते थे, और तय किया कि अतीत से ज़्यादा भविष्य को देखें
amd64 में एक दिलचस्प विशेषता थी जिसने यह काम आसान बना दिया। function call के दौरान 32-bit function arguments अपने-आप 64-bit में cast हो जाते थे, इसलिए 64-bit
time_tकी उम्मीद करने वाले function को 32-bit time integer देने पर भी platform के शुरुआती काम के दौरान ज़्यादातर चीज़ें बस चल जाती थीं। इसलिए छोटी-मोटी finishing बाद के लिए टाली जा सकती थीउस समय दूसरे 64-bit platforms भी थे, लेकिन उनमें 64-bit
time_tनहीं था, और FreeBSD/amd64 करीब 2003~2005 के आसपास उस श्रेणी में पहला था। मेरी याद में sparc64 भी 64-bittime_tपर गया थासबसे बड़ी समस्या यह थी कि उस समय tzcode 64-bit safe नहीं था।
struct tmnormalization algorithm ऐसी degenerate condition में फँस जाता था जहाँ वहtime_t(2^62)के दिन/महीना/साल की बार-बार गणना करने की कोशिश करता था। tzcode में बड़ा बदलाव करने के बजाय, मेरी याद में हमने लगभग 1900 से पहले या 10000 के बाद की dates को fail कर दिया था। अब संभव है कि upstream में यह बहुत पहले ठीक हो चुका होकुछ सालों तक third-party code में files या network की data structures में
int/long/time_tको ढीले-ढाले तरीके से handle करने से पैदा हुए 32/64-bit time confusion को whack-a-mole की तरह ठीक करना पड़ा, लेकिन कुल मिलाकर यह कोई बहुत बड़ी समस्या नहीं थी। पहले दिन से 64-bittime_tइस्तेमाल करने से ज़्यादातर समस्याएँ बच गईं, और शुरुआत से करना आसान था। Linux ने amd64/x86_64 port शुरू करते समय वही काम करने का बड़ा मौका गंवा दियासाथ में, उस समय 64-bit
ino_tपूरा नहीं हो पाया था। 32-bit inode numbers file system on-disk structures, UFS directory structures वगैरह बहुत सारी जगहों पर exposed थे। जब FreeBSD/amd64 lower-tier platform था, तब बाकी tier-1 architectures को बहुत हिलाए बिना इसे शुरू से handle करने का कोई practical तरीका नहीं था। काम दो बार किया गया, लेकिन आखिर किसी और ने इसे finish किया, और mountpoint path length जैसे बहुत छोटे constants भी साथ में ठीक किएtime_t,off_t,ino_tइस्तेमाल किए थे। अभी समस्या 32-bit Linux को 64-bittime_tपर migrate करने की हैoff_tको भी ज़्यादा आक्रामक तरीके से handle किया, इसलिए 2.0 से ही वह 64-bit हो गया। Linux के 32-bit version में अब भी पुराने size के निशान बचे हैंfunction call के दौरान 32-bit arguments अपने-आप 64-bit में cast होते हैं—इस हिस्से को मैं unsigned arguments के लिए ही काम करने वाला समझता हूँ, क्योंकि
%ediमें load करने पर%rdiका upper part clear हो जाता है। x86-64 के लिए SysV ABI spec यह नहीं कहता कि registers या stack की सभी values को पूरे 64-bit value में extend किया जाता है, और boolean पर note भी कहता है कि सिर्फ lower 1 byte meaningful है, जिससे संकेत मिलता है कि यही general rule हैtime_tको भी 64-bit पर port किया था, तो यह काफी चौंकाने वाला है। जानना चाहूँगा कि Motorola 68000 या sparc32 जैसी दूसरी 32-bit architectures भी 64-bittime_tपर गई थीं या नहींपुराने बड़े 32-bit Unix system में future dates handle करने के लिए, signed 32-bit
time_tlibc functions को unsigned 32-bittime_tcompatible functions से बदला था। इससे 2038 के बाद 68 साल और मिल गए, और तब तक मैं तो रहूँगा नहींकमी यह है कि Unix epoch यानी 1970 से पहले की dates represent नहीं की जा सकतीं, लेकिन यह scheduling system था इसलिए समस्या नहीं थी। अगर past dates important हों, तो epoch को कुछ दशक shift किया जा सकता है, या time resolution को 1 second से घटाकर 2 seconds किया जा सकता है। हर approach में subtle समस्याएँ हैं, इसलिए use case पर निर्भर करता है
असली BSD manual page में
tunefsके “Bugs” section में मशहूर मज़ाक था: “You can tune a file system, but you can't tune a fish.”, और “Expert C Programming” के मुताबिक उस manual page source code में उस मज़ाक के पास यह comment था“अगर इसे हटाया, तो UNIX daemon अभी से लेकर
time_tके wrap around होने तक तुम्हारा चार कदम पीछा करेगा।”70 के दशक में जब यह वाक्य लिखा गया था, तब 2038 सचमुच अकल्पनीय रूप से दूर भविष्य रहा होगा
https://progforperf.github.io/Expert_C_Programming.pdf
मेरी सबसे बड़ी takeaway यह है कि effort की कद्र है, लेकिन user के नज़रिए से मैं Debian जैसी non-source-based distribution पर जाकर इस समस्या को खत्म करना चाहूँगा
/और/usrpartitions परmkfs.ext4या जो file system इस्तेमाल करते हों वह चलाएँ, फिर mount करें, stage3 extract करें, chroot में जाएँ औरemerge $all-my-packages-that-where-installed-before-mkfsचलाएँincremental upgrade करने के बजाय Gentoo की नई copy install की जा सकती है
अगर third-party closed-source software है, तो binary system में भी समस्या आ सकती है। अलग step के रूप में separately install किए जाने वाले first-party packages में भी समस्या हो सकती है
मैं C विशेषज्ञ नहीं हूं, लेकिन मुझे लगा था कि
off_tजैसे type alias इसलिए लाए गए थे ताकि उन्हें बाद में बदला जा सके। मगर लगता है कि यह साफ़ तौर पर काम नहीं करता; सोच रहा हूं कि क्या मेरी समझ गलत हैoff_tजैसे typedef का इस्तेमाल करने पर आम तौर पर code फिर से लिखने की जरूरत नहीं पड़ती, लेकिन उस type का इस्तेमाल करने वाली हर चीज़ को फिर से compile करना पड़ता हैoff_tकी definition बदलने के बाद@worldको atomically फिर से build किया जा सके तो समस्या नहीं होगी, लेकिन source-based distributions@worldको atomically rebuild नहीं करतीं, बल्कि packages को एक-एक करके फिर से build करती हैंतब
libc.so64-bitoff_tका इस्तेमाल कर रहा होता है, जबकिgcc32-bitoff_tके आधार पर build हुआ होता है, और इस वजह सेgccरुक सकता है।bash,coreutils,make,binutilsजैसे@worldrebuild के लिए जरूरी packages भी टूट सकते हैं, और उस point पर आप फंस जाते हैं। इसलिए ऐसे upgrades में सावधानी चाहिएoff_tकिसी struct में जाता है, function call में इस्तेमाल होता है, या protocol में integrate होता है, abstraction गायब हो जाता है और असली size मायने रखने लगता हैlibrary load करते समय या protocol से communication करते हुए पुराने और नए code को मिलाने पर offsets गलत हो जाते हैं और crashes शुरू हो जाते हैं। आखिरकार transition के लिए सबको programs को “legacy” और “ported या कम-से-कम reviewed” में बांटना पड़ता है, इसलिए यह बहुत दर्दनाक है
समान semantics वाले बड़े type में बदलने पर भी चीजें टूट सकती हैं। एक सरल उदाहरण struct padding है, और pointer को integer में बदलकर वापस लाने वाले use cases भी बहुत हैं, इसलिए internal representation बदलने पर टूटना तय है। यह अच्छी practice है या नहीं, यह अलग बात है, लेकिन यह दुर्लभ नहीं है। मुख्य बात ABI compatibility है
off_tसे build हुई library और 64-bitoff_tसे build हुई library को link करने से रोके, और नतीजे का behavior बहुत unpredictable हो सकता हैexample struct में कहा गया कि 32-bit
time_tहोने परcका offset 8 है और 64-bit type होने पर 12, लेकिन मुझे लगता है कि असल में यह 16 होना चाहिए, है ना। क्योंकिbको 64-bit aligned होना चाहिए, इसलिएaऔरbके बीच padding आनी चाहिए। बल्कि यह लेखक के तर्क को और मजबूत करता हैयह सब देखकर Windows के अजीब time representation में भी थोड़ा फायदा दिखता है: Gregorian calendar के हिसाब से 1 जनवरी 1601, 00:00 GMT से 100ns units में 64-bit गिनती। Resolution भी शानदार है, और पूरी galaxy conquer हो जाने तक भी यह काम करता रहेगा