copy_file_range(2)

الاسم
copy_file_range - نسخ نطاق من البيانات من ملف إلى آخر

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

موجز
#define _GNU_SOURCE
#define _FILE_OFFSET_BITS 64
#include <unistd.h>

ssize_t copy_file_range(int fd_in, off_t *_Nullable off_in,
                        int fd_out, off_t *_Nullable off_out,
                        size_t size, unsigned int flags);

الوصف
استدعاء النظام copy_file_range() ينفذ نسخًا داخل النواة بين واصفي ملفين دون التكلفة الإضافية لنقل البيانات من النواة إلى مساحة المستخدم ثم العودة إلى النواة. ينسخ حتى size بايت من البيانات من واصف الملف المصدر fd_in إلى واصف الملف الهدف fd_out، مع استبدال أي بيانات موجودة ضمن النطاق المطلوب من الملف الهدف.

تنطبق الدلالات التالية على off_in، وتنطبق عبارات مماثلة على off_out:

•   إذا كان off_in فارغًا (NULL)، تُقرأ البايتات من fd_in بدءًا من إزاحة الملف، ويُضبط إزاحة الملف بعدد البايتات المنسوخة.

•   إذا لم يكن off_in فارغًا (NULL)، يجب أن يشير off_in إلى مخزن مؤقت يحدد إزاحة البداية حيث ستُقرأ البايتات من fd_in. لا تتغير إزاحة ملف fd_in، لكن يُضبط off_in بشكل مناسب.

يمكن أن يشير fd_in و fd_out إلى نفس الملف. إذا كانا يشيران إلى نفس الملف، فلا يُسمح بتداخل نطاقي المصدر والهدف.

وُفر المعامل flags للسماح بالتوسعات المستقبلية ويجب ضبطه حاليًا على 0.

قيمة الإرجاع
عند الإكمال بنجاح، يُرجع copy_file_range() عدد البايتات المنسوخة بين الملفات. قد يكون هذا أقل من الحجم المطلوب أصلاً. إذا كانت إزاحة ملف fd_in عند نهاية الملف أو بعدها، لا تُنسخ أي بايتات، ويُرجع copy_file_range() صفرًا.

عند الخطأ، يُرجع copy_file_range() -1 ويُضبط errno للإشارة إلى الخطأ.

الأخطاء

EBADF
    واصف ملف واحد أو أكثر غير صالح.

EBADF
    fd_in غير مفتوح للقراءة؛ أو fd_out غير مفتوح للكتابة.

EBADF
    عُيّنت علامة O_APPEND لوصف الملف المفتوح (انظر open(2)) المشار إليه بواصف الملف fd_out.

EFBIG
    جرت محاولة للكتابة في موضع يتجاوز أقصى إزاحة ملف تدعمها النواة.

EFBIG
    جرت محاولة لكتابة نطاق يتجاوز الحد الأقصى المسموح به لحجم الملف. يختلف الحد الأقصى لحجم الملف بين تطبيقات نظام الملفات ويمكن أن يكون مختلفًا عن أقصى إزاحة ملف مسموح بها.

EFBIG
    جرت محاولة للكتابة تتجاوز حد مورد حجم ملف العملية. قد يؤدي هذا أيضًا إلى استلام العملية إشارة SIGXFSZ.

EINVAL
    وسيطة flags ليست 0.

EINVAL
    يشير fd_in و fd_out إلى نفس الملف وتتداخل نطاقات المصدر والهدف.

EINVAL
    إما fd_in أو fd_out ليس ملفًا عاديًا.

EIO حدث خطأ إدخال/إخراج منخفض المستوى أثناء النسخ.

EISDIR
    إما fd_in أو fd_out يشير إلى دليل.

ENOMEM
    نفدت الذاكرة.

ENOSPC
    لا توجد مساحة كافية على نظام الملفات الهدف لإكمال النسخ.

EOPNOTSUPP (منذ لينكس 5.19)
    نظام الملفات لا يدعم هذه العملية.

EOVERFLOW
    نطاق المصدر أو الوجهة المطلوب كبير جدًا بحيث لا يمكن تمثيله في أنواع البيانات المحددة.

EPERM
    fd_out يشير إلى ملف غير قابل للتغيير.

ETXTBSY
    إما fd_in أو fd_out يشير إلى ملف مبادلة نشط.

EXDEV (قبل لينكس 5.3)
    الملفات المشار إليها بواسطة fd_in و fd_out ليست على نفس نظام الملفات.

EXDEV (منذ لينكس 5.19)
    الملفات المشار إليها بواسطة fd_in و fd_out ليست على نفس نظام الملفات، وأنظمة الملفات المصدر والهدف ليست من نفس النوع، أو لا تدعم النسخ عبر أنظمة الملفات.

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

منذ لينكس 5.19، يمكن تحقيق النسخ عبر أنظمة الملفات عندما يكون كلا نظامي الملفات من نفس النوع، وينفذ نظام الملفات ذلك الدعم. انظر BUGS للسلوك قبل لينكس 5.19.

يجب أن تستهدف التطبيقات سلوك ومتطلبات لينكس 5.19، والتي تم أيضًا نقلها إلى النوى المستقرة السابقة.

المعايير
لينكس، جنو.

التاريخ
لينكس 4.5.

قبل glibc 2.30، بدءًا من glibc 2.27، وفرت دالة الغلاف glibc تنفيذًا احتياطيًا في مساحة المستخدم عندما لم تنفذ النواة استدعاء النظام هذا. منذ glibc 2.30، تمت إزالة ذلك الاحتياطي؛ تفشل الدالة الآن مع ENOSYS إذا كانت النواة تفتقر إلى دعم .BR copy_file_range ().

ملاحظات
إذا كان fd_in ملفًا متناثرًا، فقد يقوم copy_file_range() بتوسيع أي ثغرات موجودة في النطاق المطلوب. قد يستفيد المستخدمون من استدعاء copy_file_range() في حلقة، واستخدام عمليات lseek(2) SEEK_DATA و SEEK_HOLE للعثور على مواقع مقاطع البيانات.

يمنح copy_file_range() أنظمة الملفات فرصة لتنفيذ تقنيات "تسريع النسخ"، مثل استخدام إعادة الروابط (أي اثنين أو أكثر من العقد التي تشترك في مؤشرات لنفس كتل القرص القابلة للنسخ عند الكتابة) أو النسخ من جانب الخادم (في حالة NFS).

يجب تعريف _FILE_OFFSET_BITS على أنه 64 في الكود الذي يستخدم off_in أو off_out غير فارغ أو الذي يأخذ عنوان copy_file_range، إذا كان الكود مخصصًا ليكون محمولاً إلى منصات x86 و ARM التقليدية 32 بت حيث يكون عرض off_t مبدئيًا 32 بت.

العلل
في لينكس 5.3 إلى لينكس 5.18، تم تنفيذ النسخ عبر أنظمة الملفات بواسطة النواة، إذا لم تكن العملية مدعومة من قبل أنظمة الملفات الفردية. ومع ذلك، في بعض أنظمة الملفات الافتراضية، فشل الاستدعاء في النسخ، مع الإبلاغ عن النجاح.

أمثلة
    #define _GNU_SOURCE
    #define _FILE_OFFSET_BITS 64
    #include <fcntl.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/stat.h>
    #include <sys/types.h>
    #include <unistd.h>

    int
    main(int argc, char *argv[])
    {
        int          fd_in, fd_out;
        off_t        size, ret;
        struct stat  stat;

        if (argc != 3) {
            fprintf(stderr, "الاستخدام: %s <المصدر> <الوجهة>\n", argv[0]);
            exit(EXIT_FAILURE);
        }

        fd_in = open(argv[1], O_RDONLY);
        if (fd_in == -1) {
            perror("open (argv[1])");
            exit(EXIT_FAILURE);
        }

        if (fstat(fd_in, &stat) == -1) {
            perror("fstat");
            exit(EXIT_FAILURE);
        }

        size = stat.st_size;

        fd_out = open(argv[2], O_CREAT | O_WRONLY | O_TRUNC, 0644);
        if (fd_out == -1) {
            perror("open (argv[2])");
            exit(EXIT_FAILURE);
        }

        do {
            ret = copy_file_range(fd_in, NULL, fd_out, NULL, size, 0);
            if (ret == -1) {
                perror("copy_file_range");
                exit(EXIT_FAILURE);
            }

            size -= ret;
        } while (size > 0 && ret > 0);

        close(fd_in);
        close(fd_out);
        exit(EXIT_SUCCESS);
    }

انظر أيضًا
lseek(2), sendfile(2), splice(2)

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

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

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