.\" -*- coding: UTF-8 -*- .\" Copyright 2014, Michael Kerrisk .\" Copyright, the authors of the Linux man-pages project .\" .\" SPDX-License-Identifier: Linux-man-pages-copyleft .\" .\"******************************************************************* .\" .\" This file was generated with po4a. Translate the source file. .\" .\"******************************************************************* .TH open_by_handle_at 2 "22 فبراير 2026" "صفحات دليل لينكس 6.18" .SH الاسم name_to_handle_at, open_by_handle_at \- الحصول على مقبض لمسار ملف وفتح ملف عبر مقبض .SH المكتبة مكتبة سي المعيارية (\fIlibc\fP،\ \fI\-lc\fP) .SH موجز .nf \fB#define _GNU_SOURCE\fP /* انظر feature_test_macros(7) */ \fB#include \fP .P \fBint name_to_handle_at(int \fP\fIdirfd\fP\fB, const char *\fP\fIpath\fP\fB,\fP \fB struct file_handle *\fP\fIhandle\fP\fB,\fP \fB int *\fP\fImount_id\fP\fB, int \fP\fIflags\fP\fB);\fP \fBint open_by_handle_at(int \fP\fImount_fd\fP\fB, struct file_handle *\fP\fIhandle\fP\fB,\fP \fB int \fP\fIflags\fP\fB);\fP .fi .SH الوصف .\" .\" استدعاءات النظام \fBname_to_handle_at\fP() و \fBopen_by_handle_at\fP() تقسم وظيفة \fBopenat\fP(2) إلى جزئين: يُعيد \fBname_to_handle_at\fP() مقبضًا غير شفاف يتوافق مع ملف محدد؛ ويفتح \fBopen_by_handle_at\fP() الملف المقابل لمقبض أُعيد بواسطة استدعاء سابق لـ \fBname_to_handle_at\fP() ويُعيد واصف ملف مفتوح. .SS name_to_handle_at() يُعيد استدعاء النظام \fBname_to_handle_at\fP() مقبض ملف ومعرف وصل يتوافقان مع الملف المحدد بوسيطي \fIdirfd\fP و \fIpath\fP. يُعاد مقبض الملف عبر الوسيط \fIhandle\fP، وهو مؤشر لبنية بالشكل التالي: .P .in +4n .EX struct file_handle { unsigned int handle_bytes; /* حجم f_handle [مدخل، مخرج] */ int handle_type; /* نوع المقبض [مخرج] */ unsigned char f_handle[0]; /* معرف الملف (حدد حجمه المستدعِي) [مخرج] */ }; .EE .in .P تقع على عاتق المستدعِي مسؤولية تخصيص البنية بحجم كبير كافٍ لاحتواء المقبض المُعاد في \fIf_handle\fP. قبل الاستدعاء، يجب تهيئة الحقل \fIhandle_bytes\fP لاحتواء الحجم المخصص لـ \fIf_handle\fP. (يحدد الثابت \fBMAX_HANDLE_SZ\fP، المُعرّف في \fI\fP، أقصى حجم متوقع لمقبض ملف. ليس حدًا أعلى مضمونًا لأن أنظمة الملفات المستقبلية قد تتطلب مساحة أكبر.) عند النجاح، يُحدّث الحقل \fIhandle_bytes\fP لاحتواء عدد البايتات المكتوبة فعليًا في \fIf_handle\fP. .P يمكن للمستدعِي اكتشاف الحجم المطلوب لبنية \fIfile_handle\fP عبر إجراء استدعاء تكون فيه قيمة \fIhandle\->handle_bytes\fP صفرًا؛ وفي هذه الحالة، يفشل الاستدعاء بالخطأ \fBEOVERFLOW\fP وتُضبط قيمة \fIhandle\->handle_bytes\fP للإشارة إلى الحجم المطلوب؛ يمكن للمستدعِي بعد ذلك استخدام هذه المعلومات لتخصيص بنية بالحجم الصحيح (انظر الأمثلة أدناه). يجب توخي الحذر هنا لأن \fBEOVERFLOW\fP قد يشير أيضًا إلى عدم توفر مقبض ملف لهذا الاسم المعين في نظام ملفات يدعم عادةً البحث عن مقابض الملفات. يمكن اكتشاف هذه الحالة عند إرجاع الخطأ \fBEOVERFLOW\fP دون زيادة \fIhandle_bytes\fP. .P بخلاف استخدام حقل \fIhandle_bytes\fP، يجب على المستدعِي معاملة بنية \fIfile_handle\fP كنوع بيانات غير شفاف: يمكن استخدام حقلي \fIhandle_type\fP و \fIf_handle\fP في استدعاء لاحق لـ \fBopen_by_handle_at\fP(). يمكن للمستدعِي أيضًا استخدام \fIfile_handle\fP غير الشفاف لمقارنة هوية كائنات نظام الملفات التي تم الاستعلام عنها في أوقات مختلفة وربما في مسارات مختلفة. يمكن للنظام الفرعي \fBfanotify\fP(7) الإبلاغ عن الأحداث بسجل معلومات يحتوي على \fIfile_handle\fP لتحديد كائن نظام الملفات. .P الوسيط \fIflags\fP هو قناع بتات يُبنى عبر إجراء عملية OR لصفر أو أكثر من \fBAT_HANDLE_FID\fP و \fBAT_HANDLE_MNT_ID_UNIQUE\fP و \fBAT_HANDLE_CONNECTABLE\fP و \fBAT_EMPTY_PATH\fP و \fBAT_SYMLINK_FOLLOW\fP، الموصوفة أدناه. .P .\" commit 96b2b072ee62be8ae68c8ecf14854c4d0505a8f8 عندما يحتوي \fIflags\fP على علم \fBAT_HANDLE_FID\fP (منذ لينكس 6.5)، يشير المستدعِي إلى أن \fIfile_handle\fP المُعاد مطلوب لتحديد كائن نظام الملفات، وليس لفتح الملف لاحقًا، لذا يُتوقع أن استدعاءً لاحقًا لـ \fBopen_by_handle_at\fP() باستخدام \fIfile_handle\fP المُعاد قد يفشل. .P .\" commit 4356d575ef0f39a3e8e0ce0c40d84ce900ac3b61 عندما يحتوي \fIflags\fP على علم \fBAT_HANDLE_MNT_ID_UNIQUE\fP (منذ لينكس 6.12)، يشير المستدعِي إلى أن عرض المخزن المؤقت \fImount_id\fP هو 64 بت على الأقل، وعندها يكون معرف الوصل المُعاد في ذلك المخزن هو معرف الوصل الفريد مثل ذلك الذي يُعيده \fBstatx\fP(2) مع علم \fBSTATX_MNT_ID_UNIQUE\fP. .P .\" commit a20853ab8296d4a8754482cb5e9adde8ab426a25 عندما يحتوي \fIflags\fP على علم \fBAT_HANDLE_CONNECTABLE\fP (منذ لينكس 6.13)، يشير المستدعِي إلى أن \fIfile_handle\fP المُعاد مطلوب لفتح ملف بمسار معروف لاحقًا، لذا يُتوقع أن استدعاءً لاحقًا لـ \fBopen_by_handle_at\fP() باستخدام \fIfile_handle\fP المُعاد قد يفشل إذا نُقل الملف، ولكن بخلاف ذلك، يُتوقع أن يكون مسار الملف المفتوح مرئيًا من الرابط السحري \fI/proc/\fPpid\fI/fd/\fP*. لا يمكن استخدام هذا العلم مع علمي \fBAT_HANDLE_FID\fP و/أو \fBAT_EMPTY_PATH\fP. .P يحدد وسيطا \fIpath\fP و \fIdirfd\fP معًا الملف المطلوب الحصول على مقبض له. هناك أربع حالات متميزة: .IP \[bu] 3 إذا كان \fIpath\fP سلسلة غير فارغة تحتوي على اسم مسار مطلق، فيُعاد مقبض للملف المشار إليه باسم المسار ذلك. وفي هذه الحالة، يُتجاهل \fIdirfd\fP. .IP \[bu] إذا كان \fIpath\fP سلسلة غير فارغة تحتوي على اسم مسار نسبي وكانت قيمة \fIdirfd\fP هي القيمة الخاصة \fBAT_FDCWD\fP، فيُفسر \fIpath\fP بالنسبة إلى دليل العمل الحالي للمستدعِي، ويُعاد مقبض للملف الذي يشير إليه. .IP \[bu] إذا كان \fIpath\fP سلسلة غير فارغة تحتوي على اسم مسار نسبي وكان \fIdirfd\fP واصف ملف يشير إلى دليل، فيُفسر \fIpath\fP بالنسبة إلى الدليل المشار إليه بواسطة \fIdirfd\fP، ويُعاد مقبض للملف الذي يشير إليه. (انظر \fBopenat\fP(2) لشرح سبب فائدة "واصفات ملفات الدليل".) .IP \[bu] إذا كان \fIpath\fP سلسلة فارغة وحدد \fIflags\fP القيمة \fBAT_EMPTY_PATH\fP، فيمكن أن يكون \fIdirfd\fP واصف ملف مفتوح يشير إلى أي نوع من الملفات، أو \fBAT_FDCWD\fP، بمعنى دليل العمل الحالي، ويُعاد مقبض للملف الذي يشير إليه. .P يُعيد وسيط \fImount_id\fP معرفًا لوصل نظام الملفات الذي يتوافق مع \fIpath\fP. يتوافق هذا مع الحقل الأول في أحد السجلات في \fI/proc/self/mountinfo\fP. ويؤدي فتح اسم المسار في الحقل الخامس من ذلك السجل إلى الحصول على واصف ملف لنقطة الوصل؛ يمكن استخدام واصف الملف هذا في استدعاء لاحق لـ \fBopen_by_handle_at\fP(). يُعاد \fImount_id\fP في حال نجاح الاستدعاء وأيضًا في حال الاستدعاء الذي ينتج عنه الخطأ \fBEOVERFLOW\fP. .P افتراضيًا، لا يتبع \fBname_to_handle_at\fP() المسار \fIpath\fP إذا كان رابطًا رمزيًا، وبالتالي يُعيد مقبضًا للرابط نفسه. إذا حُدد \fBAT_SYMLINK_FOLLOW\fP في \fIflags\fP، فسيُتبع المسار \fIpath\fP إذا كان رابطًا رمزيًا (بحيث يُعيد الاستدعاء مقبضًا للملف الذي يشير إليه الرابط). .P .\" commit 20fa19027286983ab2734b5910c4a687436e0c31 لا يطلق \fBname_to_handle_at\fP() عملية وصل عندما يكون المكون الأخير من اسم المسار نقطة وصل آلي. عندما يدعم نظام ملفات مقابض الملفات ونقاط الوصل الآلي معًا، فإن استدعاء \fBname_to_handle_at\fP() على نقطة وصل آلي سينتهي بالخطأ \fBEOVERFLOW\fP دون زيادة \fIhandle_bytes\fP. يمكن أن يحدث هذا منذ لينكس 4.13 مع NFS عند الوصول إلى دليل موجود على نظام ملفات منفصل على الخادم. في هذه الحالة، يمكن إطلاق الوصل الآلي عبر إضافة "/" إلى نهاية اسم المسار. .SS open_by_handle_at() يفتح استدعاء النظام \fBopen_by_handle_at\fP() الملف المشار إليه بواسطة \fIhandle\fP، وهو مقبض ملف أُعيد بواسطة استدعاء سابق لـ \fBname_to_handle_at\fP(). .P وسيط \fImount_fd\fP هو واصف ملف لأي كائن (ملف، دليل، إلخ) في نظام الملفات الموصول والذي يجب تفسير \fIhandle\fP بالنسبة إليه. يمكن تحديد القيمة الخاصة \fBAT_FDCWD\fP، وتعني دليل العمل الحالي للمستدعِي. .P وسيط \fIflags\fP مماثل لوسيط \fBopen\fP(2). إذا كان \fIhandle\fP يشير إلى رابط رمزي، فيجب على المستدعِي تحديد علم \fBO_PATH\fP، ولا يُتبع الرابط الرمزي؛ ويُتجاهل علم \fBO_NOFOLLOW\fP إذا حُدد. .P يجب أن يمتلك المستدعِي قدرة \fBCAP_DAC_READ_SEARCH\fP لاستدعاء \fBopen_by_handle_at\fP(). .SH "قيمة الإرجاع" عند النجاح، يُعيد \fBname_to_handle_at\fP() القيمة 0، ويُعيد \fBopen_by_handle_at\fP() واصف ملف (عدد صحيح غير سالب). .P في حال حدوث خطأ، يُعيد كلا الاستدعاءين \-1 وتُضبط قيمة \fIerrno\fP للإشارة إلى الخطأ. .SH الأخطاء يمكن أن يفشل \fBname_to_handle_at\fP() و \fBopen_by_handle_at\fP() لنفس أخطاء \fBopenat\fP(2). وبالإضافة إلى ذلك، يمكن أن يفشلا بالأخطاء المذكورة أدناه. .P يمكن أن يفشل \fBname_to_handle_at\fP() بالأخطاء التالية: .TP \fBEFAULT\fP يشير \fIpath\fP أو \fImount_id\fP أو \fIhandle\fP إلى خارج مساحة العنوان القابلة للوصول. .TP \fBEINVAL\fP يتضمن \fIflags\fP قيمة بت غير صالحة أو تركيبة بتات غير صالحة. .TP \fBEINVAL\fP قيمة \fIhandle\->handle_bytes\fP أكبر من \fBMAX_HANDLE_SZ\fP. .TP \fBENOENT\fP المسار \fIpath\fP سلسلة فارغة، ولكن لم يُحدد \fBAT_EMPTY_PATH\fP في \fIflags\fP. .TP \fBENOTDIR\fP واصف الملف المقدم في \fIdirfd\fP لا يشير إلى دليل، وليست هذه هي الحالة التي يتضمن فيها \fIflags\fP العلم \fBAT_EMPTY_PATH\fP ويكون \fIpath\fP سلسلة فارغة. .TP \fBEOPNOTSUPP\fP نظام الملفات لا يدعم فك ترميز اسم مسار إلى مقبض ملف. .TP \fBEOVERFLOW\fP .\" .\" قيمة \fIhandle\->handle_bytes\fP الممررة في الاستدعاء كانت صغيرة جدًا. عند حدوث هذا الخطأ، تُحدث قيمة \fIhandle\->handle_bytes\fP للإشارة إلى الحجم المطلوب للمقبض. .P يمكن أن يفشل \fBopen_by_handle_at\fP() بالأخطاء التالية: .TP \fBEBADF\fP \fImount_fd\fP ليس واصف ملف مفتوح. .TP \fBEBADF\fP المسار \fIpath\fP نسبي ولكن \fIdirfd\fP ليس \fBAT_FDCWD\fP ولا واصف ملف صالح. .TP \fBEFAULT\fP يشير \fIhandle\fP إلى خارج مساحة العنوان القابل للوصول. .TP \fBEINVAL\fP قيمة \fIhandle\->handle_bytes\fP أكبر من \fBMAX_HANDLE_SZ\fP أو تساوي الصفر. .TP \fBELOOP\fP يشير \fIhandle\fP إلى رابط رمزي، ولكن لم يُحدد \fBO_PATH\fP في \fIflags\fP. .TP \fBEPERM\fP المستدعِي لا يملك قدرة \fBCAP_DAC_READ_SEARCH\fP. .TP \fBESTALE\fP قيمة \fIhandle\fP المحددة غير صالحة لفتح ملف. يحدث هذا الخطأ إذا حُذف الملف مثلًا. ويمكن أن يحدث هذا الخطأ أيضًا إذا تم الحصول على \fIhandle\fP باستخدام علم \fBAT_HANDLE_FID\fP ونظام الملفات لا يدعم \fBopen_by_handle_at\fP(). كما يمكن أن يحدث هذا الخطأ إذا تم الحصول على \fIhandle\fP باستخدام علم \fBAT_HANDLE_CONNECTABLE\fP ونُقل الملف إلى أصل مختلف. .SH الإصدارات يحتوي FreeBSD على زوج مشابه إلى حد كبير من استدعاءات النظام في شكل \fBgetfh\fP() و \fBfhopen\fP(). .SH المعايير لينكس. .SH التاريخ لينكس 2.6.39، glibc 2.14. .SH ملاحظات يمكن إنشاء مقبض ملف في عملية واحدة باستخدام \fBname_to_handle_at\fP() واستخدامه لاحقًا في عملية مختلفة تستدعي \fBopen_by_handle_at\fP(). .P بعض أنظمة الملفات لا تدعم ترجمة أسماء المسارات إلى مقابض ملفات، على سبيل المثال، \fI/proc\fP و \fI/sys\fP وأنظمة ملفات شبكية متنوعة. بعض أنظمة الملفات تدعم ترجمة أسماء المسارات إلى مقابض ملفات، لكنها لا تدعم استخدام مقابض الملفات تلك في \fBopen_by_handle_at\fP(). .P قد يصبح مقبض الملف غير صالح ("قديم") إذا تم حذف ملف، أو لأسباب أخرى خاصة بنظام الملفات. يتم الإبلاغ عن المقابض غير الصالحة بواسطة خطأ \fBESTALE\fP من \fBopen_by_handle_at\fP(). .P .\" https://lwn.net/Articles/375888/ .\" "Open by handle" - Jonathan Corbet, 2010-02-23 صُممت استدعاءات النظام هذه لاستخدامها من قبل خوادم الملفات في مساحة المستخدم. على سبيل المثال، قد يُنشئ خادم NFS في مساحة المستخدم مقبض ملف ويمرره إلى عميل NFS. لاحقًا، عندما يريد العميل فتح الملف، يمكنه تمرير المقبض مرة أخرى إلى الخادم. هذا النوع من الوظائف يسمح لخادم الملفات في مساحة المستخدم بالعمل بطريقة عديمة الحالة فيما يتعلق بالملفات التي يخدمها. .P .\" commit bcda76524cd1fa32af748536f27f674a13e56700 إذا كان \fIpath\fP يشير إلى رابط رمزي و \fIflags\fP لا يحدد \fBAT_SYMLINK_FOLLOW\fP، فإن \fBname_to_handle_at\fP() تُرجع مقبضًا للرابط (بدلاً من الملف الذي يشير إليه). يمكن للعملية التي تستلم المقبض لاحقًا تنفيذ عمليات على الرابط الرمزي عن طريق تحويل المقبض إلى واصف ملف باستخدام \fBopen_by_handle_at\fP() مع العلم \fBO_PATH\fP، ثم تمرير واصف الملف كوسيطة \fIdirfd\fP في استدعاءات النظام مثل \fBreadlinkat\fP(2) و \fBfchownat\fP(2). .SS "الحصول على معرف نظام ملفات دائم" يمكن إعادة استخدام معرفات التوصيل في \fI/proc/self/mountinfo\fP عند فصل وتوصيل أنظمة الملفات. لذلك، لا ينبغي التعامل مع معرف التوصيل الذي تُرجعه \fBname_to_handle_at\fP() (في \fI*mount_id\fP) كمعرف دائم لنظام الملفات المُوصَّل المقابل. ومع ذلك، يمكن للتطبيق استخدام المعلومات في سجل \fImountinfo\fP الذي يتوافق مع معرف التوصيل لاستخلاص معرف دائم. .P .\" e.g., http://stackoverflow.com/questions/6748429/using-libblkid-to-find-uuid-of-a-partition على سبيل المثال، يمكن استخدام اسم الجهاز في الحقل الخامس من سجل \fImountinfo\fP للبحث عن UUID الجهاز المقابل عبر الروابط الرمزية في \fI/dev/disks/by\-uuid\fP. (طريقة أكثر راحة للحصول على UUID هي استخدام مكتبة \fBlibblkid\fP(3).) يمكن بعد ذلك عكس تلك العملية، باستخدام UUID للبحث عن اسم الجهاز، ثم الحصول على نقطة التوصيل المقابلة، لإنتاج وسيطة \fImount_fd\fP التي تستخدمها \fBopen_by_handle_at\fP(). .SH أمثلة يوضح البرنامجان أدناه استخدام \fBname_to_handle_at\fP() و \fBopen_by_handle_at\fP(). يستخدم البرنامج الأول (\fIt_name_to_handle_at.c\fP) \fBname_to_handle_at\fP() للحصول على مقبض ملف ومعرف وصل للملف المحدد في وسيط سطر الأوامر؛ ويُكتب المقبض ومعرف الوصل إلى المخرج القياسي. .P يقرأ البرنامج الثاني (\fIt_open_by_handle_at.c\fP) معرف توصيل ومقبض ملف من الإدخال القياسي. ثم يستخدم البرنامج \fBopen_by_handle_at\fP() لفتح الملف باستخدام ذلك المقبض. إذا تم توفير وسيطة اختيارية في سطر الأوامر، فسيتم الحصول على وسيطة \fImount_fd\fP لـ \fBopen_by_handle_at\fP() عن طريق فتح الدليل المسمى في تلك الوسيطة. بخلاف ذلك، يتم الحصول على \fImount_fd\fP عن طريق مسح \fI/proc/self/mountinfo\fP للعثور على سجل يتطابق معرف التوصيل فيه مع معرف التوصيل المقروء من الإدخال القياسي، ويتم فتح دليل التوصيل المحدد في ذلك السجل. (لا تتعامل هذه البرامج مع حقيقة أن معرفات التوصيل ليست دائمة.) .P توضح جلسة الصدفة التالية استخدام هذين البرنامجين: .P .in +4n .EX $\fB echo \[aq]Can you please think about it?\[aq] > cecilia.txt\fP; $\fB ./t_name_to_handle_at cecilia.txt > fh\fP; $\fB ./t_open_by_handle_at < fh\fP; open_by_handle_at: Operation not permitted $\fB sudo ./t_open_by_handle_at < fh\fP; # Need CAP_SYS_ADMIN Read 31 bytes $\fB rm cecilia.txt\fP; .EE .in .P .\" Christoph Hellwig: That's why the file handles contain a generation .\" counter that gets incremented in this case. الآن نحذف الملف ونعيد إنشاءه (بسرعة) بحيث يكون له نفس المحتوى و (بالصدفة) نفس العقدة. ومع ذلك، تتعرف \fBopen_by_handle_at\fP() على أن الملف الأصلي المشار إليه بواسطة مقبض الملف لم يعد موجودًا. .P .in +4n .EX $\fB stat \-\-printf=\[dq]%i\[rs]n\[dq] cecilia.txt\fP; # Display inode number 4072121 $\fB rm cecilia.txt\fP; $\fB echo \[aq]Can you please think about it?\[aq] > cecilia.txt\fP; $\fB stat \-\-printf=\[dq]%i\[rs]n\[dq] cecilia.txt\fP; # Check inode number 4072121 $\fB sudo ./t_open_by_handle_at < fh\fP; open_by_handle_at: Stale NFS file handle .EE .in .SS "مصدر البرنامج: t_name_to_handle_at.c" .\" SRC BEGIN (t_name_to_handle_at.c) \& .EX #define _GNU_SOURCE #include #include #include #include #include \& int main(int argc, char *argv[]) { int mount_id, fhsize, flags, dirfd; char *path; struct file_handle *fhp; \& if (argc != 2) { fprintf(stderr, "Usage: %s path\[rs]n", argv[0]); exit(EXIT_FAILURE); } \& path = argv[1]; \& /* Allocate file_handle structure. */ \& fhsize = sizeof(*fhp); fhp = malloc(fhsize); if (fhp == NULL) err(EXIT_FAILURE, "malloc"); \& /* Make an initial call to name_to_handle_at() to discover the size required for file handle. */ \& dirfd = AT_FDCWD; /* For name_to_handle_at() calls */ flags = 0; /* For name_to_handle_at() calls */ fhp\->handle_bytes = 0; if (name_to_handle_at(dirfd, path, fhp, &mount_id, flags) != \-1 || errno != EOVERFLOW) { fprintf(stderr, "Unexpected result from name_to_handle_at()\[rs]n"); exit(EXIT_FAILURE); } \& /* Reallocate file_handle structure with correct size. */ \& fhsize = sizeof(*fhp) + fhp\->handle_bytes; fhp = realloc(fhp, fhsize); /* Copies fhp\->handle_bytes */ if (fhp == NULL) err(EXIT_FAILURE, "realloc"); \& /* Get file handle from pathname supplied on command line. */ \& if (name_to_handle_at(dirfd, path, fhp, &mount_id, flags) == \-1) err(EXIT_FAILURE, "name_to_handle_at"); \& /* Write mount ID, file handle size, and file handle to stdout, for later reuse by t_open_by_handle_at.c. */ \& printf("%d\[rs]n", mount_id); printf("%u %d ", fhp\->handle_bytes, fhp\->handle_type); for (size_t j = 0; j < fhp\->handle_bytes; j++) printf(" %02x", fhp\->f_handle[j]); printf("\[rs]n"); \& exit(EXIT_SUCCESS); } .EE .\" SRC END .SS "مصدر البرنامج: t_open_by_handle_at.c" .\" SRC BEGIN (t_open_by_handle_at.c) \& .EX #define _GNU_SOURCE #include #include #include #include #include #include #include #include \& #define streq(...) (strcmp(__VA_ARGS__) == 0) \& /* Scan /proc/self/mountinfo to find the line whose mount ID matches \[aq]mount_id\[aq]. (An easier way to do this is to install and use the \[aq]libmount\[aq] library provided by the \[aq]util\-linux\[aq] project.) Open the corresponding mount path and return the resulting file descriptor. */ \& static int open_mount_path_by_id(int mount_id) { int mi_mount_id, found; char mount_path[PATH_MAX]; char *linep; FILE *fp; size_t lsize; ssize_t nread; \& fp = fopen("/proc/self/mountinfo", "r"); if (fp == NULL) err(EXIT_FAILURE, "fopen"); \& found = 0; linep = NULL; while (!found) { nread = getline(&linep, &lsize, fp); if (nread == \-1) break; \& nread = sscanf(linep, "%d %*d %*s %*s %s", &mi_mount_id, mount_path); if (nread != 2) { fprintf(stderr, "Bad sscanf()\[rs]n"); exit(EXIT_FAILURE); } \& if (mi_mount_id == mount_id) found = 1; } free(linep); \& fclose(fp); \& if (!found) { fprintf(stderr, "Could not find mount point\[rs]n"); exit(EXIT_FAILURE); } \& return open(mount_path, O_RDONLY); } \& int main(int argc, char *argv[]) { int mount_id, fd, mount_fd, handle_bytes; char buf[1000]; #define LINE_SIZE 100 char line1[LINE_SIZE], line2[LINE_SIZE]; char *nextp; ssize_t nread; struct file_handle *fhp; \& if ((argc > 1 && streq(argv[1], "\-\-help")) || argc > 2) { fprintf(stderr, "Usage: %s [mount\-path]\[rs]n", argv[0]); exit(EXIT_FAILURE); } \& /* Standard input contains mount ID and file handle information: \& Line 1: Line 2: */ \& if (fgets(line1, sizeof(line1), stdin) == NULL || fgets(line2, sizeof(line2), stdin) == NULL) { fprintf(stderr, "Missing mount_id / file handle\[rs]n"); exit(EXIT_FAILURE); } \& mount_id = atoi(line1); \& handle_bytes = strtoul(line2, &nextp, 0); \& /* Given handle_bytes, we can now allocate file_handle structure. */ \& fhp = malloc(sizeof(*fhp) + handle_bytes); if (fhp == NULL) err(EXIT_FAILURE, "malloc"); \& fhp\->handle_bytes = handle_bytes; \& fhp\->handle_type = strtoul(nextp, &nextp, 0); \& for (size_t j = 0; j < fhp\->handle_bytes; j++) fhp\->f_handle[j] = strtoul(nextp, &nextp, 16); \& /* Obtain file descriptor for mount point, either by opening the pathname specified on the command line, or by scanning /proc/self/mounts to find a mount that matches the \[aq]mount_id\[aq] that we received from stdin. */ \& if (argc > 1) mount_fd = open(argv[1], O_RDONLY); else mount_fd = open_mount_path_by_id(mount_id); \& if (mount_fd == \-1) err(EXIT_FAILURE, "opening mount fd"); \& /* Open file using handle and mount point. */ \& fd = open_by_handle_at(mount_fd, fhp, O_RDONLY); if (fd == \-1) err(EXIT_FAILURE, "open_by_handle_at"); \& /* Try reading a few bytes from the file. */ \& nread = read(fd, buf, sizeof(buf)); if (nread == \-1) err(EXIT_FAILURE, "read"); \& printf("Read %zd bytes\[rs]n", nread); \& exit(EXIT_SUCCESS); } .EE .\" SRC END .SH "انظر أيضًا" \fBopen\fP(2)،‏ \fBlibblkid\fP(3)،‏ \fBblkid\fP(8)،‏ \fBfindfs\fP(8)،‏ \fBmount\fP(8) .P وثائق \fIlibblkid\fP و \fIlibmount\fP في أحدث إصدار من \fIutil\-linux\fP على .UR https:\://www.kernel.org/pub/linux/utils/util\-linux/ .UE .PP .SH ترجمة تُرجمت هذه الصفحة من الدليل بواسطة زايد السعيدي . .PP هذه الترجمة هي وثيقة مجانية؛ راجع .UR https://www.gnu.org/licenses/gpl-3.0.html رخصة جنو العامة الإصدار 3 .UE أو ما بعده للاطلاع على شروط حقوق النشر. لا توجد أي ضمانات. .PP إذا وجدت أي أخطاء في ترجمة صفحة الدليل هذه، يرجى إرسال بريد إلكتروني إلى قائمة بريد المترجمين: .MT kde-l10n-ar@kde.org .ME .