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

📄 link.c

📁 一个简单的操作系统minix的核心代码
💻 C
📖 第 1 页 / 共 2 页
字号:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
				src/fs/link.c	 	 
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

25400	/* This file handles the LINK and UNLINK system calls.  It also deals with
25401	 * deallocating the storage used by a file when the last UNLINK is done to a
25402	 * file and the blocks must be returned to the free block pool.
25403	 *
25404	 * The entry points into this file are
25405	 *   do_link:   perform the LINK system call
25406	 *   do_unlink: perform the UNLINK and RMDIR system calls
25407	 *   do_rename: perform the RENAME system call
25408	 *   truncate:  release all the blocks associated with an inode
25409	 */
25410	
25411	#include "fs.h"
25412	#include <sys/stat.h>
25413	#include <string.h>
25414	#include <minix/callnr.h>
25415	#include "buf.h"
25416	#include "file.h"
25417	#include "fproc.h"
25418	#include "inode.h"
25419	#include "param.h"
25420	#include "super.h"
25421	
25422	#define SAME 1000
25423	
25424	FORWARD _PROTOTYPE( int remove_dir, (struct inode *rldirp, struct inode *rip,
25425	                        char dir_name[NAME_MAX])                        );
25426	
25427	FORWARD _PROTOTYPE( int unlink_file, (struct inode *dirp, struct inode *rip,
25428	                        char file_name[NAME_MAX])                       );
25429	
25430	
25431	/*===========================================================================*
25432	 *                              do_link                                      *
25433	 *===========================================================================*/
25434	PUBLIC int do_link()
25435	{
25436	/* Perform the link(name1, name2) system call. */
25437	
25438	  register struct inode *ip, *rip;
25439	  register int r;
25440	  char string[NAME_MAX];
25441	  struct inode *new_ip;
25442	
25443	  /* See if 'name' (file to be linked) exists. */
25444	  if (fetch_name(name1, name1_length, M1) != OK) return(err_code);
25445	  if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
25446	
25447	  /* Check to see if the file has maximum number of links already. */
25448	  r = OK;
25449	  if ( (rip->i_nlinks & BYTE) >= LINK_MAX) r = EMLINK;
25450	
25451	  /* Only super_user may link to directories. */
25452	  if (r == OK)
25453	        if ( (rip->i_mode & I_TYPE) == I_DIRECTORY && !super_user) r = EPERM;
25454	
25455	  /* If error with 'name', return the inode. */
25456	  if (r != OK) {
25457	        put_inode(rip);
25458	        return(r);
25459	  }
25460	
25461	  /* Does the final directory of 'name2' exist? */
25462	  if (fetch_name(name2, name2_length, M1) != OK) {
25463	        put_inode(rip);
25464	        return(err_code);
25465	  }
25466	  if ( (ip = last_dir(user_path, string)) == NIL_INODE) r = err_code;
25467	
25468	  /* If 'name2' exists in full (even if no space) set 'r' to error. */
25469	  if (r == OK) {
25470	        if ( (new_ip = advance(ip, string)) == NIL_INODE) {
25471	                r = err_code;
25472	                if (r == ENOENT) r = OK;
25473	        } else {
25474	                put_inode(new_ip);
25475	                r = EEXIST;
25476	        }
25477	  }
25478	
25479	  /* Check for links across devices. */
25480	  if (r == OK)
25481	        if (rip->i_dev != ip->i_dev) r = EXDEV;
25482	
25483	  /* Try to link. */
25484	  if (r == OK)
25485	        r = search_dir(ip, string, &rip->i_num, ENTER);
25486	
25487	  /* If success, register the linking. */
25488	  if (r == OK) {
25489	        rip->i_nlinks++;
25490	        rip->i_update |= CTIME;
25491	        rip->i_dirt = DIRTY;
25492	  }
25493	
25494	  /* Done.  Release both inodes. */
25495	  put_inode(rip);
25496	  put_inode(ip);
25497	  return(r);
25498	}
	
	
25501	/*===========================================================================*
25502	 *                              do_unlink                                    *
25503	 *===========================================================================*/
25504	PUBLIC int do_unlink()
25505	{
25506	/* Perform the unlink(name) or rmdir(name) system call. The code for these two
25507	 * is almost the same.  They differ only in some condition testing.  Unlink()
25508	 * may be used by the superuser to do dangerous things; rmdir() may not.
25509	 */
25510	
25511	  register struct inode *rip;
25512	  struct inode *rldirp;
25513	  int r;
25514	  char string[NAME_MAX];
25515	
25516	  /* Get the last directory in the path. */
25517	  if (fetch_name(name, name_length, M3) != OK) return(err_code);
25518	  if ( (rldirp = last_dir(user_path, string)) == NIL_INODE)
25519	        return(err_code);
25520	
25521	  /* The last directory exists.  Does the file also exist? */
25522	  r = OK;
25523	  if ( (rip = advance(rldirp, string)) == NIL_INODE) r = err_code;
25524	
25525	  /* If error, return inode. */
25526	  if (r != OK) {
25527	        put_inode(rldirp);
25528	        return(r);
25529	  }
25530	
25531	  /* Do not remove a mount point. */
25532	  if (rip->i_num == ROOT_INODE) {
25533	        put_inode(rldirp);
25534	        put_inode(rip);
25535	        return(EBUSY);
25536	  }
25537	
25538	  /* Now test if the call is allowed, separately for unlink() and rmdir(). */
25539	  if (fs_call == UNLINK) {
25540	        /* Only the su may unlink directories, but the su can unlink any dir.*/
25541	        if ( (rip->i_mode & I_TYPE) == I_DIRECTORY && !super_user) r = EPERM;
25542	
25543	        /* Don't unlink a file if it is the root of a mounted file system. */
25544	        if (rip->i_num == ROOT_INODE) r = EBUSY;
25545	
25546	        /* Actually try to unlink the file; fails if parent is mode 0 etc. */
25547	        if (r == OK) r = unlink_file(rldirp, rip, string);
25548	
25549	  } else {
25550	        r = remove_dir(rldirp, rip, string); /* call is RMDIR */
25551	  }
25552	
25553	  /* If unlink was possible, it has been done, otherwise it has not. */
25554	  put_inode(rip);
25555	  put_inode(rldirp);
25556	  return(r);
25557	}
	
	
25560	/*===========================================================================*
25561	 *                              do_rename                                    *
25562	 *===========================================================================*/
25563	PUBLIC int do_rename()
25564	{
25565	/* Perform the rename(name1, name2) system call. */
25566	
25567	  struct inode *old_dirp, *old_ip;      /* ptrs to old dir, file inodes */
25568	  struct inode *new_dirp, *new_ip;      /* ptrs to new dir, file inodes */
25569	  struct inode *new_superdirp, *next_new_superdirp;
25570	  int r = OK;                           /* error flag; initially no error */
25571	  int odir, ndir;                       /* TRUE iff {old|new} file is dir */
25572	  int same_pdir;                        /* TRUE iff parent dirs are the same */
25573	  char old_name[NAME_MAX], new_name[NAME_MAX];
25574	  ino_t numb;
25575	  int r1;
25576	  
25577	  /* See if 'name1' (existing file) exists.  Get dir and file inodes. */
25578	  if (fetch_name(name1, name1_length, M1) != OK) return(err_code);
25579	  if ( (old_dirp = last_dir(user_path, old_name))==NIL_INODE) return(err_code);
25580	
25581	  if ( (old_ip = advance(old_dirp, old_name)) == NIL_INODE) r = err_code;
25582	
25583	  /* See if 'name2' (new name) exists.  Get dir and file inodes. */
25584	  if (fetch_name(name2, name2_length, M1) != OK) r = err_code;
25585	  if ( (new_dirp = last_dir(user_path, new_name)) == NIL_INODE) r = err_code;
25586	  new_ip = advance(new_dirp, new_name); /* not required to exist */
25587	
25588	  if (old_ip != NIL_INODE)
25589	        odir = ((old_ip->i_mode & I_TYPE) == I_DIRECTORY);  /* TRUE iff dir */
25590	
25591	  /* If it is ok, check for a variety of possible errors. */
25592	  if (r == OK) {
25593	        same_pdir = (old_dirp == new_dirp);
25594	
25595	        /* The old inode must not be a superdirectory of the new last dir. */
25596	        if (odir && !same_pdir) {
25597	                dup_inode(new_superdirp = new_dirp);
25598	                while (TRUE) {          /* may hang in a file system loop */
25599	                        if (new_superdirp == old_ip) {
25600	                                r = EINVAL;
25601	                                break;
25602	                        }
25603	                        next_new_superdirp = advance(new_superdirp, dot2);
25604	                        put_inode(new_superdirp);
25605	                        if (next_new_superdirp == new_superdirp)
25606	                                break;  /* back at system root directory */
25607	                        new_superdirp = next_new_superdirp;
25608	                        if (new_superdirp == NIL_INODE) {
25609	                                /* Missing ".." entry.  Assume the worst. */
25610	                                r = EINVAL;
25611	                                break;
25612	                        }
25613	                }       
25614	                put_inode(new_superdirp);
25615	        }       
25616	
25617	        /* The old or new name must not be . or .. */
25618	        if (strcmp(old_name, ".")==0 || strcmp(old_name, "..")==0 ||
25619	            strcmp(new_name, ".")==0 || strcmp(new_name, "..")==0) r = EINVAL;
25620	
25621	        /* Both parent directories must be on the same device. */
25622	        if (old_dirp->i_dev != new_dirp->i_dev) r = EXDEV;

⌨️ 快捷键说明

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