⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 link.c

📁 一个简单的操作系统minix的核心代码
💻 C
📖 第 1 页 / 共 2 页
字号:
25623	
25624	        /* Parent dirs must be writable, searchable and on a writable device */
25625	        if ((r1 = forbidden(old_dirp, W_BIT | X_BIT)) != OK ||
25626	            (r1 = forbidden(new_dirp, W_BIT | X_BIT)) != OK) r = r1;
25627	
25628	        /* Some tests apply only if the new path exists. */
25629	        if (new_ip == NIL_INODE) {
25630	                /* don't rename a file with a file system mounted on it. */
25631	                if (old_ip->i_dev != old_dirp->i_dev) r = EXDEV;
25632	                if (odir && (new_dirp->i_nlinks & BYTE) >= LINK_MAX &&
25633	                    !same_pdir && r == OK) r = EMLINK;
25634	        } else {
25635	                if (old_ip == new_ip) r = SAME; /* old=new */
25636	
25637	                /* has the old file or new file a file system mounted on it? */
25638	                if (old_ip->i_dev != new_ip->i_dev) r = EXDEV;
25639	
25640	                ndir = ((new_ip->i_mode & I_TYPE) == I_DIRECTORY); /* dir ? */
25641	                if (odir == TRUE && ndir == FALSE) r = ENOTDIR;
25642	                if (odir == FALSE && ndir == TRUE) r = EISDIR;
25643	        }
25644	  }
25645	
25646	  /* If a process has another root directory than the system root, we might
25647	   * "accidently" be moving it's working directory to a place where it's
25648	   * root directory isn't a super directory of it anymore. This can make
25649	   * the function chroot useless. If chroot will be used often we should
25650	   * probably check for it here.
25651	   */
25652	
25653	  /* The rename will probably work. Only two things can go wrong now:
25654	   * 1. being unable to remove the new file. (when new file already exists)
25655	   * 2. being unable to make the new directory entry. (new file doesn't exists)
25656	   *     [directory has to grow by one block and cannot because the disk
25657	   *      is completely full].
25658	   */
25659	  if (r == OK) {
25660	        if (new_ip != NIL_INODE) {
25661	                  /* There is already an entry for 'new'. Try to remove it. */
25662	                if (odir) 
25663	                        r = remove_dir(new_dirp, new_ip, new_name);
25664	                else 
25665	                        r = unlink_file(new_dirp, new_ip, new_name);
25666	        }
25667	        /* if r is OK, the rename will succeed, while there is now an
25668	         * unused entry in the new parent directory.
25669	         */
25670	  }
25671	
25672	  if (r == OK) {
25673	        /* If the new name will be in the same parent directory as the old one,
25674	         * first remove the old name to free an entry for the new name,
25675	         * otherwise first try to create the new name entry to make sure
25676	         * the rename will succeed.
25677	         */
25678	        numb = old_ip->i_num;           /* inode number of old file */
25679	
25680	        if (same_pdir) {
25681	                r = search_dir(old_dirp, old_name, (ino_t *) 0, DELETE);
25682	                                                /* shouldn't go wrong. */
25683	                if (r==OK) (void) search_dir(old_dirp, new_name, &numb, ENTER);
25684	        } else {
25685	                r = search_dir(new_dirp, new_name, &numb, ENTER);
25686	                if (r == OK)
25687	                    (void) search_dir(old_dirp, old_name, (ino_t *) 0, DELETE);
25688	        }
25689	  }
25690	  /* If r is OK, the ctime and mtime of old_dirp and new_dirp have been marked
25691	   * for update in search_dir.
25692	   */
25693	
25694	  if (r == OK && odir && !same_pdir) {
25695	        /* Update the .. entry in the directory (still points to old_dirp). */
25696	        numb = new_dirp->i_num;
25697	        (void) unlink_file(old_ip, NIL_INODE, dot2);
25698	        if (search_dir(old_ip, dot2, &numb, ENTER) == OK) {
25699	                /* New link created. */
25700	                new_dirp->i_nlinks++;
25701	                new_dirp->i_dirt = DIRTY;
25702	        }
25703	  }
25704	        
25705	  /* Release the inodes. */
25706	  put_inode(old_dirp);
25707	  put_inode(old_ip);
25708	  put_inode(new_dirp);
25709	  put_inode(new_ip);
25710	  return(r == SAME ? OK : r);
25711	}
	
	
25714	/*===========================================================================*
25715	 *                              truncate                                     *
25716	 *===========================================================================*/
25717	PUBLIC void truncate(rip)
25718	register struct inode *rip;     /* pointer to inode to be truncated */
25719	{
25720	/* Remove all the zones from the inode 'rip' and mark it dirty. */
25721	
25722	  register block_t b;
25723	  zone_t z, zone_size, z1;
25724	  off_t position;
25725	  int i, scale, file_type, waspipe, single, nr_indirects;
25726	  struct buf *bp;
25727	  dev_t dev;
25728	
25729	  file_type = rip->i_mode & I_TYPE;     /* check to see if file is special */
25730	  if (file_type == I_CHAR_SPECIAL || file_type == I_BLOCK_SPECIAL) return;
25731	  dev = rip->i_dev;             /* device on which inode resides */
25732	  scale = rip->i_sp->s_log_zone_size;
25733	  zone_size = (zone_t) BLOCK_SIZE << scale;
25734	  nr_indirects = rip->i_nindirs;
25735	
25736	  /* Pipes can shrink, so adjust size to make sure all zones are removed. */
25737	  waspipe = rip->i_pipe == I_PIPE;      /* TRUE is this was a pipe */
25738	  if (waspipe) rip->i_size = PIPE_SIZE;
25739	
25740	  /* Step through the file a zone at a time, finding and freeing the zones. */
25741	  for (position = 0; position < rip->i_size; position += zone_size) {
25742	        if ( (b = read_map(rip, position)) != NO_BLOCK) {
25743	                z = (zone_t) b >> scale;
25744	                free_zone(dev, z);
25745	        }
25746	  }
25747	
25748	  /* All the data zones have been freed.  Now free the indirect zones. */
25749	  rip->i_dirt = DIRTY;
25750	  if (waspipe) {
25751	        wipe_inode(rip);        /* clear out inode for pipes */
25752	        return;                 /* indirect slots contain file positions */
25753	  }
25754	  single = rip->i_ndzones;
25755	  free_zone(dev, rip->i_zone[single]);  /* single indirect zone */
25756	  if ( (z = rip->i_zone[single+1]) != NO_ZONE) {
25757	        /* Free all the single indirect zones pointed to by the double. */
25758	        b = (block_t) z << scale;
25759	        bp = get_block(dev, b, NORMAL); /* get double indirect zone */
25760	        for (i = 0; i < nr_indirects; i++) {
25761	                z1 = rd_indir(bp, i);
25762	                free_zone(dev, z1);
25763	        }
25764	
25765	        /* Now free the double indirect zone itself. */
25766	        put_block(bp, INDIRECT_BLOCK);
25767	        free_zone(dev, z);
25768	  }
25769	
25770	  /* Leave zone numbers for de(1) to recover file after an unlink(2).  */
25771	}
	
	
25774	/*===========================================================================*
25775	 *                              remove_dir                                   *
25776	 *===========================================================================*/
25777	PRIVATE int remove_dir(rldirp, rip, dir_name)
25778	struct inode *rldirp;                   /* parent directory */
25779	struct inode *rip;                      /* directory to be removed */
25780	char dir_name[NAME_MAX];                /* name of directory to be removed */
25781	{
25782	  /* A directory file has to be removed. Five conditions have to met:
25783	   *    - The file must be a directory
25784	   *    - The directory must be empty (except for . and ..)
25785	   *    - The final component of the path must not be . or ..
25786	   *    - The directory must not be the root of a mounted file system
25787	   *    - The directory must not be anybody's root/working directory
25788	   */
25789	
25790	  int r;
25791	  register struct fproc *rfp;
25792	
25793	  /* search_dir checks that rip is a directory too. */
25794	  if ((r = search_dir(rip, "", (ino_t *) 0, IS_EMPTY)) != OK) return r;
25795	
25796	  if (strcmp(dir_name, ".") == 0 || strcmp(dir_name, "..") == 0)return(EINVAL);
25797	  if (rip->i_num == ROOT_INODE) return(EBUSY); /* can't remove 'root' */
25798	  
25799	  for (rfp = &fproc[INIT_PROC_NR + 1]; rfp < &fproc[NR_PROCS]; rfp++)
25800	        if (rfp->fp_workdir == rip || rfp->fp_rootdir == rip) return(EBUSY);
25801	                                /* can't remove anybody's working dir */
25802	
25803	  /* Actually try to unlink the file; fails if parent is mode 0 etc. */
25804	  if ((r = unlink_file(rldirp, rip, dir_name)) != OK) return r;
25805	
25806	  /* Unlink . and .. from the dir. The super user can link and unlink any dir,
25807	   * so don't make too many assumptions about them.
25808	   */
25809	  (void) unlink_file(rip, NIL_INODE, dot1);
25810	  (void) unlink_file(rip, NIL_INODE, dot2);
25811	  return(OK);
25812	}
	
	
25815	/*===========================================================================*
25816	 *                              unlink_file                                  *
25817	 *===========================================================================*/
25818	PRIVATE int unlink_file(dirp, rip, file_name)
25819	struct inode *dirp;             /* parent directory of file */
25820	struct inode *rip;              /* inode of file, may be NIL_INODE too. */
25821	char file_name[NAME_MAX];       /* name of file to be removed */
25822	{
25823	/* Unlink 'file_name'; rip must be the inode of 'file_name' or NIL_INODE. */
25824	
25825	  ino_t numb;                   /* inode number */
25826	  int   r;
25827	
25828	  /* If rip is not NIL_INODE, it is used to get faster access to the inode. */
25829	  if (rip == NIL_INODE) {
25830	        /* Search for file in directory and try to get its inode. */
25831	        err_code = search_dir(dirp, file_name, &numb, LOOK_UP);
25832	        if (err_code == OK) rip = get_inode(dirp->i_dev, (int) numb);
25833	        if (err_code != OK || rip == NIL_INODE) return(err_code);
25834	  } else {
25835	        dup_inode(rip);         /* inode will be returned with put_inode */
25836	  }
25837	
25838	  r = search_dir(dirp, file_name, (ino_t *) 0, DELETE);
25839	
25840	  if (r == OK) {
25841	        rip->i_nlinks--;        /* entry deleted from parent's dir */
25842	        rip->i_update |= CTIME;
25843	        rip->i_dirt = DIRTY;
25844	  }
25845	
25846	  put_inode(rip);
25847	  return(r);
25848	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -