aboutsummaryrefslogtreecommitdiff
path: root/libdiskfs/node-create.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdiskfs/node-create.c')
-rw-r--r--libdiskfs/node-create.c68
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;
}