diff options
Diffstat (limited to 'libdiskfs/node-create.c')
-rw-r--r-- | libdiskfs/node-create.c | 68 |
1 files changed, 54 insertions, 14 deletions
diff --git a/libdiskfs/node-create.c b/libdiskfs/node-create.c index 3f8dc4c1..4a7d108d 100644 --- a/libdiskfs/node-create.c +++ b/libdiskfs/node-create.c @@ -1,5 +1,5 @@ /* Making new files - Copyright (C) 1992, 1993, 1994, 1996 Free Software Foundation + Copyright (C) 1992,93,94,96,98,2001 Free Software Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -17,6 +17,11 @@ #include "priv.h" +/* This enables SysV style group behaviour. New nodes inherit the GID + of the user creating them unless the SGID bit is set of the parent + directory. */ +int _diskfs_no_inherit_dir_group; + /* Create a new node. Give it MODE; if that includes IFDIR, also initialize `.' and `..' in the new directory. Return the node in NPP. CRED identifies the user responsible for the call. If NAME is nonzero, @@ -26,7 +31,7 @@ strategies. */ error_t diskfs_create_node (struct node *dir, - char *name, + const char *name, mode_t mode, struct node **newnode, struct protid *cred, @@ -36,9 +41,12 @@ diskfs_create_node (struct node *dir, error_t err; uid_t newuid; gid_t newgid; - + if (diskfs_check_readonly ()) - return EROFS; + { + *newnode = NULL; + return EROFS; + } /* Make the node */ err = diskfs_alloc_node (dir, mode, newnode); @@ -46,14 +54,15 @@ diskfs_create_node (struct node *dir, { if (name) diskfs_drop_dirstat (dir, ds); + *newnode = NULL; return err; } np = *newnode; /* Initialize the on-disk fields. */ - if (cred->nuids) - newuid = cred->uids[0]; + if (cred->user->uids->num) + newuid = cred->user->uids->ids[0]; else { newuid = dir->dn_stat.st_uid; @@ -63,16 +72,43 @@ diskfs_create_node (struct node *dir, if (err) goto change_err; np->dn_stat.st_uid = newuid; + if (np->author_tracks_uid) + np->dn_stat.st_author = newuid; - if (diskfs_groupmember (dir->dn_stat.st_gid, cred)) - newgid = dir->dn_stat.st_gid; - else if (cred->ngids) - newgid = cred->gids[0]; - else + if (!_diskfs_no_inherit_dir_group) { newgid = dir->dn_stat.st_gid; - mode &= ~S_ISGID; + if (!idvec_contains (cred->user->gids, newgid)) + mode &= ~S_ISGID; + } + else + { + if (dir->dn_stat.st_mode & S_ISGID) + { + /* If the parent dir has the sgid bit set, inherit its gid. + If the new node is a directory, also inherit the sgid bit + set. */ + newgid = dir->dn_stat.st_gid; + if (S_ISDIR (mode)) + mode |= S_ISGID; + else + { + if (!idvec_contains (cred->user->gids, newgid)) + mode &= ~S_ISGID; + } + } + else + { + if (cred->user->gids->num) + newgid = cred->user->gids->ids[0]; + else + { + newgid = dir->dn_stat.st_gid; + mode &= ~S_ISGID; + } + } } + err = diskfs_validate_group_change (np, newgid); if (err) goto change_err; @@ -94,7 +130,7 @@ diskfs_create_node (struct node *dir, if (S_ISDIR (mode)) err = diskfs_init_dir (np, dir, cred); - + diskfs_node_update (np, 1); if (err) @@ -104,9 +140,10 @@ diskfs_create_node (struct node *dir, np->dn_stat.st_nlink = 0; if (name) diskfs_drop_dirstat (dir, ds); + *newnode = NULL; return err; } - + if (name) { err = diskfs_direnter (dir, name, np, ds, cred); @@ -119,5 +156,8 @@ diskfs_create_node (struct node *dir, diskfs_nput (np); } } + if (err) + *newnode = NULL; + return err; } |