📄 patch.c
字号:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/fs/path.c
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
24700 /* This file contains the procedures that look up path names in the directory
24701 * system and determine the inode number that goes with a given path name.
24702 *
24703 * The entry points into this file are
24704 * eat_path: the 'main' routine of the path-to-inode conversion mechanism
24705 * last_dir: find the final directory on a given path
24706 * advance: parse one component of a path name
24707 * search_dir: search a directory for a string and return its inode number
24708 */
24709
24710 #include "fs.h"
24711 #include <string.h>
24712 #include <minix/callnr.h>
24713 #include "buf.h"
24714 #include "file.h"
24715 #include "fproc.h"
24716 #include "inode.h"
24717 #include "super.h"
24718
24719 PUBLIC char dot1[2] = "."; /* used for search_dir to bypass the access */
24720 PUBLIC char dot2[3] = ".."; /* permissions for . and .. */
24721
24722 FORWARD _PROTOTYPE( char *get_name, (char *old_name, char string [NAME_MAX]) );
24723
24724 /*===========================================================================*
24725 * eat_path *
24726 *===========================================================================*/
24727 PUBLIC struct inode *eat_path(path)
24728 char *path; /* the path name to be parsed */
24729 {
24730 /* Parse the path 'path' and put its inode in the inode table. If not possible,
24731 * return NIL_INODE as function value and an error code in 'err_code'.
24732 */
24733
24734 register struct inode *ldip, *rip;
24735 char string[NAME_MAX]; /* hold 1 path component name here */
24736
24737 /* First open the path down to the final directory. */
24738 if ( (ldip = last_dir(path, string)) == NIL_INODE)
24739 return(NIL_INODE); /* we couldn't open final directory */
24740
24741 /* The path consisting only of "/" is a special case, check for it. */
24742 if (string[0] == '\0') return(ldip);
24743
24744 /* Get final component of the path. */
24745 rip = advance(ldip, string);
24746 put_inode(ldip);
24747 return(rip);
24748 }
24751 /*===========================================================================*
24752 * last_dir *
24753 *===========================================================================*/
24754 PUBLIC struct inode *last_dir(path, string)
24755 char *path; /* the path name to be parsed */
24756 char string[NAME_MAX]; /* the final component is returned here */
24757 {
24758 /* Given a path, 'path', located in the fs address space, parse it as
24759 * far as the last directory, fetch the inode for the last directory into
24760 * the inode table, and return a pointer to the inode. In
24761 * addition, return the final component of the path in 'string'.
24762 * If the last directory can't be opened, return NIL_INODE and
24763 * the reason for failure in 'err_code'.
24764 */
24765
24766 register struct inode *rip;
24767 register char *new_name;
24768 register struct inode *new_ip;
24769
24770 /* Is the path absolute or relative? Initialize 'rip' accordingly. */
24771 rip = (*path == '/' ? fp->fp_rootdir : fp->fp_workdir);
24772
24773 /* If dir has been removed or path is empty, return ENOENT. */
24774 if (rip->i_nlinks == 0 || *path == '\0') {
24775 err_code = ENOENT;
24776 return(NIL_INODE);
24777 }
24778
24779 dup_inode(rip); /* inode will be returned with put_inode */
24780
24781 /* Scan the path component by component. */
24782 while (TRUE) {
24783 /* Extract one component. */
24784 if ( (new_name = get_name(path, string)) == (char*) 0) {
24785 put_inode(rip); /* bad path in user space */
24786 return(NIL_INODE);
24787 }
24788 if (*new_name == '\0')
24789 if ( (rip->i_mode & I_TYPE) == I_DIRECTORY)
24790 return(rip); /* normal exit */
24791 else {
24792 /* last file of path prefix is not a directory */
24793 put_inode(rip);
24794 err_code = ENOTDIR;
24795 return(NIL_INODE);
24796 }
24797
24798 /* There is more path. Keep parsing. */
24799 new_ip = advance(rip, string);
24800 put_inode(rip); /* rip either obsolete or irrelevant */
24801 if (new_ip == NIL_INODE) return(NIL_INODE);
24802
24803 /* The call to advance() succeeded. Fetch next component. */
24804 path = new_name;
24805 rip = new_ip;
24806 }
24807 }
24810 /*===========================================================================*
24811 * get_name *
24812 *===========================================================================*/
24813 PRIVATE char *get_name(old_name, string)
24814 char *old_name; /* path name to parse */
24815 char string[NAME_MAX]; /* component extracted from 'old_name' */
24816 {
24817 /* Given a pointer to a path name in fs space, 'old_name', copy the next
24818 * component to 'string' and pad with zeros. A pointer to that part of
24819 * the name as yet unparsed is returned. Roughly speaking,
24820 * 'get_name' = 'old_name' - 'string'.
24821 *
24822 * This routine follows the standard convention that /usr/ast, /usr//ast,
24823 * //usr///ast and /usr/ast/ are all equivalent.
24824 */
24825
24826 register int c;
24827 register char *np, *rnp;
24828
24829 np = string; /* 'np' points to current position */
24830 rnp = old_name; /* 'rnp' points to unparsed string */
24831 while ( (c = *rnp) == '/') rnp++; /* skip leading slashes */
24832
24833 /* Copy the unparsed path, 'old_name', to the array, 'string'. */
24834 while ( rnp < &old_name[PATH_MAX] && c != '/' && c != '\0') {
24835 if (np < &string[NAME_MAX]) *np++ = c;
24836 c = *++rnp; /* advance to next character */
24837 }
24838
24839 /* To make /usr/ast/ equivalent to /usr/ast, skip trailing slashes. */
24840 while (c == '/' && rnp < &old_name[PATH_MAX]) c = *++rnp;
24841
24842 if (np < &string[NAME_MAX]) *np = '\0'; /* Terminate string */
24843
24844 if (rnp >= &old_name[PATH_MAX]) {
24845 err_code = ENAMETOOLONG;
24846 return((char *) 0);
24847 }
24848 return(rnp);
24849 }
24852 /*===========================================================================*
24853 * advance *
24854 *===========================================================================*/
24855 PUBLIC struct inode *advance(dirp, string)
24856 struct inode *dirp; /* inode for directory to be searched */
24857 char string[NAME_MAX]; /* component name to look for */
24858 {
24859 /* Given a directory and a component of a path, look up the component in
24860 * the directory, find the inode, open it, and return a pointer to its inode
24861 * slot. If it can't be done, return NIL_INODE.
24862 */
24863
24864 register struct inode *rip;
24865 struct inode *rip2;
24866 register struct super_block *sp;
24867 int r, inumb;
24868 dev_t mnt_dev;
24869 ino_t numb;
24870
24871 /* If 'string' is empty, yield same inode straight away. */
24872 if (string[0] == '\0') return(get_inode(dirp->i_dev, (int) dirp->i_num));
24873
24874 /* Check for NIL_INODE. */
24875 if (dirp == NIL_INODE) return(NIL_INODE);
24876
24877 /* If 'string' is not present in the directory, signal error. */
24878 if ( (r = search_dir(dirp, string, &numb, LOOK_UP)) != OK) {
24879 err_code = r;
24880 return(NIL_INODE);
24881 }
24882
24883 /* Don't go beyond the current root directory, unless the string is dot2. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -