Funkcja chown - kod zrodlowy.

Ta funkcja pochodzi z pliku fs/open.c.

asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group)
{
        struct inode * inode;
        int error;
        struct iattr newattrs;
        error = lnamei(filename,&inode);
        if (error)
                return error;
        if (IS_RDONLY(inode)) {

/* to znaczy, ze fs jest read-only */

                iput(inode);
                return -EROFS;
        }
        if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {

                iput(inode);
                return -EPERM;
        }

/******************* 
(uid_t) -1 oznacza rzutowanie -1 na typ uid_t, 
wiec gdy user == -1, to nie zmieniaj wlasciciela pliku.
Tak samo dla grupy.
********************/

        if (user == (uid_t) -1) 
                user = inode->i_uid;
        /* jesli argumentem user jest -1, to wez tego z pliku */
        if (group == (gid_t) -1)
        /* to samo dla grupy */
                group = inode->i_gid;

        newattrs.ia_mode = inode->i_mode;
        /* podstawiamy sobie te rzeczy to struktury iattr */

/********************
struct inode {  umode_t         i_mode; ... }

types.h:typedef unsigned short umode_t;
********************/

        newattrs.ia_uid = user;
        newattrs.ia_gid = group;
        newattrs.ia_valid =  ATTR_UID | ATTR_GID | ATTR_CTIME;
/******************************* 2 ******** 4 ******** 64 *********/
/*** tzn. ze traci waznosc atrybut wlasciciela, grupy i change-time ***/
                                                        (tzn. czas ostatniej
                                                        modyfikacji i-wezla )
 

        if (user != inode->i_uid && (inode->i_mode & S_ISUID)) {

        /* jesli ustawiony jest bit setuid, ... */
                newattrs.ia_mode &= ~S_ISUID;  /*** ~ ozn. bitowa negacja ***/
        /* to usun ten bit */                   
                newattrs.ia_valid |= ATTR_MODE; /*** 1 ***/
                        /* traca waznosc stare prawa dostepu do pliku */
        }
/*********** stat.h: #define S_ISUID  0004000   (osemkowo), 
oznacza setuid bit, czyli ustawienie przy wykonywaniu efektywnego euid
procesu na ten, co ma plik.
 ***********/

        /* Jesli grupa sie zmienila, usun bit setgid.
         *
         * Nie usuwaj bitu setgid, jesli nie ma bitu wykonywania dla grupy.
      
         */
        if (group != inode->i_gid &&
            ((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))) {
        /********************* 0002000    00010                                       
        /*********************         prawo wyk. dla grupy ****************/

                newattrs.ia_mode &= ~S_ISGID;
                newattrs.ia_valid |= ATTR_MODE;
        }

        inode->i_dirt = 1;

        if (inode->i_sb->dq_op) {
     
                inode->i_sb->dq_op->initialize(inode, -1);
                /* Initialize pointer in a inode to the right dquots. */

                if (inode->i_sb->dq_op->transfer(inode, &newattrs, 0))

                /* Transfer the number of inode and blocks from one 
                        diskquota to an other. */

                        return -EDQUOT;
                error = notify_change(inode, &newattrs);
                if (error)
                        inode->i_sb->dq_op->transfer(inode, &newattrs, 1);
                /* transfer quoty z powrotem */

        } else
                error = notify_change(inode, &newattrs);
        iput(inode);  /*** zwolnij i-wezel ***/
        return(error);
}



Funkcja notify_change - kod zrodlowy.

 

int notify_change(struct inode * inode, struct iattr *attr)
{
/* algorytm dokladnie opisalem w HTML'u (M.H.) */
        int retval;

        attr->ia_ctime = CURRENT_TIME;
        if (attr->ia_valid & (ATTR_ATIME | ATTR_MTIME)) {
                if (!(attr->ia_valid & ATTR_ATIME_SET))
                        attr->ia_atime = attr->ia_ctime;
                if (!(attr->ia_valid & ATTR_MTIME_SET))
                        attr->ia_mtime = attr->ia_ctime;
        }

        if (inode->i_sb && inode->i_sb->s_op  &&
            inode->i_sb->s_op->notify_change) 
        /*** ext2 ma dla notify_change NULL'a,
                        s_op to super_operations ***/

                return inode->i_sb->s_op->notify_change(inode, attr);

        if ((retval = inode_change_ok(inode, attr)) != 0)
                return retval;

        inode_setattr(inode, attr);
        return 0;
}


Funkcja inode_change_ok. /* weryfikacja typu POSIX UID/GID dla ustalania atrbutow i-wezla */ int inode_change_ok(struct inode *inode, struct iattr *attr) /* po wnikliwej analizie wyprodukowalem to, co jest pod Wordem o tej funkcji. Sa tam wg. mnie wszystkie przypadki */ { /* * Jesli ustawione jest FORCE, to nic nie sprawdzaj. */ if (attr->ia_valid & ATTR_FORCE) return 0; /* Upewnij sie, ze proces moze zmieniac wlasciciela pliku: */ if ((attr->ia_valid & ATTR_UID) && (current->fsuid != inode->i_uid || attr->ia_uid != inode->i_uid) && !fsuser()) return -EPERM; /* Upewnij sie, ze proces moze zmienic grupe plikowi: */ if ((attr->ia_valid & ATTR_GID) && (!in_group_p(attr->ia_gid) && attr->ia_gid != inode->i_gid) && !fsuser()) return -EPERM; /* in_group_p sprawdza, czy proces jest w podanej grupie */
        /* Upewnij sie, ze proces moze zmieniac tryb dostepu: */

        if (attr->ia_valid & ATTR_MODE) {
                if ((current->fsuid != inode->i_uid) && !fsuser())
                        return -EPERM;
                /* Also check the setgid bit! */
                if (!fsuser() && !in_group_p((attr->ia_valid & ATTR_GID) ? attr->ia_gid :
                                             inode->i_gid))
                        attr->ia_mode &= ~S_ISGID;
        }

        /* Sprawdz, czy proces moze zmieniac czas: */
        if ((attr->ia_valid & ATTR_ATIME_SET) &&
            ((current->fsuid != inode->i_uid) && !fsuser()))
                return -EPERM;
        if ((attr->ia_valid & ATTR_MTIME_SET) &&
            ((current->fsuid != inode->i_uid) && !fsuser()))
                return -EPERM;
        return 0;
}



Odnosniki:
kernel.h:
#define fsuser() (current->fsuid == 0)

fs.h: /* To jest struktura Atrybuty I-wezla, uzywana do notify_change().
   Zasadniczo, to sa atrybuty, ktorych warstwa wirtualnego file-systemu (VFS) moze 
   zadac (ang. request) zmiany przez rzeczywisty system plikow. */
 
struct iattr {
        unsigned int    ia_valid;
        umode_t         ia_mode;
        uid_t           ia_uid;
        gid_t           ia_gid;
        off_t           ia_size;
        time_t          ia_atime;
        time_t          ia_mtime;
        time_t          ia_ctime;
};

fs.h:
#define IS_IMMUTABLE(inode) ((inode)->i_flags & S_IMMUTABLE)
#define S_IMMUTABLE    512     /* Immutable file */
#define IS_APPEND(inode) ((inode)->i_flags & S_APPEND)
#define S_APPEND       256     /* Append-only file */


fs.h:
Czesc struktury super_block to: struct dquot_operations *dq_op;  
        
struct dquot_operations {
               void (*initialize) (struct inode *, short);
               void (*drop) (struct inode *);
               int (*alloc_block) (const struct inode *, unsigned long);
               int (*alloc_inode) (const struct inode *, unsigned long);
               void (*free_block) (const struct inode *, unsigned long);
               void (*free_inode) (const struct inode *, unsigned long);
               int (*transfer) (struct inode *, struct iattr *, char); 
};