Filehandles, αρχεία, κατάλογοι

chdir#

Αλλάζει τον τρέχοντα κατάλογο εργασίας της διεργασίας.

Η chdir είναι το περιτύλιγμα της Perl γύρω από τις κλήσεις συστήματος chdir(2) και - όπου ο πυρήνας το υποστηρίζει - fchdir(2). Αλλάζει τον κατάλογο ως προς τον οποίο επιλύονται οι σχετικές διαδρομές για την τρέχουσα διεργασία και, σε περίπτωση επιτυχίας, διατηρεί αυτή την αλλαγή για κάθε επόμενη λειτουργία αρχείου στο πρόγραμμα.

Σύνοψη#

chdir EXPR
chdir FILEHANDLE
chdir DIRHANDLE
chdir

Τι επιστρέφεται#

1 σε επιτυχία, 0 σε αποτυχία. Σε αποτυχία η $! τίθεται στο υποκείμενο errno ώστε να μπορείτε να ξεχωρίσετε το «no such directory» (ENOENT) από το «permission denied» (EACCES) από το «not a directory» (ENOTDIR):

chdir $path
    or die "chdir $path failed: $!";

Η επιστροφή είναι πάντα μια απλή λογική τιμή - δεν υπάρχει χωριστή τιμή «άλλαξε σε κανέναν κατάλογο επειδή δεν δόθηκε όρισμα». Η μορφή χωρίς όρισμα είτε πετυχαίνει αλλάζοντας στον αρχικό κατάλογο (home), είτε αποτυγχάνει όπως κάθε άλλη κλήση.

Καθολική κατάσταση που επηρεάζει#

  • %ENV - διαβάζεται όταν η chdir καλείται χωρίς όρισμα. Η σειρά αναζήτησης είναι πρώτα $ENV{HOME}, μετά $ENV{LOGDIR}. Αν κανένα δεν είναι ορισμένο, η chdir δεν κάνει τίποτα και επιστρέφει 0.

  • $! - τίθεται σε αποτυχία στο errno που αναφέρει ο πυρήνας.

Η chdir δεν ενημερώνει το $ENV{PWD}. Τα κελύφη διατηρούν το PWD τα ίδια· ένα πρόγραμμα Perl που νοιάζεται για το PWD στις θυγατρικές διεργασίες πρέπει να αναθέσει τιμή στο $ENV{PWD} μετά από επιτυχημένη chdir.

Μορφές ορίσματος#

  • chdir EXPR - η EXPR μετατρέπεται σε συμβολοσειρά και περνά στην chdir(2) ως διαδρομή. Οι σχετικές διαδρομές επιλύονται ως προς τον τρέχοντα κατάλογο εργασίας τη στιγμή της κλήσης.

  • chdir FILEHANDLE και chdir DIRHANDLE - σε Linux (και σε κάθε σύστημα με fchdir(2)) ο πυρήνας αλλάζει κατάλογο σε αυτόν στον οποίο αναφέρεται το handle. Το FILEHANDLE εδώ σημαίνει filehandle ανοιγμένο σε κατάλογο, ή directory handle από την opendir. Η χρήση της μορφής handle αποφεύγει μια κούρσα TOCTOU μεταξύ της επίλυσης μιας διαδρομής και της αλλαγής εντός αυτής.

  • chdir (χωρίς όρισμα) - αλλάζει στο $ENV{HOME}, με εφεδρεία το $ENV{LOGDIR} αν το HOME δεν είναι ορισμένο. Αν και τα δύο δεν είναι ορισμένα η κλήση αποτυγχάνει και η $! παραμένει αμετάβλητη· ελέγξτε την τιμή επιστροφής, όχι το $!.

Παραδείγματα#

Μετάβαση σε κατάλογο και έξοδος αν δεν υπάρχει:

chdir "/var/log"
    or die "cannot enter /var/log: $!";

Εκτέλεση ενός μπλοκ εργασιών σε διαφορετικό κατάλογο και επιστροφή στο σημείο εκκίνησης:

use Cwd qw(getcwd);
my $origin = getcwd;
chdir $work_dir or die "chdir $work_dir: $!";
# ... do work relative to $work_dir ...
chdir $origin  or die "chdir $origin: $!";

Αλλαγή μέσω directory handle (χωρίς κούρσα σε συστήματα με fchdir(2)):

opendir my $dh, $path or die "opendir $path: $!";
chdir $dh              or die "fchdir $path: $!";

Πήγαινε σπίτι:

chdir or die "no HOME/LOGDIR in environment";

Δοκιμή λίστας υποψηφίων, με στάση στον πρώτο που λειτουργεί:

for my $d ("/srv/app", "/opt/app", "/usr/local/app") {
    last if chdir $d;
}

Οριακές περιπτώσεις#

  • Empty string or undef: chdir "" and chdir undef both fail and set $! to ENOENT. They do not fall back to $HOME

    • the no-argument form is triggered by absence of an argument, not by an argument that happens to be empty.

  • Σχετικές διαδρομές σε thread με δικό του cwd: ο τρέχων κατάλογος εργασίας του πυρήνα είναι ανά διεργασία, όχι ανά thread, στο Linux. Δύο threads που καλούν chdir ταυτόχρονα μπαίνουν σε κούρσα.

  • Symlink σε κατάλογο: η chdir ακολουθεί τα symlinks, καταλήγοντας στον στόχο. Χρησιμοποιήστε πρώτα την readlink ή την Cwd::abs_path αν χρειάζεται να ξέρετε τον πραγματικό προορισμό.

  • Διαγραμμένος κατάλογος: αν ο κατάλογος αφαιρέθηκε αφού μπήκατε σε αυτόν, οι σχετικές λειτουργίες από μέσα αποτυγχάνουν με ENOENT και τα περισσότερα κελύφη εμφανίζουν τη διαδρομή ως (deleted). Μπορείτε ακόμη να βγείτε με chdir δίνοντας απόλυτη διαδρομή.

  • Μορφή handle σε συστήματα χωρίς fchdir(2): εγείρει εξαίρεση. Το Linux την υποστηρίζει πάντα· ο περιορισμός είναι ζήτημα φορητότητας για κώδικα που τρέχει επίσης σε παλαιότερα συστήματα.

  • Μη έμπιστη είσοδος: το να περνάτε στην chdir διαδρομή που παρέχεται από τον χρήστη χωρίς επικύρωση επιτρέπει στον καλούντα να ανακατευθύνει όλες τις επόμενες λειτουργίες σχετικής διαδρομής στο πρόγραμμα. Καταναγκαστικά κανονικοποιήστε με Cwd::abs_path και ελέγξτε έναντι λίστας επιτρεπτών πριν την κλήση αν η είσοδος διασχίζει όριο εμπιστοσύνης.

  • Μετά από fork: το παιδί κληρονομεί το cwd του γονέα. Μια chdir στο παιδί δεν επηρεάζει τον γονέα.

Διαφορές από το upstream#

Πλήρως συμβατό με το upstream Perl 5.42.

Δείτε επίσης#

  • mkdir - δημιουργία καταλόγου· συνδυάστε την με chdir όταν φτιάχνετε χώρο εργασίας και εισέρχεστε σε αυτόν

  • rmdir - αφαίρεση καταλόγου· μη κάνετε rmdir στο cwd, βγείτε πρώτα με chdir

  • opendir - άνοιγμα directory handle χρησιμοποιήσιμου ως όρισμα στην chdir για αλλαγές καταλόγου χωρίς κούρσα

  • chroot - ισχυρότερος περιορισμός από την chdir· αλλάζει τη ρίζα του συστήματος αρχείων για τη διεργασία, όχι μόνο το cwd

  • $ENV{HOME} - συμβουλεύεται από τη μορφή χωρίς όρισμα της chdir πριν την εφεδρεία στο $ENV{LOGDIR}

  • $! - μεταφέρει το errno όταν η chdir επιστρέφει 0