Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
«<br />
236 volume VI os16<br />
104.4.45 kernel/fs/path_umount.c<br />
Si veda la sezione 103.3.41.<br />
880001 |#include <br />
880002 |#include <br />
880003 |#include <br />
880004 |//----------------------------------------------------------------------<br />
880005 |int<br />
880006 |path_umount (pid_t pid, const char *path_mnt)<br />
880007 |{<br />
880008 | proc_t *ps;<br />
880009 | dev_t device; // Device to mount.<br />
880010 | inode_t *inode_mount_point; // Original mount point.<br />
880011 | inode_t *inode; // Inode table.<br />
880012 | int i; // Inode table index.<br />
880013 | //<br />
880014 | // Get process.<br />
880015 | //<br />
880016 | ps = proc_reference (pid);<br />
880017 | //<br />
880018 | // Verify to be the super user.<br />
880019 | //<br />
880020 | if (ps->euid != 0)<br />
880021 | {<br />
880022 | errset (EPERM); // Operation not permitted.<br />
880023 | return (-1);<br />
880024 | }<br />
880025 | //<br />
880026 | // Get the directory mount point.<br />
880027 | //<br />
880028 | inode_mount_point = path_inode (pid, path_mnt);<br />
880029 | if (inode_mount_point == NULL)<br />
880030 | {<br />
880031 | errset (ENOENT); // No such file or directory.<br />
880032 | return (-1);<br />
880033 | }<br />
880034 | //<br />
880035 | // Verify that the path is a directory.<br />
880036 | //<br />
880037 | if (!S_ISDIR (inode_mount_point->mode))<br />
880038 | {<br />
880039 | inode_put (inode_mount_point);<br />
880040 | errset (ENOTDIR); // Not a directory.<br />
880041 | return (-1);<br />
880042 | }<br />
880043 | //<br />
880044 | // Verify that there is something attached.<br />
880045 | //<br />
880046 | device = inode_mount_point->sb_attached->device;<br />
880047 | if (device == 0)<br />
880048 | {<br />
880049 | //<br />
880050 | // There is nothing to unmount.<br />
880051 | //<br />
880052 | inode_put (inode_mount_point);<br />
880053 | errset (E_NOT_MOUNTED); // Not mounted.<br />
880054 | return (-1);<br />
880055 | }<br />
880056 | //<br />
880057 | // Are there exactly two internal references? Let’s explain:<br />
880058 | // the directory that act as mount point, should have one reference<br />
880059 | // because it is mounting something and another because it was just<br />
880060 | // opened again, a few lines above. If there are more references<br />
880061 | // it is wrong; if there are less, it is also wrong at this point.<br />
880062 | //<br />
880063 | if (inode_mount_point->references != 2)<br />
880064 | {<br />
880065 | inode_put (inode_mount_point);<br />
880066 | errset (EUNKNOWN); // Unknown error.<br />
880067 | return (-1);<br />
880068 | }<br />
880069 | //<br />
880070 | // All data is available: find if there are open file inside<br />
880071 | // the file system to unmount. But first load the inode table<br />
880072 | // pointer.<br />
880073 | //<br />
880074 | inode = inode_reference ((dev_t) 0, (ino_t) 0);<br />
880075 | if (inode == NULL)<br />
880076 | {<br />
880077 | //<br />
880078 | // This error should not happen.<br />
880079 | //<br />
880080 | inode_put (inode_mount_point);<br />
880081 | errset (EUNKNOWN); // Unknown error.<br />
880082 | return (-1);<br />
880083 | }<br />
880084 | //<br />
880085 | // Scan the inode table.<br />
880086 | //<br />
880087 | for (i = 0; i < INODE_MAX_SLOTS; i++)<br />
880088 | {<br />
880089 | if (inode[i].sb == inode_mount_point->sb_attached &&<br />
880090 | inode[i].references > 0)<br />
880091 | {<br />
880092 | //<br />
880093 | // At least one file is open inside the super block to<br />
880094 | // release: cannot unmount.<br />
880095 | //<br />
880096 | inode_put (inode_mount_point);<br />
880097 | errset (EBUSY); // Device or resource busy.<br />
880098 | return (-1);<br />
880099 | }<br />
880100 | }<br />
880101 | //<br />
880102 | // Can unmount: save and remove the super block memory;<br />
880103 | // clear the mount point reference and put inode.<br />
880104 | //<br />
880105 | inode_mount_point->sb_attached->changed = 1;<br />
880106 | sb_save (inode_mount_point->sb_attached);<br />
880107 | //<br />
880108 | inode_mount_point->sb_attached->device = 0;<br />
880109 | inode_mount_point->sb_attached->inode_mounted_on = NULL;<br />
880110 | inode_mount_point->sb_attached->blksize = 0;<br />
880111 | inode_mount_point->sb_attached->options = 0;<br />
880112 | //<br />
880113 | inode_mount_point->sb_attached = NULL;<br />
880114 | inode_mount_point->references = 0;<br />
Script e sorgenti del kernel 237<br />
880115 | inode_put (inode_mount_point);<br />
880116 | //<br />
880117 | inode_put (inode_mount_point);<br />
880118 | //<br />
880119 | return (0);<br />
880120 |}<br />
104.4.46 kernel/fs/path_unlink.c<br />
Si veda la sezione 103.3.44.<br />
890001 |#include <br />
890002 |#include <br />
890003 |#include <br />
890004 |#include <br />
890005 |#include <br />
890006 |//----------------------------------------------------------------------<br />
890007 |int<br />
890008 |path_unlink (pid_t pid, const char *path)<br />
890009 |{<br />
890010 | proc_t *ps;<br />
890011 | inode_t *inode_unlink;<br />
890012 | inode_t *inode_directory;<br />
890013 | char path_unlink[PATH_MAX];<br />
890014 | char path_copy[PATH_MAX];<br />
890015 | char *path_directory;<br />
890016 | char *name_unlink;<br />
890017 | dev_t device;<br />
890018 | off_t start;<br />
890019 | char buffer[SB_MAX_ZONE_SIZE];<br />
890020 | directory_t *dir = (directory_t *) buffer;<br />
890021 | int status;<br />
890022 | ssize_t size_read;<br />
890023 | ssize_t size_written;<br />
890024 | int d; // Directory buffer index.<br />
890025 | //<br />
890026 | // Get process.<br />
890027 | //<br />
890028 | ps = proc_reference (pid);<br />
890029 | //<br />
890030 | // Get full paths.<br />
890031 | //<br />
890032 | path_full (path, ps->path_cwd, path_unlink);<br />
890033 | strncpy (path_copy, path_unlink, PATH_MAX);<br />
890034 | path_directory = dirname (path_copy);<br />
890035 | //<br />
890036 | // Get the inode to be unlinked.<br />
890037 | //<br />
890038 | inode_unlink = path_inode (pid, path_unlink);<br />
890039 | if (inode_unlink == NULL)<br />
890040 | {<br />
890041 | return (-1);<br />
890042 | }<br />
890043 | //<br />
890044 | // If it is a directory, verify that it is empty.<br />
890045 | //<br />
890046 | if (S_ISDIR (inode_unlink->mode))<br />
890047 | {<br />
890048 | if (!inode_dir_empty (inode_unlink))<br />
890049 | {<br />
890050 | inode_put (inode_unlink);<br />
890051 | errset (ENOTEMPTY); // Directory not empty.<br />
890052 | return (-1);<br />
890053 | }<br />
890054 | }<br />
890055 | //<br />
890056 | // Get the inode of the directory containing it.<br />
890057 | //<br />
890058 | inode_directory = path_inode (pid, path_directory);<br />
890059 | if (inode_directory == NULL)<br />
890060 | {<br />
890061 | inode_put (inode_unlink);<br />
890062 | return (-1);<br />
890063 | }<br />
890064 | //<br />
890065 | // Check if something is mounted on the directory.<br />
890066 | //<br />
890067 | if (inode_directory->sb_attached != NULL)<br />
890068 | {<br />
890069 | //<br />
890070 | // Must select the right directory.<br />
890071 | //<br />
890072 | device = inode_directory->sb_attached->device;<br />
890073 | inode_put (inode_directory);<br />
890074 | inode_directory = inode_get (device, 1);<br />
890075 | if (inode_directory == NULL)<br />
890076 | {<br />
890077 | inode_put (inode_unlink);<br />
890078 | return (-1);<br />
890079 | }<br />
890080 | }<br />
890081 | //<br />
890082 | // Check if write is allowed for the file system.<br />
890083 | //<br />
890084 | if (inode_directory->sb->options & MOUNT_RO)<br />
890085 | {<br />
890086 | errset (EROFS); // Read-only file system.<br />
890087 | return (-1);<br />
890088 | }<br />
890089 | //<br />
890090 | // Verify access permissions for the directory. The number "3" means<br />
890091 | // that the user must have access permission and write permission:<br />
890092 | // "-wx" == 2+1 == 3.<br />
890093 | //<br />
890094 | status = inode_check (inode_directory, S_IFDIR, 3, ps->uid);<br />
890095 | if (status != 0)<br />
890096 | {<br />
890097 | errset (EPERM); // Operation not permitted.<br />
890098 | inode_put (inode_unlink);<br />
890099 | inode_put (inode_directory);<br />
890100 | return (-1);<br />
890101 | }<br />
890102 | //<br />
890103 | // Get the base name to be unlinked: this will alter the<br />
890104 | // original path.<br />
890105 | //<br />
«