Scroll to navigation

fanotify(7) Miscellaneous Information Manual fanotify(7)

الاسم

fanotify - مراقبة أحداث نظام الملفات

الوصف

توفر واجهة برمجة تطبيقات fanotify إشعارات واعتراضًا لأحداث نظام الملفات. تشمل حالات الاستخدام فحص الفيروسات وإدارة التخزين الهرمي. في واجهة fanotify الأصلية، دُعمت مجموعة محدودة فقط من الأحداث. على وجه الخصوص، لم يتوفر دعم لأحداث الإنشاء والحذف والنقل. أُضيف الدعم لهذه الأحداث في لينكس 5.1. (انظر inotify(7) لتفاصيل واجهة برمجة التطبيقات التي كانت تُشعر بتلك الأحداث قبل إصدار لينكس 5.1.)

تشمل القدرات الإضافية مقارنة بواجهة inotify(7) القدرة على مراقبة جميع الكائنات في نظام ملفات موصول، والقدرة على اتخاذ قرارات أذونات الوصول، وإمكانية قراءة الملفات أو تعديلها قبل وصول التطبيقات الأخرى إليها.

تُستخدم استدعاءات النظام التالية مع هذه الواجهة: fanotify_init(2)، و fanotify_mark(2)، و read(2)، و write(2)، و close(2).

fanotify_init()‎، و fanotify_mark()‎، ومجموعات الإشعارات

يُنشئ استدعاء النظام fanotify_init(2) مجموعة إشعارات fanotify ويُهيئها ويعيد واصف ملف يشير إليها.

مجموعة إشعارات fanotify هي كائن داخلي في النواة يحمل قائمة بالملفات، والأدلة، وأنظمة الملفات، والوصولات التي يجب إنشاء أحداث لها.

لكل مدخلة في مجموعة إشعارات fanotify، يوجد قناعان من البتات: قناع mark وقناع ignore. يحدد قناع العلامة (mark) أنشطة الملفات التي يجب إنشاء حدث لها. ويحدد قناع التجاهل (ignore) الأنشطة التي لا يجب توليد أحداث لها. يسمح وجود هذين النوعين من الأقنعة بوسم نظام ملفات أو وصلة أو دليل لاستلام الأحداث، وفي الوقت نفسه تجاهل الأحداث لكائنات محددة تحت تلك الوصلة أو الدليل.

يضيف استدعاء النظام fanotify_mark(2) ملفًا أو دليلاً أو نظام ملفات أو وصلة إلى مجموعة إشعارات ويحدد الأحداث التي يجب الإبلاغ عنها (أو تجاهلها)، أو يزيل أو يعدل مثل هذه المدخلة.

من الاستخدامات الممكنة لقناع التجاهل هي خبيئة الملفات. الأحداث المهمة لخبيئة الملفات هي تعديل الملف وإغلاقه. لذا، يوسم الدليل أو الوصلة المخبأة لاستلام هذه الأحداث. بعد استلام أول حدث يفيد بتعديل ملف ما، ستُبطل مدخلة الخبيئة المقابلة. لا تهم أي أحداث تعديل إضافية لهذا الملف حتى يُغلق. لذا، يمكن إضافة حدث التعديل إلى قناع التجاهل. وعند استلام حدث الإغلاق، يمكن إزالة حدث التعديل من قناع التجاهل وتحديث مدخلة خبيئة الملف.

تشير المدخلات في مجموعات إشعارات fanotify إلى الملفات والأدلة عبر رقم inode الخاص بها وإلى الوصلات عبر معرف الوصلة (mount ID). إذا أُعيدت تسمية الملفات أو الأدلة أو نُقلت ضمن نفس الوصلة، فإن المدخلات المعنية تبقى. أما إذا حُذفت الملفات أو الأدلة أو نُقلت إلى وصلة أخرى أو إذا فُصلت أنظمة الملفات أو الوصلات، فستُحذف المدخلات المقابلة.

طابور الأحداث

عند وقوع أحداث على كائنات نظام الملفات المراقبة بواسطة مجموعة إشعارات، يولد نظام fanotify أحداثًا تُجمع في طابور. يمكن بعد ذلك قراءة هذه الأحداث (باستخدام read(2) أو ما شابه) من واصف ملف fanotify الذي أعاده fanotify_init(2).

يولَّد نوعان من الأحداث: أحداث إشعار وأحداث إذن. أحداث الإشعار هي معلوماتية فقط ولا تتطلب اتخاذ أي إجراء من قبل التطبيق المستلم باستثناء حالة واحدة: إذا وُفر واصف ملف صالح ضمن حدث عام، فيجب إغلاق واصف الملف هذا. أحداث الإذن هي طلبات للتطبيق المستلم ليقرر ما إذا كان سيُمنح إذن للوصول إلى الملف أم لا. بالنسبة لهذه الأحداث، يجب على المستلم كتابة رد يقرر ما إذا كان سيُسمح بالوصول أم لا.

يُزال الحدث من طابور أحداث مجموعة fanotify عند قراءته. أحداث الإذن التي قُرئت تُحفظ في قائمة داخلية لمجموعة fanotify حتى يتم اتخاذ قرار بشأن الإذن عن طريق الكتابة إلى واصف ملف fanotify أو حتى يُغلق واصف ملف fanotify.

قراءة أحداث fanotify

استدعاء read(2) لواصف الملف الذي أعاده fanotify_init(2) يحجب (إذا لم يُحدد علم FAN_NONBLOCK في استدعاء fanotify_init(2)) حتى يقع حدث ملف أو يُقاطع الاستدعاء بإشارة (انظر signal(7)).

بعد نجاح read(2)، ستحتوي مخبأة القراءة على بنية واحدة أو أكثر من البنى التالية:


struct fanotify_event_metadata {

__u32 event_len;
__u8 vers;
__u8 reserved;
__u16 metadata_len;
__aligned_u64 mask;
__s32 fd;
__s32 pid; };

سجلات المعلومات هي قطع تكميلية من المعلومات التي قد تُوفر جنباً إلى جنب مع بنية fanotify_event_metadata العامة. تؤثر الـ flags الممررة إلى fanotify_init(2) على نوع سجلات المعلومات التي قد تُعاد لحدث ما. على سبيل المثال، إذا هُيئت مجموعة إشعارات باستخدام FAN_REPORT_FID أو FAN_REPORT_DIR_FID، فيجب على مستمعي الأحداث توقع استلام بنية fanotify_event_info_fid مع بنية fanotify_event_metadata، حيث تُستخدم مقابض الملفات لتحديد كائنات نظام الملفات بدلاً من واصفات الملفات. يمكن أيضاً تكديم سجلات المعلومات، مما يعني أن استخدام أعلام FAN_REPORT_* المتنوعة مع بعضها البعض أمر مدعوم. في هذه الحالات، يمكن إعادة سجلات معلومات متعددة لحدث ما. على سبيل المثال، إذا هُيئت مجموعة إشعارات باستخدام FAN_REPORT_TARGET_FID و FAN_REPORT_PIDFD، فيجب على مستمع الأحداث توقع استلام ما يصل إلى سجلي معلومات fanotify_event_info_fid وسجل معلومات fanotify_event_info_pidfd واحد. والأهم من ذلك، لا يوفر fanotify أي ضمانات حول ترتيب سجلات المعلومات عند تهيئة مجموعة إشعارات بتكوين مكدس. لكل سجل معلومات بنية متداخلة من نوع fanotify_event_info_header. من الضروري لمستمعي الأحداث فحص حقل info_type في هذه البنية لتحديد نوع سجل المعلومات الذي استُلم لحدث معين.

في الحالات التي تحدد فيها مجموعة fanotify كائنات نظام الملفات عن طريق مقابض الملفات، يجب على مستمعي الأحداث أيضاً توقع استلام واحد أو أكثر من كائنات سجل المعلومات أدناه مع بنية fanotify_event_metadata العامة داخل مخبأة القراءة:


struct fanotify_event_info_fid {

struct fanotify_event_info_header hdr;
__kernel_fsid_t fsid;
unsigned char handle[]; };

في الحالات التي تُهيأ فيها مجموعة fanotify باستخدام FAN_REPORT_PIDFD، يجب على مستمعي الأحداث توقع استلام كائن سجل المعلومات أدناه مع بنية fanotify_event_metadata العامة داخل مخبأة القراءة:


struct fanotify_event_info_pidfd {

struct fanotify_event_info_header hdr;
__s32 pidfd; };

في الحالات التي تُهيأ فيها مجموعة fanotify باستخدام FAN_REPORT_MNT، يجب على مستمعي الأحداث توقع استلام كائن سجل المعلومات أدناه مع بنية fanotify_event_metadata العامة داخل مخبأة القراءة. تُعرف هذه البنية كالتالي:


struct fanotify_event_info_mnt {

struct fanotify_event_info_header hdr;
__u64 mnt_id; };

في حالة حدث FAN_FS_ERROR، يُعاد سجل معلومات إضافي يصف الخطأ الذي حدث مع بنية fanotify_event_metadata العامة داخل مخبأة القراءة. تُعرف هذه البنية كالتالي:


struct fanotify_event_info_error {

struct fanotify_event_info_header hdr;
__s32 error;
__u32 error_count; };

في حالة أحداث FAN_PRE_ACCESS، يُعاد سجل معلومات إضافي يصف نطاق الوصول مع بنية fanotify_event_metadata العامة داخل مخبأة القراءة. تُعرف هذه البنية كالتالي:


struct fanotify_event_info_range {

struct fanotify_event_info_header hdr;
__u32 pad;
__u64 offset;
__u64 count; };

تحتوي جميع سجلات المعلومات على بنية متداخلة من نوع fanotify_event_info_header. تحمل هذه البنية معلومات وصفية حول سجل المعلومات الذي قد يكون قد أعيد مع بنية fanotify_event_metadata العامة. تُعرف هذه البنية كالتالي:


struct fanotify_event_info_header {
	__u8 info_type;
	__u8 pad;
	__u16 len;
};

لأسباب تتعلق بالأداء، يوصى باستخدام حجم مخبأة كبير (على سبيل المثال، 4096 بايت)، بحيث يمكن جلب أحداث متعددة من خلال استدعاء read(2) واحد.

قيمة الإرجاع لـ read(2) هي عدد البايتات التي وُضعت في المخبأة، أو -1 في حالة حدوث خطأ (لكن انظر قسم BUGS).

حقول بنية fanotify_event_metadata هي كما يلي:

هذا هو حجم بيانات الحدث الحالي والإزاحة إلى الحدث التالي في المخبأة. ما لم تحدد المجموعة كائنات نظام الملفات عن طريق مقابض الملفات، فإن قيمة event_len هي دائماً FAN_EVENT_METADATA_LEN. بالنسبة للمجموعة التي تحدد كائنات نظام الملفات عن طريق مقابض الملفات، فإن event_len يشمل أيضاً سجلات معرف الملف ذات الحجم المتغير.
يحمل هذا الحقل رقم إصدار البنية. يجب مقارنته بـ FANOTIFY_METADATA_VERSION للتحقق من أن البنى التي أُعيدت في وقت التشغيل تطابق البنى المحددة في وقت التصريف. في حالة عدم التطابق، يجب على التطبيق التخلي عن محاولة استخدام واصف ملف fanotify.
هذا الحقل غير مستخدم.
هذا هو حجم البنية. قُدم هذا الحقل لتسهيل تنفيذ ترويسات اختيارية لكل نوع حدث. لا توجد مثل هذه الترويسات الاختيارية في التنفيذ الحالي.
هذا قناع بتات يصف الحدث (انظر أدناه).
هذا واصف ملف مفتوح للكائن الذي يتم الوصول إليه، أو FAN_NOFD في حالة حدوث طوفان في الطابور. مع مجموعة fanotify التي تحدد كائنات نظام الملفات عن طريق مقابض الملفات، يجب أن تتوقع التطبيقات ضبط هذه القيمة على FAN_NOFD لكل حدث يُستلم. يمكن استخدام واصف الملف للوصول إلى محتويات الملف أو الدليل المراقب. التطبيق القارئ مسؤول عن إغلاق واصف الملف هذا.
عند استدعاء fanotify_init(2)، قد يحدد المستدعِي (عبر وسيط event_f_flags) أعلام حالة ملف متنوعة ليتم ضبطها على وصف الملف المفتوح الذي يقابل واصف الملف هذا. بالإضافة إلى ذلك، يُضبط علم حالة الملف FMODE_NONOTIFY (الداخلي للنواة) على وصف الملف المفتوح. هذا العلم يكبح توليد أحداث fanotify. ومن ثم، عندما يصل مستلم حدث fanotify إلى الملف أو الدليل المُشعر به باستخدام واصف الملف هذا، لن تُنشأ أي أحداث إضافية.
عند تهيئة مجموعة fanotify باستخدام FAN_REPORT_FD_ERROR، سيحتوي هذا الحقل على قيمة خطأ سالبة في حالة تعذر فتح واصف ملف، وفي حالة طوفان الطابور، ستكون القيمة -EBADF.
إذا ضُبط العلم FAN_REPORT_TID في fanotify_init(2)، فهذا هو معرف الخيط (TID) للخيط الذي تسبب في الحدث. وإلا، فهذا هو معرف العملية (PID) للعملية التي تسببت في الحدث.

يمكن لبرنامج يستمع إلى أحداث fanotify مقارنة معرف العملية (PID) هذا بالمعرف الذي يعيده getpid(2)، لتحديد ما إذا كان الحدث ناتجاً عن المستمع نفسه، أو بسبب وصول لملف من قبل عملية أخرى.

يشير قناع البتات في mask إلى الأحداث التي وقعت لكائن نظام ملفات واحد. قد تُضبط بتات متعددة في هذا القناع إذا وقع أكثر من حدث لكائن نظام الملفات المراقب. على وجه الخصوص، قد تُدمج الأحداث المتتالية لنفس كائن نظام الملفات والناتجة عن نفس العملية في حدث واحد، باستثناء أحداث الإذن حيث لا تُدمج أبداً في مدخلة طابور واحدة.

البتات التي قد تظهر في mask هي كما يلي:

وُصل إلى ملف أو دليل (قراءة) (لكن انظر قسم BUGS).
فُتح ملف أو دليل.
فُتح ملف بقصد تنفيذه. انظر قسم NOTES في fanotify_mark(2) لمزيد من التفاصيل.
غُيرت البيانات الوصفية لملف أو دليل.
أُنشئ ملف أو دليل ابن في دليل أب مراقب.
حُذف ملف أو دليل ابن في دليل أب مراقب.
حُذف ملف أو دليل مراقب.
نُقل ملف أو دليل من أو إلى دليل أب مراقب.
نُقل ملف أو دليل من دليل أب مراقب.
نُقل ملف أو دليل إلى دليل أب مراقب.
نُقل ملف أو دليل مراقب.
عُدل ملف.
أُغلق ملف كان مفتوحاً للكتابة (O_WRONLY أو O_RDWR).
أُغلق ملف أو دليل كان مفتوحاً للقراءة فقط (O_RDONLY).
وُصلت وصلة بمساحة أسماء الوصل.
فُصلت وصلة من مساحة أسماء الوصل.
كُشف عن خطأ في نظام الملفات.
تجاوز طابور الأحداث الحد المسموح به لعدد الأحداث. يمكن تخطي هذا الحد عن طريق تحديد علم FAN_UNLIMITED_QUEUE عند استدعاء fanotify_init(2).
يريد تطبيق قراءة ملف أو دليل، على سبيل المثال باستخدام read(2) أو readdir(2). يجب على القارئ كتابة رد (كما هو موضح أدناه) يحدد ما إذا كان سيُمنح إذن للوصول إلى كائن نظام الملفات.
يريد تطبيق فتح ملف أو دليل. يجب على القارئ كتابة رد يحدد ما إذا كان سيُمنح إذن لفتح كائن نظام الملفات.
يريد تطبيق ما فتح ملف للتنفيذ. يجب على القارئ كتابة استجابة تحدد ما إذا كان سيُمنح إذن فتح كائن نظام الملفات للتنفيذ. راجع الملاحظات (NOTES) في fanotify_mark(2) لمزيد من التفاصيل.

للتحقق من أي حدث إغلاق، يمكن استخدام قناع البتات التالي:

أُغلق ملف. هذا مرادف لـ:

FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE
    

للتحقق من أي حدث نقل، يمكن استخدام قناع البتات التالي:

نُقل ملف أو دليل. هذا مرادف لـ:

FAN_MOVED_FROM | FAN_MOVED_TO
    

قد تظهر البتات التالية في mask فقط بالاقتران مع بتات أنواع أحداث أخرى:

الأحداث الموضحة في mask وقعت على كائن دليل. يتطلب الإبلاغ عن الأحداث في الأدلة ضبط هذه الراية في قناع العلامة. راجع fanotify_mark(2) لمزيد من التفاصيل. يُبلغ عن الراية FAN_ONDIR في قناع الحدث فقط إذا كانت مجموعة fanotify تحدد كائنات نظام الملفات عن طريق مقابض الملفات.

سجلات المعلومات التي تُوفر جنباً إلى جنب مع هيكل fanotify_event_metadata العام ستحتوي دائماً على هيكل متداخل من نوع fanotify_event_info_header. حقول fanotify_event_info_header هي كما يلي:

قيمة عددية فريدة تمثل نوع كائن سجل المعلومات المُستلم لحدث ما. يمكن ضبط قيمة هذا الحقل على أحد الخيارات التالية.
تعتمد القيمة المضبوطة لهذا الحقل على الرايات التي تم تزويدها لـ fanotify_init(2). ارجع إلى تفاصيل الحقول لكل نوع كائن سجل معلومات أدناه لفهم الحالات المختلفة التي يمكن فيها ضبط قيم info_type.
هذا الحقل غير مُستخدم حالياً من قبل أي نوع كائن سجل معلومات، ولذلك يُضبط على الصفر.
تُضبط قيمة len على حجم كائن سجل المعلومات، بما في ذلك fanotify_event_info_header. لا يُتوقع أن يكون الحجم الإجمالي لجميع سجلات المعلومات الإضافية أكبر من (event_len - metadata_len).

حقول هيكل fanotify_event_info_fid هي كما يلي:

هذا هيكل من نوع fanotify_event_info_header. على سبيل المثال، عندما يُنشأ واصف ملف fanotify باستخدام FAN_REPORT_FID، يُتوقع إرفاق سجل معلومات واحد بالحدث مع قيمة حقل info_type هي FAN_EVENT_INFO_TYPE_FID. عندما يُنشأ واصف ملف fanotify باستخدام مزيج من FAN_REPORT_FID و FAN_REPORT_DIR_FID، قد يكون هناك سجلان للمعلومات مرفقان بالحدث: أحدهما بقيمة حقل info_type هي FAN_EVENT_INFO_TYPE_DFID، للتعريف بكائن دليل أب، والآخر بقيمة حقل info_type هي FAN_EVENT_INFO_TYPE_FID، للتعريف بكائن ابن. لاحظ أنه بالنسبة لأحداث تعديل مدخلات الدليل FAN_CREATE و FAN_DELETE و FAN_MOVE و FAN_RENAME، لا يُبلغ عن سجل معلومات يحدد الكائن الابن المنشأ/المحذوف/المنقول إلا إذا بُدئت مجموعة fanotify باستخدام الراية FAN_REPORT_TARGET_FID.
هذا معرف فريد لنظام الملفات الذي يحتوي على الكائن المرتبط بالحدث. هو هيكل من نوع __kernel_fsid_t ويحتوي على نفس قيمة f_fsid عند استدعاء statfs(2). لاحظ أن بعض أنظمة الملفات (مثل fuse(4)) تبلغ عن fsid بصفر. في هذه الحالات، لا يمكن استخدام fsid لربط الحدث بمثيل معين لنظام الملفات، لذا فإن مراقبة مثيلات أنظمة ملفات مختلفة تبلغ عن fsid بصفر باستخدام نفس مجموعة fanotify غير مدعومة.
يحتوي هذا الحقل على هيكل متغير الحجم من نوع struct file_handle. هو مقبض مبهم يتوافق مع كائن محدد في نظام ملفات كما يعيده name_to_handle_at(2). يمكن استخدامه لتعريف ملف بشكل فريد في نظام ملفات ويمكن تمريره كمعامل لـ open_by_handle_at(2). إذا كانت قيمة حقل info_type هي FAN_EVENT_INFO_TYPE_DFID_NAME، يتبع مقبض الملف سلسلة نصية منتهية بصفر تحدد اسم مدخل الدليل المنشأ/المحذوف/المنقول. بالنسبة للأحداث الأخرى مثل FAN_OPEN و FAN_ATTRIB و FAN_DELETE_SELF و FAN_MOVE_SELF، إذا كانت قيمة حقل info_type هي FAN_EVENT_INFO_TYPE_FID، فإن handle يحدد الكائن المرتبط بالحدث. إذا كانت قيمة حقل info_type هي FAN_EVENT_INFO_TYPE_DFID، فإن handle يحدد كائن الدليل المرتبط بالحدث أو الدليل الأب لكائن ليس دليلاً ومرتبط بالحدث. إذا كانت قيمة حقل info_type هي FAN_EVENT_INFO_TYPE_DFID_NAME، فإن handle يحدد نفس كائن الدليل الذي سيُبلغ عنه باستخدام FAN_EVENT_INFO_TYPE_DFID، ويتبع مقبض الملف سلسلة نصية منتهية بصفر تحدد اسم مدخل الدليل في ذلك الدليل، أو '.' لتعريف كائن الدليل نفسه.

حقول هيكل fanotify_event_info_pidfd هي كما يلي:

هذا هيكل من نوع fanotify_event_info_header. عندما تُبدأ مجموعة fanotify باستخدام FAN_REPORT_PIDFD، تُضبط قيمة حقل info_type في fanotify_event_info_header على FAN_EVENT_INFO_TYPE_PIDFD.
هذا واصف ملف عملية يشير إلى العملية المسؤولة عن توليد الحدث. واصف ملف العملية المُعاد لا يختلف عن ذلك الذي يمكن الحصول عليه يدوياً إذا استدعي pidfd_open(2) على fanotify_event_metadata.pid. في حالة مواجهة خطأ أثناء إنشاء pidfd، قد يُعاد أحد نوعي أخطاء محتملين ممثلين بقيمة صحيحة سالبة في حقل pidfd هذا. في الحالات التي تنتهي فيها العملية المسؤولة عن توليد الحدث قبل أن يتمكن مستمع الأحداث من قراءة الأحداث من طابور الإشعارات، يُعاد FAN_NOPIDFD. يُنفذ إنشاء pidfd للحدث فقط في وقت قراءة الأحداث من طابور الإشعارات. تُمثل جميع إخفاقات إنشاء pidfd المحتملة الأخرى بـ FAN_EPIDFD. بمجرد أن يتعامل مستمع الحدث مع الحدث ولم يعد الـ pidfd مطلوباً، يجب إغلاق الـ pidfd عبر close(2).
عند بدء مجموعة fanotify باستخدام FAN_REPORT_FD_ERROR، سيحتوي هذا الحقل على قيمة خطأ سالبة في حالة فشل إنشاء pidfd وفي حالة العملية المنتهية، ستكون القيمة -ESRCH.

حقول هيكل fanotify_event_info_mnt هي كما يلي:

.hdr
هذا هيكل من نوع fanotify_event_info_header. يُضبط حقل .info_type على FAN_EVENT_INFO_TYPE_MNT.
.mnt_id
يحدد الوصل المرتبط بالحدث. هو معرف وصل فريد 64-بت كالذي يعيده statx(2) مع الراية STATX_MNT_ID_UNIQUE.

حقول هيكل fanotify_event_info_error هي كما يلي:

هذا هيكل من نوع fanotify_event_info_header. يُضبط حقل info_type على FAN_EVENT_INFO_TYPE_ERROR.
يحدد نوع الخطأ الذي حدث.
هذا عداد لعدد الأخطاء التي كُتمت منذ آخر قراءة للخطأ.

حقول هيكل fanotify_event_info_range هي كما يلي:

هذا هيكل من نوع fanotify_event_info_header. يُضبط حقل info_type على FAN_EVENT_INFO_TYPE_RANGE.
عدد البايتات التي تُقرأ أو تُكتب في الملف.
الإزاحة التي تُقرأ منها أو تُكتب فيها البايتات في الملف.

تتوفر وحدات الماكرو التالية للتكرار عبر مخزن يحتوي على بيانات وصفية لأحداث fanotify أعادها read(2) من واصف ملف fanotify:

يتحقق هذا الماكرو من الحجم المتبقي size للمخزن meta مقابل حجم هيكل البيانات الوصفية وحقل event_len لأول هيكل بيانات وصفية في المخزن.
يستخدم هذا الماكرو الحجم المشار إليه في حقل event_len لهيكل البيانات الوصفية الذي يشير إليه meta لحساب عنوان هيكل البيانات الوصفية التالي الذي يلي meta. يمثل size عدد بايتات البيانات الوصفية المتبقية حالياً في المخزن. يعيد الماكرو مؤشراً إلى هيكل البيانات الوصفية التالي الذي يلي meta، ويقلل size بمقدار عدد البايتات في هيكل البيانات الوصفية الذي تُخطي (أي يطرح meta->event_len من size).

بالإضافة إلى ذلك، هناك:

يعيد هذا الماكرو حجم (بالبايتات) الهيكل fanotify_event_metadata. هذا هو الحد الأدنى للحجم (والحجم الوحيد حالياً) لأي بيانات وصفية للحدث.

مراقبة واصف ملف fanotify بحثاً عن أحداث

عند وقوع حدث fanotify، يشير واصف ملف fanotify إلى أنه قابل للقراءة عند تمريره إلى epoll(7) أو poll(2) أو select(2).

التعامل مع أحداث الأذونات

بالنسبة لأحداث الأذونات، يجب على التطبيق استدعاء write(2) لهيكل بالشكل التالي في واصف ملف fanotify:


struct fanotify_response {

__s32 fd;
__u32 response; };

حقول هذا الهيكل هي كالتالي:

هذا هو واصف الملف من الهيكل fanotify_event_metadata.
يشير هذا الحقل إلى ما إذا كان سيُمنح الإذن أم لا. يجب أن تحتوي قيمته إما على الراية FAN_ALLOW للسماح بعملية الملف أو FAN_DENY لرفضها.

إذا رُفض الوصول، سيتلقى استدعاء التطبيق الطالب خطأ EPERM. منذ لينكس 6.13، إذا بُدئت مجموعة إشعارات بالفئة FAN_CLASS_PRE_CONTENT، يمكن رفض عملية الملف بأخطاء غير EPERM. على سبيل المثال، لكي يحصل التطبيق الطالب على خطأ EIO، يمكن لمستمع الحدث كتابة الاستجابة FAN_DENY_ERRNO(EIO). في وقت الكتابة، يمكن إعادة قيم الأخطاء التالية فقط إلى التطبيق باستخدام ماكرو FAN_DENY_ERRNO(e): EPERM و EIO و EBUSY و ETXTBSY و EAGAIN و ENOSPC و EDQUOT.

بالإضافة إلى ذلك، إذا أُنشئت مجموعة الإشعارات مع الراية FAN_ENABLE_AUDIT، فيمكن حينئذٍ ضبط الراية FAN_AUDIT في حقل response. في هذه الحالة، سيقوم نظام التدقيق الفرعي بتسجيل معلومات حول قرار الوصول في سجلات التدقيق.

منذ لينكس 6.3، يمكن ضبط الراية FAN_INFO في حقل .response. تشير هذه الراية إلى أن سجل استجابة إضافي متغير الطول يتبع هيكل fanotify_response. تبدأ سجلات الاستجابة الإضافية بترويسة مشتركة:


struct fanotify_response_info_header {

__u8 type;
__u8 pad;
__u16 len; };

تحدد قيمة .type تنسيق سجل الاستجابة الإضافي.

يُتوقع سجل الاستجابة التالي مع تفاصيل إضافية لسجل التدقيق:

struct fanotify_response_info_audit_rule {

struct fanotify_response_info_header hdr;
__u32 rule_number;
__u32 subj_trust;
__u32 obj_trust; };

مراقبة أنظمة الملفات بحثاً عن أخطاء

يُخزن حدث FAN_FS_ERROR واحد لكل نظام ملفات في المرة الواحدة. تُكتم رسائل الأخطاء الإضافية وتُحسب في حقل error_count لسجل حدث FAN_FS_ERROR الموجود، ولكن تُفقد تفاصيل تلك الأخطاء.

الأخطاء التي يبلغ عنها FAN_FS_ERROR هي قيم errno عامة، ولكن لا يُبلغ عن جميع أنواع الأخطاء من قبل جميع أنظمة الملفات.

الأخطاء غير المرتبطة مباشرة بملف (أي تلف الكتلة الفائقة) يُبلغ عنها بـ handle غير صالح. لهذه الأخطاء، سيُضبط حقل handle_type في handle على FILEID_INVALID، ويُضبط حجم مخزن المقبض على 0.

إغلاق واصف ملف fanotify

عند إغلاق جميع واصفات الملفات التي تشير إلى مجموعة إشعارات fanotify، تُحرر مجموعة fanotify وتُخلى مواردها ليعيد الـ kernel استخدامها. عند close(2)، ستُضبط أحداث الأذونات المعلقة على مسموح بها.

واجهات /proc

يحتوي الملف /proc/pid/fdinfo/fd على معلومات حول علامات fanotify لواصف الملف fd للعملية pid. راجع proc(5) للتفاصيل.

منذ لينكس 5.13 (و 5.10.220)، يمكن استخدام الواجهات التالية للتحكم في كمية موارد الـ kernel التي يستهلكها fanotify:

/proc/sys/fs/fanotify/max_queued_events
تُستخدم القيمة الموجودة في هذا الملف عندما يستدعي تطبيق ما fanotify_init(2) لضبط حد أقصى لعدد الأحداث التي يمكن وضعها في طابور مجموعة fanotify المقابلة. تُسقط الأحداث التي تتجاوز هذا الحد، ولكن يُولد دائماً حدث FAN_Q_OVERFLOW. قبل نواة لينكس 5.13، كان الحد المبرمج صلباً هو 16384 حدثاً.
/proc/sys/fs/fanotify/max_user_group
يحدد هذا حداً أقصى لعدد مجموعات fanotify التي يمكن إنشاؤها لكل معرف مستخدم حقيقي. قبل نواة لينكس 5.13، كان الحد المبرمج صلباً هو 128 مجموعة لكل مستخدم.
/proc/sys/fs/fanotify/max_user_marks
يحدد هذا حداً أقصى لعدد علامات fanotify التي يمكن إنشاؤها لكل معرف مستخدم حقيقي. قبل نواة لينكس 5.13، كان الحد المبرمج صلباً هو 8192 علامة لكل مجموعة (وليس لكل مستخدم).

الأخطاء

بالإضافة إلى الأخطاء المعتادة لـ read(2)، يمكن أن تحدث الأخطاء التالية عند القراءة من واصف ملف fanotify:

الخبيئة أصغر من أن تتسع لهذا الحدث.
بُلغ الحد الأقصى لعدد الملفات المفتوحة لكل عملية. انظر وصف RLIMIT_NOFILE في getrlimit(2).
بُلغ الحد الأقصى لعدد الملفات المفتوحة على مستوى النظام بأكمله. انظر /proc/sys/fs/file-max في proc(5).
يُرجع الاستدعاء read(2) هذا الخطأ إذا حُدد O_RDWR أو O_WRONLY في المعامل event_f_flags عند استدعاء fanotify_init(2) ووقع حدث لملف مراقب يجري تنفيذه حاليًا.

بالإضافة إلى الأخطاء المعتادة للاستدعاء write(2)، يمكن أن تقع الأخطاء التالية عند الكتابة في واصف ملف fanotify:

أذونات الوصول لـ Fanotify غير مفعّلة في ضبط النواة أو أن قيمة response في بنية الاستجابة غير صالحة.
واصف الملف fd في بنية الاستجابة غير صالح. قد يحدث هذا عندما تكون استجابة حدث الإذن قد كُتبت بالفعل.

المعايير

لينكس.

التاريخ

قُدمت واجهة برمجة تطبيقات fanotify في لينكس 2.6.36 وفُعّلت في لينكس 2.6.37. أُضيف دعم fdinfo في لينكس 3.8.

ملاحظات

واجهة برمجة تطبيقات fanotify متاحة فقط إذا بُنيت النواة مع تفعيل خيار الضبط CONFIG_FANOTIFY. بالإضافة إلى ذلك، فإن معالجة أذونات fanotify متاحة فقط إذا فُعّل خيار الضبط CONFIG_FANOTIFY_ACCESS_PERMISSIONS.

القيود والتحذيرات

يبلغ fanotify فقط عن الأحداث التي يطلقها برنامج في مساحة المستخدم عبر واجهة برمجة تطبيقات نظام الملفات. ونتيجة لذلك، فإنه لا يلتقط الأحداث البعيدة التي تقع في أنظمة الملفات الشبكية.

لا تبلغ واجهة برمجة تطبيقات fanotify عن عمليات الوصول إلى الملفات وتعديلها التي قد تحدث بسبب mmap(2) و msync(2) و munmap(2).

تُنشأ أحداث الأدلة فقط إذا فُتح الدليل نفسه وقُرئ وأُغلق. إضافة أو إزالة أو تغيير أبناء دليل موسوم لا يُنشئ أحداثًا للدليل المراقب نفسه.

مراقبة fanotify للأدلة ليست عودية: لمراقبة الأدلة الفرعية تحت دليل ما، يجب إنشاء وسوم إضافية. يمكن استخدام حدث FAN_CREATE لاكتشاف وقت إنشاء دليل فرعي تحت دليل موسوم. يجب بعد ذلك وضع وسم إضافي على الدليل الفرعي المنشأ حديثًا. هذا النهج عرضة لظروف السباق (racy)، لأنه قد يفقد الأحداث التي وقعت داخل الدليل الفرعي المنشأ حديثًا قبل إضافة وسم عليه. توفر مراقبة نقاط الوصل القدرة على مراقبة شجرة أدلة كاملة بطريقة خالية من السباق. توفر مراقبة أنظمة الملفات القدرة على مراقبة التغييرات التي تجري من أي وصل لمثيل نظام ملفات بطريقة خالية من السباق.

قد يفيض طابور الأحداث. في هذه الحالة، تُفقد الأحداث.

العلل

قبل لينكس 3.19، لم يكن fallocate(2) يولد أحداث fanotify. منذ لينكس 3.19، تولد استدعاءات fallocate(2) أحداث FAN_MODIFY.

بدءًا من لينكس 3.17، توجد العلل التالية:

في لينكس، يمكن الوصول إلى كائن نظام ملفات عبر مسارات متعددة، على سبيل المثال، قد يُعاد وصل جزء من نظام ملفات باستخدام خيار --bind للأمر mount(8). المستمع الذي وسم وصلًا سيُخطر فقط بالأحداث التي أُطلقت لكائن نظام ملفات باستخدام الوصل نفسه. أي حدث آخر سيمر دون ملاحظة.
عند توليد حدث، لا يُجرى أي فحص لمعرفة ما إذا كان معرف المستخدم للعملية المستلمة لديه تفويض للقراءة أو الكتابة في الملف قبل تمرير واصف ملف لذلك الملف. يمثل هذا خطرًا أمنيًا، عندما تُضبط إمكانية CAP_SYS_ADMIN للبرامج التي ينفذها مستخدمون غير مفوضين.
إذا عالج استدعاء read(2) أحداثًا متعددة من طابور fanotify وحدث خطأ، فستكون القيمة المرجعة هي الحجم الإجمالي للأحداث التي نُسخت بنجاح إلى خبيئة مساحة المستخدم قبل وقوع الخطأ. لن تكون القيمة المرجعة -1، ولن يُضبط errno. وبالتالي، لا تملك التطبيقات القارئة أي وسيلة لاكتشاف الخطأ.

أمثلة

يوضح البرنامجان المثالان أدناه استخدام واجهة برمجة تطبيقات fanotify.

برنامج مثال: fanotify_example.c

البرنامج الأول هو مثال لاستخدام fanotify مع تمرير معلومات كائن الحدث الخاص به في شكل واصف ملف. يوسم البرنامج نقطة الوصل الممررة كمعامل في سطر الأوامر وينتظر أحداثًا من النوع FAN_OPEN_PERM و FAN_CLOSE_WRITE. عند وقوع حدث إذن، تُعطى استجابة FAN_ALLOW.

تُظهر جلسة الصدفة التالية مثالًا على تشغيل هذا البرنامج. تضمنت هذه الجلسة تحرير الملف /home/user/temp/notes. قبل أن يُفتح الملف، وقع حدث FAN_OPEN_PERM. بعد إغلاق الملف، وقع حدث FAN_CLOSE_WRITE. ينتهي تنفيذ البرنامج عندما يضغط المستخدم على مفتاح ENTER.


# ./fanotify_example /home;
اضغط على مفتاح ENTER للإنهاء.
الاستماع للأحداث.
FAN_OPEN_PERM: File /home/user/temp/notes
FAN_CLOSE_WRITE: File /home/user/temp/notes
توقف الاستماع للأحداث.

مصدر البرنامج: fanotify_example.c

#define _GNU_SOURCE     /* مطلوب للحصول على تعريف O_LARGEFILE */
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/fanotify.h>
#include <unistd.h>
/* اقرأ جميع أحداث fanotify المتاحة من واصف الملف 'fd'.  */
static void
handle_events(int fd)
{

const struct fanotify_event_metadata *metadata;
struct fanotify_event_metadata buf[200];
ssize_t size;
char path[PATH_MAX];
ssize_t path_len;
char procfd_path[PATH_MAX];
struct fanotify_response response;
/* التكرار طالما يمكن قراءة الأحداث من واصف ملف fanotify. */
for (;;) {
/* قراءة بعض الأحداث. */
size = read(fd, buf, sizeof(buf));
if (size == -1 && errno != EAGAIN) {
perror("read");
exit(EXIT_FAILURE);
}
/* التحقق مما إذا كان قد وصل إلى نهاية البيانات المتاحة. */
if (size <= 0)
break;
/* الإشارة إلى الحدث الأول في الخبيئة. */
metadata = buf;
/* التكرار عبر كافة الأحداث في الخبيئة. */
while (FAN_EVENT_OK(metadata, size)) {
/* التحقق من تطابق بنيات وقت التشغيل ووقت التجميع. */
if (metadata->vers != FANOTIFY_METADATA_VERSION) {
fprintf(stderr,
"Mismatch of fanotify metadata version.\n");
exit(EXIT_FAILURE);
}
/* metadata->fd يحتوي إما على FAN_NOFD، مما يشير إلى
فيضان الطابور، أو واصف ملف (عدد صحيح غير سالب).
هنا، نتجاهل ببساطة فيضان الطابور. */
if (metadata->fd >= 0) {
/* معالجة حدث إذن الفتح. */
if (metadata->mask & FAN_OPEN_PERM) {
printf("FAN_OPEN_PERM: ");
/* السماح بفتح الملف. */
response.fd = metadata->fd;
response.response = FAN_ALLOW;
write(fd, &response, sizeof(response));
}
/* معالجة حدث إغلاق ملف قابل للكتابة. */
if (metadata->mask & FAN_CLOSE_WRITE)
printf("FAN_CLOSE_WRITE: ");
/* جلب وطباعة اسم المسار للملف الذي تم الوصول إليه. */
snprintf(procfd_path, sizeof(procfd_path),
"/proc/self/fd/%d", metadata->fd);
path_len = readlink(procfd_path, path,
sizeof(path) - 1);
if (path_len == -1) {
perror("readlink");
exit(EXIT_FAILURE);
}
path[path_len] = '\0';
printf("File %s\n", path);
/* إغلاق واصف الملف الخاص بالحدث. */
close(metadata->fd);
}
/* الانتقال إلى الحدث التالي. */
metadata = FAN_EVENT_NEXT(metadata, size);
}
} } int main(int argc, char *argv[]) {
char buf;
int fd, poll_num;
nfds_t nfds;
struct pollfd fds[2];
/* التحقق من توفير نقطة الوصل. */
if (argc != 2) {
fprintf(stderr, "Usage: %s MOUNT\n", argv[0]);
exit(EXIT_FAILURE);
}
printf("Press enter key to terminate.\n");
/* إنشاء واصف الملف للوصول إلى واجهة برمجة تطبيقات fanotify. */
fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT | FAN_NONBLOCK,
O_RDONLY | O_LARGEFILE);
if (fd == -1) {
perror("fanotify_init");
exit(EXIT_FAILURE);
}
/* وسم نقطة الوصل لـ:
- أحداث الإذن قبل فتح الملفات
- أحداث الإشعار بعد إغلاق واصف ملف
مفعّل للكتابة. */
if (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT,
FAN_OPEN_PERM | FAN_CLOSE_WRITE, AT_FDCWD,
argv[1]) == -1) {
perror("fanotify_mark");
exit(EXIT_FAILURE);
}
/* التحضير للاستطلاع (polling). */
nfds = 2;
fds[0].fd = STDIN_FILENO; /* إدخال الكونسول */
fds[0].events = POLLIN;
fds[1].fd = fd; /* إدخال Fanotify */
fds[1].events = POLLIN;
/* هذا هو التكرار لانتظار الأحداث القادمة. */
printf("Listening for events.\n");
for (;;) {
poll_num = poll(fds, nfds, -1);
if (poll_num == -1) {
if (errno == EINTR) /* قُطع بواسطة إشارة */
continue; /* إعادة تشغيل poll() */
perror("poll"); /* خطأ غير متوقع */
exit(EXIT_FAILURE);
}
if (poll_num > 0) {
if (fds[0].revents & POLLIN) {
/* إدخال الكونسول متاح: إفراغ stdin والخروج. */
while (read(STDIN_FILENO, &buf, 1) > 0 && buf != '\n')
continue;
break;
}
if (fds[1].revents & POLLIN) {
/* أحداث Fanotify متاحة. */
handle_events(fd);
}
}
}
printf("Listening for events stopped.\n");
exit(EXIT_SUCCESS); }

برنامج مثال: fanotify_fid.c

البرنامج الثاني هو مثال لاستخدام fanotify مع مجموعة تحدد الكائنات بواسطة مقابض الملفات. يوسم البرنامج كائن نظام الملفات الذي يُمرر كمعامل سطر أوامر وينتظر حتى يقع حدث من النوع FAN_CREATE. يشير قناع الحدث إلى نوع كائن نظام الملفات—إما ملف أو دليل—الذي أُنشئ. وبمجرد قراءة جميع الأحداث من الخبيئة ومعالجتها وفقًا لذلك، ينتهي البرنامج ببساطة.

تُظهر جلسات الصدفة التالية استدعاءين مختلفين لهذا البرنامج، مع تنفيذ إجراءات مختلفة على كائن مراقب.

تُظهر الجلسة الأولى وضع وسم على /home/user. ويتبع ذلك إنشاء ملف عادي، /home/user/testfile.txt. ينتج عن هذا توليد حدث FAN_CREATE والإبلاغ عنه مقابل كائن الدليل الأب المراقب للملف ومع اسم الملف المنشأ. ينتهي تنفيذ البرنامج بمجرد معالجة جميع الأحداث الملتقطة داخل الخبيئة.


# ./fanotify_fid /home/user;
الاستماع للأحداث.
FAN_CREATE (أُنشئ ملف):

عُدّل الدليل /home/user.
المدخل 'testfile.txt' ليس دليلاً فرعيًا. عولجت جميع الأحداث بنجاح. يخرج البرنامج. $ touch /home/user/testfile.txt; # في طرفية أخرى

تُظهر الجلسة الثانية وضع وسم على /home/user. ويتبع ذلك إنشاء دليل، /home/user/testdir. ينتج عن هذا الإجراء المحدد توليد حدث FAN_CREATE ويُبلغ عنه مع تعيين علم FAN_ONDIR ومع اسم الدليل المنشأ.


# ./fanotify_fid /home/user;
الاستماع للأحداث.
FAN_CREATE | FAN_ONDIR (أُنشئ دليل فرعي):

عُدّل الدليل /home/user.
المدخل 'testdir' هو دليل فرعي. عولجت جميع الأحداث بنجاح. يخرج البرنامج. $ mkdir -p /home/user/testdir; # في طرفية أخرى

مصدر البرنامج: fanotify_fid.c

#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fanotify.h>
#include <unistd.h>
#define BUF_SIZE 256
int
main(int argc, char *argv[])
{

int fd, ret, event_fd, mount_fd;
ssize_t size, path_len;
char path[PATH_MAX];
char procfd_path[PATH_MAX];
char events_buf[BUF_SIZE];
struct file_handle *file_handle;
struct fanotify_event_metadata *metadata;
struct fanotify_event_info_fid *fid;
const char *file_name;
struct stat sb;
if (argc != 2) {
fprintf(stderr, "Invalid number of command line arguments.\n");
exit(EXIT_FAILURE);
}
mount_fd = open(argv[1], O_DIRECTORY | O_RDONLY);
if (mount_fd == -1) {
perror(argv[1]);
exit(EXIT_FAILURE);
}
/* إنشاء واصف ملف fanotify مع FAN_REPORT_DFID_NAME كـ
علم حتى يتمكن البرنامج من استقبال أحداث fid مع اسم
مدخل الدليل. */
fd = fanotify_init(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME, 0);
if (fd == -1) {
perror("fanotify_init");
exit(EXIT_FAILURE);
}
/* وضع وسم على كائن نظام الملفات الموفر في argv[1]. */
ret = fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_ONLYDIR,
FAN_CREATE | FAN_ONDIR,
AT_FDCWD, argv[1]);
if (ret == -1) {
perror("fanotify_mark");
exit(EXIT_FAILURE);
}
printf("Listening for events.\n");
/* قراءة الأحداث من طابور الأحداث إلى خبيئة. */
size = read(fd, events_buf, sizeof(events_buf));
if (size == -1 && errno != EAGAIN) {
perror("read");
exit(EXIT_FAILURE);
}
/* معالجة جميع الأحداث داخل الخبيئة. */
for (metadata = (struct fanotify_event_metadata *) events_buf;
FAN_EVENT_OK(metadata, size);
metadata = FAN_EVENT_NEXT(metadata, size)) {
fid = (struct fanotify_event_info_fid *) (metadata + 1);
file_handle = (struct file_handle *) fid->handle;
/* التأكد من أن معلومات الحدث من النوع الصحيح. */
if (fid->hdr.info_type == FAN_EVENT_INFO_TYPE_FID ||
fid->hdr.info_type == FAN_EVENT_INFO_TYPE_DFID) {
file_name = NULL;
} else if (fid->hdr.info_type == FAN_EVENT_INFO_TYPE_DFID_NAME) {
file_name = file_handle->f_handle +
file_handle->handle_bytes;
} else {
fprintf(stderr, "Received unexpected event info type.\n");
exit(EXIT_FAILURE);
}
if (metadata->mask == FAN_CREATE)
printf("FAN_CREATE (file created):\n");
if (metadata->mask == (FAN_CREATE | FAN_ONDIR))
printf("FAN_CREATE | FAN_ONDIR (subdirectory created):\n"); /* يُضبط metadata->fd على FAN_NOFD عندما تحدد المجموعة الكائنات بواسطة مقابض الملفات. للحصول على واصف ملف لكائن الملف المقابل لحدث ما، يمكنك استخدام struct file_handle الموفرة داخل fanotify_event_info_fid بالاقتران مع استدعاء النظام open_by_handle_at(2). يُجرى فحص لـ ESTALE لاستيعاب الموقف الذي حُذف فيه مقبض الملف للكائن قبل استدعاء النظام هذا. */
event_fd = open_by_handle_at(mount_fd, file_handle, O_RDONLY);
if (event_fd == -1) {
if (errno == ESTALE) {
printf("File handle is no longer valid. "
"File has been deleted\n");
continue;
} else {
perror("open_by_handle_at");
exit(EXIT_FAILURE);
}
}
snprintf(procfd_path, sizeof(procfd_path), "/proc/self/fd/%d",
event_fd);
/* جلب وطباعة مسار dentry المعدل. */
path_len = readlink(procfd_path, path, sizeof(path) - 1);
if (path_len == -1) {
perror("readlink");
exit(EXIT_FAILURE);
}
path[path_len] = '\0';
printf("\tDirectory '%s' has been modified.\n", path);
if (file_name) {
ret = fstatat(event_fd, file_name, &sb, 0);
if (ret == -1) {
if (errno != ENOENT) {
perror("fstatat");
exit(EXIT_FAILURE);
}
printf("\tEntry '%s' does not exist.\n", file_name);
} else if ((sb.st_mode & S_IFMT) == S_IFDIR) {
printf("\tEntry '%s' is a subdirectory.\n", file_name);
} else {
printf("\tEntry '%s' is not a subdirectory.\n",
file_name);
}
}
/* إغلاق واصف الملف المرتبط بهذا الحدث. */
close(event_fd);
}
printf("All events processed successfully. Program exiting.\n");
exit(EXIT_SUCCESS); }

انظر أيضًا

fanotify_init(2)، fanotify_mark(2)، inotify(7)

ترجمة

تُرجمت هذه الصفحة من الدليل بواسطة زايد السعيدي <zayed.alsaidi@gmail.com>

هذه الترجمة هي وثيقة مجانية؛ راجع رخصة جنو العامة الإصدار 3 أو ما بعده للاطلاع على شروط حقوق النشر. لا توجد أي ضمانات.

إذا وجدت أي أخطاء في ترجمة صفحة الدليل هذه، يرجى إرسال بريد إلكتروني إلى قائمة بريد المترجمين: kde-l10n-ar@kde.org.

14 فبراير 2026 صفحات دليل لينكس (لم تصدر بعد)