| guestfs-hacking(1) | Virtualization Support | guestfs-hacking(1) |
نام (NAME)
guestfs-hacking - توسعه و مشارکت در libguestfs
توضیحات (DESCRIPTION)
این صفحه راهنما برای توسعهدهندگانی است که میخواهند خودِ libguestfs را گسترش دهند.
کد منبع (THE SOURCE CODE)
کد منبع libguestfs در مخزن گیتهاب زیر قرار دارد: https://github.com/libguestfs/libguestfs
بخش زیادی از کدهای تکراری (boilerplate) در libguestfs (مانند RPC، بایندینگها و مستندات) به صورت خودکار تولید میشوند. این بدان معناست که در یک git checkout معمولی، بسیاری از فایلهای منبع وجود نخواهند داشت. برای ایجاد این فایلها باید مولد (generator) را اجرا کنید ("./configure && make -C generator").
ابزار libguestfs از یک سیستم ساخت مبتنی بر autotools استفاده میکند که فایلهای اصلی آن configure.ac و Makefile.am هستند. بخش "THE BUILD SYSTEM" را ببینید.
زیرپوشهٔ generator شامل مولد بههمراه فایلهای توصیفکنندهٔ API است. زیرپوشهٔ lib شامل کدهای منبع کتابخانه است. زیرپوشههای appliance و daemon به ترتیب شامل کدهای منبع ساخت appliance و کدهایی هستند که درون appliance اجرا میشوند. سایر دایرکتوریها در بخش "SOURCE CODE SUBDIRECTORIES" در ادامه توضیح داده شدهاند.
صرفنظر از این واقعیت که تمام نقاط ورودی API از طریق کدهای تولیدشدهٔ خودکار هدایت میشوند، ساختار کتابخانه سرراست و ساده است. (در واقع، حتی کدهای تولیدشده نیز به گونهای طراحی شدهاند که خوانا باشند و باید مانند کدهای معمولی خوانده شوند). برخی از عملیات به طور کامل درون کتابخانه اجرا میشوند و به صورت توابع C در فایلهای زیر lib نوشته شدهاند. برخی دیگر به دیمن (daemon) ارسال میشوند؛ جایی که (پس از مقداری مرتبسازی تولیدشده توسط RPC) به صورت توابع C در فایلهای زیر daemon ظاهر میگردند.
برای ساخت از طریق کد منبع، ابتدا guestfs-building(1) را مطالعه کنید..SS "زیردایرکتوریهای کد منبع (SOURCE CODE SUBDIRECTORIES)" زیردایرکتوریهای زیادی در درخت کد منبع وجود دارند! ابتدا باید روی کدامیک تمرکز کنید؟ lib و daemon که حاوی کد منبع کتابخانه اصلی هستند. generator همان تولیدکننده کدی است که در بالا توضیح داده شد، بنابراین بسیار مهم است. فایل Makefile.am در دایرکتوری ریشه به شما نشان میدهد که زیردایرکتوریها به چه ترتیبی ساخته میشوند. سپس اگر به دنبال ابزار خاصی (مانند customize) یا اتصالات زبانی (مانند python) هستید، مستقیماً به آن زیردایرکتوری بروید، اما به یاد داشته باشید که اگر هنوز تولیدکننده (generator) را اجرا نکرده باشید، ممکن است فایلهایی وجود داشته باشند که به نظر مفقود برسند.
- align
- دستور و مستندات virt-alignment-scan(1).
- appliance
- ماشین تعبیهشده (appliance) libguestfs، اسکریپتهای ساخت و غیره.
- bash
- اسکریپتهای تکمیل خودکار کلید تب (tab-completion) در Bash.
- build-aux
- اسکریپتهای ساخت گوناگون مورد استفاده توسط autotools.
- builder
- دستور و مستندات virt-builder(1).
- cat
- دستورات و مستندات virt-cat(1)، virt-filesystems(1)، virt-log(1)، virt-ls(1) و virt-tail(1).
- common
- کتابخانههای گوناگونی از کدهای داخلی را میتوان در زیردایرکتوری common یافت:
- common/edit
- کد مشترک برای ویرایش تعاملی و غیرتعاملی فایلها درون یک سیستمفایل libguestfs.
- common/errnostring
- پروتکل ارتباطی مورد استفاده میان کتابخانه و daemon در حال اجرا درون ماشین تعبیهشده، باید errnoها را بهصورت رشته کدگذاری کند که این کار توسط این کتابخانه انجام میشود.
- common/mlcustomize
- کد کتابخانهای مرتبط با "virt-customize" که در ابزارهای دیگر نیز استفاده میشود.
- common/mlgettext
- پوشش (wrapper) کوچک و تولیدشدهای که به libguestfs اجازه میدهد با یا بدون ocaml-gettext کامپایل شود. این فایل توسط ./configure تولید میشود.
- common/mlpcre
- اتصالات سبک OCaml برای عبارات باقاعده سازگار با پرل (PCRE). توجه داشته باشید که این به هیچ وجه به کتابخانه ocaml-pcre اثر Markus Mottl مربوط نیست.
- common/mlprogress
- اتصالات OCaml برای توابع نوار پیشرفت (ببینید common/progress).
- common/mlstdutils
- کتابخانهای از توابع سودمند OCaml محض که در جاهای زیادی به کار رفته است.
- common/mltools
- توابع سودمند OCaml که تنها توسط ابزارهای virt بر پایه OCaml (مانند "virt-sysprep"، "virt-customize" و غیره) استفاده میشوند.
- common/mlutils
- اتصالات OCaml برای توابع C در "common/utils"، و برخی اتصالات POSIX که در کتابخانه استاندارد OCaml وجود ندارند.
- common/mlvisit
- اتصالات OCaml برای توابع پیمایش (visit) (ببینید common/visit).
- common/mlxml
- اتصالات OCaml برای کتابخانه libxml2.
- common/options
- تجزیه مشترک گزینهها برای guestfish، guestmount و برخی ابزارهای virt.
- common/parallel
- چارچوبی مورد استفاده برای پردازش موازی چندین دامنه libvirt.
- common/progress
- کد مشترک برای چاپ نوارهای پیشرفت.
- common/protocol
- پروتکل ارتباطی مبتنی بر XDR که میان کتابخانه و daemon در حال اجرا درون ماشین تعبیهشده استفاده میشود، در اینجا تعریف شده است.
- common/qemuopts
- ریزکتابخانهای برای نوشتن خطوط فرمان qemu و فایلهای پیکربندی qemu.
- common/structs
- کد مشترک برای چاپ و آزادسازی ساختارهای (structs) libguestfs، استفادهشده توسط کتابخانه و برخی ابزارها.
- common/utils
- توابع سودمند گوناگون مورد استفاده در سرتاسر کتابخانه و ابزارها.
- common/visit
- پیمایش بازگشتی ساختار سلسلهمراتبی سیستمفایل guestfs.
- common/windows
- توابع سودمند برای مدیریت حروف درایوهای ویندوز.
- contrib
- مشارکتهای بیرونی، بخشهای آزمایشی.
- customize
- دستور و مستندات virt-customize(1).
- daemon
- سرویس پسزمینهای (daemon) که درون ماشین تعبیهشده libguestfs اجرا میشود و اقدامات را انجام میدهد.
- df
- دستور و مستندات virt-df(1).
- dib
- دستور و مستندات virt-dib(1).
- diff
- دستور و مستندات virt-diff(1).
- docs
- صفحات راهنمای متفرقه.
- edit
- دستور و مستندات virt-edit(1).
- examples
- کد نمونه برای API به زبان C.
- fish
- پوسته خط فرمان guestfish(1)، و اسکریپتهای شل مختلفی که بر روی آن ساخته شدهاند مانند virt-copy-in(1)، virt-copy-out(1)، virt-tar-in(1) و virt-tar-out(1).
- format
- دستور و مستندات virt-format(1).
- fuse
- ابزار guestmount(1)، FUSE (سیستمفایل فضای کاربری) ساختهشده بر پایه libguestfs.
- generator
- تولیدکننده کدی بسیار حیاتی که برای تولید خودکار مقادیر زیادی از کدهای قالبی (boilerplate) به زبان C برای مواردی همچون RPC و اتصالات به کار میرود.
- get-kernel
- دستور و مستندات virt-get-kernel(1).
- inspector
- ابزار virt-inspector(1)، بازرس تصویر ماشین مجازی.
- lib
- کد منبع کتابخانه C.
- logo
- نشانواره مورد استفاده در وبسایت. ضمناً نام این ماهی Arthur است.
- m4
- ماکروهای M4 استفادهشده توسط autoconf. بخش "سیستم ساخت (THE BUILD SYSTEM)" را ببینید.
- make-fs
- دستور و مستندات virt-make-fs(1).
- po
- ترجمههای رشتههای ساده gettext.
- po-docs
- زیرساخت ساخت و فایلهای PO برای ترجمه صفحات راهنما و فایلهای POD. سرانجام این بخش با دایرکتوری po ترکیب خواهد شد، اما این کار تا حدی پیچیده است.
- rescue
- دستور و مستندات virt-rescue(1)..IP resize 4 دستور و مستندات virt-resize(1).
- sparsify
- دستور و مستندات virt-sparsify(1).
- sysprep
- دستور و مستندات virt-sysprep(1).
- tests
- آزمونها.
- test-data
- فایلها و سایر دادههای آزمایشی مورد استفاده در آزمونها.
- test-tool
- ابزار آزمون برای کاربران نهایی جهت بررسی اینکه آیا ترکیب qemu/kernel آنها با libguestfs کار خواهد کرد یا خیر.
- tmp
- برای فایلهای موقت هنگام اجرای آزمونها (به جای /tmp و غیره) استفاده میشود. دلیل این امر امکان اجرای چندین آزمون موازی از libguestfs بدون بازنویسی اَپلاینس (appliance) ایجادشده توسط آزمونی دیگر است.
- tools
- ابزارهای خط فرمان نوشتهشده به زبان Perl (virt-win-reg(1) و بسیاری دیگر).
- utils
- ابزارهای متفرقه، مانند "boot-benchmark".
- v2v
- تا libguestfs > 1.42 این بخش حاوی ابزار virt-v2v(1) بود، اما اکنون به یک مخزن جداگانه منتقل شده است: https://github.com/libguestfs/virt-v2v
- website
- فایلهای وبسایت http://libguestfs.org.
- csharp
- erlang
- golang
- haskell
- java
- lua
- ocaml
- php
- perl
- python
- ruby
- اتصالهای زبانی (Language bindings).
سیستم ساخت (THE BUILD SYSTEM)
ابزار Libguestfs از سیستم ساخت GNU autotools استفاده میکند (شامل autoconf، automake و libtool).
اسکریپت ./configure از configure.ac و m4/guestfs-*.m4 تولید میشود. بیشتر بخشهای اسکریپت configure بر اساس موضوع بین چندین فایل ماکروی m4 تقسیم شده است؛ برای مثال m4/guestfs-daemon.m4 وابستگیهای دیمن (daemon) را مدیریت میکند.
وظیفه Makefile.am در بالاترین سطح اساساً فهرست کردن زیردایرکتوریها ("SUBDIRS") به ترتیبی است که باید کامپایل شوند.
فایل common-rules.mk در تمام Makefile.amها (سطح بالا و زیردایرکتوریها) گنجانده شده است. subdir-rules.mk فقط در فایلهای Makefile.am زیردایرکتوریها قرار دارد.
تارگتهای make متعددی وجود دارد. برای دیدن فهرست همه آنها از این دستور استفاده کنید:
make help
افزودن API جدید (ADDING A NEW API)
از آنجا که بخش بزرگی از کدهای تکراری (boilerplate) در libguestfs به طور خودکار تولید میشوند، گسترش دادن API مربوط به libguestfs آسان است.
برای افزودن یک کنش (action) جدید به API، دو مرحله تغییر لازم است:
- 1.
- باید شرح
فراخوانی
(نام،
پارامترها،
نوع
بازگشتی،
آزمونها،
مستندات) را
به generator/actions_*.ml و
احتمالا
generator/proc_nr.ml اضافه
کنید.
بسته به اینکه فراخوانی به daemon در appliance ارسال میشود یا به طور کامل توسط کتابخانه پاسخ داده میشود، دو نوع کنش API وجود دارد (بخش "ARCHITECTURE" در guestfs-internals(1) را ببینید). تابع "guestfs_sync" در guestfs(3) نمونهای از نوع اول است، زیرا همگامسازی درون appliance انجام میشود. تابع "guestfs_set_trace" در guestfs(3) نمونهای از نوع دوم است، زیرا پرچم ردگیری در handle نگهداری میشود و تمام ردگیری در سمت کتابخانه صورت میگیرد.
بیشتر کنشهای جدید از نوع اول هستند و به فهرست "daemon_functions" اضافه میشوند. هر تابع دارای یک شمارهٔ رویهٔ (procedure number) یکتا است که در پروتکل RPC استفاده میشود؛ این شماره هنگام انتشار libguestfs به آن کنش اختصاص مییابد و بازاستفادهشدنی نیست. آخرین شمارهٔ رویه را برداشته و یکی به آن بیفزایید.
برای کنشهای نوع دوم که صرفاً به کتابخانه مربوط میشوند، آنها را به فهرست "non_daemon_functions" اضافه کنید. از آنجا که این توابع توسط کتابخانه مدیریت میشوند و از طریق سازوکار RPC به daemon منتقل نمیشوند، نیازی به شمارهٔ رویه ندارند و مقدار آن روی -1 تنظیم میشود.
- 2.
- پیادهسازی
کنش (به
زبان C):
برای کنشهای daemon، تابع "do_<name>" را در دایرکتوری "daemon/" پیادهسازی کنید.
برای کنشهای کتابخانه، تابع "guestfs_impl_<name>" را در دایرکتوری "lib/" پیادهسازی کنید.
در هر دو مورد، از تابع دیگری به عنوان الگویی برای نحوهٔ انجام کار استفاده نمایید.
- 3.
- به عنوان جایگزینی برای مرحلهٔ ۲: از نسخهٔ libguestfs 1.38 به بعد، میتوان کنشهای daemon را در OCaml پیادهسازی کرد. باید پرچم "impl = OCaml ..." را در generator تنظیم کنید. برای نمونه به daemon/file.ml نگاهی بیندازید.
پس از اعمال این تغییرات، از دستور "make" برای کامپایل استفاده کنید.
توجه داشته باشید که نیازی به پیادهسازی RPC، بایندرهای زبانها (language bindings)، صفحات راهنما یا موارد دیگر ندارید. تمام این موارد به صورت خودکار از شرح OCaml تولید میشوند.
افزودن آزمونها برای یک API
میتوانید به هر تعداد که میخواهید (یا صفر) برای هر فراخوانی API آزمون ارائه دهید. آزمونها میتوانند یا به عنوان بخشی از توصیف API (generator/actions_*.ml) اضافه شوند، یا در موارد نادرتر ممکن است بخواهید اسکریپتی را در "tests/*/" قرار دهید. توجه کنید که افزودن اسکریپت به "tests/*/" کُندتر است، بنابراین در صورت امکان از روش اول استفاده کنید.
در ادامه محیط آزمونی که هنگام افزودن آزمون API در actions_*.ml به کار میرود، توضیح داده شده است.
محیط آزمون دارای ۴ دستگاه بلوکی است:
- /dev/sda 2 GB
- دستگاه بلوکی عمومی برای آزمایش.
- /dev/sdb 2 GB
- پارتیشن /dev/sdb1 یک فایلسیستم ext2 است که برای آزمودن عملیات نوشتن روی فایلسیستم استفاده میشود.
- /dev/sdc 10 MB
- در تعداد معدودی از آزمونها که به دو دستگاه بلوکی نیاز است استفاده میشود.
- /dev/sdd
- فایل ISO با محتوای ثابت (به images/test.iso مراجعه کنید).
برای اینکه امکان اجرای آزمونها در مدتزمانی معقول فراهم باشد، appliance و دستگاههای بلوکی libguestfs بین آزمونها مجدداً استفاده میشوند. بنابراین سعی نکنید "guestfs_kill_subprocess" در guestfs(3) را بیازمایید :-x
هر آزمون با یک سناریوی اولیه آغاز میشود که با استفاده از یکی از عبارات "Init*" که در generator/types.ml توصیف شدهاند، انتخاب میشود. اینها دیسکهای ذکرشده در بالا را به شیوهای خاص که در types.ml مستند شده است مقداردهی اولیه میکنند. نباید هیچ فرضی در مورد محتویات قبلی دیسکهای دیگری که مقداردهی اولیه نشدهاند داشته باشید.
میتوانید یک بند پیشنیاز (prerequisite clause) به هر آزمون منفرد اضافه کنید. این یک بررسی زمان اجرا است که در صورت ناموفق بودن، منجر به صرفنظر کردن (skip) از آزمون میشود. این ویژگی برای آزمودن دستوری که ممکن است در تمام نسخهها یا ساختهای مختلف libguestfs کار نکند، مفید است. آزمونی که پیشنیاز "Always" دارد، به معنای اجرای بدون قید و شرط آن است.
علاوه بر این، بستهبندها (packagers) میتوانند با تنظیم متغیرهای محیطی قبل از اجرای دستور "make check"، آزمونهای خاصی را نادیده بگیرند.
SKIP_TEST_<CMD>_<NUM>=1
برای مثال: "SKIP_TEST_COMMAND_3=1" آزمون شمارهٔ ۳ از "guestfs_command" در guestfs(3) را نادیده میگیرد.
یا:
SKIP_TEST_<CMD>=1
برای مثال: "SKIP_TEST_ZEROFREE=1" تمام آزمونهای مربوط به "guestfs_zerofree" در guestfs(3) را رد میکند.
بستهبندها میتوانند برای مثال با تنظیم زیر تنها آزمونهای مشخصی را اجرا کنند:
TEST_ONLY="vfs_type zerofree"
برای جزئیات بیشتر دربارهٔ نحوهٔ کار این متغیرهای محیطی، tests/c-api/tests.c را مشاهده کنید.
اشکالزدایی APIهای جدید
پیش از ارسال کنشهای جدید، از کارکرد صحیح آنها مطمئن شوید.
میتوانید از guestfish برای آزمودن دستورات جدید استفاده کنید.
اشکالزدایی daemon دشوار است زیرا درون یک محیط کمینه اجرا میشود. با این حال میتوانید با استفاده از fprintf پیامها را در daemon به stderr بفرستید، و اگر از "guestfish -v" استفاده کنید، آن پیامها نمایش داده خواهند شد..SS "افزودن بایندینگ زبان جدید (ADDING A NEW LANGUAGE BINDING)" تمام بایندینگهای زبان باید توسط generator تولید شوند (زیردایرکتوری generator را ببینید).
هنوز هیچ مستنداتی برای این بخش وجود ندارد. پیشنهاد میکنیم به یکی از بایندینگهای موجود، برای مثال generator/ocaml.ml یا generator/perl.ml نگاهی بیندازید.
افزودن آزمونها برای بایندینگهای زبان
بایندینگهای زبان باید همراه با آزمونها ارائه شوند. در گذشته آزمایش بایندینگهای زبان تا حدی موردی (ad-hoc) بود، اما ما تلاش کردهایم مجموعه آزمونهایی را که هر بایندینگ زبان باید استفاده کند، مدون و یکپارچه کنیم.
در حال حاضر تنها بایندینگهای OCaml و Perl مجموعه کامل آزمونها را عملاً پیادهسازی کردهاند، و بایندینگهای OCaml حالت مرجع (canonical) دارند؛ بنابراین باید از آنچه آزمونهای OCaml انجام میدهند الگوبرداری کنید.
این طرح شمارهگذاری مورد استفاده توسط آزمونها است:
- 000+ آزمونهای پایه: 010 بارگذاری کتابخانه 020 create 030 create-flags 040 ایجاد چندین handle 050 آزمون تنظیم و دریافت ویژگیهای پیکربندی 060 بستن صریح (explicit close) 065 بستن ضمنی (در زبانهای دارای GC) 070 optargs 080 version 090 retvalues - 100 راهاندازی (launch)، ایجاد پارتیشنها، LVها و سیستمهای فایل - 400+ رویدادها: 410 رویداد close 420 پیامهای log 430 پیامهای پیشرفت (progress messages) - 800+ آزمونهای رگرسیون (مختص به زبان) - 900+ هرگونه آزمون سفارشی دیگر برای زبان
جهت صرفهجویی در زمان هنگام اجرای آزمونها، تنها آزمونهای 100، 430، +800 و +900 باید handle را راهاندازی (launch) کنند.
قالببندی کد (FORMATTING CODE)
کد منبع C ما بهطور کلی از برخی قواعد پایهای قالببندی کد پیروی میکند. پایهکد موجود در این زمینه کاملاً یکدست نیست، اما ترجیح میدهیم کدهای ارائهشده نیز به شکلی مشابه قالببندی شوند. بهطور خلاصه، برای تورفتگی از فاصله بهجای TAB استفاده کنید (spaces-not-TABs)، برای هر سطح تورفتگی ۲ فاصله در نظر بگیرید، و به غیر از آن، از سبک K&R پیروی کنید.
اگر از Emacs استفاده میکنید، موارد زیر را به یکی از فایلهای راهاندازی خود (مانند ~/.emacs) بیفزایید تا به درست بودن تورفتگیها کمک کند:
;;; In libguestfs, indent with spaces everywhere (not TABs).
;;; Exceptions: Makefile and ChangeLog modes.
(add-hook 'find-file-hook
'(lambda () (if (and buffer-file-name
(string-match "/libguestfs\\>"
(buffer-file-name))
(not (string-equal mode-name "Change Log"))
(not (string-equal mode-name "Makefile")))
(setq indent-tabs-mode nil))))
;;; When editing C sources in libguestfs, use this style.
(defun libguestfs-c-mode ()
"C mode with adjusted defaults for use with libguestfs."
(interactive)
(c-set-style "K&R")
(setq c-indent-level 2)
(setq c-basic-offset 2))
(add-hook 'c-mode-hook
'(lambda () (if (string-match "/libguestfs\\>"
(buffer-file-name))
(libguestfs-c-mode))))
هنگام توسعه، هشدارها را به خطا تبدیل کنید تا نادیده گرفتن آنها دشوار شود:
./configure --enable-werror
تارگتهای مفید عبارتند از:
- "make check"
- مجموعه
آزمونهای
معمول را
اجرا
میکند.
این مورد با استفاده از تارگت معمول "TESTS" در automake پیادهسازی شده است. برای جزئیات به مستندات automake مراجعه کنید.
- "make check-valgrind"
- زیرمجموعهای
از مجموعه
آزمونها
را تحت valgrind
اجرا
میکند.
بخش «VALGRIND» را در زیر ببینید.
- "make check-valgrind-local-guests"
- زیرمجموعهای از مجموعه آزمونها را با استفاده از مهمانهای libvirt محلیِ نصبشده (بهصورت فقطخواندنی) تحت valgrind اجرا میکند.
- "make check-direct"
- تمام آزمونها را با استفاده از backend پیشفرض appliance اجرا میکند. این دستور تنها زمانی اثر دارد که یک backend غیرپیشفرض با استفاده از "./configure --with-default-backend=..." انتخاب شده باشد.
- "make check-valgrind-direct"
- زیرمجموعهای از مجموعه آزمونها را تحت valgrind با استفاده از backend پیشفرض appliance اجرا میکند.
- "make check-with-upstream-qemu"
- تمام
آزمونها
را با
استفاده از
یک باینری
محلی qemu اجرا
میکند. این
دستور
باینری qemu را
در QEMUDIR (بهطور
پیشفرض
$HOME/d/qemu)
جستجو
میکند،
اما
میتوانید
آن را در خط
فرمان روی
دایرکتوری
دیگری
تنظیم
کنید، برای
مثال:
make check-with-upstream-qemu QEMUDIR=/usr/src/qemu
- "make check-with-upstream-libvirt"
- تمام
آزمونها
را با
استفاده از
یک libvirt محلی
اجرا
میکند. این
دستور تنها
در صورتی
اثر دارد که
backend مربوط به libvirt
با استفاده
از "./configure
--with-default-backend=libvirt"
انتخاب شده
باشد.
این دستور libvirt را در LIBVIRTDIR (بهطور پیشفرض $HOME/d/libvirt) جستجو میکند، اما میتوانید آن را در خط فرمان روی دایرکتوری دیگری تنظیم کنید، برای مثال:
make check-with-upstream-libvirt LIBVIRTDIR=/usr/src/libvirt
- "make check-slow"
- برخی
آزمونهای
کُند/طولانیمدت
را که
بهطور
پیشفرض
اجرا
نمیشوند،
اجرا
میکند.
برای مشخص کردن یک آزمون بهعنوان کُند/طولانیمدت:
- آن را دقیقاً مانند یک آزمون عادی به فهرست "TESTS" در Makefile.am اضافه کنید.
- آزمون را طوری تغییر دهید که تنظیم بودن متغیر محیطی "SLOW=1" را بررسی کند، و اگر تنظیم نشده بود، از آن رد شود (یعنی با کد خروج 77 پایان یابد). در صورت استفاده از tests/functions.sh، میتوانید تابع "slow_test" را برای این منظور فراخوانی کنید.
- متغیر "SLOW_TESTS" را به Makefile.am اضافه کنید که آزمونهای کند را فهرست میکند.
- یک قاعده به
Makefile.am اضافه
کنید:
check-slow: $(MAKE) check TESTS="$(SLOW_TESTS)" SLOW=1
- "sudo make check-root"
- برخی
آزمونها
را که به
امتیازات
ریشه (root) نیاز
دارند اجرا
میکند. این
آزمونها
باید ایمن
باشند، اما
احتیاط
کنید. باید
این دستور
را به عنوان
ریشه اجرا
کنید (مثلاً
صریحاً با
استفاده از
sudo(8)).
برای مشخص کردن اینکه یک آزمون نیازمند دسترسی ریشه است:
- آن را دقیقاً مانند یک آزمون عادی به فهرست "TESTS" در Makefile.am اضافه کنید.
- آزمون را طوری تغییر دهید که euid == 0 را بررسی کند، و اگر برقرار نبود، از آن رد شود (یعنی با کد خروج 77 پایان یابد). در صورت استفاده از tests/functions.sh، میتوانید تابع "root_test" را برای این منظور فراخوانی کنید.
- متغیر "ROOT_TESTS" را به Makefile.am اضافه کنید که آزمونهای ریشه را فهرست میکند.
- یک قاعده به
Makefile.am اضافه
کنید:
check-root: $(MAKE) check TESTS="$(ROOT_TESTS)"
- "make check-all"
- معادل اجرای تمام قواعد "make check*" به جز "check-root" است.
- "make check-release"
- زیرمجموعهای از قواعد "make check*" را اجرا میکند که قبولی در آنها پیش از انتشار فایل فشرده tarball الزامی است. در حال حاضر این موارد عبارتند از:
- check
- check-valgrind
- check-direct
- check-valgrind-direct
- check-slow
- "make installcheck"
- دستور "make
check" را روی
نسخه
نصبشده libguestfs
اجرا
میکند.
نسخه libguestfs نصبشدهای که مورد آزمایش قرار میگیرد و نسخه درخت کد منبع libguestfs باید یکسان باشند.
مراحل زیر را اجرا کنید:
./configure make clean ||: make make installcheck هنگامی که دستور "make check-valgrind" را اجرا میکنید، هر Makefile.am در درخت پروژه را که دارای هدف "check-valgrind:" باشد جستجو کرده و آن را اجرا میکند.
نگارش صحیح Makefile.am و آزمونها برای استفاده از valgrind و هماهنگی با آزمونهای موازی automake، دارای ظرافتها و پیچیدگیهایی است.
اگر آزمونهای شما از طریق یک اسکریپت پوششی شل (wrapper script) اجرا میشوند، درون اسکریپت پوششی از عبارت زیر استفاده کنید:
$VG virt-foo
و در Makefile.am از دستور زیر استفاده کنید:
check-valgrind:
make VG="@VG@" check
با این حال، اگر باینریهای شما مستقیماً از طریق قاعده "TESTS" اجرا میشوند، باید Makefile.am را مانند زیر تغییر دهید:
LOG_COMPILER = $(VG)
check-valgrind:
make VG="@VG@" check
در هر دو حالت، با بررسی دقیق فایلهای لاگ در tmp/valgrind* اطمینان حاصل کنید که برنامهٔ صحیح تحت آزمایش قرار گرفته است.
ارسال وصلهها (SUBMITTING PATCHES)
وصلهها (patches) را به فهرست پستی ارسال کنید: https://lists.libguestfs.org و به rjones@redhat.com نیز رونوشت (CC) بزنید.
اگر تمایل ندارید، نیازی به عضویت در فهرست پستی نیست. ممکن است پیام شما تا زمان بررسی و تأیید توسط ناظران، کمی با تأخیر مواجه شود.
پشتیبانی از بینالمللیسازی (I18N) (INTERNATIONALIZATION (I18N) SUPPORT)
ما در این کتابخانه از i18n (بههرحال از gettext) پشتیبانی میکنیم.
با این وجود، بسیاری از پیامها از دیمِن (daemon) صادر میشوند و ما در حال حاضر آنها را ترجمه نمیکنیم. یک دلیل آن این است که در ماشین کمکی (appliance) عموماً همه فایلهای محلی (locale) حذف شدهاند، زیرا فضای زیادی را اشغال میکنند. بنابراین ناچار خواهیم بود برخی از آنها را دوباره اضافه کنیم و همچنین فایلهای PO خود را درون appliance کپی نماییم.
پیامهای اشکالزدایی (debugging) هرگز ترجمه نمیشوند، چرا که این پیامها برای برنامهنویسان در نظر گرفته شدهاند.
مباحث گوناگون (MISCELLANEOUS TOPICS)
نحوه کامپایل و پیوند برنامههای OCAML (HOW OCAML PROGRAMS ARE COMPILED AND LINKED)
این بخش بیشتر درباره «چگونگی هماهنگسازی automake و ocamlopt برای کار با یکدیگر» است، چرا که کامپایل کردن خود برنامههای OCaml کار سادهای است.
ابزار automake هیچ پشتیبانی پیشفرضی از برنامههای OCaml، چه ocamlc و چه ocamlopt ندارد. کاری که ما در عوض انجام میدهیم این است که با برنامههای OCaml مانند برنامههای C رفتار کنیم که اتفاقاً حاوی این «اشیاء دیگر» (در اصطلاح automake همان "DEPENDENCIES") هستند که همان شیءهای OCaml میباشند. این روش پاسخگو است زیرا برنامههای OCaml معمولاً دارای فایلهای C برای اتصالات بومی (native bindings) و موارد مشابه هستند.
بنابراین یک برنامه معمولی صرفاً با فایلهای منبع C خود توصیف میشود:
virt_customize_SOURCES = ... crypt-c.c perl_edit-c.c
برای برنامههایی که هیچ منبع C مشخصی ندارند، یک فایل خالی dummy.c ایجاد کرده و آن را به جای آن فهرست میکنیم:
virt_resize_SOURCES = dummy.c
شیءهای OCaml که دربردارنده بیشتر کدها هستند، بهعنوان وابستگیهای automake فهرست میشوند (سایر وابستگیها نیز ممکن است درج شوند):
virt_customize_DEPENDENCIES = ... customize_main.cmx
تنها کار خاص دیگری که باید انجام دهیم، ارائه یک دستور پیوند (link) سفارشی است. این امر ضروری است زیرا در غیر این صورت، automake دستور ocamlopt، فهرست اشیاء و کتابخانههای "-cclib" را به ترتیب صحیح سرهم نخواهد کرد.
virt_customize_LINK = \
$(top_builddir)/ocaml-link.sh -cclib '-lutils' -- ...
قواعد واقعی، که میتوانید آنها را در customize/Makefile.am بررسی کنید، کمی پیچیدهتر از این هستند زیرا باید موارد زیر را مدیریت کنند:
- کامپایل برای بایتکد یا کد بومی (native code).
- قواعد
الگویی (pattern rules)
مورد نیاز
برای
کامپایل
کدهای منبع
OCaml به شیءها.
این موارد اکنون در فایل subdir-rules.mk در بالاترین سطح نگهداری میشوند که در Makefile.am هر زیرشاخه گنجانده شده است.
- افزودن
فایلهای
منبع OCaml به
"EXTRA_DIST".
ابزار Automake از فهرست کامل کدهای منبع یک فایل باینری آگاه نیست، بنابراین تمام آنها را بهطور خودکار اضافه نخواهد کرد..SH "وظایف نگهدارنده (MAINTAINER TASKS)"
هدفهای MAKEFILE نگهدارنده (MAINTAINER MAKEFILE TARGETS)
این هدفهای "make" احتمالاً کار نخواهند کرد و مفید نخواهند بود مگر اینکه شما یکی از نگهدارندگان libguestfs باشید.
make maintainer-commit
این فرمان تمام تغییرات دایرکتوری کاری را با پیام کامیت "Version $(VERSION)." کامیت میکند. ابتدا باید configure.ac را بهروزرسانی، پاکسازی (clean) و مجدداً بازسازی (rebuild) کنید.
make maintainer-tag
این فرمان روی کامیت HEAD فعلی برچسب "v$(VERSION)" را با یکی از این پیامها ثبت میکند:
Version $(VERSION) stable Version $(VERSION) development
(برای آگاهی از تفاوت میان انتشار پایدار و توسعه، بخش «LIBGUESTFS VERSION NUMBERS» را در guestfs(3) ببینید.)
make maintainer-check-authors
بررسی میکند که نام تمام مؤلفان (یافتشده در پیامهای کامیت git) در فایل generator/authors.ml گنجانده شده باشد.
make maintainer-check-extra-dist
این قاعده باید پس از "make dist" اجرا شود (بهطوری که یک tarball در دایرکتوری کاری وجود داشته باشد). این فرمان محتویات tarball را با محتویات git مقایسه میکند تا اطمینان حاصل شود هیچ فایلی از قواعد "EXTRA_DIST" در Makefile.am از قلم نیفتاده است.
make maintainer-upload-website
این هدف توسط نرمافزاری استفاده میشود که برای خودکارسازی انتشارهای libguestfs بهکار میرود تا پیش از بارگذاری وبسایت libguestfs روی کارساز وب، آن را در یک مخزن git دیگر کپی کند.
ایجاد یک انتشار پایدار (MAKING A STABLE RELEASE)
هنگام ایجاد یک انتشار پایدار، مراحلی وجود دارد که در اینجا مستند شده است. برای اطلاعات کلی دربارهٔ سیاست شاخهٔ پایدار، بخش «LIBGUESTFS VERSION NUMBERS» را در guestfs(3) ببینید.
- •
- بررسی کنید که "make && make check" دستکم روی این موارد کار کند:
- بررسی کنید که "./configure --without-libvirt" کار کند.
- نهاییسازی فایل guestfs-release-notes.pod.
- ایجاد دایرکتوریهای جدید stable و development در http://libguestfs.org/download.
- ویرایش website/index.html.in.
- تنظیم نسخه
(در configure.ac) به
نسخهٔ
پایدار (stable)
جدید، یعنی
1.XX.0، و کامیت
کردن آن:
./localconfigure make distclean -k ./localconfigure make && make dist make maintainer-commit make maintainer-tag
- ایجاد
شاخهٔ stable در git:
git branch stable-1.XX git push origin stable-1.XX
- انتشار کامل شاخهٔ پایدار.
- تنظیم نسخه به نسخهٔ توسعهٔ بعدی و کامیت کردن آن. در صورت تمایل، یک انتشار کامل از شاخهٔ توسعه انجام دهید..SH "مستندات داخلی (INTERNAL DOCUMENTATION)" این بخش به مستندسازی توابع داخلی libguestfs و ابزارهای مختلف آن میپردازد. این بخش تنها برای توسعهدهندگان libguestfs در نظر گرفته شده است.
این بخش به طور خودکار از کامنتهای "/**" در فایلهای منبع که با قالب POD نشانهگذاری شدهاند، تولید شده است.
این توابع به صورت عمومی برونریزی (export) نشدهاند و ممکن است در هر زمان تغییر کنند یا حذف شوند.
زیردایرکتوری lib
فایل lib/actions-support.c
توابع کمکی برای کد اقدامات (actions) در lib/actions-*.c.
فایل lib/appliance-cpu.c
انتخاب مدل CPU اپلاینس.
تابع "lib/appliance-cpu.c:guestfs_int_get_cpu_model"
const char * guestfs_int_get_cpu_model (int kvm)
مدل CPU مناسب را برای استفاده به عنوان پارامتر "-cpu" در qemu یا معادل آن در libvirt برمیگرداند. این تابع مقادیر زیر را بازمیگرداند:
- "host"
- رشته صریح "host" به معنای استفاده از "-cpu host" است.
- "max"
- رشته صریح "max" به معنای استفاده از "-cpu max" (بهترین حالت ممکن) است. این مقدار نیازمند ترجمه پیچیدهای برای libvirt است.
- یک رشته (some string)
- رشتهای مانند "cortex-a57" به معنای استفاده از "-cpu cortex-a57" است.
- "NULL"
- "NULL" به معنای عدم استفاده از گزینه "-cpu" است. توجه داشته باشید که بازگرداندن "NULL" نشاندهنده خطا نیست.
این موضوع به دلیل دو تصمیم نامناسب در QEMU به شکلی غیرضروری دشوار و شکننده شده است:
- رفتار پیشفرض برای "qemu-system-aarch64 -M virt" شبیهسازی یک "cortex-a15" است (واقعاً چرا؟!).
- ما با قطعیت نمیدانیم که KVM کار خواهد کرد یا خیر، اما "-cpu host" در کنار TCG با شکست مواجه میشود؛ بنابراین اگر KVM به هر نحوی دچار اختلال باشد، تقریباً همیشه یک پرچم نامعتبر "-cpu" ارسال میکنیم.
فایل lib/appliance-kcmdline.c
خط فرمان هسته (kernel) اپلاینس.
تعریف "lib/appliance-kcmdline.c:VALID_TERM"
#define VALID_TERM
بررسی اینکه متغیر محیطی $TERM پیش از ارسال به اپلاینس مقداری معقول داشته باشد.
تابع "lib/appliance-kcmdline.c:get_root_uuid_with_file"
static char * get_root_uuid_with_file (guestfs_h *g, const char *appliance)
با دریافت یک ایمیج دیسک حاوی سیستمفایل extX، مقدار UUID آن را برمیگرداند.
تابع "lib/appliance-kcmdline.c:run_qemu_img_dd"
static int run_qemu_img_dd (guestfs_h *g, const char *in_file, char *out_file)
خواندن ۲۵۶ کیلوبایت نخست in_file با استفاده از دستور qemu-img(1) و نوشتن آن در out_file. این کار ممکن است برای به دست آوردن UUID ایمیج دیسک QCOW2 با استفاده از "get_root_uuid_with_file" کاربردی باشد.
این تابع در صورت موفقیت صفر و در غیر این صورت -1 برمیگرداند.
تابع "lib/appliance-kcmdline.c:get_root_uuid"
static char * get_root_uuid (guestfs_h *g, const char *appliance)
دریافت UUID از ایمیج دیسک اپلاینس.
تابع "lib/appliance-kcmdline.c:guestfs_int_appliance_command_line"
char *
guestfs_int_appliance_command_line (guestfs_h *g,
const char *appliance,
int flags)
ساخت خط فرمان لینوکس ارسالی به اپلاینس. این تابع توسط بکاندهای "direct" و "libvirt" استفاده میشود و قرارگیری آن در این فایل صرفاً به این دلیل است که مکانی مناسب برای این کد مشترک به شمار میرود.
پارامتر "appliance" نام فایل اپلاینس است (میتواند NULL باشد) که UUID ریشه از آن دریافت میشود.
پارامتر "flags" میتواند شامل پرچمهای زیر باشد که با هم OR منطقی شدهاند (یا 0):
- "APPLIANCE_COMMAND_LINE_IS_TCG"
- اگر در حال راهاندازی یک مهمان TCG در qemu هستیم (یعنی مشخص شده است که KVM غیرفعال است یا در دسترس نیست). اگر اطمینان ندارید، این پرچم را ارسال نکنید.
توجه داشته باشید که این تابع یک بافر تازه تخصیصیافته بازمیگرداند که باید توسط فراخواننده آزاد (free) شود.
فایل lib/appliance-uefi.c
یافتن سفتافزار UEFI مورد نیاز برای بوت کردن اپلاینس.
همچنین ببینید lib/uefi.c (فایل خودکار تولید شده) که حاوی مکانهای فایلهای سفتافزار است.
تابع "lib/appliance-uefi.c:guestfs_int_get_uefi"
int
guestfs_int_get_uefi (guestfs_h *g, char *const *firmwares,
const char **firmware, char **code, char **vars,
int *flags)
مکان سفتافزار مورد نیاز برای بوت کردن اپلاینس را بازمیگرداند. این مورد در حال حاضر فقط برای معماری aarch64 است، چرا که تنها معماری است که در آن UEFI اجباری است (و آن هم فقط برای RHEL).
"firmwares" یک فهرست اختیاری از مقادیر مجاز برای انتخاب خودکار سفتافزار libvirt است. مقدار "NULL" نشاندهنده عدم پشتیبانی است. در صورتی که یکی از آنها قابل استفاده باشد، *firmware روی یکی از رشتههای موجود در "firmwares" تنظیم میشود.
*code با مسیر فایل فقطخواندنی کد UEFI مقداردهی اولیه میشود. *vars با مسیر نسخهای از فایل متغیرهای UEFI مقداردهی اولیه میشود (که هنگام خروج به طور خودکار پاکسازی میگردد).
در صورتی که سفتافزار UEFI موجود باشد، یا *firmware به مقداری غیر از "NULL" تنظیم میشود، یا *code و *vars.
*code و *vars باید توسط فراخواننده آزاد شوند، اما *firmware نباید آزاد شود.
اگر تابع مقدار -1 را بازگرداند، خطایی واقعی رخ داده است که باید موجب شکست در ساخت اپلاینس شود (نبود سفتافزار UEFI خطا محسوب نمیشود).
همچنین ببینید virt-v2v.git/v2v/utils.ml:find_uefi_firmware.PP فایل lib/appliance.c
این فایل به ساخت اپلاینس (appliance) libguestfs میپردازد.
تابع "lib/appliance.c:guestfs_int_build_appliance"
int
guestfs_int_build_appliance (guestfs_h *g,
char **kernel_rtn,
char **initrd_rtn,
char **appliance_rtn)
یافتن مکان یا ساخت اپلاینس.
این تابع در صورت نیاز، اپلاینس را پیدا کرده یا میسازد و مدیریت اپلاینس supermin، کَش کردن اپلاینسهای ساختهشده با supermin، یا استفاده از اپلاینس ثابت (fixed) یا سبک قدیمی (old-style) را بر عهده دارد.
مقدار بازگشتی 0 = موفق و -1 = خطا است. در "appliance.kernel" نام کرنل مورد استفاده، در "appliance.initrd" نام initrd و در "appliance.image" نام سیستمفایل ریشه ext2 بازگردانده خواهد شد. "appliance.image" میتواند "NULL" باشد، به این معنی که از یک اپلاینس سبک قدیمی (غیر ext2) استفاده میشود. هر سه رشته باید توسط فراخواننده آزاد (free) شوند. با این حال خود فایلهای ارجاعشده نباید حذف گردند.
فرایند به شرح زیر است:
- 1.
- بررسی "path" که حاوی اسکلت اپلاینس supermin است. اگر هیچ عنصری آن را نداشت، مستقیماً به مرحله ۳ بروید.
- 2.
- فراخوانی "supermin --build" برای ساخت اپلاینس کامل (در صورتی که نیاز به بازسازی داشته باشد). اگر موفقیتآمیز بود، اپلاینس کامل را بازگردانید.
- 3.
- بررسی "path" جهت جستجوی یک اپلاینس ثابت. در صورت یافتن، آن را بازگردانید.
- 4.
- بررسی "path" جهت جستجوی یک اپلاینس سبک قدیمی. در صورت یافتن، آن را بازگردانید.
دایرکتوری کَش اپلاینس supermin در $TMPDIR/.guestfs-$UID/ قرار دارد و حداکثر از چهار فایل تشکیل شده است:
$TMPDIR/.guestfs-$UID/lock - فایل قفل supermin $TMPDIR/.guestfs-$UID/appliance.d/kernel - کرنل $TMPDIR/.guestfs-$UID/appliance.d/initrd - تصویر initrd مربوط به supermin $TMPDIR/.guestfs-$UID/appliance.d/root - اپلاینس
ممکن است چندین نمونه از libguestfs با UID یکسان برای ایجاد یک اپلاینس دچار شرایط رقابتی (race condition) شوند. با این حال (از supermin ≥ 5 به بعد) ابزار supermin یک پرچم --lock و بهروزرسانی اتمیک زیردایرکتوری appliance.d را فراهم میکند.
تابع "lib/appliance.c:locate_or_build_appliance"
static int
locate_or_build_appliance (guestfs_h *g,
struct appliance_files *appliance,
const char *path)
بررسی "path" برای جستجوی یکی از انواع اپلاینس: اپلاینس supermin، اپلاینس ثابت یا اپلاینس سبک قدیمی. اگر یکی از اپلاینسهای ثابت پیدا شود، آن را بازمیگرداند. اگر اسکلت اپلاینس supermin پیدا شود، اپلاینس را ساخته و بازمیگرداند.
مقادیر بازگشتی:
1 = اپلاینس پیدا شد، C<appliance> را بازمیگرداند، 0 = اپلاینس پیدا نشد، -1 = خطایی که فرایند راهاندازی را لغو میکند.
تابع "lib/appliance.c:search_appliance"
static int search_appliance (guestfs_h *g, struct appliance_files *appliance)
عناصر "g->path" را جستجو کرده و اولین عنصر "appliance" را که با تابع گزارهای "locate_or_build_appliance" مطابقت دارد بازمیگرداند.
مقادیر بازگشتی:
1 = یک عنصر مسیر مطابقت داشت، C<appliance> را بازمیگرداند، 0 = هیچ عنصر مسیری مطابقت نداشت، -1 = خطایی که فرایند راهاندازی را لغو میکند.
تابع "lib/appliance.c:build_supermin_appliance"
static int
build_supermin_appliance (guestfs_h *g,
const char *supermin_path,
struct appliance_files *appliance)
اپلاینس supermin را از "supermin_path" در مسیر $TMPDIR/.guestfs-$UID میسازد.
بازگشتی: 0 = ساخته شد یا -1 = خطا (لغو راهاندازی).
تابع "lib/appliance.c:run_supermin_build"
static int
run_supermin_build (guestfs_h *g,
const char *lockfile,
const char *appliancedir,
const char *supermin_path)
دستور "supermin --build" را اجرا کرده و به آن دستور تولید اپلاینس را میدهد.
تابع "lib/appliance.c:dir_contains_file"
static int dir_contains_file (guestfs_h *g, const char *dir, const char *file)
مقدار true برمیگرداند اگر و تنها اگر "file" در "dir" وجود داشته باشد.
تابع "lib/appliance.c:dir_contains_files"
static int dir_contains_files (guestfs_h *g, const char *dir, ...)
مقدار true برمیگرداند اگر و تنها اگر تکتک فایلهای فهرستشده در "dir" وجود داشته باشند.
فایل lib/command.c
یک پوشش (wrapper) برای اجرای دستورهای خارجی، تا حدی بر پایهٔ رابط "virCommand" در libvirt.
به طور کلی برای استفاده از این رابط باید:
- 1.
- یک هندل
(دستگیره)
دستور جدید
ایجاد کنید:
struct command *cmd; cmd = guestfs_int_new_command (g);
- 2.
- یا
آرگومانها
را اضافه
کنید:
guestfs_int_cmd_add_arg (cmd, "qemu-img"); guestfs_int_cmd_add_arg (cmd, "info"); guestfs_int_cmd_add_arg (cmd, filename);
(توجه: نیازی به افزودن آرگومان "NULL" در انتها ندارید.)
- 3.
- یا با
ترکیبی از
رشتههای
نقلقولشده
(quoted) و نشده
دستوری را
بسازید.
(این شیوه
برای
دستورهای
پوسته به
سبک
system(3)/popen("r")
مفید است و
امنیت
مضاعف ناشی
از امکان
کوتیشنگذاری
صحیح
آرگومانها
را فراهم
میآورد).
guestfs_int_cmd_add_string_unquoted (cmd, "qemu-img info "); guestfs_int_cmd_add_string_quoted (cmd, filename); تنظیم پرچمهای گوناگون؛ از قبیل اینکه آیا میخواهید خطاها در گزارش خطای (error log) معمول libguestfs ثبت شوند یا خیر.
- 5.
-
اجرای دستور. این بخش فراخوانی fork(2) را انجام میدهد، بهطور اختیاری روی خروجی حلقه میزند، و سپس یک waitpid(3) انجام داده و وضعیت خروج دستور را بازمیگرداند. r = guestfs_int_cmd_run (cmd); if (r == -1) // error // else test r using the WIF* functions
- 6.
- بستن
دستگیره (handle):
guestfs_int_cmd_close (cmd);
(یا استفاده از "CLEANUP_CMD_CLOSE").
تابع "lib/command.c:guestfs_int_new_command"
struct command * guestfs_int_new_command (guestfs_h *g)
ایجاد یک دستگیره دستور (command handle) جدید.
تابع "lib/command.c:guestfs_int_cmd_add_arg"
void guestfs_int_cmd_add_arg (struct command *cmd, const char *arg)
افزودن یک آرگومان تکی (برای اجرای دستور به سبک "execv").
تابع "lib/command.c:guestfs_int_cmd_add_arg_format"
void guestfs_int_cmd_add_arg_format (struct command *cmd, const char *fs, ...)
افزودن یک آرگومان تکی (برای اجرای دستور به سبک "execv") با استفاده از رشته قالببندی به سبک printf(3).
تابع "lib/command.c:guestfs_int_cmd_add_string_unquoted"
void guestfs_int_cmd_add_string_unquoted (struct command *cmd, const char *str)
افزودن یک رشته (برای اجرای دستور به سبک system(3)).
این نوع، رشتهها را بدون قرار دادن در نقلقول اضافه میکند که در صورت داشتن محتوای غیرقابلاعتماد در رشته، خطرناک است.
تابع "lib/command.c:guestfs_int_cmd_add_string_quoted"
void guestfs_int_cmd_add_string_quoted (struct command *cmd, const char *str)
افزودن یک رشته (برای اجرای دستور به سبک system(3)).
رشته درون گیومه دوتایی (double quotes) قرار میگیرد و هر نویسه ویژه درون آن که نیاز به فراردهی (escaping) داشته باشد، فراردهی میشود. از این تابع برای افزودن یک آرگومان تکی به یک رشته دستوری به سبک system(3) استفاده میشود.
تابع "lib/command.c:guestfs_int_cmd_set_stdout_callback"
void
guestfs_int_cmd_set_stdout_callback (struct command *cmd,
cmd_stdout_callback stdout_callback,
void *stdout_data, unsigned flags)
تنظیم یک تابع فراخوان (callback) که خروجی استاندارد (stdout) را دریافت کند.
اگر flags شامل "CMD_STDOUT_FLAG_LINE_BUFFER" باشد (حالت پیشفرض)، تابع فراخوان خط به خط روی خروجی صدا زده میشود. در صورتی که یک "\n" پایانی وجود داشته باشد، پیش از فراخوانی تابع callback بهطور خودکار حذف میشود. بافر خط به "\0" ختم میشود.
اگر flags شامل "CMD_STDOUT_FLAG_UNBUFFERED" باشد، بافرها به همان صورت که از دستور دریافت میشوند به تابع callback ارسال میگردند. توجه داشته باشید در این حالت بافر به "\0" ختم نمیشود، بنابراین باید به فیلد length در تابع callback توجه کنید.
اگر flags شامل "CMD_STDOUT_FLAG_WHOLE_BUFFER" باشد، تابع callback دقیقاً یک بار با کل بافر فراخوانی میشود. توجه داشته باشید در این حالت بافر به "\0" ختم نمیشود، بنابراین باید به فیلد length در تابع callback توجه کنید.
تابع "lib/command.c:guestfs_int_cmd_set_stderr_to_stdout"
void guestfs_int_cmd_set_stderr_to_stdout (struct command *cmd)
معادل افزودن "2>&1" به انتهای دستور. این کار با پرچم "capture_errors" ناسازگار است، زیرا ترکیب آنها با یکدیگر منطقی نیست.
تابع "lib/command.c:guestfs_int_cmd_clear_capture_errors"
void guestfs_int_cmd_clear_capture_errors (struct command *cmd)
پاک کردن پرچم "capture_errors". این بدان معناست که هر خطایی به جای ثبت شدن در گزارش رویداد (event log)، به stderr فرستاده میشود که معمولاً نامطلوب است.
تابع "lib/command.c:guestfs_int_cmd_set_child_callback"
void
guestfs_int_cmd_set_child_callback (struct command *cmd,
cmd_child_callback child_callback,
void *data)
تنظیم تابعی برای اجرا در پردازه فرزند (child)، دقیقاً قبل از اجرای دستور. میتواند برای راهاندازی فرزند، مانند تغییر دایرکتوری جاری آن، استفاده شود.
تابع "lib/command.c:guestfs_int_cmd_set_child_rlimit"
void guestfs_int_cmd_set_child_rlimit (struct command *cmd, int resource, long limit)
تنظیم rlimitهای فرزند، در صورتی که فرایند در حال اجرا ممکن است فضا یا زمان زیادی مصرف کند.
تابع "lib/command.c:finish_command"
static void finish_command (struct command *cmd)
پایان دادن به کار دستور با خاتمه دادن آرایه argv با مقدار "NULL" یا افزودن نویسه پایانی "\0" به رشته، یا توقف اجرای برنامه با یک خطای داخلی در صورتی که هیچ دستوری اضافه نشده باشد.
تابع "lib/command.c:loop"
static int loop (struct command *cmd)
حلقهای که خطاها و خروجی را میخواند و آن را بر حسب مورد به گزارش (log) یا به تابع callback مربوط به stdout هدایت میکند..PP تابع "lib/command.c:guestfs_int_cmd_run"
int guestfs_int_cmd_run (struct command *cmd)
انشعاب (fork) ایجاد میکند، دستور را اجرا مینماید، روی خروجی پیمایش میکند، و waitpid را فراخوانی میکند.
وضعیت خروج (exit status) را برمیگرداند. آن را با استفاده از ماکروهای "WIF*" بررسی کنید.
در صورت بروز خطا: "error" را فراخوانی کرده و -1 را برمیگرداند.
تابع "lib/command.c:guestfs_int_cmd_pipe_run"
int guestfs_int_cmd_pipe_run (struct command *cmd, const char *mode)
انشعاب ایجاد کرده و دستور را اجرا میکند، اما منتظر نمیماند. تقریباً معادل با "popen (..., "r"|"w")" است.
توصیفکننده فایل (file descriptor) لوله (pipe) را برمیگرداند که به خروجی استاندارد ("r") یا ورودی استاندارد ("w") فرایند فرزند متصل است.
پس از خواندن یا نوشتن در این لوله، "guestfs_int_cmd_pipe_wait" را برای انتظار وضعیت فرزند فراخوانی کنید.
خطاهای زیردستور (subcommand) را نمیتوان با استفاده از این رابط در لاگ خطا ثبت کرد. در عوض فراخواننده باید (پس از اینکه "guestfs_int_cmd_pipe_wait" خطایی برگرداند) "guestfs_int_cmd_get_pipe_errors" را فراخوانی کند.
تابع "lib/command.c:guestfs_int_cmd_pipe_wait"
int guestfs_int_cmd_pipe_wait (struct command *cmd)
منتظر پایان زیرفرایند ایجادشده توسط "guestfs_int_cmd_pipe_run" میماند. در صورت بروز خطا (مانند شکست syscall) مقدار -1 را برمیگرداند و خطا را تنظیم میکند. اگر زیردستور با شکست مواجه شود، از ماکروهای "WIF*" برای بررسی آن استفاده کنید و "guestfs_int_cmd_get_pipe_errors" را جهت خواندن پیامهای خطای چاپشده توسط فرزند فراخوانی نمایید.
تابع "lib/command.c:guestfs_int_cmd_get_pipe_errors"
char * guestfs_int_cmd_get_pipe_errors (struct command *cmd)
پیامهای خطای چاپشده توسط فرزند را میخواند. فراخواننده باید بافر بازگرداندهشده را پس از استفاده آزاد (free) کند.
تابع "lib/command.c:guestfs_int_cmd_close"
void guestfs_int_cmd_close (struct command *cmd)
شیء "cmd" را بسته و تمام منابع را آزاد میکند.
تابع "lib/command.c:process_line_buffer"
static void process_line_buffer (struct command *cmd, int closed)
بافرسازی خروجی استاندارد (stdout) را برای بازخوانی (callback) مدیریت میکند.
فایل lib/conn-socket.c
این فایل اتصالها به فرایند فرزند را در مواردی که از طریق سوکتهای معمولی POSIX انجام میشود، مدیریت میکند.
تابع "lib/conn-socket.c:handle_log_message"
static int
handle_log_message (guestfs_h *g,
struct connection_socket *conn)
این تابع زمانی فراخوانی میشود که در حین انجام یکی از عملیاتهای اتصال فوق، "conn->console_sock" آماده خواندن شود. این تابع پیام لاگ را خوانده و پردازش میکند.
مقادیر بازگشتی:
- 1
- پیام(های) لاگ با موفقیت پردازش شد(ند)
- 0
- اتصال به ماشین مجازی (appliance) بسته شد
- -1
- خطا
تابع "lib/conn-socket.c:guestfs_int_new_conn_socket_listening"
struct connection *
guestfs_int_new_conn_socket_listening (guestfs_h *g,
int daemon_accept_sock,
int console_sock)
یک اتصال سوکت جدید در حالت شنود (listening) ایجاد میکند.
توجه داشته باشید که ارسال مقدار -1 برای "console_sock" مجاز است، به این معنی که هیچ کنسولی برای این ماشین مجازی در دسترس نیست.
پس از فراخوانی این تابع، مالکیت "daemon_accept_sock" در اختیار اتصال قرار میگیرد و به درستی در "accept_connection" یا "free_connection" بسته خواهد شد.
تابع "lib/conn-socket.c:guestfs_int_new_conn_socket_connected"
struct connection *
guestfs_int_new_conn_socket_connected (guestfs_h *g,
int daemon_sock,
int console_sock)
یک اتصال سوکت جدید در حالت متصلشده (connected) ایجاد میکند.
مانند بالا، با این تفاوت که فراخواننده یک "daemon_sock" متصلشده را به ما تحویل میدهد و متعهد میشود که "accept_connection" را فراخوانی نکند.
فایل lib/create.c
رابطهای برنامهنویسی (APIها) برای ایجاد دیسکهای خالی.
این بخش بیشتر شامل پوستههایی پیرامون برنامهٔ qemu-img(1) است.
تعریف "lib/create.c:VALID_FORMAT"
#define VALID_FORMAT
بررسی معتبر بودن قالب پشتیبان (backing format). هر عبارت "^[[:alnum]]+$" را (در محلیسازی C) مجاز میداند، اما طول آن را به مقداری منطقی محدود میکند.
فایل lib/drives.c
درایوهای اضافهشده در یک آرایه درون دستگیره (handle) ذخیره میشوند. کدهای این بخش آن آرایه و دادههای هر "struct drive" جداگانه را مدیریت میکنند.
تابع "lib/drives.c:create_overlay"
static int create_overlay (guestfs_h *g, struct drive *drv)
برای درایوهای فقطخواندنی، یک لایه همپوشان (overlay) ایجاد میکند تا از محتوای اصلی درایو محافظت شود. توجه داشته باشید که هرگز نیازی به پاکسازی این overlayها نیست زیرا آنها در دایرکتوری موقت ایجاد شده و هنگام بسته شدن دستگیره (handle) حذف میشوند..PP تابع "lib/drives.c:create_drive_file"
static struct drive * create_drive_file (guestfs_h *g, const struct drive_create_data *data)
ایجاد و آزادسازی "struct drive".
تابع "lib/drives.c:create_drive_dev_null"
static struct drive *
create_drive_dev_null (guestfs_h *g,
struct drive_create_data *data)
ایجاد درایو ویژهٔ /dev/null.
بهطور سنتی شما میتوانستید به هر تعداد دفعه که مایلید از /dev/null به عنوان نام فایل استفاده کنید. KVM قدیمی (RHEL 5) نمیتواند افزودن /dev/null را بهصورت readonly مدیریت کند. همچنین qemu 1.2 + virtio-scsi هنگامی که از هر فایل با اندازهٔ صفر از جمله /dev/null استفاده کنید دچار خطای segfault میشود.
به دلیل این مشکلات، ما /dev/null را با یک فایل موقت با اندازهٔ غیر صفر جایگزین میکنیم. این نباید تفاوتی ایجاد کند، چرا که قرار نیست کاربران تلاشی برای دسترسی به یک درایو null انجام دهند.
تابع "lib/drives.c:drive_to_string"
static char * drive_to_string (guestfs_h *g, const struct drive *drv)
تبدیل یک "struct drive" به یک رشته برای اشکالزدایی. فراخواننده باید این رشته را آزاد کند.
تابع "lib/drives.c:add_drive_to_handle_at"
static void add_drive_to_handle_at (guestfs_h *g, struct drive *d, size_t drv_index)
افزودن "struct drive" به بردار "g->drives" در اندیس مشخصشدهٔ "drv_index". اگر آرایه به اندازهٔ کافی بزرگ نباشد، بازتخصیص مییابد. این اندیس نباید از پیش حاوی درایو باشد.
تابع "lib/drives.c:add_drive_to_handle"
static void add_drive_to_handle (guestfs_h *g, struct drive *d)
افزودن struct drive به انتهای بردار "g->drives" در handle.
تابع "lib/drives.c:guestfs_int_add_dummy_appliance_drive"
void guestfs_int_add_dummy_appliance_drive (guestfs_h *g)
در حین راهاندازی (launch) فراخوانی میشود تا یک اسلات ساختگی به "g->drives" اضافه کند.
تابع "lib/drives.c:guestfs_int_free_drives"
void guestfs_int_free_drives (guestfs_h *g)
آزادسازی تمام درایوهای موجود در handle.
تعریف "lib/drives.c:VALID_FORMAT"
#define VALID_FORMAT
بررسی اینکه آیا پارامتر رشتهای با عبارت باقاعدهٔ "^[-_[:alnum:]]+$" (در C locale) مطابقت دارد یا خیر.
تعریف "lib/drives.c:VALID_DISK_LABEL"
#define VALID_DISK_LABEL
بررسی معقول بودن برچسب دیسک. این برچسب نمیتواند شامل نویسههای خاصی مانند '/' یا ',' باشد. با این حال، در اینجا سختگیری بیشتری اعمال شده و اطمینان حاصل میشود که تنها الفبایی بوده و طول آن ≤ 20 نویسه باشد.
تعریف "lib/drives.c:VALID_HOSTNAME"
#define VALID_HOSTNAME
بررسی معقول بودن نام میزبان (hostname) سرور.
تابع "lib/drives.c:valid_port"
static int valid_port (int port)
بررسی معقول بودن شماره پورت.
تابع "lib/drives.c:valid_blocksize"
static int valid_blocksize (int blocksize)
بررسی معقول بودن اندازهٔ بلوک. این مقدار نمیتواند چیزی جز 512 یا 4096 باشد.
تابع "lib/drives.c:guestfs_int_checkpoint_drives"
size_t guestfs_int_checkpoint_drives (guestfs_h *g)
نشانهگذاری (checkpoint) و بازگردانی (roll back) درایوها، تا گروههایی از درایوها بتوانند بهصورت اتمیک اضافه شوند. فقط توسط “guestfs_add_domain” در guestfs(3) استفاده میشود.
تابع "lib/drives.c:guestfs_impl_debug_drives"
char ** guestfs_impl_debug_drives (guestfs_h *g)
تابع داخلی برای بازگرداندن فهرست درایوها.
فایل lib/errors.c
این فایل خطاها و همچنین پیامهای اشکالزدایی (debug)، ردگیری (trace) و هشدار (warning) را مدیریت میکند.
خطاها در فراخوانیهای API در libguestfs با تنظیم یک پیام خطا و یک errno اختیاری در handle مدیریت میشوند. فراخواننده این امکان را دارد که فراخوانیهای API را بیازماید تا از شکست آنها آگاه شود و سپس آخرین خطا را از handle جویا شود، و/یا یک callback دریافت کند.
از نقطه نظر سورس کتابخانه، بهطور کلی باید در مسیرهای خطا از ماکروهای "error" یا "perrorf" استفاده کنید؛ به عنوان مثال:
if (something_bad) {
error (g, "something bad happened");
return -1;
}
اطمینان حاصل کنید که ماکروی "error" یا "perrorf" را در هر مسیر خطا دقیقاً یک بار فراخوانی کنید، چرا که handle تنها میتواند یک خطا را ذخیره کند و خطای پیشین بازنویسی خواهد شد.
تابع "lib/errors.c:guestfs_int_warning"
void guestfs_int_warning (guestfs_h *g, const char *fs, ...)
یک هشدار چاپ میکند.
کد نباید این تابع را مستقیماً فراخوانی کند. از ماکروی "warning (g, fs, ...)" استفاده کنید.
هشدارها بدون قید و شرط چاپ میشوند. ما تلاش میکنیم این موارد نادر باشند: بهطور کلی، یک هشدار یا باید یک خطا باشد، یا اگر برای کاربران نهایی اهمیتی ندارد، باید یک پیام اشکالزدایی باشد.
تابع "lib/errors.c:guestfs_int_debug"
void guestfs_int_debug (guestfs_h *g, const char *fs, ...)
یک پیام اشکالزدایی چاپ میکند.
کد نباید این تابع را مستقیماً فراخوانی کند. برای افزودن پیامهای اشکالزدایی در کتابخانه، از ماکروی "debug (g, fs, ...)" استفاده کنید. این ماکرو بررسی میکند که آیا "g->verbose" نادرست (false) است یا خیر و از فراخوانی تابع جلوگیری میکند، به این معنی که این ماکرو کارآمدتر است.
تابع "lib/errors.c:guestfs_int_trace"
void guestfs_int_trace (guestfs_h *g, const char *fs, ...)
یک پیام ردگیری (trace) چاپ میکند.
این تابع را فراخوانی نکنید. تمامی فراخوانیها بهصورت خودکار تولید میشوند.
تابع "lib/errors.c:guestfs_int_error_errno"
void guestfs_int_error_errno (guestfs_h *g, int errnum, const char *fs, ...)
آخرین خطا و errno را در دستگیره (handle) تنظیم میکند و در صورت تعریف بودن، بهصورت اختیاری کالبک خطا (error callback) را فراخوانی میکند.
اگر نیازی به تنظیم errno ندارید، به جای فراخوانی مستقیم این تابع از ماکروی "error (g, fs, ...)" استفاده کنید. اگر نیاز به تنظیم errno دارید، هیچ ماکروی پوششدهندهای وجود ندارد، بنابراین فراخوانی مستقیم این تابع بلامانع است.
تابع "lib/errors.c:guestfs_int_perrorf"
void guestfs_int_perrorf (guestfs_h *g, const char *fs, ...)
مشابه با perror(3) است، اما آخرین خطا را در دستگیره تنظیم میکند، در صورت تعریف بودن کالبک خطا آن را فراخوانی میکند، و از رشتههای قالببندی (format strings) پشتیبانی میکند.
احتمالاً باید به جای فراخوانی مستقیم این تابع، از ماکروی "perrorf (g, fs, ...)" استفاده کنید.
تابع "lib/errors.c:guestfs_int_launch_failed_error"
void guestfs_int_launch_failed_error (guestfs_h *g)
یک خطای راهاندازی ناموفق (launch failed) را در قالبی استاندارد صادر میکند.
از آنجا که این رایجترین خطایی است که افراد دارای مشکلات نصب، qemu دارای اشکال و غیره با آن مواجه میشوند، و از آنجا که هیچکس FAQ را نمیخواند، در این پیام خطا توضیح دهید چه منابعی برای اشکالزدایی مشکلات راهاندازی در دسترس هستند.
تابع "lib/errors.c:guestfs_int_unexpected_close_error"
void guestfs_int_unexpected_close_error (guestfs_h *g)
اگر appliance پس از راهاندازی بهطور غیرمنتظرهای کرش کند، خطایی صادر میکند.
تابع "lib/errors.c:guestfs_int_launch_timeout"
void guestfs_int_launch_timeout (guestfs_h *g)
اگر appliance در حین راهاندازی متوقف شود (hang کند)، خطایی صادر میکند.
تابع "lib/errors.c:guestfs_int_external_command_failed"
void
guestfs_int_external_command_failed (guestfs_h *g, int status,
const char *cmd_name, const char *extra)
اگر یک دستور خارجی ناموفق باشد، خطایی صادر میکند.
"status" کد وضعیت دستور است (مثلاً مقدار بازگرداندهشده از waitpid(2) یا system(3)). این تابع کد وضعیت را به یک رشته توضیحی تبدیل میکند.
فایل lib/events.c
تابع "lib/events.c:replace_old_style_event_callback"
static void
replace_old_style_event_callback (guestfs_h *g,
guestfs_event_callback cb,
uint64_t event_bitmask,
void *opaque,
void *opaque2)
API کالبک سبک قدیمی را شبیهسازی میکند.
هیچ دستگیره رویدادی (event handle) وجود نداشت، بنابراین چندین کالبک به ازای هر رویداد پشتیبانی نمیشد. فراخوانی همان تابع "guestfs_set_*_callback" جایگزین رویداد موجود میشد. فراخوانی آن با "cb == NULL" به این معنی بود که فراخواننده میخواست کالبک را حذف کند.
فایل lib/guestfs-internal-all.h
این هدر شامل تعاریفی است که میان تمام بخشهای libguestfs مشترک است، یعنی دیمن، کتابخانه، بایندرهای زبان و ابزارهای virt (یعنی تمام کدهای C).
اگر به تعریفی نیاز دارید که فقط توسط کتابخانه استفاده میشود، در عوض آن را در lib/guestfs-internal.h قرار دهید.
اگر یک تعریف تنها توسط یک ابزار منفرد استفاده میشود، اصلاً نباید در هیچ فایل هدر مشترکی قرار گیرد.
فایل lib/guestfs-internal.h
این فایل هدر تنها در کتابخانه libguestfs (lib/) گنجانده شده است.
همچنین نگاه کنید به lib/guestfs-internal-all.h.
ساختار "lib/guestfs-internal.h:event"
struct event {
uint64_t event_bitmask;
guestfs_event_callback cb;
void *opaque;
/* opaque2 is not exposed through the API, but is used internally to
* emulate the old-style callback API.
*/
void *opaque2;
};
این struct برای نگهداری فهرستی از رویدادهای ثبتشده در
handle استفاده میشود. "g->events" را در handle ببینید.
ساختار "lib/guestfs-internal.h:drive"
struct drive {
/* منبع اصلی درایو، مثلاً file:...، http:... */
struct drive_source src;
/* اگر درایو readonly باشد، آنگاه یک overlay [یک فایل محلی] پیش از
* launch ایجاد میشود تا از محتوای اصلی درایو محافظت کند، و
* نام فایل در اینجا ذخیره میشود. Backends باید این فایل را در صورت
* non-NULL بودن باز کنند، در غیر این صورت به منبع اصلی بالا رجوع کنند.
*
* توجه داشته باشید که overlay در قالبی وابسته به backend است، که احتمالاً
* با قالب منبع متفاوت است. مانند qcow2
*/
char *overlay;
/* پرچمهای گوناگون به ازای هر درایو. */
bool readonly;
char *name;
char *disk_label;
char *cachemode;
enum discard discard;
bool copyonread;
int blocksize;
};
به ازای هر درایو یک "struct drive" وجود دارد.
ساختار "lib/guestfs-internal.h:backend_ops"
struct backend_ops {
/* اندازه (به بایت) ساختار داده به ازای هر handle که این backend
* به آن نیاز دارد. اشارهگر data توسط libguestfs تخصیص یافته و آزاد میشود
* و به توابع در پارامتر 'void *data' فرستاده میشود.
* درون ساختار داده برای libguestfs مات (opaque) است. هر رشته و
* مواردی از این دست که به آن اشاره دارد باید توسط backend در طول
* shutdown آزاد شوند.
*/
size_t data_size;
/* ایجاد یک overlay از نوع COW بر روی یک درایو. این باید یک فایل
* محلی باشد که در دایرکتوری موقت ایجاد شده است. این تابع زمانی
* فراخوانی میشود که درایو به handle اضافه شود.
*/
char *(*create_cow_overlay) (guestfs_h *g, void *data, struct drive *drv);
/* دریافت hypervisor پیشفرض (qemu)، در صورتی که کاربر با
* فراخوانی guestfs_set_hv یا تنظیم LIBGUESTFS_HV آن را بازنویسی نکند.
*/
const char *(*get_default_hv) (guestfs_h *g, void *data);
/* راهاندازی (Launch) و خاموش کردن (shutdown). */
int (*launch) (guestfs_h *g, void *data, const char *arg);
int (*shutdown) (guestfs_h *g, void *data, int check_for_errors);
/* متفرقه. */
int (*get_pid) (guestfs_h *g, void *data);
int (*max_disks) (guestfs_h *g, void *data);
};
عملیاتهای backend.
هر backend (مانند libvirt، direct) توابعی را تعریف میکند که در نقاط مختلفی از چرخهٔ حیات handle (مثلاً هنگام راهاندازی (launch) یا خاموش شدن (shutdown)) اجرا میشوند. backend این struct را اشارهکننده به آن توابع تعریف میکند.
ساختار "lib/guestfs-internal.h:connection"
struct connection {
const struct connection_ops *ops;
/* در struct واقعی، دادههای اختصاصی مورد استفاده توسط هر ماژول connection
* در اینجا قرار میگیرد.
*/
};
ماژول اتصال (Connection module).
یک "connection" نشاندهندهٔ اتصال کنسول appliance به همراه اتصال daemon است. این ساختار بازنمود زیرین (سوکتهای POSIX، "virStreamPtr") را پنهان میکند.
ساختار "lib/guestfs-internal.h:cached_feature"
struct cached_feature {
char *group;
int result;
};
کَش ویژگیهای استعلامشده.
برای کَش کردن ویژگیهای appliance استفاده میشود (lib/available.c را ببینید).
ساختار "lib/guestfs-internal.h:guestfs_h"
struct guestfs_h {
struct guestfs_h *next; /* فهرست پیوندی از handleهای باز. */
enum state state; /* نمودار ماشین حالت را در guestfs(3) ببینید */
/* قفلی که هنگام ورود به هر تابع عمومی guestfs_* برای
* محافظت از handle دریافت میشود.
*/
pthread_mutex_t lock;
/**** پیکربندی handle. ****/
bool verbose; /* اشکالزدایی. */
bool trace; /* ردگیری فراخوانیها. */
bool autosync; /* همگامسازی خودکار. */
bool direct_mode; /* حالت مستقیم. */
bool recovery_proc; /* ایجاد یک فرایند بازیابی. */
bool enable_network; /* فعالسازی شبکه. */
bool selinux; /* آیا selinux فعال است؟ */
bool pgroup; /* ایجاد گروه فرایند برای فرزندان؟ */
bool close_on_exit; /* آیا این handle در فهرست atexit قرار دارد؟ */
int smp; /* اگر > 1 باشد، پرچم -smp به hv ارسال میشود. */
int memsize; /* اندازه RAM (مگابایت). */
char *path; /* مسیر به appliance. */
char *hv; /* باینری Hypervisor (HV). */
char *append; /* الحاق به خط فرمان کرنل. */
struct hv_param *hv_params; /* پارامترهای اضافی hv. */
char *program; /* نام برنامه. */
char *identifier; /* شناسه handle. */
/* آرایهای از درایوهای اضافهشده توسط APIهای add-drive*.
*
* پیش از launch این فهرست میتواند خالی باشد یا شامل چند درایو باشد.
*
* هنگام launch، ممکن است یک اسلات ساختگی (dummy) اضافه شود که نشاندهندهٔ
* اسلات اشغالشده توسط درایو appliance است.
*
* هنگام shutdown، این فهرست حذف میشود، تا هر launch یک مجموعهٔ
* تازه از درایوها دریافت کند (با این حال فراخوانها: این کار را انجام ندهید،
* هر بار یک handle جدید ایجاد کنید).
*
* همواره از ماکروی ITER_DRIVES برای پیمایش روی این فهرست استفاده کنید!
*/
struct drive **drives;
size_t nr_drives;
#define ITER_DRIVES(g,i,drv) \
for (i = 0; i < (g)->nr_drives; ++i) \
if (((drv) = (g)->drives[i]) != NULL)
/* Backend. توجه: از guestfs_int_set_backend برای تغییر backend استفاده کنید. */
char *backend; /* رشته کامل، همیشه non-NULL. */
char *backend_arg; /* اشارهگر به بخش آرگومان. */
const struct backend_ops *backend_ops;
void *backend_data; /* داده به ازای هر handle. */
char **backend_settings; /* تنظیمات backend (میتواند NULL باشد). */
/**** اطلاعات زمان اجرا (Runtime). ****/
/* دایرکتوریهای موقت و حافظه موقت (کَش). */
/* دایرکتوری موقت واقعی - این دایرکتوری همراه با handle ایجاد نمیشود،
* شما باید guestfs_int_lazy_make_tmpdir را فراخوانی کنید.
*/
char *tmpdir;
char *sockdir;
/* متغیرهای محیطی که مکانهای tmpdir/cachedir/sockdir را تحت تأثیر قرار میدهند. */
char *env_tmpdir; /* $TMPDIR (اگر تنظیم نشده باشد NULL) */
char *env_runtimedir; /* $XDG_RUNTIME_DIR (اگر تنظیم نشده باشد NULL)*/
char *int_tmpdir; /* $LIBGUESTFS_TMPDIR یا guestfs_set_tmpdir یا NULL */
char *int_cachedir; /* $LIBGUESTFS_CACHEDIR یا guestfs_set_cachedir یا NULL */
/* کنترلکننده خطا، به همراه پشتهای از کنترلکنندههای خطای قدیمی. */
pthread_key_t error_data;
/* فهرست پیوندی از ساختارهای error_data تخصیصیافته برای این handle،
* به همراه یک mutex برای محافظت از فهرست پیوندی.
*/
pthread_mutex_t error_data_list_lock;
struct error_data *error_data_list;
/* کنترلکننده خطای کمبود حافظه (Out of memory). */
guestfs_abort_cb abort_cb;
/* رویدادها. */
struct event *events;
size_t nr_events;
/* ناحیه داده خصوصی. */
struct hash_table *pda;
struct pda_entry *pda_next;
/* انتقال لغوشده توسط کاربر. به صورت signal-atomic نیست، اما
* در این مورد اهمیتی ندارد زیرا فقط != 0 بودن آن برای ما مهم است.
*/
int user_cancel;
struct timeval launch_t; /* زمانی که ما guestfs_launch را فراخوانی کردیم. */
/* مورد استفاده bindtests. */
FILE *test_fp;
/* برای تولید اعداد یکتا، مثلاً برای فایلهای موقت، استفاده میشود. برای استفاده،
* '++g->unique'. توجه داشته باشید اینها فقط به ازای هر handle یکتا هستند،
* نه به صورت سراسری.
*/
int unique;
/*** پروتکل. ***/
struct connection *conn; /* اتصال به appliance. */
int msg_next_serial;
#if HAVE_FUSE
/**** مورد استفاده APIهای mount-local. ****/
char *localmountpoint;
struct fuse *fuse; /* دستگیره FUSE handle. */
int ml_dir_cache_timeout; /* مهلت زمانی کَش دایرکتوری. */
Hash_table *lsc_ht, *xac_ht, *rlc_ht; /* کَش دایرکتوری. */
int ml_read_only; /* اگر به صورت فقطخواندنی mount شده باشد. */
int ml_debug_calls; /* اطلاعات اشکالزدایی اضافی در هر فراخوانی FUSE. */
#endif
#ifdef HAVE_LIBVIRT
/* مورد استفاده lib/libvirt-auth.c. */
#define NR_CREDENTIAL_TYPES 9
unsigned int nr_supported_credentials;
int supported_credentials[NR_CREDENTIAL_TYPES];
const char *saved_libvirt_uri; /* نیازی به آزاد شدن ندارد. */
bool wrapper_warning_done;
unsigned int nr_requested_credentials;
virConnectCredentialPtr requested_credentials;
#endif
/* ویژگیهای کَششده. */
struct cached_feature *features;
size_t nr_features;
/* مورد استفاده lib/info.c. مقدار -1 = آزمایشنشده یا خطا؛ وگرنه 0 یا 1. */
int qemu_img_supports_U_option;
};
دستگیرهٔ libguestfs.
ساختار "lib/guestfs-internal.h:version"
struct version {
int v_major;
int v_minor;
int v_micro;
};
برای ذخیره شمارههای نگارش major.minor.micro به کار میرود. برای اطلاعات بیشتر به lib/version.c مراجعه کنید.
فایل lib/guid.c
تابع "lib/guid.c:guestfs_int_validate_guid"
int guestfs_int_validate_guid (const char *str)
بررسی میکند که آیا رشتهای که قرار است حاوی یک GUID باشد واقعاً شامل آن است یا خیر. این تابع میتواند رشتهها را به هر یک از دو صورت "{21EC2020-3AEA-1069-A2DD-08002B30309D}" یا "21EC2020-3AEA-1069-A2DD-08002B30309D" شناسایی کند.
فایل lib/handle.c
این فایل به دستگیرهٔ "guestfs_h"، ایجاد آن، بستن آن، و راهاندازی/تنظیم/دریافت فیلدها میپردازد.
تابع "lib/handle.c:init_libguestfs"
static void init_libguestfs (void)
هیچ راهاندازی اولیهای از سوی libguestfs لازم نیست، اما اگر احتمال فراخوانی libvirt و libxml2 از چندین رشته (thread) وجود داشته باشد، آنها نیاز به مقداردهی اولیه دارند. از این رو، این تابع سازنده (constructor) هنگامی که libguestfs برای نخستین بار بارگذاری میشود، فراخوانی میگردد.
تابع "lib/handle.c:shutdown_backend"
static int shutdown_backend (guestfs_h *g, int check_for_errors)
این تابع مسیر مشترک برای متوقف کردن پردازهٔ پشتیبان qemu است.
تابع "guestfs_shutdown"، تابع "shutdown_backend" را با "check_for_errors=1" فراخوانی میکند. "guestfs_close"، "shutdown_backend" را با "check_for_errors=0" فراخوانی میکند.
"check_for_errors" اشارهای به پشتیبان دربارهٔ این است که آیا خطاها برای ما مهم هستند یا خیر. در مورد libvirt میتوان از آن برای بهینهسازی سرعت متوقفسازی هنگامی که خطاها اهمیتی ندارند استفاده کرد.
تابع "lib/handle.c:close_handles"
static void close_handles (void)
بستن تمام دستگیرههای باز (فراخوانیشده از atexit(3)).
تابع "lib/handle.c:guestfs_int_get_backend_setting_bool"
int guestfs_int_get_backend_setting_bool (guestfs_h *g, const char *name)
این یک تابع کمکی است، اما ممکن است در آینده خروجی دادن آن را به عنوان یک API مد نظر قرار دهیم.
فایل lib/info.c
تابع "lib/info.c:qemu_img_supports_U_option"
static int qemu_img_supports_U_option (guestfs_h *g)
بررسی میکند که آیا دستور qemu-img info از گزینهٔ "-U" برای غیرفعال کردن قفلگذاری پشتیبانی میکند یا خیر. نتیجه در دستگیره به خاطر سپرده (memoized) میشود.
توجه داشته باشید این گزینه در qemu 2.11 اضافه شد. زمانی که بتوانیم فرض کنیم همه از qemu >= 2.11 استفاده میکنند، میتوانیم این آزمون را حذف کنیم.
فایل lib/inspect-icon.c
تابع "lib/inspect-icon.c:guestfs_int_download_to_tmp"
char *
guestfs_int_download_to_tmp (guestfs_h *g, const char *filename,
const char *extension,
uint64_t max_size)
بارگیری یک فایل مهمان به یک فایل موقت محلی.
نام فایل موقت (بارگیریشده) بازگردانده میشود. فراخواننده باید اشارهگر را آزاد کند (free)، اما نیازی نیست فایل موقت را حذف کند. این فایل هنگام بسته شدن دستگیره حذف خواهد شد.
نام فایل موقت به صورت تصادفی تولید میشود، اما میتوان با استفاده از "extension" یک پسوند برای آن مشخص کرد (یا برای نداشتن پسوند مقدار "NULL" ارسال کرد).
در صورتی که فایل مهمان بزرگتر از "max_size" باشد، از بارگیری آن خودداری میشود. در این حالت و هنگام بروز سایر خطاها، مقدار "NULL" بازگردانده میشود.
فایل lib/launch-direct.c
پیادهسازی پشتیبان "direct".
برای جزئیات بیشتر بخش "BACKENDS" را در guestfs(3) ببینید.
تابع "lib/launch-direct.c:add_drive_standard_params"
static int
add_drive_standard_params (guestfs_h *g, struct backend_direct_data *data,
struct qemuopts *qopts,
size_t i, struct drive *drv)
عناصر استاندارد پارامتر "-drive" را اضافه میکند.
تابع "lib/launch-direct.c:add_device_blocksize_params"
static int
add_device_blocksize_params (guestfs_h *g, struct qemuopts *qopts,
struct drive *drv)
عناصر physical_block_size و logical_block_size مربوط به پارامتر "-device" را اضافه میکند.
تابع "lib/launch-direct.c:launch_passt"
static int launch_passt (guestfs_h *g, long *passt_pid, char (*sockpath)[UNIX_PATH_MAX])
ابزار passt را بهگونهای اجرا میکند که به یک دیمون تبدیل شود (daemonize شود).
در صورت بروز خطا، مقدار -1 بازگردانده میشود؛ "passt_pid" و "sockpath" تغییر داده نمیشوند.
در صورت موفقیت، مقدار 0 بازگردانده میشود. "passt_pid" شامل PID پردازهٔ پسزمینهٔ passt خواهد بود. "sockpath" شامل مسیر سوکت دامنهٔ یونیکس (unix domain socket) است که passt در آن یک اتصال منفرد را میپذیرد..PP فایل lib/launch-libvirt.c
تابع "lib/launch-libvirt.c:get_source_format_or_autodetect"
static char * get_source_format_or_autodetect (guestfs_h *g, struct drive *drv)
مقدار "drv->src.format" را بازمیگرداند، اما اگر "NULL" باشد، قالب را بهطور خودکار تشخیص میدهد.
libvirt قابلیت تشخیص خودکار قالب دیسک را غیرفعال کرده است، مگر اینکه مدیر سیستم مقدار "allow_disk_format_probing=1" را در /etc/libvirt/qemu.conf تنظیم کرده باشد. هیچ راهی برای تشخیص اینکه آیا این گزینه تنظیم شده است وجود ندارد، بنابراین ما باید تشخیص قالب را در اینجا با استفاده از "qemu-img" انجام دهیم و آن را به libvirt ارسال کنیم.
این موضوع همچنان میتواند یک مشکل امنیتی باشد، بنابراین در اکثر موارد به کاربران توصیه میشود که قالب را به libguestfs مشخص کنند تا مستقیماً و بدون انجام تشخیص خودکار، به libvirt ارسال شود.
فراخواننده باید رشته بازگرداندهشده را آزاد (free) کند. در صورت بروز خطا، این تابع خطا را در هندل تنظیم کرده و "NULL" را برمیگرداند.
تابع "lib/launch-libvirt.c:make_qcow2_overlay"
static char *
make_qcow2_overlay (guestfs_h *g, const char *backing_drive,
const char *format)
یک لایه همپوشان (overlay) با قالب qcow2 بر روی "backing_drive" (فایل) مشخصشده ایجاد میکند. پارامتر "format" قالب فایل پشتیبان (backing file) است. پارامتر "format" میتواند NULL باشد که در این حالت قالب فایل پشتیبان بهطور خودکار تعیین میشود. از این تابع برای ایجاد overlay مربوط به appliance و همچنین برای درایوهای فقطخواندنی استفاده میشود.
فایل lib/launch.c
این فایل "guestfs_launch" در guestfs(3) را پیادهسازی میکند.
بیشتر کارها توسط بکاندها انجام میشود (بخش "BACKEND" در guestfs(3) را ببینید) که در lib/launch-direct.c، lib/launch-libvirt.c و غیره پیادهسازی شدهاند؛ بنابراین این فایل بیشتر فراخوانیها را به backend فعلی هدایت میکند.
تابع "lib/launch.c:guestfs_int_launch_send_progress"
void guestfs_int_launch_send_progress (guestfs_h *g, int perdozen)
این تابع یک پیام پیشرفت راهاندازی ارسال میکند.
راهاندازی appliance پیامهای تقریبی پیشرفت تولید میکند. در حال حاضر این پیامها به صورت زیر تعریف شدهاند:
0 / 12: launch clock starts 3 / 12: appliance created 6 / 12: detected that guest kernel started 9 / 12: detected that /init script is running 12 / 12: launch completed successfully
نکات:
- 1.
- این یک ABI مستندسازیشده نیست و ممکن است رفتار آن در آینده تغییر کند یا حذف شود.
- 2.
- پیامها فقط در صورتی ارسال میشوند که بیش از ۵ ثانیه از شروع زمان راهاندازی سپری شده باشد.
- 3.
- یک ترفند در lib/proto.c برای عملکرد این بخش وجود دارد.
تابع "lib/launch.c:guestfs_int_timeval_diff"
int64_t guestfs_int_timeval_diff (const struct timeval *x, const struct timeval *y)
مقدار "y - x" را محاسبه کرده و نتیجه را بر حسب میلیثانیه برمیگرداند.
تقریباً مشابه این کد است: http://www.mpp.mpg.de/~huber/util/timevaldiff.c
تابع "lib/launch.c:guestfs_int_unblock_sigterm"
void guestfs_int_unblock_sigterm (void)
مسدودیت سیگنال "SIGTERM" را لغو میکند. این تابع را پس از fork(2) فراخوانی کنید تا در صورتی که "SIGTERM" مسدود شده باشد، فرایند والد بتواند "SIGTERM" را به فرایند فرزند ارسال کند. ببینید: https://bugzilla.redhat.com/1460338.
تابع "lib/launch.c:guestfs_impl_max_disks"
int guestfs_impl_max_disks (guestfs_h *g)
حداکثر تعداد دیسکهای مجاز برای افزودن به backend را بازمیگرداند (وابسته به backend).
تابع "lib/launch.c:guestfs_impl_wait_ready"
int guestfs_impl_wait_ready (guestfs_h *g)
پیادهسازی "guestfs_wait_ready" در guestfs(3). در نسخههای ≤ 1.0.70 لازم بود این تابع پس از راهاندازی فراخوانی شود، اما اکنون (تقریباً) یک دستور بیاثر (no-op) است.
تابع "lib/launch.c:guestfs_int_register_backend"
void guestfs_int_register_backend (const char *name, const struct backend_ops *ops)
هنگامی که کتابخانه بارگذاری میشود، هر backend این تابع را فراخوانی میکند تا خود را در یک فهرست سراسری ثبت کند.
تابع "lib/launch.c:guestfs_int_set_backend"
int guestfs_int_set_backend (guestfs_h *g, const char *method)
پیادهسازی "guestfs_set_backend" در guestfs(3).
- فراخوانندگان باید اطمینان حاصل کنند که این تابع فقط در وضعیت پیکربندی (config) فراخوانی شود.
- این تابع نباید "error" را فراخوانی کند، زیرا ممکن است در اوایل مقداردهی اولیه هندل صدا زده شود. با این حال میتواند یک کد خطا بازگرداند.
تابع "lib/launch.c:guestfs_int_passt_runnable"
bool guestfs_int_passt_runnable (guestfs_h *g)
اگر بتوان دستور "passt --help" را فراخوانی کرد و با وضعیت خروج 0 یا 1 خاتمه یابد، مقدار "true" را برمیگرداند.
(دستکم نسخه "passt-0^20230222.g4ddbcb9-2.el9_2.x86_64" در پاسخ به "--help" با وضعیت خروج 1 خارج میشود، که مسلماً نادرست است و احتمالاً در آینده تغییر خواهد کرد، اما واقعاً تأثیری ندارد.)
فایل lib/private-data.c
یک ناحیه داده اختصاصی پیادهسازی میکند که کاربران C API مربوط به libguestfs میتوانند دادههای دلخواه را به هندل "guestfs_h" متصل کنند.
برای اطلاعات بیشتر، بخش "PRIVATE DATA AREA" در guestfs(3) را ببینید..PP بستهبندیهای زبانی (Language bindings) عموماً این مورد را ارائه نمیدهند، تا حد زیادی به این دلیل که در زبانهای غیر از C، مرتبط ساختن دادهها با هندلها (handles) به روشهای دیگر (با استفاده از جدولهای درهمسازی یا نگاشتها) آسان است.
ساختار "lib/private-data.c:pda_entry"
struct pda_entry {
char *key; /* key */
void *data; /* opaque user data pointer */
};
ناحیه دادههای خصوصی بهصورت داخلی در قالب یک جدول درهمسازی gnulib حاوی ساختارهای "pda_entry" ذخیره میشود.
توجه داشته باشید که ناحیه دادههای خصوصی بهصورت تنبل (lazily) تخصیص مییابد، زیرا اکثریت قریب به اتفاق فراخوانندهها هرگز از آن استفاده نخواهند کرد. این بدان معناست که "g->pda" احتمالاً "NULL" خواهد بود.
فایل lib/proto.c
این کدی است که برای ارسال و دریافت پیامهای RPC و (برای انواع خاصی از پیامها) جهت انجام انتقال فایل استفاده میشود. این کد توسط کنشهای تولیدشده (lib/actions-*.c) هدایت میشود. پنج حالت مختلف برای بررسی وجود دارد:
- 1.
- یک تابع غیردیمن (مانند «guestfs_set_verbose» در guestfs(3)). هیچ RPCای اصلاً در کار نیست و همهچیز در داخل کتابخانه رسیدگی میشود.
- 2.
- یک RPC ساده
(مانند «guestfs_mount»
در guestfs(3)). ما
درخواست را
مینویسیم،
سپس پاسخ را
میخوانیم.
توالی
فراخوانیها
به این صورت
است:
guestfs_int_send guestfs_int_recv
- 3.
- یک RPC با
پارامترهای
"FileIn"
(مانند «guestfs_upload»
در guestfs(3)). ما
درخواست را
مینویسیم،
سپس
فایل(ها) را
ارسال
میکنیم، و
سپس پاسخ را
میخوانیم.
توالی
فراخوانیها
به این صورت
است:
guestfs_int_send guestfs_int_send_file (possibly multiple times) guestfs_int_recv
- 4.
- یک RPC با
پارامترهای
"FileOut"
(مانند «guestfs_download»
در guestfs(3)). ما
درخواست را
مینویسیم،
سپس پاسخ را
میخوانیم،
و سپس
فایل(ها) را
دریافت
میکنیم.
توالی
فراخوانیها
به این صورت
است:
guestfs_int_send guestfs_int_recv guestfs_int_recv_file (possibly multiple times)
- 5.
- هر دو پارامتر "FileIn" و "FileOut". در API فعلی هیچ فراخوانیای به این شکل وجود ندارد، اما در صورت وجود، به عنوان ترکیبی از موارد ۳ و ۴ پیادهسازی میشوند.
تمامی عملیات خواندن/نوشتن/غیره با استفاده از ماژول اتصال فعلی ("g->conn") انجام میشوند. در حین عملیات، ماژول اتصال پیامهای لاگی (log) را که روی کنسول ظاهر میشوند، بهصورت شفاف مدیریت میکند.
تابع "lib/proto.c:child_cleanup"
static void child_cleanup (guestfs_h *g)
این تابع زمانی فراخوانی میشود که EOF تشخیص داده شود، یعنی qemu متوقف شده باشد.
تابع "lib/proto.c:guestfs_int_progress_message_callback"
void
guestfs_int_progress_message_callback (guestfs_h *g,
const guestfs_progress *message)
پوششدهندهای راحت برای تولید کالبک پیام پیشرفت.
تابع "lib/proto.c:guestfs_int_log_message_callback"
void guestfs_int_log_message_callback (guestfs_h *g, const char *buf, size_t len)
ماژولهای اتصال هنگامی که یک پیام لاگ دریافت میکنند، با این تابع فراخوانی برگشتی انجام میدهند.
تابع "lib/proto.c:check_daemon_socket"
static ssize_t check_daemon_socket (guestfs_h *g)
پیش از نوشتن روی سوکت دیمن، بخش خواندن سوکت دیمن را برای هر یک از این شرایط بررسی کنید:
- خطا
- بازگرداندن -1
- پیام لغو دیمن
- بازگرداندن -2
- پیام پیشرفت
- در همینجا رسیدگی میشود
- پایان ورودی یا خروج غیرمنتظره ماشین (appliance)
- بازگرداندن 0
- هر چیز دیگر
- بازگرداندن 1
تابع "lib/proto.c:guestfs_int_send_file"
int guestfs_int_send_file (guestfs_h *g, const char *filename)
ارسال یک فایل.
در صورت موفقیت مقدار 0، در صورت بروز خطا مقدار -1، و در صورتی که دیمن عملیات را لغو کرده باشد (باید پیام خطا را بخوانیم) مقدار -2 را برمیگرداند.
تابع "lib/proto.c:send_file_data"
static int send_file_data (guestfs_h *g, const char *buf, size_t len)
ارسال یک قطعه (chunk) از دادههای فایل.
تابع "lib/proto.c:send_file_cancellation"
static int send_file_cancellation (guestfs_h *g)
ارسال پیام لغو.
تابع "lib/proto.c:send_file_complete"
static int send_file_complete (guestfs_h *g)
ارسال قطعه اتمام فایل.
تابع "lib/proto.c:recv_from_daemon"
static int recv_from_daemon (guestfs_h *g, uint32_t *size_rtn, void **buf_rtn)
این تابع یک پیام، قطعه فایل، پرچم راهاندازی یا پرچم لغو تکی را از دیمن میخواند. اگر چیزی خوانده شود، مقدار 0 و در غیر این صورت -1 را برمیگرداند..PP هر دو پارامتر "size_rtn" و "buf_rtn" باید توسط فراخواننده به صورت non-NULL ارسال شوند.
مقدار *size_rtn اندازه پیام بازگردانده شده را برمیگرداند یا ممکن است "GUESTFS_LAUNCH_FLAG" یا "GUESTFS_CANCEL_FLAG" باشد.
مقدار *buf_rtn حاوی پیام (در صورت وجود) بازگردانده میشود یا بر روی "NULL" تنظیم خواهد شد. *buf_rtn باید توسط فراخواننده آزاد (free) شود.
این بررسی برای EOF (از کار افتادن appliance) انجام میشود و آن را از طریق تابع child_cleanup در بالا به سطوح بالاتر منتقل میکند.
پیامهای ثبت وقایع (log) و پیامهای پیشرفت در اینجا به صورت شفاف مدیریت میشوند.
تابع "lib/proto.c:guestfs_int_recv"
int
guestfs_int_recv (guestfs_h *g, const char *fn,
guestfs_message_header *hdr,
guestfs_message_error *err,
xdrproc_t xdrp, char *ret)
یک پاسخ دریافت میکند.
تابع "lib/proto.c:guestfs_int_recv_discard"
int guestfs_int_recv_discard (guestfs_h *g, const char *fn)
مشابه "guestfs_int_recv" است، اما پیام پاسخ را نادیده میگیرد (دور میریزد).
نکات (XXX):
- این تابع یک مقدار int برمیگرداند، اما همه فراخوانندههای کنونی آن را نادیده میگیرند.
- رشته خطا ممکن است در مسیرهای خطا دو بار مقداردهی شود.
تابع "lib/proto.c:guestfs_int_recv_file"
int guestfs_int_recv_file (guestfs_h *g, const char *filename)
مقادیر بازگشتی: -1 = خطا، 0 = EOF، ">0" = داده بیشتر
تابع "lib/proto.c:receive_file_data"
static ssize_t receive_file_data (guestfs_h *g, void **buf_r)
یک تکه (chunk) از دادههای فایل را دریافت میکند.
مقادیر بازگشتی: -1 = خطا، 0 = EOF، ">0" = داده بیشتر
فایل lib/qemu.c
توابعی برای مدیریت نسخهها و قابلیتهای qemu.
تابع "lib/qemu.c:generic_qmp_test"
static int
generic_qmp_test (guestfs_h *g,
const char *qemu, const char *qmp_command, char **outp)
اجرای یک آزمون عمومی QMP بر روی فایل باینری QEMU.
تابع "lib/qemu.c:parse_has_kvm"
static int parse_has_kvm (guestfs_h *g, const char *json)
تجزیه خروجی json از دستور query-kvm در QMP برای پی بردن به اینکه آیا KVM روی این ماشین فعال است یا خیر.
خروجی JSON شبیه به این است: {"return": {"enabled": true, "present": true}}
تابع "lib/qemu.c:guestfs_int_platform_has_kvm"
int guestfs_int_platform_has_kvm (guestfs_h *g, const char *qemu)
آزمایش اینکه آیا بستر (platform) از KVM پشتیبانی میکند یا خیر.
تنها qemu این موضوع را به طور موثق «میداند»، بنابراین ما qemu را اجرا کرده، با استفاده از دستور QMP به نام «query-kvm» وضعیت را استعلام میکنیم، و خروجی JSON حاصل از آن دستور را تجزیه مینماییم.
تابع "lib/qemu.c:guestfs_int_qemu_escape_param"
char * guestfs_int_qemu_escape_param (guestfs_h *g, const char *param)
گریزدهی (escape) یک پارامتر qemu.
هر "," تبدیل به ",," میشود. فراخواننده باید رشته بازگردانده شده را آزاد کند.
XXX این قابلیت در حال حاضر تنها هنگام ساخت دستور qemu-img در lib/create.c استفاده میشود. ما باید کتابخانه qemuopts را گسترش دهیم تا این مورد کاربرد را پوشش دهد.
تابع "lib/qemu.c:guestfs_int_drive_source_qemu_param"
char *
guestfs_int_drive_source_qemu_param (guestfs_h *g,
const struct drive_source *src)
تابعی کاربردی برای قالببندی درایو + پروتکل برای qemu.
توجه داشته باشید که پارامتر qemu بخش بعد از "file=" است. این مقدار در اینجا گریزدهی نمیشود، اما اگر به عنوان بخشی از یک پارامتر کامل -drive به qemu ارسال شود معمولاً باید گریزدهی شود (اما نه برای qemu-img(1)).
تابع "lib/qemu.c:guestfs_int_discard_possible"
bool guestfs_int_discard_possible (guestfs_h *g, struct drive *drv)
آزمایش اینکه آیا discard با فایل یا دستگاه زیربنایی امکانپذیر است یا خیر. این تابع در صورت ممکن بودن discard مقدار 1 را برمیگرداند. در صورت غیرممکن بودن مقدار 0 را برگردانده و خطا را روی دلیل آن تنظیم میکند.
این تابع زمانی فراخوانی میشود که کاربر "discard == "enable"" را تنظیم کرده باشد.
فایل lib/rescue.c
پشتیبانی از virt-rescue(1).
فایل lib/stringsbuf.c
یک بردار قابل گسترش خاتمهیافته به NULL از رشتهها (مشابه "argv").
برای تعریف stringsbuf از ماکروی "DECLARE_STRINGSBUF" استفاده کنید.
نکته: این ساختار را با stringsbuf در دیمِن (daemon) اشتباه نگیرید؛ آن ساختار نوع دیگری با متدهای متفاوت است.
تابع "lib/stringsbuf.c:guestfs_int_add_string_nodup"
void guestfs_int_add_string_nodup (guestfs_h *g, struct stringsbuf *sb, char *str)
افزودن یک رشته به انتهای فهرست.
این تابع strdup(3) را روی رشته فراخوانی نمیکند، بنابراین خود رشته در داخل بردار ذخیره میشود..PP تابع "lib/stringsbuf.c:guestfs_int_add_string"
void guestfs_int_add_string (guestfs_h *g, struct stringsbuf *sb, const char *str)
افزودن یک رشته به انتهای فهرست.
این تابع یک رونوشت از رشته تهیه میکند.
تابع "lib/stringsbuf.c:guestfs_int_add_sprintf"
void
guestfs_int_add_sprintf (guestfs_h *g, struct stringsbuf *sb,
const char *fs, ...)
افزودن یک رشته به انتهای فهرست.
هنگام ایجاد رشته، از یک رشتهٔ قالب مشابه -sprintf استفاده میکند.
تابع "lib/stringsbuf.c:guestfs_int_end_stringsbuf"
void guestfs_int_end_stringsbuf (guestfs_h *g, struct stringsbuf *sb)
پایان دادن به بافر رشته.
این کار NULL پایانی را به انتهای بردار اضافه میکند.
تابع "lib/stringsbuf.c:guestfs_int_free_stringsbuf"
void guestfs_int_free_stringsbuf (struct stringsbuf *sb)
آزادسازی بافر رشته و رشتهها.
فایل lib/tmpdirs.c
مدیریت دایرکتوریهای موقت.
تابع "lib/tmpdirs.c:set_abs_path"
static int
set_abs_path (guestfs_h *g, const char *ctxstr,
const char *tmpdir, char **tmpdir_ret)
ما باید تمام مسیرهای tmpdir را مطلق کنیم چرا که بخشهای زیادی از کد اینگونه فرض میکنند. این کار در هنگام تنظیم مسیر یا خواندن متغیر محیطی انجام میشود (https://bugzilla.redhat.com/882417).
پارامتر "ctxstr" رشتهای است که در پیامهای خطا نمایش داده میشود و زمینهٔ عملیات را مشخص میکند (مانند نام متغیر محیطی در حال استفاده، یا تابع API در حال فراخوانی).
تابع "lib/tmpdirs.c:guestfs_impl_get_tmpdir"
char * guestfs_impl_get_tmpdir (guestfs_h *g)
پیادهسازی API مربوط به "guestfs_get_tmpdir".
توجه داشته باشید که این تابع در واقع tmpdir را محاسبه میکند، بنابراین هرگز "NULL" برنمیگرداند.
تابع "lib/tmpdirs.c:guestfs_impl_get_cachedir"
char * guestfs_impl_get_cachedir (guestfs_h *g)
پیادهسازی API مربوط به "guestfs_get_cachedir".
توجه داشته باشید که این تابع در واقع cachedir را محاسبه میکند، بنابراین هرگز "NULL" برنمیگرداند.
تابع "lib/tmpdirs.c:guestfs_impl_get_sockdir"
char * guestfs_impl_get_sockdir (guestfs_h *g)
پیادهسازی API مربوط به "guestfs_get_sockdir".
توجه داشته باشید که این تابع در واقع sockdir را محاسبه میکند، بنابراین هرگز "NULL" برنمیگرداند.
تابع "lib/tmpdirs.c:guestfs_int_lazy_make_tmpdir"
int guestfs_int_lazy_make_tmpdir (guestfs_h *g)
مقدار "g->tmpdir" (دایرکتوری موقت به ازای هر handle) هنگام ایجاد handle ساخته نمیشود. در عوض، ما آن را به صورت تنبلانه (lazy) پیش از نخستین باری که استفاده شود، یا در هنگام راهاندازی (launch) ایجاد میکنیم.
تابع "lib/tmpdirs.c:guestfs_int_make_temp_path"
char *
guestfs_int_make_temp_path (guestfs_h *g,
const char *name, const char *extension)
تولید مسیرهای موقت یکتا برای فایلهای موقت.
در صورت موفقیت یک مسیر یکتا یا در صورت بروز خطا NULL برمیگرداند.
تابع "lib/tmpdirs.c:guestfs_int_create_socketname"
int
guestfs_int_create_socketname (guestfs_h *g, const char *filename,
char (*sockpath)[UNIX_PATH_MAX])
ایجاد مسیر برای یک سوکت با filename انتخابشده در sockdir.
تابع "lib/tmpdirs.c:guestfs_int_make_pid_path"
char * guestfs_int_make_pid_path (guestfs_h *g, const char *name)
تولید مسیرهای یکتا برای فایلهای PID.
در صورت موفقیت یک مسیر یکتا یا در صورت بروز خطا NULL برمیگرداند. در صورت موفقیت، مسیر فایل به زیر sockdir و نه tmpdir اشاره میکند؛ دیمنهایی که پس از رها کردن امتیازات (dropping privileges) فایلهای PID را مینویسند ممکن است به tmpdir دسترسی نداشته باشند.
تابع "lib/tmpdirs.c:guestfs_int_lazy_make_supermin_appliance_dir"
char * guestfs_int_lazy_make_supermin_appliance_dir (guestfs_h *g)
ایجاد دایرکتوری supermin appliance در زیر cachedir، در صورتی که وجود نداشته باشد.
بررسی صحت و سلامت دسترسیها (permissions) روی cachedir، برای اطمینان از اینکه از پیش با اهداف مخرب ایجاد نشده یا دستکاری نشده باشد.
نام دایرکتوری را برمیگرداند که فراخواننده باید آن را آزاد کند.
تابع "lib/tmpdirs.c:guestfs_int_recursive_remove_dir"
void guestfs_int_recursive_remove_dir (guestfs_h *g, const char *dir) حذف بازگشتی یک دایرکتوری موقت. اگر حذف با شکست مواجه شد، فقط بازگردید (این یک دایرکتوری موقت است، بنابراین در نهایت توسط یک پاککنندهٔ فایلهای موقت پاکسازی خواهد شد).
این کار با استفاده از "rm -rf" پیادهسازی شده است چرا که سادهتر و
امنتر است.
فایل lib/umask.c
بازگرداندن umask فعلی به روشی thread-safe.
کتابخانهٔ glibc فراخوانی «getumask(3)» را مستند کرده است، اما در عمل آن را پیادهسازی نمیکند.
ما از "Umask" در /proc/self/status برای Linux ≥ 4.7 استفاده میکنیم.
برای نسخههای قدیمیتر Linux و سایر یونیکسها، این فایل روشی پرهزینه
اما thread-safe را برای دریافت umask فرایند جاری پیادهسازی میکند.
با تشکر از: Josh Stone، Jiri Jaburek، Eric Blake.
تابع "lib/umask.c:guestfs_int_getumask"
int guestfs_int_getumask (guestfs_h *g)
مقدار umask فرایند جاری را بازمیگرداند. در صورت شکست، -1 را بازگردانده و خطا را در دستگیرهٔ (handle) guestfs تنظیم میکند.
تابع "lib/umask.c:get_umask_from_proc"
static int get_umask_from_proc (guestfs_h *g)
برای Linux ≥ 4.7 مقدار umask را از /proc/self/status دریافت میکند.
در صورت شکست، این تابع -1 را بازمیگرداند. با این حال اگر نتوانیم فایل /proc را باز کنیم یا مدخل "Umask" را در آن پیدا کنیم، -2 را بازمیگرداند که باعث اجرای مسیر جایگزین (fallback) میشود.
تابع "lib/umask.c:get_umask_from_fork"
static int get_umask_from_fork (guestfs_h *g)
روش جایگزین دریافت umask با استفاده از fork.
فایل lib/unit-tests.c
آزمونهای واحد (Unit tests) توابع داخلی.
این آزمونها ممکن است از یک دستگیرهٔ libguestfs استفاده کنند، اما نباید آن را اجرا (launch) کنند. همچنین، از آزمونهای طولانیمدت اجتناب کنید.
تابع "lib/unit-tests.c:test_split"
static void test_split (void)
آزمون "guestfs_int_split_string".
تابع "lib/unit-tests.c:test_concat"
static void test_concat (void)
آزمون "guestfs_int_concat_strings".
تابع "lib/unit-tests.c:test_join"
static void test_join (void)
آزمون "guestfs_int_join_strings".
تابع "lib/unit-tests.c:test_validate_guid"
static void test_validate_guid (void)
آزمون "guestfs_int_validate_guid".
تابع "lib/unit-tests.c:test_drive_name"
static void test_drive_name (void)
آزمون "guestfs_int_drive_name".
تابع "lib/unit-tests.c:test_drive_index"
static void test_drive_index (void)
آزمون "guestfs_int_drive_index".
تابع "lib/unit-tests.c:test_getumask"
static void test_getumask (void)
آزمون "guestfs_int_getumask".
تابع "lib/unit-tests.c:test_command"
static void test_command (void)
آزمون "guestfs_int_new_command" و غیره.
XXX این آزمونها میتوانند بسیار جامعتر شوند. تا کنون ما صرفاً بررسی میکنیم که بهطور آشکار خراب نباشد.
تابع "lib/unit-tests.c:test_qemu_escape_param"
static void test_qemu_escape_param (void)
آزمون "guestfs_int_qemu_escape_param"
XXX میخواستم این آزمون qemu را با ارسال برخی پارامترها که نیاز به گریز (escape) دارند اجرا کند، اما راهی برای انجام این کار بدون راهاندازی یک ماشین مجازی (VM) به ذهنم نمیرسد.
تابع "lib/unit-tests.c:test_timeval_diff"
static void test_timeval_diff (void)
آزمون "guestfs_int_timeval_diff".
فایل lib/version.c
این فایل مدیریت سادهٔ شمارهٔ نسخه را فراهم میکند.
تابع
"lib/version.c:guestfs_int_version_from_x_y"
int guestfs_int_version_from_x_y (guestfs_h *g, struct version *v, const
char *str)
یک نگارش را از یک رشته با جستجو برای الگوی "X.Y" تجزیه میکند.
در صورت شکست (مانند شکست در تجزیه عدد صحیح) مقدار -1، در صورت عدم تطابق مقدار 0، و در صورت تطابق و تجزیه موفقیتآمیز مقدار 1 را بازمیگرداند. "v" تنها در صورت تطابق موفقیتآمیز تغییر داده میشود.
تابع "lib/version.c:guestfs_int_version_from_x_y_re"
int
guestfs_int_version_from_x_y_re (guestfs_h *g, struct version *v,
const char *str, const pcre2_code *re)
یک نگارش را از یک رشته، با استفاده از "re" مشخصشده به عنوان عبارت باقاعده که باید (دستکم) دو تطابق ارائه دهد، تجزیه میکند.
در صورت شکست (مانند شکست در تجزیه عدد صحیح) مقدار -1، در صورت عدم تطابق مقدار 0، و در صورت تطابق و تجزیه موفقیتآمیز مقدار 1 را بازمیگرداند. "v" تنها در صورت تطابق موفقیتآمیز تغییر داده میشود.
تابع "lib/version.c:guestfs_int_version_from_x_y_or_x"
int
guestfs_int_version_from_x_y_or_x (guestfs_h *g, struct version *v,
const char *str)
یک نگارش را از یک رشته تجزیه میکند، یا با جستجو برای الگوی "X.Y" یا با در نظر گرفتن آن به عنوان یک عدد صحیح کامل.
در صورت شکست (مانند شکست در تجزیه عدد صحیح) مقدار -1، در صورت عدم تطابق مقدار 0، و در صورت تطابق و تجزیه موفقیتآمیز مقدار 1 را بازمیگرداند. "v" تنها در صورت تطابق موفقیتآمیز تغییر داده میشود.
تابع "lib/version.c:guestfs_int_parse_unsigned_int"
int guestfs_int_parse_unsigned_int (guestfs_h *g, const char *str)
اعداد صحیح بدون علامت و کوچک را، همانگونه که در شمارههای نگارش به کار میروند، تجزیه میکند.
اگر نویسههای اضافی در انتهای عدد صحیح یافت شوند، این تابع با خطا با شکست مواجه میشود.
در صورت موفقیت مقدار ≥ 0 و در صورت شکست مقدار -1 را بازمیگرداند.
فایل lib/wait.c
تابع "lib/wait.c:guestfs_int_waitpid"
int guestfs_int_waitpid (guestfs_h *g, pid_t pid, int *status, const char *errmsg)
نسخهای امن از waitpid(3) که در صورت بازگشت "EINTR" دوباره تلاش میکند.
نکته: این تابع تنها نیاز است در کتابخانه یا در برنامههایی استفاده شود که یک گردانندهٔ "SIGCHLD" غیرقابل شروع مجدد (non-restartable) نصب میکنند (که در حال حاضر در مورد هیچیک از ابزارهای virt در libguestfs اینچنین نیست).
اگر برنامه اصلی یک گردانندهٔ SIGCHLD نصب کند و آن را روی غیرقابل شروع مجدد تنظیم نماید، آنگاه ممکن است کتابخانه در فراخوان سیستمی wait منتظر بماند، فرزند خارج شود، سیگنال "SIGCHLD" به فرایند فرستاده شود، و فراخوان سیستمی wait مقدار "EINTR" را بازگرداند. از آنجا که کتابخانه نمیتواند گردانندهٔ سیگنال را کنترل کند، باید در عوض فراخوان سیستمی wait را دوباره آغاز کنیم؛ که این هدف اصلی این تابع پوششی است.
تابع "lib/wait.c:guestfs_int_waitpid_noerror"
void guestfs_int_waitpid_noerror (pid_t pid)
مشابه "guestfs_int_waitpid"، اما خطاها را نادیده میگیرد.
تابع "lib/wait.c:guestfs_int_wait4"
int
guestfs_int_wait4 (guestfs_h *g, pid_t pid, int *status,
struct rusage *rusage, const char *errmsg)
نسخهای امن از wait4(2) که در صورت بازگشت "EINTR" دوباره تلاش میکند.
فایل lib/whole-file.c
تابع "lib/whole-file.c:guestfs_int_read_whole_file"
int
guestfs_int_read_whole_file (guestfs_h *g, const char *filename,
char **data_r, size_t *size_r)
تمام فایل "filename" را درون یک بافر حافظه میخواند.
بافر حافظه مقداردهی اولیه شده و در "data_r" بازگردانده میشود. اندازه فایل بر حسب بایت در "size_r" بازگردانده میشود. بافر بازگرداندهشده باید توسط فراخواننده آزاد شود.
در صورت بروز خطا، این تابع خطا را در handle تنظیم کرده و مقدار -1 را بازمیگرداند.
برای سهولت فراخوانندهها، بافر بازگرداندهشده با NUL خاتمه مییابد (نویسه NUL در اندازه محاسبه نمیشود).
فایل باید یک فایل عادی، محلی و مورد اعتماد باشد. بهویژه، از این تابع برای خواندن فایلهایی که ممکن است تحت کنترل یک کاربر غیرقابلاعتماد باشند استفاده نکنید، زیرا این کار منجر به یک حمله محرومسازی از سرویس (denial-of-service) خواهد شد..SS "زیرشاخه common/edit" فایل common/edit/file-edit.c
این فایل، ویرایش مشترک فایلها را در مجموعهای از ابزارها از جمله guestfish(1)، virt-edit(1)، virt-customize(1) و virt-builder(1) پیادهسازی میکند.
این بخش شامل کدهایی برای هر دو روش ویرایش تعاملی (مبتنی بر ویرایشگر متن) و ویرایش غیرتعاملی با استفاده از قطعهکدهای Perl است.
تابع "common/edit/file-edit.c:edit_file_editor"
int
edit_file_editor (guestfs_h *g, const char *filename, const char *editor,
const char *backup_extension, int verbose)
ویرایش "filename" با استفاده از برنامه ویرایشگر "editor" مشخصشده.
اگر "backup_extension" تهی (null) نباشد، یک رونوشت از "filename" با الحاق "backup_extension" به انتهای نام فایل ذخیره میشود.
اگر "editor" مقدار null باشد، متغیر محیطی $EDITOR برای برنامه ویرایشگر پرسوجو خواهد شد و در صورت تنظیمنبودن، "vi" به عنوان جایگزین پیشفرض در نظر گرفته میشود.
در صورت بروز شکست -1، در صورت موفقیت 0 و اگر ویرایشگر فایل را تغییر نداده باشد (برای مثال، کاربر ویرایشگر را بدون ذخیره ببندد) مقدار 1 برمیگرداند.
تابع "common/edit/file-edit.c:edit_file_perl"
int
edit_file_perl (guestfs_h *g, const char *filename, const char *perl_expr,
const char *backup_extension, int verbose)
ویرایش "filename" با اجرای "perl_expr" مشخصشده با استفاده از Perl.
اگر "backup_extension" تهی (null) نباشد، یک رونوشت از "filename" با الحاق "backup_extension" به انتهای نام فایل ذخیره میشود.
در صورت بروز شکست -1 و در صورت موفقیت 0 را برمیگرداند.
زیرشاخه common/options
فایل common/options/config.c
این فایل، فایل پیکربندی guestfish را که معمولاً ~/.libguestfs-tools.rc یا /etc/libguestfs-tools.conf است، تجزیه میکند.
توجه داشته باشید که "parse_config" بسیار زود فراخوانی میشود؛ پیش از تجزیه خط فرمان، پیش از تنظیم پرچم "verbose"، و حتی پیش از آنکه هندل سراسری "g" باز شود.
فایل common/options/decrypt.c
این فایل رمزگشایی ایمیجهای دیسک را پیادهسازی میکند که معمولاً پیش از سوار کردن (mount) پارتیشنهای آنها انجام میشود.
تابع "common/options/decrypt.c:make_mapname"
static char * make_mapname (const char *device)
ایجاد یک نام نگاشت LUKS از روی نام پارتیشن یا حجم منطقی (logical volume)، به عنوان مثال: "/dev/vda2" => "cryptvda2"، یا "/dev/vg-ssd/lv-root7" => "cryptvgssdlvroot7". توجه داشته باشید که در نام دستگاههای حجم منطقی، c_isalnum() جداکننده "/" میان VG و LV را حذف میکند، بنابراین این نگاشت یکتا نیست؛ اما برای مقاصد ما کافی خواهد بود.
تابع "common/options/decrypt.c:inspect_do_decrypt"
void inspect_do_decrypt (guestfs_h *g, struct key_store *ks)
پیادهسازی ساده رمزگشایی: جستجو برای هرگونه پارتیشن رمزگذاریشده و رمزگشایی آنها، سپس پویش دوباره برای یافتن VGها.
فایل common/options/display-options.c
این فایل شامل کدهای مشترکی است که برای پیادهسازی --short-options و --long-options در ابزارهای virt به زبان C به کار میرود. (معادل این موارد برای ابزارهای virt در OCaml توسط common/mltools/getopt.ml پیادهسازی شده است).
این گزینههای «پنهان» برای پیادهسازی تکمیل خودکار با کلید تب (tab completion) در bash استفاده میشوند.
تابع "common/options/display-options.c:display_short_options"
void display_short_options (const char *format)
پرچم داخلی "tool --short-options" را پیادهسازی میکند که صرفاً گزینههای کوتاه موجود را فهرست مینماید. در تکمیل خودکار bash به کار میرود.
تابع "common/options/display-options.c:display_long_options"
void display_long_options (const struct option *long_options)
پرچم داخلی "tool --long-options" را پیادهسازی میکند که صرفاً گزینههای بلند موجود را فهرست مینماید. در تکمیل خودکار bash به کار میرود.
فایل common/options/domain.c
گزینه -d در guestfish (و دیگر ابزارها) را پیادهسازی میکند.
تابع "common/options/domain.c:add_libvirt_drives"
int add_libvirt_drives (guestfs_h *g, const char *guest)
این تابع هنگامی فراخوانی میشود که کاربر "guestfish -d guest" را اجرا کند.
تعداد درایوهای اضافهشده ("> 0")، یا در صورت بروز شکست -1 را برمیگرداند.
فایل common/options/inspect.c
این فایل، بازرسی ماشین مهمان و سوار کردن سیستمفایلهای یافتشده در مکانهای مناسب را پیادهسازی میکند. این قابلیت توسط گزینه -i در guestfish(1) و برخی ابزارهای دیگر مانند virt-cat(1) استفاده میشود.
تابع "common/options/inspect.c:inspect_mount_handle"
void inspect_mount_handle (guestfs_h *g, struct key_store *ks)
این تابع گزینه -i را پیادهسازی میکند.
تابع "common/options/inspect.c:print_inspect_prompt"
void print_inspect_prompt (void)
این تابع تنها در صورتی فراخوانی میشود که "inspect_mount_root" فراخوانی شده باشد، و تنها پس از اینکه خط اعلان را در حالت تعاملی چاپ کردیم اجرا میشود.
فایل common/options/keys.c
تابع "common/options/keys.c:read_key"
char * read_key (const char *param)
خواندن یک عبارت عبور ('Key') از /dev/tty بدون نمایش نویسهها در خروجی (echo off)..PP فراخوانکننده (fish/cmds.c) پس از آن free را روی رشته فراخوانی خواهد کرد.
رشتهٔ واردشده برای جلوگیری از ابهام با “text:...” پیشوندگذاری میشود (در libguestfs >= 1.60). در اینجا نمیتوان از کدگذاری Base64 استفاده کرد.
بر اساس کد موجود در فایل lib/utils.c در cryptsetup.
فایل common/options/options.c
این فایل شامل کد تجزیهٔ گزینههای مشترک است که توسط guestfish و بسیاری از ابزارهای دیگر که نحو گزینههای یکسانی دارند استفاده میشود.
برای نمونه، guestfish، virt-cat، virt-ls و غیره همگی از گزینهٔ -a پشتیبانی میکنند، و این کار در تمام آن ابزارها با استفاده از ماکروی "OPTION_a" تعریفشده در fish/options.h مدیریت میشود.
متغیرهای عمومی مشترک زیادی استفاده میشوند؛ "drvs" فهرست درایوها را جمعآوری میکند، "verbose" برای پرچم -v به کار میرود، و بسیاری موارد دیگر.
تابع "common/options/options.c:option_a"
void
option_a (const char *arg, const char *format, int blocksize,
struct drv **drvsp)
گزینهٔ -a برنامهٔ guestfish در خط فرمان را مدیریت میکند.
تابع "common/options/options.c:option_d"
void option_d (const char *arg, struct drv **drvsp)
گزینهٔ -d را هنگامی که در خط فرمان فرستاده شود مدیریت میکند.
تابع "common/options/options.c:display_mountpoints_on_failure"
static void
display_mountpoints_on_failure (const char *mp_device,
const char *user_supplied_options)
اگر گزینهٔ -m در هر دستوری با شکست مواجه شود، یک پیام خطای سودمند شامل فهرست نقاط اتصال (mountpoints) را نمایش میدهد.
فایل common/options/uri.c
این فایل تجزیهٔ URI را برای گزینهٔ -a در ابزارهای متعددی از جمله guestfish(1)، virt-cat(1)، virt-builder(1)، virt-customize(1) و غیره پیادهسازی میکند.
زیردایرکتوری common/parallel
فایل common/parallel/domains.c
این فایل توسط "virt-df" و برخی از ابزارهای دیگر هنگامی استفاده میشود که بهطور ضمنی از آنها خواسته شده باشد تا روی همهٔ دامنههای libvirt (ماشینهای مجازی) عمل کنند؛ برای نمونه هنگامی که "virt-df" بدون مشخص کردن تصویر دیسک خاصی فراخوانی میشود.
این فایل پیچیدگی پرسوجوی فهرست دامنهها از libvirt را پنهان میسازد.
تابع "common/parallel/domains.c:free_domains"
void free_domains (void)
تمام مواردی را که توسط "get_all_libvirt_domains" تخصیص یافته است آزاد میکند.
تابع "common/parallel/domains.c:get_all_libvirt_domains"
void get_all_libvirt_domains (const char *libvirt_uri)
تمام مهمانهای libguest را در متغیرهای عمومی "domains" و "nr_domains" میخواند. مهمانها بر پایهٔ نام مرتب میشوند. این تابع با بروز هر خطایی خارج میشود.
فایل common/parallel/estimate-max-threads.c
تابع "common/parallel/estimate-max-threads.c:estimate_max_threads"
size_t estimate_max_threads (void)
این تابع از خروجی "free -m" استفاده میکند تا تخمین بزند چه تعداد appliance مربوط به libguestfs را میتوان با اطمینان بهصورت موازی اجرا کرد. توجه داشته باشید که همیشه مقداری ≥ 1 برمیگرداند.
تابع "common/parallel/estimate-max-threads.c:read_line_from"
static char * read_line_from (const char *cmd)
دستور خارجی را اجرا کرده و نخستین خط خروجی را میخواند.
فایل common/parallel/parallel.c
این فایل توسط "virt-df" و برخی از ابزارهای دیگر هنگامی استفاده میشود که نیاز به اجرای چندین نمونهٔ موازی libguestfs داشته باشند تا بر روی شمار زیادی از دامنههای libvirt بهصورت کارآمد عمل کنند.
یک صف کاری چندنخی را پیادهسازی میکند. افزون بر این، ترتیب خروجی را بازآرایی میکند تا خروجی همچنان با همان ترتیب ورودی نمایش داده شود (یعنی همچنان بر پایهٔ الفبا مرتب باشد).
تابع "common/parallel/parallel.c:start_threads"
int start_threads (size_t option_P, guestfs_h *options_handle, work_fn work)
نخها را اجرا کرده و فهرست عمومی دامنههای libvirt را پردازش میکند.
"option_P" مقداری است که کاربر در گزینهٔ -P ارسال کرده، یا 0 اگر کاربر از گزینهٔ -P استفاده نکرده باشد (که در این صورت تعداد نخها بهصورت مکاشفهای انتخاب میشود).
"options_handle" (که ممکن است "NULL" باشد) دستگیرهٔ (handle) عمومی guestfs است که توسط کتابخانه کوچک گزینهها ایجاد شده است.
تابع کاری ("work") باید کار (بازرسی دامنه و غیره) را روی نمایهٔ دامنهٔ "i" انجام دهد. با این حال این تابع نباید هیچ نتیجهای را مستقیماً چاپ کند. در عوض، هر آنچه نیاز دارد را در "FILE *" ارائهشده چاپ میکند. تابع کاری باید در صورت موفقیت 0 یا در صورت بروز خطا -1 برگرداند.
تابع "start_threads" در صورتی که تمام موارد کاری با موفقیت کامل شوند 0 و در صورت بروز خطا -1 را برمیگرداند..SS "زیردایرکتوری common/progress" فایل common/progress/progress.c
این فایل نوار پیشرفت را در guestfish(1)، virt-resize(1) و virt-sparsify(1) پیادهسازی میکند.
تابع "common/progress/progress.c:progress_bar_init"
struct progress_bar * progress_bar_init (unsigned flags)
مقداردهی اولیه یک struct نوار پیشرفت.
هدف این است که بتوانید از همان struct برای چندین دستور استفادهٔ مجدد کنید (اما تنها در یک thread واحد). پیش از هر دستور جدید، "progress_bar_reset" را فراخوانی کنید.
تابع "common/progress/progress.c:progress_bar_free"
void progress_bar_free (struct progress_bar *bar)
آزادسازی یک struct نوار پیشرفت.
تابع "common/progress/progress.c:progress_bar_reset"
void progress_bar_reset (struct progress_bar *bar)
این تابع باید دقیقاً پیش از صدور هر دستوری فراخوانی شود.
تابع "common/progress/progress.c:estimate_remaining_time"
static double estimate_remaining_time (struct progress_bar *bar, double ratio)
تخمین زمان باقیمانده (به ثانیه) را برای فراخوانی فعلی بازمیگرداند.
این تابع تخمین میانگین متحرک زمان باقیمانده را بازمیگرداند، اما اگر آخرین تخمین از زمان کل بیشتر از دو انحراف معیار (s.d.) با میانگین متحرک فاصله داشته باشد، چیزی چاپ نمیکنیم چرا که اطمینان کافی از معنادار بودن تخمین وجود ندارد. (مقدار بازگرداندهشده در زمانی که نباید چیزی چاپ شود، کمتر از 0.0 است).
تابع "common/progress/progress.c:progress_bar_set"
void
progress_bar_set (struct progress_bar *bar,
uint64_t position, uint64_t total)
تنظیم موقعیت نوار پیشرفت.
این تابع باید از یک callback رویداد "GUESTFS_EVENT_PROGRESS" فراخوانی شود.
زیردایرکتوری common/qemuopts
فایل common/qemuopts/qemuopts-tests.c
آزمونهای واحد توابع داخلی.
این آزمونها میتوانند از یک handle در libguestfs استفاده کنند، اما نباید آن handle را راهاندازی (launch) کنند. همچنین، از اجرای آزمونهای طولانیمدت خودداری کنید.
فایل common/qemuopts/qemuopts.c
کتابخانهای کوچک برای نوشتن خطوط فرمان qemu و فایلهای پیکربندی qemu.
کاستیهایی در مدل استفادهشده برای گزینههای qemu وجود دارد که تا زمانی که اقدام به تبدیل گزینهها به یک فایل پیکربندی نکنید آشکار نمیشوند. با این حال، اگر تلاش میکردیم گزینهها را با جزئیات بیشتری مدلسازی کنیم، استفاده از این کتابخانه هم بسیار دشوار میشد و هم با نسخههای قدیمیتر qemu ناسازگار میبود. امید است مدل فعلی مصالحهای مناسب باشد.
جهت ارجاع، مشکلات عبارتند از:
- ناسازگاری
در qemu میان
گزینهها و
فایل
پیکربندی؛
برای نمونه
"-smp 4"
تبدیل
میشود به:
[smp-opts] cpus = "4"
- مشابه مورد پیشین، میتوانید یا "-smp 4" یا "-smp cpus=4" را بنویسید (اگرچه این مورد در qemuهای بسیار قدیمی کار نخواهد کرد). هنگام تولید یک فایل پیکربندی، باید نام کلید ضمنی را بدانید.
- در "-opt key=value,..."، بخش "key" در واقع یک مشخصکنندهٔ درخت/آرایه است. نحوهٔ کارکرد این سازوکار پیچیده است اما در اینجا به آن اشاره شده است: http://git.qemu.org/?p=qemu.git;a=blob;f=util/keyval.c;h=93d5db6b590427e412dfb172f1c406d6dd8958c1;hb=HEAD
- برخی از گزینهها نوعی سادهنویسی نحوی (syntactic sugar) هستند؛ برای نمونه "-kernel foo" سادهنویسی نحوی برای "-machine kernel=foo" است.
تابع "common/qemuopts/qemuopts.c:qemuopts_create"
struct qemuopts * qemuopts_create (void)
ایجاد یک فهرست خالی از گزینههای qemu.
فراخواننده باید در نهایت با فراخوانی "qemuopts_free" این فهرست را آزاد کند.
در صورت بروز خطا، مقدار "NULL" را بازمیگرداند و "errno" را تنظیم میکند.
تابع "common/qemuopts/qemuopts.c:qemuopts_free"
void qemuopts_free (struct qemuopts *qopts)
آزادسازی فهرست گزینههای qemu.
تابع "common/qemuopts/qemuopts.c:qemuopts_add_flag"
int qemuopts_add_flag (struct qemuopts *qopts, const char *flag)
افزودن یک پرچم خط فرمان بدون آرگومان؛ مانند:
qemuopts_add_flag (qopts, "-no-user-config");
در صورت موفقیت مقدار 0 را بازمیگرداند. در صورت بروز خطا، مقدار -1 را بازگردانده و "errno" را تنظیم میکند.
تابع "common/qemuopts/qemuopts.c:qemuopts_add_arg"
int qemuopts_add_arg (struct qemuopts *qopts, const char *flag, const char *value)
افزودن یک پرچم خط فرمان با یک آرگومان منفرد؛ مانند:
qemuopts_add_arg (qopts, "-m", "1024");
اگر آرگومان فهرستی جداشده با کاما است از این تابع استفاده نکنید، زیرا نقلقولگذاری به درستی انجام نخواهد شد. به "qemuopts_add_arg_list" مراجعه کنید.
در صورت موفقیت مقدار 0 را بازمیگرداند. در صورت بروز خطا، مقدار -1 را بازگردانده و "errno" را تنظیم میکند.
تابع "common/qemuopts/qemuopts.c:qemuopts_add_arg_format"
int
qemuopts_add_arg_format (struct qemuopts *qopts, const char *flag,
const char *fs, ...)
یک پرچم خط فرمان را که دارای یک آرگومان قالببندیشدهی تکی است اضافه میکند. به عنوان مثال:
qemuopts_add_arg_format (qopts, "-m", "%d", 1024);
اگر آرگومان یک فهرست جداشده با کاما است از این تابع استفاده نکنید، زیرا نقلقولگذاری به درستی انجام نخواهد شد. "qemuopts_add_arg_list" را ببینید.
در صورت موفقیت 0 را برمیگرداند. در صورت بروز خطا -1 را برمیگرداند و "errno" را تنظیم میکند.
تابع "common/qemuopts/qemuopts.c:qemuopts_add_arg_noquote"
int
qemuopts_add_arg_noquote (struct qemuopts *qopts, const char *flag,
const char *value)
این تابع شبیه به "qemuopts_add_arg" است، با این تفاوت که هیچ نقلقولگذاری روی مقدار انجام نمیشود.
برای "qemuopts_to_script" و "qemuopts_to_channel"، این به این معنی است که نه نقلقولگذاری شل و نه نقلقولگذاری کاما در qemu، هیچکدام روی مقدار انجام نمیگیرد.
برای "qemuopts_to_argv" این بدان معناست که نقلقولگذاری کاما در qemu انجام نمیشود.
"qemuopts_to_config*" با شکست مواجه خواهد شد.
باید با احتیاط بسیار از این تابع استفاده کنید.
تابع "common/qemuopts/qemuopts.c:qemuopts_start_arg_list"
int qemuopts_start_arg_list (struct qemuopts *qopts, const char *flag)
یک آرگومان را که فهرستی از فیلدهای جداشده با کاما دریافت میکند، آغاز مینماید.
کاربرد متداول آن به این شکل است (با صرفنظر از مدیریت خطا):
qemuopts_start_arg_list (qopts, "-drive"); qemuopts_append_arg_list (qopts, "file=foo"); qemuopts_append_arg_list_format (qopts, "if=%s", "ide"); qemuopts_end_arg_list (qopts);
که عبارت "-drive file=foo,if=ide" را میسازد.
همچنین برای روشی جهت انجام موارد ساده در یک فراخوانی، "qemuopts_add_arg_list" را ببینید.
در صورت موفقیت 0 را برمیگرداند. در صورت بروز خطا -1 را برمیگرداند و "errno" را تنظیم میکند.
تابع "common/qemuopts/qemuopts.c:qemuopts_add_arg_list"
int
qemuopts_add_arg_list (struct qemuopts *qopts, const char *flag,
const char *elem0, ...)
یک پرچم خط فرمان را اضافه میکند که دارای فهرستی از آرگومانها است. به عنوان مثال:
qemuopts_add_arg_list (qopts, "-drive", "file=foo", "if=ide", NULL);
این به یک فهرست جداشده با کاما تبدیل میشود، مانند: "-drive file=foo,if=ide". توجه داشته باشید که این تابع نقلقولگذاری qemu را به درستی مدیریت میکند، بنابراین عناصر منفرد میتوانند حاوی کاما باشند و کار به درستی انجام خواهد شد.
در صورت موفقیت 0 را برمیگرداند. در صورت بروز خطا -1 را برمیگرداند و "errno" را تنظیم میکند.
تابع "common/qemuopts/qemuopts.c:qemuopts_set_binary"
int qemuopts_set_binary (struct qemuopts *qopts, const char *binary)
نام باینری qemu را تعیین میکند.
در صورت موفقیت 0 را برمیگرداند. در صورت بروز خطا -1 را برمیگرداند و "errno" را تنظیم میکند.
تابع "common/qemuopts/qemuopts.c:qemuopts_set_binary_by_arch"
int qemuopts_set_binary_by_arch (struct qemuopts *qopts, const char *arch)
نام باینری qemu را به "qemu-system-[arch]" تنظیم میکند.
به عنوان یک حالت خاص اگر "arch" برابر با "NULL" باشد، باینری به باینری KVM برای معماری میزبانِ فعلی تنظیم میشود:
qemuopts_set_binary_by_arch (qopts, NULL);
در صورت موفقیت 0 را برمیگرداند. در صورت بروز خطا -1 را برمیگرداند و "errno" را تنظیم میکند.
تابع "common/qemuopts/qemuopts.c:qemuopts_to_script"
int qemuopts_to_script (struct qemuopts *qopts, const char *filename)
گزینههای qemu را درون یک اسکریپت مینویسد.
ابتدا باید "qemuopts_set_binary*" فراخوانی شود.
فایل اسکریپت با "#!/bin/sh" آغاز خواهد شد و با دستور chmod به حالت دسترسی 0755 تغییر خواهد یافت.
در صورت موفقیت 0 را برمیگرداند. در صورت بروز خطا -1 را برمیگرداند و "errno" را تنظیم میکند.
تابع "common/qemuopts/qemuopts.c:shell_quote"
static void shell_quote (const char *str, FILE *fp)
رشتهی "str" را در "fp" چاپ میکند و در صورت نیاز نقلقولگذاری شل را روی آن اعمال مینماید.
تابع "common/qemuopts/qemuopts.c:shell_and_comma_quote"
static void shell_and_comma_quote (const char *str, FILE *fp)
رشتهی "str" را با اعمال همزمان نقلقولگذاری شل و نقلقولگذاری کاما در qemu، در "fp" چاپ میکند.
تابع "common/qemuopts/qemuopts.c:qemuopts_to_channel"
int qemuopts_to_channel (struct qemuopts *qopts, FILE *fp)
گزینههای qemu را در یک "FILE *fp" مینویسد.
ابتدا باید "qemuopts_set_binary*" فراخوانی شود.
فقط خط فرمان qemu نوشته میشود. ممکن است لازم باشد فراخواننده عبارت "#!/bin/sh" را اضافه کرده و مجوز فایل حاصل را با chmod به 0755 تغییر دهد.
در صورت موفقیت 0 را برمیگرداند. در صورت بروز خطا -1 را برمیگرداند و "errno" را تنظیم میکند.
تابع "common/qemuopts/qemuopts.c:qemuopts_to_argv"
char ** qemuopts_to_argv (struct qemuopts *qopts)
یک فهرست از آرگومانها با پایاندهندهی NULL برمیگرداند، از همان نوعی که میتواند مستقیماً به execv(3) ارسال شود.
ابتدا باید "qemuopts_set_binary*" فراخوانی شود. این باینری به عنوان "argv[0]" در فهرست بازگرداندهشده قرار خواهد گرفت..PP فهرست رشتهها و خود رشتهها باید توسط فراخواننده آزاد شوند.
در صورت بروز خطا، "NULL" را بازمیگرداند و "errno" را تنظیم میکند.
تابع "common/qemuopts/qemuopts.c:qemuopts_to_config_file"
int qemuopts_to_config_file (struct qemuopts *qopts, const char *filename)
گزینههای qemu را در یک فایل پیکربندی qemu مینویسد که برای خواندن با استفاده از "qemu -readconfig filename" مناسب است.
توجه داشته باشید که فایلهای پیکربندی qemu در محتوا و نقلقولها (quoting) محدودیتهایی دارند، بنابراین امکان نوشتن همه ساختارهای qemuopts وجود ندارد (این تابع در چنین مواردی یک خطا بازمیگرداند). برای اطلاعات بیشتر ببینید: https://habkost.net/posts/2016/12/qemu-apis-qemuopts.html https://bugs.launchpad.net/qemu/+bug/1686364
همچنین، نام آرگومانهای خط فرمان و بخشهای فایل پیکربندی گاهی متفاوت است. برای نمونه، معادل "-m 1024" عبارت است از:
[memory] size = "1024"
این کد تلاشی نمیکند که بین این دو شکل تبدیل انجام دهد. تنها باید خودتان بدانید چگونه این تبدیل را انجام دهید.
در صورت موفقیت 0 را بازمیگرداند. در صورت بروز خطا -1 را بازمیگرداند و "errno" را تنظیم میکند.
تابع "common/qemuopts/qemuopts.c:qemuopts_to_config_channel"
int qemuopts_to_config_channel (struct qemuopts *qopts, FILE *fp)
مشابه "qemuopts_to_config_file" است، اما این تابع در یک "FILE *fp" مینویسد.
زیردایرکتوری common/utils
فایل common/utils/cleanups.c
ابزار libguestfs از ماکروهای "CLEANUP_*" برای سادهسازی تخصیصهای موقت استفاده میکند. آنها با استفاده از قابلیت "__attribute__((cleanup))" در gcc و clang پیادهسازی شدهاند. کاربرد معمول آن چنین است:
fn ()
{
CLEANUP_FREE char *str = NULL;
str = safe_asprintf (g, "foo");
// str is freed automatically when the function returns
}
چند نکته و دام وجود دارد که در مورد سازوکار cleanup باید از آنها آگاه باشید:
- اگر یک متغیر cleanup مقداردهی اولیه نشود، ممکن است کار به فراخوانی free(3) با مقداری تعریفنشده ختم شود که سبب کرش کردن برنامه میگردد. به همین دلیل، معمولاً باید هر متغیر cleanup را با مقداری مقداردهی اولیه کنید، مثلاً "NULL"
- متغیرهای حامل مقادیر بازگشتی را به عنوان متغیر cleanup علامتگذاری نکنید.
- تابع main() نباید از متغیرهای cleanup استفاده کند، زیرا خروج از آن معمولاً با فراخوانی exit(3) صورت میگیرد و این کار گردانندههای cleanup را فراخوانی نمیکند.
توابع موجود در این فایل به صورت داخلی توسط ماکروهای "CLEANUP_*" استفاده میشوند. آنها را مستقیماً فراخوانی نکنید.
فایل common/utils/gnulib-cleanups.c
ابزار libguestfs از ماکروهای "CLEANUP_*" برای سادهسازی تخصیصهای موقت استفاده میکند. آنها با استفاده از قابلیت "__attribute__((cleanup))" در gcc و clang پیادهسازی شدهاند. کاربرد معمول آن چنین است:
fn ()
{
CLEANUP_FREE char *str = NULL;
str = safe_asprintf (g, "foo");
// str is freed automatically when the function returns
}
چند نکته و دام وجود دارد که در مورد سازوکار cleanup باید از آنها آگاه باشید:
- اگر یک متغیر cleanup مقداردهی اولیه نشود، ممکن است کار به فراخوانی free(3) با مقداری تعریفنشده ختم شود که سبب کرش کردن برنامه میگردد. به همین دلیل، معمولاً باید هر متغیر cleanup را با مقداری مقداردهی اولیه کنید، مثلاً "NULL"
- متغیرهای حامل مقادیر بازگشتی را به عنوان متغیر cleanup علامتگذاری نکنید.
- تابع main() نباید از متغیرهای cleanup استفاده کند، زیرا خروج از آن معمولاً با فراخوانی exit(3) صورت میگیرد و این کار گردانندههای cleanup را فراخوانی نمیکند.
توابع موجود در این فایل به صورت داخلی توسط ماکروهای "CLEANUP_*" استفاده میشوند. آنها را مستقیماً فراخوانی نکنید.
فایل common/utils/guestfs-utils.h
این فایل سرایند (header) در تمام بخشهای فرانتاند libguestfs، یعنی خود کتابخانه، بایندینگهای زبانهای غیر C، ابزارهای virt و آزمونها گنجانده شده است.
دیمن (daemon) از این سرایند استفاده نمیکند. اگر به مکانی برای قرار دادن موردی مشترک با همه بخشها از جمله دیمن نیاز دارید، آن را در lib/guestfs-internal-all.h بگذارید.
اگر تعریفی تنها توسط یک مؤلفه از libguestfs مورد نیاز باشد (مثلاً فقط کتابخانه، یا فقط یک ابزار virt منفرد)، پس نباید در اینجا قرار گیرد!
فایل common/utils/libxml2-writer-macros.h
این ماکروها نوشتن XML را سادهتر میکنند. برای استفاده صحیح از آنها باید از این مفروضات آگاه باشید:
- اشارهگر "xmlTextWriterPtr" با نام "xo" نامیده میشود. این متغیر به صورت ضمنی توسط تمام ماکروها استفاده میشود.
- در زمان شکست، تابعی به نام "xml_error" فراخوانی میشود که خودتان باید آن را تعریف کنید (معمولاً به عنوان یک ماکرو). اگر میخواهید متغیرهای محلی در طول مسیر خطا به درستی پاکسازی شوند، باید از ماکروهای "CLEANUP_*" در توابع خود استفاده کنید.
- تمام تبدیلهای نوع (casting) «نامناسب» درون ماکروها پنهان شدهاند.
تعریف "common/utils/libxml2-writer-macros.h:start_element"
#define start_element
برای تعریف یک عنصر XML از این ساختار استفاده کنید:
start_element ("name") {
...
} end_element ();
که عبارت "<name>...</name>" را تولید میکند.
تعریف "common/utils/libxml2-writer-macros.h:empty_element"
#define empty_element
برای تعریف یک عنصر خالی:
empty_element ("name");
که عبارت "<name/>" را تولید میکند.
تعریف "common/utils/libxml2-writer-macros.h:single_element"
#define single_element برای تعریف یک عنصر منفرد بدون مشخصه حاوی مقداری متن:
single_element ("name", text);
که عبارت "<name>text</name>" را تولید میکند
تعریف "common/utils/libxml2-writer-macros.h:single_element_format"
#define single_element_format
برای تعریف یک عنصر منفرد و بدون مشخصه حاوی مقداری متن با استفاده از یک رشته قالببندی:
single_element_format ("cores", "%d", nr_cores);
که عبارت "<cores>4</cores>" را تولید میکند
تعریف "common/utils/libxml2-writer-macros.h:attribute"
#define attribute
برای تعریف یک عنصر XML دارای مشخصه، از این شیوه استفاده کنید:
start_element ("name") {
attribute ("foo", "bar");
attribute_format ("count", "%d", count);
...
} end_element ();
که عبارت "<name foo="bar" count="123">...</name>" را تولید میکند
تعریف "common/utils/libxml2-writer-macros.h:attribute_ns"
#define attribute_ns
"attribute_ns (prefix, key, namespace_uri, value)" یک مشخصه دارای فضای نام را تعریف میکند.
تعریف "common/utils/libxml2-writer-macros.h:string"
#define string
برای تعریف یک رشته عینی (verbatim)، از این شیوه استفاده کنید:
string ("hello");
تعریف "common/utils/libxml2-writer-macros.h:string_format"
#define string_format
برای تعریف یک رشته عینی با استفاده از یک رشته قالببندی، از این شیوه استفاده کنید:
string ("%s, world", greeting);
تعریف "common/utils/libxml2-writer-macros.h:base64"
#define base64
برای نوشتن یک رشته کدگذاریشده به صورت base64:
base64 (data, size);
تعریف "common/utils/libxml2-writer-macros.h:comment"
#define comment
برای تعریف یک توضیح (comment) در XML، از این شیوه استفاده کنید:
comment ("number of items = %d", nr_items);
فایل common/utils/stringlists-utils.c
توابع کمکی مورد استفاده توسط کتابخانه، ابزارها و اتصالات زبان.
این توابع نباید توابع داخلی کتابخانه نظیر "safe_*"، "error"، "perrorf" یا هر تابع "guestfs_int_*" دیگری را فراخوانی کنند.
تابع "common/utils/stringlists-utils.c:guestfs_int_split_string"
char ** guestfs_int_split_string (char sep, const char *str)
رشته را در محل نویسه جداکننده "sep" تجزیه کرده و فهرستی از رشتهها را بازمیگرداند. در صورت شکست تخصیص حافظه، مقدار "NULL" را بازمیگرداند.
نکته (با فرض اینکه "sep" برابر با ":" باشد):
- "str == NULL"
- متوقف میشود
- "str == """
- مقدار "[]" را بازمیگرداند
- "str == "abc""
- مقدار "["abc"]" را بازمیگرداند
- "str == ":""
- مقدار "["", ""]" را بازمیگرداند
فایل common/utils/utils.c
توابع کمکی مورد استفاده توسط کتابخانه، ابزارها و اتصالات زبان.
این توابع نباید توابع داخلی کتابخانه نظیر "safe_*"، "error"، "perrorf" یا هر تابع "guestfs_int_*" دیگری را فراخوانی کنند.
تابع "common/utils/utils.c:guestfs_int_replace_string"
char * guestfs_int_replace_string (const char *str, const char *s1, const char *s2)
تمام موارد رخداد "s1" موجود در "str" را با "s2" جایگزین میکند. یک رشته تازه تخصیصیافته بازگردانده میشود که آزادسازی آن بر عهده فراخواننده است. اگر تخصیص حافظه با شکست مواجه شود، ممکن است "NULL" بازگرداند.
برای مثال:
replace_string ("abcabb", "ab", "a");
مقدار "acab" را بازمیگرداند.
تابع "common/utils/utils.c:guestfs_int_exit_status_to_string"
char *
guestfs_int_exit_status_to_string (int status, const char *cmd_name,
char *buffer, size_t buflen)
وضعیت خروج wait/system را به یک رشته قابلچاپ تبدیل میکند..PP تابع "common/utils/utils.c:guestfs_int_random_string"
int guestfs_int_random_string (char *ret, size_t len)
یک رشته تصادفی از نویسهها را برمیگرداند.
نکات:
- بافر "ret" برای ذخیره نویسه پایانی "\0" باید طولی برابر با "len+1" داشته باشد.
- بهازای هر نویسه خروجی حدود ۵ بیت تصادفی بودن وجود دارد (بنابراین حدود "5*len" بیت تصادفی بودن در رشته حاصل وجود خواهد داشت).
تابع "common/utils/utils.c:guestfs_int_drive_name"
char * guestfs_int_drive_name (size_t index, char *ret)
این تابع یک نمایه درایو (مثلاً 27) را به یک نام درایو (مثلاً "ab") تبدیل میکند.
شمارش نمایههای درایو از 0 آغاز میشود. بافر بازگشتی باید بهاندازه کافی برای رشته نهایی بزرگ باشد، و اشارهگر بازگرداندهشده به *انتهای* رشته اشاره میکند.
https://rwmj.wordpress.com/2011/01/09/how-are-linux-drives-named-beyond-drive-26-devsdz
تابع "common/utils/utils.c:guestfs_int_drive_index"
ssize_t guestfs_int_drive_index (const char *name)
معکوس "guestfs_int_drive_name". رشتهای مانند "ab" را میگیرد و نمایه را برمیگرداند (مثلاً 27).
توجه داشته باشید که باید پیش از فراخوانی این تابع، هرگونه پیشوند مانند "hd"، "sd" و غیره، یا هر شماره پارتیشنی را حذف کنید.
تابع "common/utils/utils.c:guestfs_int_is_true"
int guestfs_int_is_true (const char *str)
مشابه "Tcl_GetBoolean".
تابع "common/utils/utils.c:guestfs_int_string_is_valid"
bool
guestfs_int_string_is_valid (const char *str,
size_t min_length, size_t max_length,
int flags, const char *extra)
بررسی معتبر بودن یک رشته، از نظر اینکه تنها شامل نویسههای مشخصی باشد، و حداقل و حداکثر طول آن بررسی شود. این تابع معمولاً در یک ماکروی *VALID_ گنجانده میشود؛ برای نمونه به lib/drives.c مراجعه کنید.
"str" رشتهای است که باید بررسی شود.
"min_length" و "max_length" بررسیهای حداقل و حداکثر طول هستند. 0 به معنای عدم بررسی است.
پرچمها این موارد را کنترل میکنند:
- "VALID_FLAG_ALPHA"
- نویسههای الفبایی صرفاً ASCII هفتبیتی (7-bit) مجاز هستند.
- "VALID_FLAG_DIGIT"
- ارقام صرفاً ASCII هفتبیتی (7-bit) مجاز هستند.
"extra" مجموعهای از نویسههای اضافی مجاز است، علاوه بر حروف الفبا و/یا ارقام. ("extra = NULL" برای عدم وجود نویسه اضافی).
اگر رشته معتبر باشد (از تمام آزمونها عبور کند) مقدار بولی "true"، و در غیر این صورت "false" برگردانده میشود.
تابع "common/utils/utils.c:guestfs_int_fadvise_normal"
void guestfs_int_fadvise_normal (int fd)
راهنمایی مبنی بر اینکه خواندن یا نوشتن روی توصیفگر فایل بهصورت عادی انجام خواهد شد.
در لینوکس، این تابع پرچم "FMODE_RANDOM" را روی فایل پاک میکند [پایین را ببینید] و تعداد صفحات پیشخوانی (readahead) را به ازای هر فایل برابر با تنظیمات پیشخوانی دستگاه بلوکی قرار میدهد.
فراخوانی این روی یک غیرفایل مشکلی ایجاد نمیکند، زیرا از آنجا که تنها یک راهنمایی است، شکست آن نادیده گرفته میشود.
تابع "common/utils/utils.c:guestfs_int_fadvise_sequential"
void guestfs_int_fadvise_sequential (int fd)
راهنمایی مبنی بر اینکه خواندن یا نوشتن روی توصیفگر فایل بهصورت ترتیبی انجام خواهد شد.
در لینوکس، این تابع پرچم "FMODE_RANDOM" را روی فایل پاک میکند [پایین را ببینید] و تعداد صفحات پیشخوانی (readahead) را به ازای هر فایل برابر با دو برابر تنظیمات پیشخوانی دستگاه بلوکی قرار میدهد.
فراخوانی این روی یک غیرفایل مشکلی ایجاد نمیکند، زیرا از آنجا که تنها یک راهنمایی است، شکست آن نادیده گرفته میشود.
تابع "common/utils/utils.c:guestfs_int_fadvise_random"
void guestfs_int_fadvise_random (int fd)
راهنمایی مبنی بر اینکه خواندن یا نوشتن روی توصیفگر فایل بهصورت تصادفی انجام خواهد شد.
در لینوکس، این تابع پرچم "FMODE_RANDOM" را روی فایل تنظیم میکند. اثر این پرچم به این شرح است:
- غیرفعالسازی پیشخوانی (readahead) ترتیبی و معمول فایل.
- اگر خواندنی از فایل انجام شود که در حافظه پنهان صفحه (page cache) موجود نباشد، ۲ مگابایت به درون حافظه پنهان صفحه خوانده میشود. [فکر میکنم - مطمئن نیستم کاملاً فهمیده باشم این کار دقیقاً چه میکند]
فراخوانی این روی یک غیرفایل مشکلی ایجاد نمیکند، زیرا از آنجا که تنها یک راهنمایی است، شکست آن نادیده گرفته میشود.
تابع "common/utils/utils.c:guestfs_int_fadvise_noreuse"
void guestfs_int_fadvise_noreuse (int fd)
راهنمایی مبنی بر اینکه دادهها تنها یکبار مورد دسترسی قرار خواهند گرفت.
در لینوکس، این تابع هیچ کاری انجام نمیدهد.
فراخوانی این روی یک غیرفایل مشکلی ایجاد نمیکند، زیرا از آنجا که تنها یک راهنمایی است، شکست آن نادیده گرفته میشود.
تابع "common/utils/utils.c:guestfs_int_fadvise_dontneed"
void guestfs_int_fadvise_dontneed (int fd)
راهنمایی مبنی بر اینکه در آینده نزدیک به دادهها دسترسی نخواهیم داشت.
در لینوکس، این تابع بلافاصله تمام صفحات کثیف (dirty pages) را در حافظه پنهان صفحه (page cache) مینویسد و سپس تمام صفحات مرتبط با این فایل را از حافظه پنهان صفحه باطل (drop) میکند. ظاهراً این کار حتی در صورتی که فایل باز بوده یا توسط فرآیندهای دیگر در حال استفاده باشد نیز انجام میشود. این تنظیم پایدار نیست؛ اگر متعاقباً فایل را بخوانید، طبق روال معمول در حافظه پنهان صفحه ذخیره خواهد شد..PP فراخوانی این تابع روی غیرفایلها اشکالی ندارد، چرا که شکست در آن نادیده گرفته میشود زیرا صرفاً یک اشاره (hint) است.
تابع "common/utils/utils.c:guestfs_int_fadvise_willneed"
void guestfs_int_fadvise_willneed (int fd)
اشاره به اینکه در آیندهٔ نزدیک به این دادهها دسترسی خواهیم داشت.
در لینوکس، این کار فوراً کل فایل را در حافظهٔ نهان صفحه (page cache) میخواند. این تنظیم ماندگار نیست؛ متعاقباً ممکن است صفحات طبق روال معمول از page cache خارج شوند.
فراخوانی این تابع روی غیرفایلها اشکالی ندارد، چرا که شکست در آن نادیده گرفته میشود زیرا صرفاً یک اشاره است.
تابع "common/utils/utils.c:guestfs_int_shell_unquote"
char * guestfs_int_shell_unquote (const char *str)
حذف نقلقولهای پوسته از یک رشته.
ابزار Augeas رشتههایی را به ما ارسال میکند که ممکن است دارای نقلقول باشند، برای مثال اگر از فایلهای درون /etc/sysconfig آمده باشند. این تابع میتواند نقلقولزدایی سادهای روی این رشتهها انجام دهد.
توجه داشته باشید که این تابع جایگزینی متغیرها را انجام نمیدهد، زیرا این کار بدون دانستن زمینهٔ فایل و در واقع محیطی که اسکریپت شل تحت آن اجرا میشود غیرممکن است. فایلهای پیکربندی نباید از نقلقولهای پیچیده استفاده کنند.
"str" رشتهٔ ورودی از Augeas است؛ رشتهای که ممکن است دارای نقلقول تکی، دوتایی یا فاقد نقلقول باشد. رشتهٔ بازگرداندهشده بدون نقلقول است و باید توسط فراخواننده آزاد (free) شود. در صورت بروز خطا "NULL" بازگردانده شده و "errno" به طور مناسب تنظیم میشود.
برای اطلاعات دربارهٔ نقلقولهای دوتایی در bash، پیوند زیر را ببینید: https://www.gnu.org/software/bash/manual/html_node/Double-Quotes.html
تابع "common/utils/utils.c:guestfs_int_is_reg"
int guestfs_int_is_reg (int64_t mode)
اگر فیلد "st_mode" در "guestfs_statns" یا "guestfs_lstatns" نشاندهندهٔ یک فایل معمولی (regular file) باشد، مقدار درست (true) برمیگرداند.
تابع "common/utils/utils.c:guestfs_int_is_dir"
int guestfs_int_is_dir (int64_t mode)
اگر فیلد "st_mode" در "guestfs_statns" یا "guestfs_lstatns" نشاندهندهٔ یک دایرکتوری باشد، مقدار درست (true) برمیگرداند.
تابع "common/utils/utils.c:guestfs_int_is_chr"
int guestfs_int_is_chr (int64_t mode)
اگر فیلد "st_mode" در "guestfs_statns" یا "guestfs_lstatns" نشاندهندهٔ یک دستگاه نویسهای (char device) باشد، مقدار درست (true) برمیگرداند.
تابع "common/utils/utils.c:guestfs_int_is_blk"
int guestfs_int_is_blk (int64_t mode)
اگر فیلد "st_mode" در "guestfs_statns" یا "guestfs_lstatns" نشاندهندهٔ یک دستگاه بلوکی (block device) باشد، مقدار درست (true) برمیگرداند.
تابع "common/utils/utils.c:guestfs_int_is_fifo"
int guestfs_int_is_fifo (int64_t mode)
اگر فیلد "st_mode" در "guestfs_statns" یا "guestfs_lstatns" نشاندهندهٔ یک لولهٔ نامگذاریشده (FIFO) باشد، مقدار درست (true) برمیگرداند.
تابع "common/utils/utils.c:guestfs_int_is_lnk"
int guestfs_int_is_lnk (int64_t mode)
اگر فیلد "st_mode" در "guestfs_statns" یا "guestfs_lstatns" نشاندهندهٔ یک پیوند نمادین باشد، مقدار درست (true) برمیگرداند.
تابع "common/utils/utils.c:guestfs_int_is_sock"
int guestfs_int_is_sock (int64_t mode)
اگر فیلد "st_mode" در "guestfs_statns" یا "guestfs_lstatns" نشاندهندهٔ یک سوکت دامنه یونیکس (Unix domain socket) باشد، مقدار درست (true) برمیگرداند.
تابع "common/utils/utils.c:guestfs_int_full_path"
char * guestfs_int_full_path (const char *dir, const char *name)
الحاق "dir" و "name" برای ایجاد یک مسیر. این تابع حالت الحاق "/" + "filename" و همچنین "/dir" + "filename" را به درستی مدیریت میکند. "name" میتواند "NULL" باشد.
فراخواننده باید مسیر بازگرداندهشده را آزاد (free) کند.
این تابع در صورت بروز خطا "errno" را تنظیم کرده و "NULL" برمیگرداند.
تابع "common/utils/utils.c:guestfs_int_hexdump"
void guestfs_int_hexdump (const void *data, size_t len, FILE *fp)
تخلیهٔ هگزادسیمال (hexdump) یک بلوک از حافظه در "FILE *"، مورد استفاده برای اشکالزدایی.
تابع "common/utils/utils.c:guestfs_int_strerror"
const char * guestfs_int_strerror (int errnum, char *buf, size_t buflen)
تابع strerror_r امن در برابر چندنخی (Thread-safe).
این تابع یک پوشش پیرامون دو نسخهٔ strerror_r(3) در glibc است، چرا که استفادهٔ صحیح از آن دشوار است (RHBZ#2030396).
بافر ارسالشده باید به اندازهٔ کافی برای ذخیرهٔ پیام خطا بزرگ باشد (حداقل ۲۵۶ نویسه) و نباید ایستا (non-static) باشد. توجه داشته باشید که ممکن است از بافر استفاده نشود؛ از مقدار بازگشتی استفاده کنید.
فایل common/utils/whole-file.c
تابع "common/utils/whole-file.c:read_whole_file"
int read_whole_file (const char *filename, char **data_r, size_t *size_r)
خواندن کل فایل "filename" در یک بافر حافظه..PP بافر حافظه مقداردهی اولیه شده و در "data_r" بازگردانده میشود. اندازه فایل بر حسب بایت در "size_r" بازگردانده میشود. بافر بازگرداندهشده باید توسط فراخواننده آزاد شود.
در صورت بروز خطا، این تابع پیامی را در "stderr" چاپ کرده و -1 را برمیگرداند. برخلاف تابع مشابه "guestfs_int_read_whole_file"، این تابع از هندل libguestfs استفاده نمیکند و error() را فرا نمیخواند.
برای راحتی فراخوانندهها، بافر بازگرداندهشده با NUL پایان مییابد (NUL در اندازه محاسبه نمیشود).
فایل باید یک فایل عادی، محلی و قابلاعتماد باشد. بهویژه، از این تابع برای خواندن فایلهایی که ممکن است تحت کنترل یک کاربر غیرقابلاعتماد باشند استفاده نکنید، زیرا این کار منجر به یک حمله انکار سرویس (denial-of-service) خواهد شد.
زیردایرکتوری common/visit
فایل common/visit/visit.c
این فایل شامل یک تابع بازگشتی برای پیمایش تمام فایلها و دایرکتوریها در یک سیستمفایل guestfs است.
برگرفته از https://rwmj.wordpress.com/2010/12/15/tip-audit-virtual-machine-for-setuid-files
تابع "common/visit/visit.c:visit"
int visit (guestfs_h *g, const char *dir, visitor_function f, void *opaque)
تمام فایلها و دایرکتوریهای یک سیستمفایل guestfs را با شروع از "dir" پیمایش میکند.
"dir" میتواند برای پیمایش تمام سیستمفایل برابر با "/" باشد، یا یک زیردایرکتوری باشد. پیوندهای نمادین دنبال نمیشوند.
تابع پیمایشگر "f" یک بار به ازای هر دایرکتوری و هر فایل فراخوانی میشود. پارامترهای ارسالشده به "f" شامل نام دایرکتوری جاری، نام فایل جاری (یا "NULL" در هنگام پیمایش یک دایرکتوری)، "guestfs_statns" (مجوزهای فایل و غیره)، و فهرست ویژگیهای گسترشیافته فایل است. تابع پیمایشگر ممکن است مقدار -1 را برگرداند که باعث متوقف شدن کل بازگشت همراه با خطا میشود.
همچنین یک اشارهگر "opaque" به این تابع ارسال میشود که مستقیماً به تابع پیمایشگر هدایت میگردد.
در صورت انجام موفقیتآمیز مقدار 0 و در صورت بروز خطا -1 را برمیگرداند. سازوکار مدیریت خطا چندان دقیق تعریف نشده است؛ یا خطایی را در هندل libguestfs تنظیم میکند یا خطایی را در stderr چاپ مینماید، اما راهی برای فراخواننده وجود ندارد که تفاوت این دو را تشخیص دهد.
زیردایرکتوری common/windows
فایل common/windows/windows.c
این فایل پشتیبانی از مسیر فایل ویندوزی "win:" را در guestfish(1) پیادهسازی میکند.
تابع "common/windows/windows.c:is_windows"
int is_windows (guestfs_h *g, const char *root)
بررسی میکند که آیا "root" یک نصب ویندوز است یا خیر.
این تابع به دروننگریای (introspection) که از قبل انجام شده باشد متکی است.
تابع "common/windows/windows.c:windows_path"
char * windows_path (guestfs_h *g, const char *root, const char *path, int readonly)
"path" را به عنوان یک مسیر احتمالی ویندوز بر اساس "root" حل میکند و مسیر جدیدی ارائه میدهد که میتواند در فراخوانیهای API در libguestfs به کار رود.
نکات:
- "root" باید یک نصب ویندوز باشد
- به دروننگری که پیشتر انجام شده متکی است
- تمام نقاط اتصال موجود را unmount کرده و ریشه ویندوز را (با توجه به "readonly") mount میکند
- در هنگام شکست در تخصیص حافظه exit(3) را فرا میخواند.SS "زیردایرکتوری daemon" فایل daemon/command.c
این فایل شامل تعدادی تابع کاربردی برای اجرای دستورهای خارجی و دریافت خروجی آنها است.
تابع "daemon/command.c:commandf"
int
commandf (char **stdoutput, char **stderror, unsigned flags,
const char *name, ...)
یک دستور را اجرا میکند. به صورت اختیاری stdout و stderr را در قالب رشته دریافت مینماید.
در صورت اجرای موفقیتآمیز دستور مقدار 0 و در صورت بروز هرگونه خطا مقدار -1 را برمیگرداند.
برای توضیحات مربوط به "flags" به "commandrvf" مراجعه کنید.
همچنین یک ماکرو به نام "command(out,err,name,...)" وجود دارد که "commandf" را با "flags=0" فراخوانی میکند.
تابع "daemon/command.c:commandrf"
int
commandrf (char **stdoutput, char **stderror, unsigned flags,
const char *name, ...)
مشابه "command" است، اما اجازه میدهد کد وضعیت خروجی زیردستور غیرصفر باشد و همان کد وضعیت را برمیگرداند.
در صورت بروز هرگونه خطای دیگر، کماکان -1 را بازمیگرداند.
همچنین یک ماکرو به نام "commandr(out,err,name,...)" وجود دارد که "commandrf" را با "flags=0" فراخوانی میکند.
تابع "daemon/command.c:commandvf"
int
commandvf (char **stdoutput, char **stderror, unsigned flags,
char const *const *argv)
مشابه "command" است، با این تفاوت که یک آرایه argv به آن ارسال میشود.
همچنین یک ماکرو به نام "commandv(out,err,argv)" وجود دارد که "commandvf" را با "flags=0" فراخوانی میکند.
تابع "daemon/command.c:commandrvf"
int
commandrvf (char **stdoutput, char **stderror, unsigned flags,
char const* const *argv)
این نسخهٔ معقولتر و مطمئنتری از system(3) برای اجرای دستورهای خارجی است. این تابع از fork/execvp استفاده میکند، بنابراین نیازی نیست نگران نقلقولگذاری پارامترها باشیم، و به ما امکان میدهد هرگونه پیام خطا را در یک بافر ثبت کنیم.
اگر "stdoutput" برابر با "NULL" نباشد، آنگاه *stdoutput مقدار stdout دستور را به صورت یک رشته برمیگرداند.
اگر "stderror" برابر با "NULL" نباشد، آنگاه *stderror مقدار stderr دستور را برمیگرداند. در صورتی که کاراکتر انتهایی \n وجود داشته باشد، حذف میشود تا بتوانید رشتهٔ خطا را مستقیماً در فراخوانی "reply_with_error" به کار ببرید.
پرچمها عبارتند از:
- "COMMAND_FLAG_FOLD_STDOUT_ON_STDERR"
- برای دستورهای خارجی معیوبی که پیامهای خطا را به stdout ارسال میکنند (مانند parted) اما خروجی مفید دیگری در stdout ندارند، از این پرچم برای ثبت پیامهای خطا در بافر *stderror استفاده کنید. در صورت استفاده از این پرچم، باید مقدار "stdoutput=NULL" را ارسال کنید زیرا هرگز چیزی در آن بافر ذخیره نخواهد شد.
- "COMMAND_FLAG_CHROOT_COPY_FILE_TO_STDIN"
- برای اجرای صحیح دستورهای خارجی روی فایلهای chrootشده (به https://bugzilla.redhat.com/579608 مراجعه کنید)، تعیین این پرچم باعث فورک شدن فرایند دیگری میشود که به sysroot عملیات chroot را انجام داده و صرفاً فایل ورودی را در stdin دستور مشخصشده کپی میکند. توصیفگر فایل با پرچمها OR میشود و آن توصیفگر فایل همیشه توسط این تابع بسته خواهد شد. برای مشاهدهٔ نمونهای از کاربرد، به daemon/hexdump.c مراجعه کنید.
همچنین یک ماکرو به نام "commandrv(out,err,argv)" وجود دارد که "commandrvf" را با "flags=0" فراخوانی میکند.
فایل daemon/device-name-translation.c
تابع "daemon/device-name-translation.c:device_name_translation_init"
void device_name_translation_init (void)
کشکردن نگاشت دیسکهای daemon.
هنگام راهاندازی daemon، حافظهٔ موقت را با محتویات /dev/disk/by-path پر میکند. از آنجا که نامها با ترتیب نامتعارفی چیده شدهاند، سادهترین کار استفاده از "ls -lv" در اینجا است.
تابع "daemon/device-name-translation.c:device_name_translation"
char * device_name_translation (const char *device)
ترجمهٔ نام دستگاه را انجام میدهد.
نرمافزار Libguestfs چند قالب استاندارد را برای نام دستگاهها تعریف میکند (همچنین به "BLOCK DEVICE NAMING" در guestfs(3) و "guestfs_canonical_device_name" در guestfs(3) مراجعه کنید). آنها عبارتند از:
- /dev/sdX[N]
- /dev/hdX[N]
- /dev/vdX[N]
- اینها به معنای پارتیشن Nام روی دستگاه Xام هستند. از آنجا که لینوکس دیگر دستگاهها را بر اساس ترتیبی که به qemu فرستاده میشوند شمارهگذاری نمیکند، باید با جستجوی دستگاه واقعی با استفاده از /dev/disk/by-path/ این موارد را ترجمه کنیم.
- /dev/mdX
- /dev/VG/LV
- /dev/mapper/...
- /dev/dm-N
- این موارد در اینجا ترجمه نمیشوند.
این تابع یک رشتهٔ تازه تخصیصیافته را برمیگرداند که فراخواننده باید حافظهٔ آن را آزاد (free) کند.
در صورت بروز خطا، مقدار "NULL" بازگردانده میشود. توجه داشته باشید که این تابع "reply_with_*" را فراخوانی نمیکند.
باید دستگاه را باز کرده و وجود "ENXIO" را بررسی کنیم، چرا که گرههای دستگاه ممکن است در appliance وجود داشته باشند.
فایل daemon/guestfsd.c
این همان daemon مربوط به guestfs است که داخل guestfs appliance اجرا میشود. این فایل راهاندازی و اتصال مجدد به کتابخانه را مدیریت میکند.
تابع "daemon/guestfsd.c:shell_quote"
void shell_quote (const char *str, FILE *fp)
مقدار "str" را در فایل "fp" مینویسد و اطمینان حاصل میکند که برای شل نقلقولگذاری (shell quoted) شده است..PP تابع "daemon/guestfsd.c:sysroot_shell_quote"
void sysroot_shell_quote (const char *path, FILE *fp)
مقدار "sysroot" + "path" را در فایل "fp" مینویسد و اطمینان حاصل میکند که نقلقول پوسته (shell quoted) روی آن اعمال شده است. مسیر باید یک مسیر مطلق باشد.
فایل daemon/internal.c
توابع داخلی که بخشی از API عمومی نیستند.
فایل daemon/utils-c.c
پیوندها (Bindings) برای توابع کمکی.
توجه داشته باشید توابعی که از کد OCaml فراخوانی میشوند هرگز نباید هیچیک از توابع "reply*" را فراخوانی کنند.
فایل daemon/utils.c
توابع کمکی متفرقه که توسط دیمن (daemon) استفاده میشوند.
تابع "daemon/utils.c:is_root_device_stat"
static int is_root_device_stat (struct stat *statbuf)
اگر و تنها اگر دستگاه همان دستگاه ریشه (root device) باشد true برمیگرداند (و بنابراین از دیدگاه فراخوانیهای کاربر باید نادیده گرفته شود).
تابع "daemon/utils.c:is_device_parameter"
int is_device_parameter (const char *device)
به پارامترهایی که به عنوان "Device"، "Dev_or_Path" و غیره نشانهگذاری شدهاند میتوان نام یک دستگاه بلوکی را ارسال کرد. این تابع بررسی میکند که آیا پارامتر نام یک دستگاه بلوکی است یا خیر.
همچنین میتوان در کد دیمن از آن برای بررسی اینکه آیا رشتهٔ ارسالشده به عنوان پارامتر "Dev_or_Path" یک دستگاه است یا یک مسیر استفاده کرد.
تابع "daemon/utils.c:sysroot_path"
char * sysroot_path (const char *path)
تبدیل "/path" به "/sysroot/path".
در صورت شکست "NULL" برمیگرداند. فراخواننده باید این مورد را بررسی کرده و "reply_with_perror ("malloc")" را فراخوانی کند. فراخواننده همچنین باید رشتهٔ بازگرداندهشده را آزاد (free) کند.
همچنین قالببند سفارشی %R در printf را ببینید که نقلقول پوسته (shell quoting) را نیز انجام میدهد.
تابع "daemon/utils.c:sysroot_realpath"
char * sysroot_realpath (const char *path)
مسیر را درون sysroot تفکیک کرده و "sysroot_path" را روی مسیر تفکیکشده فراخوانی میکند.
در صورت شکست "NULL" برمیگرداند. فراخواننده باید این مورد را بررسی کرده و "reply_with_perror ("malloc")" را فراخوانی کند. فراخواننده همچنین باید رشتهٔ بازگرداندهشده را آزاد (free) کند.
همچنین قالببند سفارشی %R در printf را ببینید که نقلقول پوسته (shell quoting) را نیز انجام میدهد.
تابع "daemon/utils.c:is_power_of_2"
int is_power_of_2 (unsigned long v)
اگر "v" توانی از ۲ باشد true برمیگرداند.
از الگوریتم شرح داده شده در نشانی زیر استفاده میکند: http://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2
تابع "daemon/utils.c:split_lines_sb"
struct stringsbuf split_lines_sb (char *str)
یک رشتهٔ خروجی را به یک فهرست از خطها که با NULL خاتمه مییابد تقسیم کرده و در یک stringsbuf میپیچد.
معمولاً این تابع در مواردی استفاده میشود که یک دستور خارجی را اجرا کردهایم که فهرستی از موارد را در خروجی چاپ کرده است و میخواهیم یک فهرست واقعی بازگردانیم.
حالتهای خاص در اینجا بسیار ظریف و حساس هستند. بهویژه توجه کنید:
- ""
- مقدار "[]" را برمیگرداند
- "\n"
- مقدار "[""]" را برمیگرداند
- "a\nb"
- مقدار "["a"; "b"]" را برمیگرداند
- "a\nb\n"
- مقدار "["a"; "b"]" را برمیگرداند
- "a\nb\n\n"
- مقدار "["a"; "b"; ""]" را برمیگرداند
رشتهٔ اصلی توسط این تابع بازنویسی و تخریب میشود (که معمولاً مشکلی ایجاد نمیکند زیرا این رشته همان رشتهٔ 'out' از "command*()" است). شما میتوانید رشتهٔ اصلی را آزاد کنید، زیرا add_string() رشتهها را با strdup تکثیر میکند.
در صورت بروز خطا مقدار "argv" در "struct stringsbuf" برابر "NULL" خواهد بود.
تابع "daemon/utils.c:filter_list"
char ** filter_list (bool (*p) (const char *str), char **strs)
یک فهرست از رشتهها را فیلتر میکند. یک فهرست تازه تخصیصیافته را بازمیگرداند که فقط حاوی رشتههایی است که در آنها "p (str) == true" باشد.
توجه داشته باشید که رشتهها را کپی نمیکند؛ مراقب باشید آنها را دوبار آزاد (double-free) نکنید.
تابع "daemon/utils.c:trim"
void trim (char *str)
فاصلههای خالی ابتدایی و انتهایی را نادیده گرفته و رشتهٔ اصلی را درجا بهروزرسانی میکند.
تابع "daemon/utils.c:parse_btrfsvol"
int parse_btrfsvol (const char *desc_orig, mountable_t *mountable)
توصیفگر mountable را برای یک زیرحجم (subvolume) btrfs تجزیه میکند. این تابع را مستقیماً فراخوانی نکنید؛ تنها از طریق stubها استفاده میشود..PP یک زیرحجم (subvolume) متعلق به btrfs به صورت زیر مشخص میشود:
btrfsvol:/dev/sda3/root
که در آن /dev/sda3 یک دستگاه بلوکی شامل یک سیستمفایل btrfs است، و root نام یک زیرحجم روی آن میباشد. رشتهای که پس از "btrfsvol:" میآید به این تابع ارسال میشود.
در صورت موفقیت، "mountable->device" و "mountable->volume" باید توسط فراخواننده آزاد شوند.
تابع "daemon/utils.c:mountable_to_string"
char * mountable_to_string (const mountable_t *mountable)
تبدیل یک "mountable_t" به بازنمایی رشتهای آن
این تابع میتواند در مسیر خطا استفاده شود، بنابراین نباید "reply_with_error" را فراخوانی کند.
تابع "daemon/utils.c:prog_exists"
int prog_exists (const char *prog)
بررسی میکند که برنامه وجود داشته و در $PATH قابل اجرا باشد.
تابع "daemon/utils.c:random_name"
int random_name (char *template)
الگویی مانند "/sysroot/XXXXXXXX.XXX" را ارسال کنید. این تابع الگو را بهروزرسانی میکند تا حاوی نام فایلی تصادفی باشد. هر نویسهٔ 'X' پس از آخرین '/' در الگو با نویسههای تصادفی جایگزین میشود.
نکات: احتمالاً باید از یک مسیر 8.3 استفاده کنید تا با تمام سیستمفایلها از جمله FAT اولیه سازگار باشد. همچنین این تابع فقط حروف کوچک ASCII و اعداد را جایگزین میکند، باز هم برای سازگاری با سیستمفایلهای دارای کمترین مخرج مشترک.
این تابع فایلی ایجاد نمیکند یا وجود داشتن فایل را بررسی نمیکند (تا زمانی که RNG درست کار کند، وجود آن بسیار بعید خواهد بود).
در صورت بروز خطا، -1 برگردانده میشود.
تابع "daemon/utils.c:udev_settle_file"
void udev_settle_file (const char *file)
دستورات LVM و سایر دستورات همگام نیستند، بهویژه زمانی که udev درگیر است. برای مثال، میتوانید دستگاهی را ایجاد یا حذف کنید، اما گره دستگاه در "/dev" تا مدتی بعد ظاهر نمیشود. این بدان معناست که اگر فرمانی را بلافاصله پس از فرمان دیگری اجرا کنید، با خطا مواجه خواهید شد.
پس از برخی دستورات خاص از "udevadm settle" استفاده کنید، اما اگر ناموفق بود چندان نگران نشوید.
تابع "daemon/utils.c:make_exclude_from_file"
char * make_exclude_from_file (const char *function, char *const *excludes)
فهرست "excludes" را به یک فایل موقت تبدیل کرده و رشتهای حاوی نام فایل موقت را برمیگرداند. فراخواننده باید پیوند فایل را حذف کرده (unlink) و رشته را آزاد کند.
"function" تابعی است که این تابع کمکی را فراخوانی کرده و عمدتاً برای خطاها و اشکالزدایی استفاده میشود.
فایل daemon/xattr.c
تابع "daemon/xattr.c:split_attr_names"
static char ** split_attr_names (char *buf, size_t len)
listxattr(2) رشتهٔ "foo\0bar\0baz" با طول "len" را برمیگرداند. (آخرین رشته در فهرست با \0 پایان مییابد اما \0 در "len" گنجانده نمیشود).
این تابع آن را به یک فهرست عادی از رشتهها تفکیک میکند.
توجه داشته باشید که فهرست برگرداندهشده حاوی اشارهگرهایی به رشتههای اصلی در "buf" است، بنابراین مراقب باشید که آنها را دوبار آزاد (double-free) نکنید..SS "زیردایرکتوری fish" فایل fish/alloc.c
این فایل دستورهای "alloc" و "sparse" در guestfish را پیادهسازی میکند.
تابع "fish/alloc.c:alloc_disk"
int alloc_disk (const char *filename, const char *size_str, int add, int sparse)
این تابع تخصیص زیربنایی است. این تابع از چند جای دیگر در guestfish نیز فراخوانی میشود.
فایل fish/copy.c
این فایل دستورهای "copy-in" و "copy-out" در guestfish را پیادهسازی میکند.
فایل fish/destpaths.c
این فایل تکمیل خودکار با کلید تب (tab-completion) را برای مسیرهای سیستمفایل در guestfish مدیریت میکند.
فایل fish/display.c
این فایل دستور "display" در guestfish را برای نمایش فایلهای گرافیکی (شمایلها، تصاویر) در ایمیجهای دیسک پیادهسازی میکند.
فایل fish/echo.c
این فایل دستور "echo" در guestfish را پیادهسازی میکند.
فایل fish/edit.c
دستور "edit" در guestfish، پیشنهاد شده توسط Ján Ondrej.
فایل fish/events.c
این فایل دستورهای مرتبط با رویداد در guestfish را پیادهسازی میکند: "event"، "delete-event" و "list-events".
فایل fish/fish.c
دستور guestfish، پوسته سیستمفایل مهمان. این فایل شامل حلقه اصلی و ابزارهای کمکی است.
تابع "fish/fish.c:parse_command_line"
static struct parsed_command parse_command_line (char *buf, int *exit_on_error_rtn)
یک رشته دستور را تجزیه کرده، آن را بر اساس فاصلههای سفید جدا میکند و مواردی چون '!'، '#' و غیره را مدیریت میکند. این تابع مقدار "buf" را بهصورت مخرب (درجا) بهروزرسانی میکند.
آرگومان "exit_on_error_rtn" برای ارسال تنظیم سراسری "exit_on_error" و بازگرداندن تنظیم محلی (برای نمونه اگر دستور با '-' آغاز شود) استفاده میشود.
در "parsed_command.status" بازمیگرداند:
- 1
- یک دستور guestfish دریافت شد (در "cmd_rtn"/"argv_rtn"/"pipe_rtn" بازگردانده میشود)
- 0
- هیچ دستور guestfish دریافت نشد، اما خطایی رخ نداده است
- -1
- یک خطا
تابع "fish/fish.c:parse_quoted_string"
static ssize_t parse_quoted_string (char *p)
رشتههای محصور در نقلقول جفت را تجزیه کرده و توالیهای گریز با بکاسلش را با نویسه واقعی جایگزین میکند. از آنجا که رشته درجا بازگردانده میشود، توالیهای گریز باید طول رشته را کوتاهتر کنند.
تابع "fish/fish.c:execute_and_inline"
static int execute_and_inline (const char *cmd, int global_exit_on_error)
برای مدیریت ساختار "<!" (اجرای دستور و درج مستقیم نتیجه در خط) استفاده میشود.
تابع "fish/fish.c:issue_command"
int
issue_command (const char *cmd, char *argv[], const char *pipecmd,
int rc_exit_on_error_flag)
یک دستور را اجرا میکند.
پرچم "rc_exit_on_error_flag" همان پرچم "exit_on_error" است که به کارگزار راه دور (هنگام ارسال دستورهای --remote) فرستاده میشود. این پرچم باعث خروج خود "issue_command" در صورت بروز خطا نمیشود.
تابع "fish/fish.c:extended_help_message"
void extended_help_message (void)
هنگامی که کاربر برای نخستین دستور اجراشده یک دستور ناشناخته وارد کند، یک پیام راهنمای تکمیلی چاپ میکند. یک حالت متداول زمانی است که کاربر چنین دستوری اجرا کند:
guestfish disk.img
با این انتظار که guestfish فایل disk.img را باز کند (در عمل، این کار تلاش برای اجرای دستور ناموجود "disk.img" بوده است).
تابع "fish/fish.c:error_cb"
static void error_cb (guestfs_h *g, void *data, const char *msg)
کالبک خطا. این تابع جایگزین گرداننده خطای استاندارد libguestfs میشود.
تابع "fish/fish.c:free_n_strings"
static void free_n_strings (char **str, size_t len)
آزادسازی رشتهها از یک ساختار "char**" که به NULL ختم نشده است.
تابع "fish/fish.c:decode_ps1"
static char * decode_ps1 (const char *str)
رمزگشایی "str" به رشته نهایی خط اعلان (پرامپت) قابل چاپ.
تابع "fish/fish.c:win_prefix"
char * win_prefix (const char *path)
بررسی و پردازش ساختار ویژه "win:..." برای مسیرهای خاص Windows. کد تولیدشده این تابع را برای تمام آرگومانهای مربوط به دستگاه یا مسیر فراخوانی میکند..PP این تابع یک رشتهٔ تازه تخصیصیافته را برمیگرداند و فراخواننده باید این رشته را آزاد کند؛ در غیر این صورت یک خطا نمایش داده و "NULL" را برمیگرداند.
تابع "fish/fish.c:file_in"
char * file_in (const char *arg)
مسیرهای ویژهٔ "FileIn" ("-" یا "-<<END" یا نام فایل) را حل میکند.
فراخواننده (fish/cmds.c) پس از اجرای دستور، "free_file_in" را فراخوانی خواهد کرد که باید منابع را پاکسازی کند.
تابع "fish/fish.c:file_out"
char * file_out (const char *arg)
مسیرهای ویژهٔ "FileOut" ("-" یا نام فایل) را حل میکند.
فراخواننده (fish/cmds.c) پس از اجرای دستور، "free (str)" را فراخوانی خواهد کرد.
تابع "fish/fish.c:progress_callback"
void
progress_callback (guestfs_h *g, void *data,
uint64_t event, int event_handle, int flags,
const char *buf, size_t buf_len,
const uint64_t *array, size_t array_len)
یک فراخوانی بازگشتی (callback) که یک نوار پیشرفت را نمایش میدهد.
فایل fish/glob.c
این فایل دستور "glob" در guestfish را پیادهسازی میکند.
تابع "fish/glob.c:expand_devicename"
static char ** expand_devicename (guestfs_h *g, const char *device)
گسترش الگوهای دستگاه با استفاده از glob، مانند "/dev/sd*" (https://bugzilla.redhat.com/635971).
هیچ تابع "guestfs_glob_expand_device" وجود ندارد زیرا معادل آن را میتوان با استفاده از توابعی مانند "guestfs_list_devices" پیادهسازی کرد.
در نگاه اول مشخص نیست که گسترش الگویی مانند "/dev/sd*" چه معنایی دارد. آیا باید شامل ترجمهٔ نام دستگاه باشد؟ آیا نتیجه باید هم پارتیشنها و هم دستگاهها را در بر گیرد؟
آیا "/dev/" + "*" باید تمام دستگاهها و سیستمهای فایل ممکن را برگرداند؟ در مورد VGها چطور؟ LVها چطور؟
برای حل این مسئله، کاری که انجام میدهیم ساخت فهرستی از تمام دستگاهها، پارتیشنها و غیره است، و سپس اعمال glob بر روی آن فهرست.
یادداشتهایی برای کارهای آینده (XXX):
- این بخش ترجمهٔ نام دستگاه را انجام نمیدهد. افزودن آن کار چندان دشواری نخواهد بود.
- میتوان تابعی در API برای بازگرداندن تمام موارد شبیه به دستگاه در نظر گرفت.
تابع "fish/glob.c:add_strings_matching"
static int
add_strings_matching (char **pp, const char *glob,
char ***ret, size_t *size_r)
با استفاده از fnmatch(3) در POSIX، رشتههایی را در فهرست "pp" پیدا میکند که با الگوی "glob" مطابقت دارند. رشتههای منطبق را به آرایهٔ "ret" اضافه میکند. *size_r اندازهٔ کنونی آرایهٔ "ret" است، که با اندازهٔ جدید بهروزرسانی میشود.
تابع "fish/glob.c:single_element_list"
static char ** single_element_list (const char *element)
یک فهرست تکعنصری شامل "element" را برمیگرداند.
فایل fish/help.c
این فایل دستور "help" در guestfish را پیادهسازی میکند.
تابع "fish/help.c:display_help"
int display_help (const char *cmd, size_t argc, char *argv[])
دستور "help".
این بخش در گذشته تنها تمام دستورها را فهرست میکرد، اما این کار چندان کاربردی نیست. در عوض، مقداری راهنمای حساس به بافتار (context-sensitive) مفید نمایش داده میشود. این ویژگی در صورتی که میدانستیم تاکنون چه تعداد درایو اضافه شده و آیا چیزی متصل (mount) شده است یا خیر، میتوانست بهبود یابد.
فایل fish/hexedit.c
این فایل دستور "hexedit" در guestfish را پیادهسازی میکند.
فایل fish/lcd.c
تابع "fish/lcd.c:run_lcd"
int run_lcd (const char *cmd, size_t argc, char *argv[])
دستور "lcd" در guestfish (مشابه با دستور "lcd" در BSD ftp).
فایل fish/man.c
تابع "fish/man.c:run_man"
int run_man (const char *cmd, size_t argc, char *argv[])
دستور "man" در guestfish
فایل fish/more.c
این فایل دستور "more" در guestfish را پیادهسازی میکند.
فایل fish/not.c
این فایل دستور "not" در guestfish را پیادهسازی میکند.
فایل fish/prep.c
این فایل گزینهٔ -N در guestfish را برای ایجاد چیدمانهای از پیش آمادهشدهٔ دیسک پیادهسازی میکند.
فایل fish/rc.c
این فایل پشتیبانی از راه دور (دستور) در guestfish را پیادهسازی میکند.
تابع "fish/rc.c:rc_listen"
void
rc_listen (void)
سرور کنترل از راه دور (یعنی "guestfish --listen").
تابع "fish/rc.c:rc_remote"
int
rc_remote (int pid, const char *cmd, size_t argc, char *argv[],
int exit_on_error)
کلاینت کنترل از راه دور (یعنی "guestfish --remote").
فایل fish/reopen.c
این فایل دستور "reopen" در guestfish را پیادهسازی میکند.
فایل fish/setenv.c
این فایل دستورهای "setenv" و "unsetenv" در guestfish را پیادهسازی میکند.
فایل fish/supported.c
این فایل دستور "supported" در guestfish را پیادهسازی میکند.
فایل fish/tilde.c
این فایل بسط تیلدا ("~") را برای دایرکتوریهای خانگی در guestfish(1) پیادهسازی میکند.
تابع "fish/tilde.c:try_tilde_expansion"
char * try_tilde_expansion (char *str)
این تابع در صورت یافتن نامزدی برای "~username" (بسط تیلدا)، از درون حلقهٔ اسکریپت فراخوانی میشود.
تابع "fish/tilde.c:expand_home"
static char * expand_home (char *orig, const char *append)
رشتهٔ $HOME + append را بازمیگرداند.
تابع "fish/tilde.c:find_home_for_username"
static const char * find_home_for_username (const char *username, size_t ulen)
شناسهٔ "username" (با طول "ulen") را جستجو میکند؛ در صورت یافت شدن، دایرکتوری خانگی و در غیر این صورت "NULL" را بازمیگرداند.
فایل fish/time.c
این فایل دستور "time" در guestfish را پیادهسازی میکند.
زیردایرکتوری python
فایل python/handle.c
این فایل شامل تعداد اندکی تابع است که بهصورت دستی نوشته شدهاند. بیشتر بایندینگها بهطور خودکار تولید میشوند (ببینید python/actions-*.c)..SH "همچنین ببینید (SEE ALSO)" guestfs(3), guestfs-building(1), guestfs-examples(3), guestfs-internals(1), guestfs-performance(1), guestfs-release-notes(1), guestfs-testing(1), libguestfs-test-tool(1), libguestfs-make-fixed-appliance(1), http://libguestfs.org.
نویسندگان (AUTHORS)
Richard W.M. Jones ("rjones at redhat dot com")
کپیرایت و تکثیر (COPYRIGHT)
Copyright (C) 2009-2025 Red Hat Inc.
مجوز (LICENSE)
این کتابخانه یک نرمافزار آزاد است؛ شما میتوانید آن را تحت شرایط «مجوز عمومی جامعتر گنو» (GNU Lesser General Public License) همانطور که توسط بنیاد نرمافزار آزاد منتشر شده است—طبق نسخهٔ ۲ مجوز یا (به انتخاب خودتان) هر نسخهٔ جدیدتری از آن—دوباره توزیع کرده و/یا تغییر دهید.
این کتابخانه با این امید که سودمند واقع شود توزیع شده است، اما بدون هرگونه ضمانت؛ حتی بدون ضمانت ضمنی قابلیت فروش یا مناسب بودن برای هدفی مشخص. برای جزئیات بیشتر «مجوز عمومی جامعتر گنو» را مطالعه کنید.
شما باید بههمراه این کتابخانه یک نسخه از «مجوز عمومی جامعتر گنو» را دریافت کرده باشید؛ در غیر این صورت به آدرس زیر برای بنیاد نرمافزار آزاد نامه بفرستید: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
گزارش باگها (BUGS)
برای دریافت فهرستی از باگهای ثبتشده برای libguestfs از این پیوند استفاده کنید: https://bugzilla.redhat.com/buglist.cgi?component=libguestfs&product=Virtualization+Tools
برای گزارش یک باگ جدید در libguestfs از این پیوند استفاده کنید: https://bugzilla.redhat.com/enter_bug.cgi?component=libguestfs&product=Virtualization+Tools
هنگام گزارش یک باگ، لطفاً موارد زیر را ارائه دهید:
- نسخهٔ libguestfs.
- محل تهیهٔ libguestfs (برای نمونه کدام توزیع لینوکس، کامپایلشده از کد منبع، و غیره).
- باگ را بهدقت شرح داده و روشی برای بازتولید آن ارائه دهید.
- ابزار libguestfs-test-tool(1) را اجرا کرده و خروجی کامل و ویرایشنشده را در گزارش باگ جایگذاری کنید.
| 2026-07-14 | libguestfs-1.60.1 |