rename(2)

الاسم
rename, renameat, renameat2 - تغيير اسم أو موقع ملف

المكتبة
مكتبة سي المعيارية (libc، -lc)

موجز
#include <stdio.h>

int rename(const char *oldpath, const char *newpath);

#include <fcntl.h>           /* Definition of AT_* constants */
#include <stdio.h>

int renameat(int olddirfd, const char *oldpath,
             int newdirfd, const char *newpath);
int renameat2(int olddirfd, const char *oldpath,
             int newdirfd, const char *newpath, unsigned int flags);

    متطلبات ماكروات اختبار الميزات لـ glibc (انظر feature_test_macros(7)):

renameat():
    Since glibc 2.10:
        _POSIX_C_SOURCE >= 200809L
    Before glibc 2.10:
        _ATFILE_SOURCE

renameat2():
    _GNU_SOURCE

الوصف
rename() يعيد تسمية ملف، وينقله بين الدلائل إذا لزم الأمر. أي روابط صلبة أخرى للملف (كما أُنشئت باستخدام link(2)) لا تتأثر. واصفات الملفات المفتوحة لـ oldpath لا تتأثر أيضًا.

قيود مختلفة تحدد نجاح عملية إعادة التسمية من عدمه: انظر الأخطاء أدناه.

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

إذا كان oldpath و newpath رابطين صلبيين موجودين يشيران إلى نفس الملف، فإن rename() لا يفعل شيئًا، ويعيد حالة نجاح.

إذا كان newpath موجودًا لكن العملية فشلت لسبب ما، يضمن rename() ترك نسخة من newpath في مكانها.

يمكن أن يحدد oldpath دليلًا. في هذه الحالة، يجب أن يكون newpath إما غير موجود، أو يجب أن يحدد دليلًا فارغًا.

إذا كان oldpath يشير إلى رابط رمزي، يُعاد تسمية الرابط؛ إذا كان newpath يشير إلى رابط رمزي، يُستبدل الرابط.

  renameat()
تعمل استدعاء النظام renameat() بنفس طريقة rename()، باستثناء الاختلافات الموصوفة هنا.

إذا كان اسم المسار المعطى في oldpath نسبيًا، فإنه يُفسر بالنسبة للدليل المشار إليه بواسطة واصف الملف olddirfd (بدلاً من كونه نسبيًا لدليل العمل الحالي للعملية المستدعية، كما يفعل rename() لاسم مسار نسبي).

إذا كان oldpath نسبيًا و olddirfd هو القيمة الخاصة AT_FDCWD، فإن oldpath يُفسر بالنسبة لدليل العمل الحالي للعملية المستدعية (مثل rename()).

إذا كان oldpath مطلقا، يُتجاهل olddirfd.

تفسير newpath هو نفسه بالنسبة لـ oldpath، باستثناء أن مسار الملف النسبي يُفسر بالنسبة للدليل الذي يشير إليه واصف الملف newdirfd.

انظر openat(2) لشرح الحاجة إلى renameat().

  renameat2()
لدى renameat2() وسيط flags إضافي. استدعاء renameat2() مع وسيط flags صفري يعادل renameat().

وسيط flags هو قناع بتات يتكون من صفر أو أكثر من الأعلام التالية:

RENAME_EXCHANGE
    يتبادل oldpath و newpath آليًا. يجب أن يكون كلا اسمي المسار موجودين لكن قد يكونان من أنواع مختلفة (مثلًا، قد يكون أحدهما دليلًا غير فارغ والآخر رابطًا رمزيًا).

RENAME_NOREPLACE
    لا يُستبدل newpath في إعادة التسمية. يُعيد خطأ إذا كان newpath موجودًا بالفعل.

    لا يمكن استخدام RENAME_NOREPLACE مع RENAME_EXCHANGE.

    يتطلب RENAME_NOREPLACE دعمًا من نظام الملفات الأساسي. أُضيف الدعم لأنظمة الملفات المختلفة كما يلي:

    •   ext4 (لينكس 3.15);

    •   btrfs, tmpfs, و cifs (لينكس 3.17);

    •   xfs (لينكس 4.0)؛

    •   دعم العديد من أنظمة الملفات الأخرى أُضيف في لينكس 4.9، بما في ذلك ext2 و minix و reiserfs و jfs و vfat و bpf.

RENAME_WHITEOUT (منذ لينكس 3.18)
    هذه العملية منطقية فقط لتطبيقات أنظمة الملفات التراكبية/الاتحادية.

    تحديد RENAME_WHITEOUT ينشئ كائن "whiteout" في مصدر إعادة التسمية في نفس وقت تنفيذ إعادة التسمية. العملية بأكملها ذرية، بحيث إذا نجحت إعادة التسمية فإن whiteout سيكون قد أُنشئ أيضًا.

    "whiteout" هو كائن له معنى خاص في بنى أنظمة الملفات الاتحادية/التراكبية. في هذه البنى، توجد طبقات متعددة ويتم تعديل الطبقة العليا فقط. whiteout على طبقة عليا سيخفي فعليًا ملفًا مطابقًا في الطبقة السفلى، مما يجعله يبدو وكأن الملف غير موجود.

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

    عندما لا يكون جزءًا من اتحاد/تراكب، يظهر whiteout كجهاز حرفي برقم جهاز {0,0}. (لاحظ أن تطبيقات اتحاد/تراكب أخرى قد تستخدم طرقًا مختلفة لتخزين إدخالات whiteout؛ على وجه التحديد، يستخدم BSD union mount نوع inode منفصل، DT_WHT، والذي، على الرغم من دعمه من قبل بعض أنظمة الملفات المتاحة في لينكس، مثل CODA و XFS، يتم تجاهله بواسطة كود دعم whiteout للنواة، اعتبارًا من لينكس 4.19 على الأقل.)

    RENAME_WHITEOUT يتطلب نفس الامتيازات مثل إنشاء عقدة جهاز (أي إمكانية CAP_MKNOD).

    RENAME_WHITEOUT لا يمكن استخدامه مع RENAME_EXCHANGE.

    RENAME_WHITEOUT يتطلب دعمًا من نظام الملفات الأساسي. من بين أنظمة الملفات التي تدعمه tmpfs (منذ لينكس 3.18)، و ext4 (منذ لينكس 3.18)، و XFS (منذ لينكس 4.1)، و f2fs (منذ لينكس 4.2)، و btrfs (منذ لينكس 4.7)، و ubifs (منذ لينكس 4.9).

قيمة الإرجاع
عند النجاح، يُعاد الصفر. وعند حدوث خطأ، يُعاد الرقم -1، ويُضبط errno للإشارة إلى الخطأ.

الأخطاء

EACCES
    إذن الكتابة مرفوض للدليل الذي يحتوي على oldpath أو newpath، أو إذن البحث مرفوض لأحد الدلائل في بادئة المسار لـ oldpath أو newpath، أو oldpath هو دليل ولا يسمح بإذن الكتابة (مطلوب لتحديث الإدخال ..). (انظر أيضًا path_resolution(7).)

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

EDQUOT
    استُنفدت حصة المستخدم من كتل القرص على نظام الملفات.

EFAULT
    يشير oldpath أو newpath إلى خارج مساحة العناوين التي يمكن الوصول إليها.

EINVAL
    اسم المسار الجديد احتوى على بادئة مسار للقديم، أو، بشكل عام، تمت محاولة جعل دليل دليلاً فرعيًا لنفسه.

EISDIR
    newpath هو دليل موجود، لكن oldpath ليس دليلاً.

ELOOP
    وُجهت روابط رمزية كثيرة جدًا عند حل oldpath أو newpath.

EMLINK
    oldpath لديه بالفعل الحد الأقصى لعدد الروابط إليه، أو كان دليلاً والدليل الذي يحتوي على newpath لديه الحد الأقصى لعدد الروابط.

ENAMETOOLONG
    كان oldpath أو newpath طويلًا جدًا.

ENOENT
    الرابط المسمى بـ oldpath غير موجود؛ أو، مكون دليل في newpath غير موجود؛ أو، oldpath أو newpath هو سلسلة فارغة.

ENOMEM
    ذاكرة النواة المتوفرة غير كافية.

ENOSPC
    الجهاز الذي يحتوي على الملف ليس به مساحة لمدخل الدليل الجديد.

ENOTDIR
    مكون يُستخدم كدليل في oldpath أو newpath ليس في الواقع دليلاً. أو، oldpath هو دليل، و newpath موجود لكنه ليس دليلاً.

ENOTEMPTY أو EEXIST
    newpath هو دليل غير فارغ، أي يحتوي على إدخالات غير "." و "..".

EPERM أو EACCES
    الدليل الذي يحتوي على oldpath لديه البت اللاصق (S_ISVTX) مضبوطًا ومعرف المستخدم الفعال للعملية ليس معرف المستخدم للملف المراد حذفه ولا معرف المستخدم للدليل الذي يحتويه، والعملية ليست مميزة (لينكس: لا تملك إمكانية CAP_FOWNER)؛ أو newpath هو ملف موجود والدليل الذي يحتويه لديه البت اللاصق مضبوطًا ومعرف المستخدم الفعال للعملية ليس معرف المستخدم للملف المراد استبداله ولا معرف المستخدم للدليل الذي يحتويه، والعملية ليست مميزة (لينكس: لا تملك إمكانية CAP_FOWNER)؛ أو نظام الملفات الذي يحتوي على oldpath لا يدعم إعادة التسمية من النوع المطلوب.

EROFS
    الملف موجود في نظام ملفات للقراءة فقط.

EXDEV
    oldpath و newpath ليسا على نفس نظام الملفات المُوصَل. (لينكس يسمح لنظام ملفات بأن يُوصَل في نقاط متعددة، لكن rename() لا يعمل عبر نقاط وصل مختلفة، حتى لو كان نفس نظام الملفات موصلاً على كليهما.)

الأخطاء الإضافية التالية يمكن أن تحدث لـ renameat() و renameat2():

EBADF
    oldpath (newpath) نسبي لكن olddirfd (newdirfd) ليس واصف ملف صالحًا.

ENOTDIR
    oldpath نسبي و olddirfd واصف ملف يشير إلى ملف غير الدليل؛ أو ما شابه ذلك لـ newpath و newdirfd

الأخطاء الإضافية التالية يمكن أن تحدث لـ renameat2():

EEXIST
    flags يحتوي على RENAME_NOREPLACE و newpath موجود بالفعل.

EINVAL
    عَلَم غير صالح حُدد في flags.

EINVAL
    كل من RENAME_NOREPLACE و RENAME_EXCHANGE حُددا في flags.

EINVAL
    كل من RENAME_WHITEOUT و RENAME_EXCHANGE حُددا في flags.

EINVAL
    نظام الملفات لا يدعم أحد الأعلام في flags.

ENOENT
    يحتوي flags على RENAME_EXCHANGE و newpath غير موجود.

EPERM
    تم تحديد RENAME_WHITEOUT في flags، لكن المتصل لا يملك صلاحية CAP_MKNOD.

المعايير

rename()
    C11، ‏POSIX.1-2024.

renameat()
    POSIX.1-2024.

renameat2()
    لينكس.

التاريخ

rename()
    C89، POSIX.1-2001، 4.3BSD.

renameat()
    POSIX.1-2008. لينكس 2.6.16،‏ glibc 2.4.

renameat2()
    لينكس 3.15، glibc 2.28.

  ملاحظات glibc
على النوى الأقدم حيث renameat() غير متوفرة، ترجع دالة الغلاف glibc إلى استخدام rename(). عندما يكون oldpath و newpath مسارات نسبية، تبني glibc المسارات بناءً على الروابط الرمزية في /proc/self/fd التي تتوافق مع وسيطات olddirfd و newdirfd.

العلل
على أنظمة ملفات NFS، لا يمكنك افتراض أنه إذا فشلت العملية، لم يتم إعادة تسمية الملف. إذا قام الخادم بعملية إعادة التسمية ثم تعطل، فإن RPC المعاد إرساله والذي سيعالج عند عودة الخادم يسبب فشلاً. يُتوقع من التطبيق التعامل مع هذا. انظر link(2) لمشكلة مماثلة.

انظر أيضًا
mv(1)، rename(1)، chmod(2)، link(2)، symlink(2)، unlink(2)، path_resolution(7)، symlink(7)

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

هذه الترجمة هي وثيقة مجانية؛ راجع رخصة جنو العامة الإصدار 3 (https://www.gnu.org/licenses/gpl-3.0.html) أو ما بعده للاطلاع على شروط حقوق النشر. لا توجد أي ضمانات.

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