מטפלי קובץ קבצים ספריות

lstat#

מחזיר את רשימת הסטטוס בת 13 האיברים עבור נתיב מבלי לעקוב אחר קישור סימבולי.

lstat עושה בדיוק את מה ש־stat עושה - אותה תוצאה בת 13 איברים, אותו מטמון מטפל קובץ _ מיוחד, אותה סמנטיקת כשל - בהבדל אחד: אם הארגומנט נושא שם של קישור סימבולי, lstat מחזיר מידע על הקישור עצמו (mode, owner, size, mtime שלו), לא על המטרה שאליה הקישור מצביע. עבור כל מה שאינו קישור סימבולי, lstat ו־stat אינם נבדלים. במערכות ללא קישורים סימבוליים lstat יורד בשקט ל־stat.

תקציר#

lstat FILEHANDLE
lstat EXPR
lstat DIRHANDLE
lstat

מה מקבלים בחזרה#

בהקשר רשימה, אותה רשימה בת 13 איברים כמו stat:

my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
    $atime,$mtime,$ctime,$blksize,$blocks)
       = lstat($path);

משמעויות השדות זהות ל־stat - device, inode, mode (סוג + הרשאות), מספר קישורים, uid/gid של בעלים, rdev, גודל, atime, mtime, ctime, גודל בלוק I/O מועדף, ובלוקים מוקצים. ביטי הסוג ב־$mode הם אלה שמבחינים קישור סימבולי: על הקישור עצמו הם מדווחים S_IFLNK, בעוד stat על אותו שם ידווח את הסוג של המטרה.

בהקשר סקלר lstat מחזיר ערך אמת בהצלחה ומחרוזת ריקה בכישלון. בכישלון, צורת הרשימה מחזירה רשימה ריקה ו־$! נקבע לסיבה (ENOENT, EACCES וכדומה).

אם EXPR מושמט, lstat פועל על $_.

מטפל הקובץ _#

כל lstat מוצלח (וכל stat או filetest מוצלח) מאכלסים את ה־״buffer של ה־stat האחרון״ הפנימי של המפענח. העברת ה־bareword _ כארגומנט עושה שימוש חוזר ב־buffer הזה במקום לבצע קריאת מערכת נוספת:

if (-l $path && (my @s = lstat(_))) {
    # $path was a symlink; @s describes the link, not the target
}

מכיוון ש־-l עצמו מבצע lstat מתחת לפני השטח, ה־lstat(_) למעלה אינו עולה דבר. זוהי הדרך הקנונית ״לשאול מספר שאלות על קובץ אחד מבלי לבצע stat מחדש״. שימו לב ש־filetest על שם קובץ כ־bareword (-l $path) משאיר את ה־buffer מתאר את הקישור; filetest על מטפל קובץ עוקב אחר ה־descriptor הפתוח ולכן משאיר buffer בצורת stat. כאשר רוצים נתוני symlink, יש לפנות במפורש ל־lstat.

מצב גלובלי שהוא נוגע בו#

  • $_ - הארגומנט כאשר EXPR מושמט.

  • $! - נקבע בכישלון ל־errno מקריאת lstat(2) הבסיסית.

  • מטפל הקובץ המיוחד _ - נדרס בכל קריאה מוצלחת.

דוגמאות#

הבחנה בין symlink למטרה שלו. stat על symlink עוקב אחריו בשקט; lstat לא:

symlink "/etc/passwd", "link.tmp";

my $via_stat  = (stat  "link.tmp")[7];  # size of /etc/passwd
my $via_lstat = (lstat "link.tmp")[7];  # size of the link inode
                                        # (length of "/etc/passwd")

מעבר על ספרייה והפרדה בין קישורים לבין קבצים רגילים ללא syscall נוסף לכל רשומה, באמצעות ה־buffer _:

use Fcntl ':mode';

for my $name (readdir $dh) {
    next if $name eq '.' || $name eq '..';
    lstat "$dir/$name" or next;
    if (S_ISLNK((lstat(_))[2])) {
        print "link: $name\n";
    } elsif (-f _) {
        print "file: $name\n";
    } elsif (-d _) {
        print "dir:  $name\n";
    }
}

זיהוי symlink תלוי באוויר - lstat מצליח על הקישור, stat נכשל כי המטרה איננה:

if (lstat $path and not stat $path) {
    warn "$path is a dangling symlink: $!\n";
}

מעקב ידני אחר הקישור כאשר רוצים את שני פיסות המידע:

my @link   = lstat $path       or die "lstat $path: $!";
my $target = readlink $path    // die "readlink $path: $!";
my @target = stat $path        or die "stat $path: $!";

צורה ללא־ארגומנטים הפועלת על $_, אידיומטית בבלוקי preprocess של File::Find ובמסנני grep:

my @symlinks = grep { lstat; -l _ } @paths;

מקרי קצה#

  • לא symlink: lstat מתנהג בדיוק כמו stat - אין עונש על העדפת lstat כשעומדים להסתעף על -l.

  • מערכות ללא symlinks: lstat נופל בשקט ל־stat. קוד שנכתב מול lstat נשאר נייד; הוא רק מאבד את ההתנהגות המבחינה.

  • ארגומנט filehandle / dirhandle: FILEHANDLE או DIRHANDLE שמועבר מתייחס ל־descriptor פתוח כבר, שאינו יכול להיות symlink בעצמו (הקרנל פתר את הקישור בזמן open). lstat FILEHANDLE לכן מחזיר אותה תוצאה כמו stat על אותו מטפל. יש להשתמש בצורת EXPR על הנתיב כאשר נחוצה מטא־דאטה של הקישור.

  • lstat(_) לאחר lstat שנכשל: ה־buffer _ נשאר במצב שאליו ה־stat המוצלח האחרון הביא אותו. lstat שנכשל אינו מנקה אותו. תמיד יש לבדוק את ערך ההחזרה לפני קריאת _.

  • נתיבים יחסיים: נפתרים מול ספריית העבודה הנוכחית של התהליך, בדיוק כמו stat.

  • הרשאה ל־lstat: דורש הרשאת חיפוש (x) על כל רכיב ספרייה בנתיב, אבל - בניגוד ל־stat - אינו דורש כל הרשאה על מטרת הקישור. lstat לכן מצליח על קישורים אל ספריות שאי־אפשר לקרוא.

  • Bareword מול ביטוי: lstat $fh כאשר $fh מחזיק filehandle מבצע stat על המטפל; lstat "$fh" ממיר את $fh למחרוזת ומבצע stat על הנתיב (בדרך־כלל חסר־משמעות) שמתקבל. יש לצטט בכוונה.

הבדלים מ־upstream#

תואם מלא ל־upstream Perl 5.42.

ראו גם#

  • stat - המקבילה העוקבת אחר קישור; אותה צורת החזרה וסמנטיקת _ זהות

  • readlink - קריאת מחרוזת המטרה של קישור סימבולי מבלי לבצע עליו stat

  • symlink - יצירת קישור סימבולי

  • -l - אופרטור filetest עבור ״האם זהו קישור סימבולי״; מבצע פנימית lstat ומשאיר את התוצאה ב־_

  • $_ - ארגומנט ברירת מחדל כאשר EXPR מושמט

  • $! - סיבת הכישלון כאשר lstat מחזיר רשימה ריקה