sysopen#
פותח קובץ בדרך הרמה־נמוכה, מעביר מסיכת ביטים שלמה של MODE ישירות לקריאת המערכת open(2) הבסיסית.
sysopen הוא מוצא החירום למקרה ש־DWIM של מצב מחרוזת של open בדרך - כשצריך O_EXCL ליצירה־אם־לא־קיים אטומית, O_NOFOLLOW לסירוב ל־symlinks, O_NONBLOCK על FIFO, או כל דגל אחר שאין לו מחרוזת "<" / ">" / ">>" מתאימה. קבועי הדגלים חיים ב־Fcntl ומשולבים עם |.
תקציר#
sysopen FILEHANDLE, FILENAME, MODE
sysopen FILEHANDLE, FILENAME, MODE, PERMS
מה מקבלים בחזרה#
1 בהצלחה, undef בכשל (כאשר $! מוגדר ל־errno מה־syscall שנכשל). שלא כמו open, אין קסם - FILENAME נלקח מילולית, אף >, <, |, או - מובילים אינם מפורשים, אף מחרוזת מצב שכבתית אינה מנותחת.
אם FILEHANDLE הוא סקלר לא־מוגדר, הוא מאוטוויפיק למטפל רענן:
sysopen my $fh, $path, O_RDONLY
or die "sysopen $path: $!";
MODE - מסיכת הביטים של Fcntl#
MODE הוא מספר שלם הנבנה על ידי OR של קבועים מ־Fcntl. מצב הגישה הוא חובה ובלעדי הדדית; דגלי המתאם הם אופציונליים ומשולבים בחופשיות:
דגל | משמעות |
|---|---|
| פותח לקריאה בלבד. |
| פותח לכתיבה בלבד. |
| פותח לקריאה ולכתיבה. |
| יוצר את הקובץ אם הוא אינו קיים. |
| עם |
| כל כתיבה מבצעת seek לסוף הקובץ תחילה (צירוף אטומי). |
| קוטם את הקובץ לאורך אפס בפתיחה. |
| מצב לא־חוסם עבור ה־descriptor המתקבל. |
| נכשל עם |
יש לייבא אותם בשם או עם תג:
use Fcntl qw(O_RDWR O_CREAT O_EXCL O_APPEND);
# or
use Fcntl ':DEFAULT';
הערכים הישנים 0, 1, 2 עבור לקריאה־בלבד, לכתיבה־בלבד, קריאה־כתיבה עובדים גם בכל מערכת ש־Perl תומך בה, אך יש לתת שם לקבועים - הקוד המתקבל שורד סקירה בין־פלטפורמית ונקרא ללא מילון מונחים.
PERMS - ביטי ההרשאה בזמן יצירה#
PERMS הוא מצב אוקטלי (כפי ש־chmod לוקח) המוחל על ה־inode רק כאשר O_CREAT יוצר בפועל את הקובץ. אם PERMS מושמט, Perl מעביר 0666. ה־umask של התהליך מוחל על ידי הקרנל מעל, כך ש־umask ברירת מחדל של 022 מניב 0644 על הדיסק.
sysopen my $fh, $path, O_WRONLY | O_CREAT | O_EXCL, 0600
or die "create $path: $!";
אסור לכתוב 0644 כארגומנט PERMS ללא סיבה. 0644 קשיח מסיר כתיבת קבוצה אפילו ממשתמשים שהגדירו בכוונה umask סלחני; 0666 בתוספת ה־umask של המשתמש הוא ברירת המחדל הנישאת וזה מה ש־sysopen משתמש בו כשמשמיטים את הארגומנט לחלוטין.
מצב גלובלי שהוא נוגע בו#
${^OPEN}- תצורת השכבות של ה־pragmaopen.sysopenמחיל את אותה מחסנית PerlIO ברירת מחדל ש־openהיה מחיל עבור קריאה ללא שכבות. יש להשתמש ב־binmodeמיד אחריsysopenמוצלח כשצריך לדרוס או להסיר שכבות (טיפוסי לקבצים בינאריים, sockets־כקבצים, או descriptors שלO_NONBLOCK).umaskשל תהליך - מסכל אתPERMSכש־O_CREATיוצר את הקובץ.
דוגמאות#
יצירה־אם־לא־קיים אטומית - הסיבה הקנונית לפנות ל־sysopen:
use Fcntl qw(O_WRONLY O_CREAT O_EXCL);
sysopen my $fh, "lock.pid", O_WRONLY | O_CREAT | O_EXCL, 0644
or die "another instance is already running: $!";
print $fh "$$\n";
close $fh;
פתיחה־או־יצירה לקריאה/כתיבה, תוך שימור התוכן הקיים:
use Fcntl qw(O_RDWR O_CREAT);
sysopen my $fh, $path, O_RDWR | O_CREAT, 0666
or die "sysopen $path: $!";
לוג רק־לצירוף עם ערובת הצירוף - כל כתיבה נוחתת ב־EOF ללא קשר לשילוב עם כותבים אחרים:
use Fcntl qw(O_WRONLY O_CREAT O_APPEND);
sysopen my $log, "/var/log/app.log", O_WRONLY | O_CREAT | O_APPEND, 0644
or die "open log: $!";
print $log "startup\n";
פתיחת FIFO מבלי לחסום בלחיצת היד של צד הקורא:
use Fcntl qw(O_RDONLY O_NONBLOCK);
sysopen my $fifo, "/tmp/q", O_RDONLY | O_NONBLOCK
or die "sysopen fifo: $!";
סירוב לעקוב אחרי symlink בעלה - שימושי בספריות שניתנות לכתיבה על ידי משתמשים לא־אמינים:
use Fcntl qw(O_RDONLY O_NOFOLLOW);
sysopen my $fh, "$dir/config", O_RDONLY | O_NOFOLLOW
or die "sysopen config: $!";
כפייה של קלט/פלט ברמת בייט אחרי פתיחה - הסרה של כל שכבת :utf8 או :crlf שמחסנית PerlIO ברירת המחדל הייתה מתקינה אחרת:
sysopen my $fh, $path, O_RDONLY or die $!;
binmode $fh;
מקרי קצה#
O_EXCLללאO_CREATהוא no-op. בדיקת הבלעדיות מופעלת רק כש־O_CREATמבקש מהקרנל ליצור את הקובץ. תמיד יש לכתוב אותם יחד:O_CREAT | O_EXCL.O_EXCLאינו נעילה. הוא מונע פתיחה מוצלחת על קובץ שכבר קיים, לא יותר. ברגע שהקובץ קיים, כלsysopenעוקב עםO_CREAT | O_EXCLנכשל. הוא אינו מסדרל גישה לתוכן - יש להשתמש ב־flockלכך.O_EXCLבמערכות קבצים רשת. מימושי NFS משתנים; גרסאות NFS ישנות מאבדות בשקט את הסמנטיקה הבלעדית. אסור להסתמך עלO_EXCLלרוחב NFSv2.O_CREAT | O_EXCLו־symlinks. כששני הדגלים מוגדרים, הקרנל מסרב לפתוח symlink קיים מראש ברכיב הנתיב הסופי. הוא אינו מגן על רכיבי נתיב ביניים; יש להשתמש ב־O_NOFOLLOWאו לפתור את הספרייה עםopendirבתוספת סמנטיקתopenatאם צריך זאת.O_TRUNCעםO_RDONLY. ההתנהגות אינה מוגדרת על ידי POSIX. אסור לשלב אותם.PERMSמושמט. ברירת המחדל היא0666, ממוסכת על ידיumask. זה לא0644. יש להשמיט אתPERMSאלא אם רוצים באופן פעיל לדרוס את ה־umaskשל המשתמש.FILEHANDLEכביטוי. אםFILEHANDLEהוא bareword, הוא מציין גלובל של חבילה. אם הוא ביטוי המוערך ל־glob, globref, אוIO::Handle, המטפל הזה נפתח. אם הוא סקלר לא־מוגדר, מטפל רענן מאוטוויפיק לתוכו - הצורה הלקסיקלית בשימוש לאורך הדוגמאות האלה.אין קסם ב־
FILENAME.FILENAMEשל"-"פותח קובץ הנקרא מילולית-, לאSTDIN.>מוביל פותח קובץ הנקרא מילולית>filename, לא כתיבה ל־filename. זוהי כל הנקודה שלsysopenמולopen.שכבות PerlIO ברירת מחדל עדיין חלות.
sysopenהוא ”רמה נמוכה“ יחסית למחרוזת המצב, לא יחסית ל־PerlIO. המטפל המתקבל כולל את אותה מחסנית שכבות כמוopenללא שכבות; יש לקרוא ל־binmodeכדי לשנות אותה.ביטוי
FILEHANDLEסגור או לא־חוקי. מחזירundefכאשר$!מוגדר (לרובEBADFעבור descriptor קיים גרוע;ENOENT,EACCES,EEXIST,ELOOPעבור שגיאות ברמת הנתיב).
הבדלים מהמקור#
תואם במלואו ל־Perl 5.42 במקור.
ראו גם#
open- פותח ברמה גבוהה יותר עם ניתוח מצב מחרוזת, pipes,-כ־STDIN/STDOUT, ומצבים שכבתיים; יש להשתמש בו אלא אם צריכים במיוחד דגל ש־sysopenחושףfcntl- משנה דגלים על descriptor שכבר פתוח (לדוגמה, הגדרתO_NONBLOCKבדיעבד); חולק את אוצר הקבועים שלFcntlsysread- קריאה לא־buffered; עובד על כל מטפל, לא רק על אחד שהושג מ־sysopen, למרות השםsyswrite- כתיבה לא־buffered, אותה הערהFcntl- המודול שמייצא קבועיO_*ואת התגים:DEFAULT/:flock/:modebinmode- קובע או מסיר שכבות PerlIO על המטפל לאחר פתיחהumask- מסיכת התהליך המחסירה ביטים מ־PERMSכש־O_CREATיוצר את הקובץ