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

chmod#

שינוי ביטי הרשאות של רשימת קבצים.

chmod קובע לכל קובץ ב־LIST את ההרשאה MODE. הערך MODE הוא ערך מספרי - שנים־עשר הביטים התחתונים הם שלישיית ההרשאות הרגילה של Unix בתוספת ביטי setuid, setgid והביט הדביק, בדיוק כפי שמתקבל ב־chmod(2). ב־LIST מתקבלים גם שמות נתיב רגילים וגם מטפלי קובץ פתוחים. מחזיר את מספר הקבצים שעבורם קריאת המערכת התשתיתית הצליחה.

תקציר#

chmod MODE, LIST

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

מספר הקבצים ששונו בהצלחה, כמספר שלם. אפס משמעו שכל קריאה נכשלה; ערך הקטן מ־scalar @files משמעו כישלון חלקי. chmod אינו זורק חריגה על כישלון בקובץ בודד - הוא ממשיך הלאה וסופר את ההצלחות.

$! משקף את השגיאה רק מהקובץ האחרון שנכשל. בריצה מעורבת של הצלחה/כישלון אין דרך מובנית לדעת אילו קבצים נכשלו; אם נדרש דיווח שגיאה לכל קובץ, יש לקרוא ל־chmod פעם אחת לכל קובץ ולבדוק את ערך ההחזרה בכל פעם:

for my $f (@files) {
    chmod 0644, $f
        or warn "chmod $f: $!";
}

כתיבת MODE כראוי#

MODE הוא מספר שלם. שלוש הדרכים לכתוב אותו:

  • ליטרל אוקטלי עם אפס מוביל: 0644, 0755, 0600. זוהי הצורה המקובלת והיא תואמת את הספרות שהיו מוקלדות ב־chmod(1).

  • ליטרל אוקטלי עם הקידומת 0o: 0o644, 0o755. מתקבל החל מ־Perl 5.34; שקול לצורת האפס המוביל וקל יותר לזיהוי כ“אוקטלי“ במבט חטוף.

  • קבועים סימבוליים מ־Fcntl: use Fcntl qw(:mode); S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH מתערך ל־0755. שימושי כאשר קבוצת הרשאות נבנית מחלקים.

ארגומנט מחרוזת הוא כמעט תמיד באג:

chmod "0644", "foo";     # WRONG - stringifies as decimal 644 (octal 1204),
                         #         grants mode --w----r-T
chmod 644,    "foo";     # WRONG - decimal 644 is octal 1204, same result
chmod 0644,   "foo";     # right
chmod 0o644,  "foo";     # right (Perl 5.34+)

אם ה־mode מגיע באמת כמחרוזת (קובץ תצורה, ארגומנט CLI), יש להמיר אותו תחילה עם oct:

my $mode = "0644";       # string from config
chmod oct($mode), "foo"; # oct("0644") == 0644

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

קובע את $! בכל כישלון כך שיתאים לקריאת ה־chmod(2) / fchmod(2) האחרונה שנכשלה. אינו קורא משתנים גלובליים של המפרש.

דוגמאות#

שינוי קובץ אחד, בדיקת הצלחה:

chmod 0755, "install.sh"
    or die "chmod install.sh: $!";

שינוי קבצים רבים בקריאה אחת, קליטת המונה:

my $cnt = chmod 0644, "a.txt", "b.txt", "c.txt";
print "updated $cnt of 3 files\n";

עם מערך של שמות נתיב:

my @executables = glob "bin/*";
chmod 0755, @executables;

שמירת הביטים הקיימים, הוספת הרשאת כתיבה לבעלים. קוראים את ה־mode עם stat, ממסכים לביטי ההרשאות, מבצעים OR עם הביט החדש, וכותבים בחזרה:

open my $fh, "<", "foo" or die $!;
my $perm = (stat $fh)[2] & 07777;
chmod $perm | 0200, $fh;

צורה סימבולית באמצעות Fcntl:

use Fcntl qw(:mode);
chmod S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH, @executables;
# identical to: chmod 0755, @executables;

דיווח שגיאה לכל קובץ (נדרש כדי לדעת איזה קובץ נכשל בקריאה רב־קבצים):

my @failed;
for my $f (@files) {
    push @failed, $f unless chmod 0644, $f;
}
warn "chmod failed on: @failed\n" if @failed;

מקרי קצה#

  • רשימה ריקה: chmod 0644 מחזיר 0. ה־mode מתערך אך אין קריאת מערכת.

  • מצבי מחרוזת: chmod "0644", $f ו־chmod "+x", $f שניהם שגויים. chmod לעולם אינו מנתח מחרוזות mode סימבוליות - בניגוד ל־chmod(1), הפונקציה המובנית מקבלת מספר, לא מפרט.

  • מטפלי קובץ מול barewords: bareword ב־LIST הוא שם קובץ, לא מטפל קובץ. יש להעביר מטפל קובץ כ־glob או כהפניה ל־glob:

    chmod 0644, *FH;         # filehandle
    chmod 0644, \*FH;        # filehandle
    chmod 0644, $fh;         # filehandle (lexical)
    chmod 0644, "FH";        # filename "FH" - almost certainly a bug
    

    במערכות ללא fchmod(2), העברת מטפל קובץ מעלה חריגה. Linux תומך ב־fchmod(2), כך שבפלטפורמות שאליהן pperl מכוון זה תמיד עובד.

  • ביטי setuid / setgid / sticky: שלושת הביטים העליונים של מילת ה־mode (04000, 02000, 01000) קובעים את setuid, setgid והביט הדביק, בהתאמה. 0o4755 יוצר קובץ הרצה setuid; 0o2775 ספרייה setgid.

  • Symlinks: chmod follows symlinks. Changing permissions on the symlink itself is not portable and is not exposed by this built-in

    • use lchmod from a module if the platform supports it.

  • הרשאה לשנות הרשאה: רק בעל הקובץ (ו־root) רשאים לקרוא ל־chmod(2) על קובץ. כישלון קובע את $! ל־EPERM.

  • נתיבים שאינם קיימים: chmod על נתיב חסר קובע את $! ל־ENOENT ותורם 0 למונה ההצלחות. אינו מזהיר ואינו מת.

  • umask אינו חל: umask ממסך את ה־mode של קבצים שזה עתה נוצרו מ־open, sysopen, mkdir, ודומיהם. chmod קובע את ה־mode כפשוטו - ללא מיסוך.

הבדלים מהמקור#

תאימות מלאה עם Perl 5.42 המקורי.

ראו גם#

  • chown - הקריאה המקבילה לשינוי בעלים/קבוצה; אותה צורת רשימה־ומונה־החזרה

  • stat - קריאת ה־mode הנוכחי כדי לאפשר שינוי שלו במקום החלפה מלאה

  • umask - מסכת הרשאות ברירת מחדל החלה על קבצים חדשים; לא קשור ל־chmod, שקובע ביטים כפשוטם

  • open / sysopen - יצירת קבצים; ארגומנט ה־mode ל־sysopen ממוסך על־ידי umask בעת היצירה וניתן לאחר מכן להדק או להרפות אותו עם chmod

  • oct - פירוק "0644" למספר השלם 0644 כאשר ה־mode מגיע כמחרוזת

  • $! - שגיאת מערכת מהקובץ האחרון שנכשל; משמעותי רק לקריאות קובץ־בודד או מיד לאחר קריאה־לכל־קובץ שנכשלה בלולאה