]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
windows-fs-chown-chgrp-20090701
authorJeffrey Altman <jaltman@secure-endpoints.com>
Wed, 1 Jul 2009 21:25:28 +0000 (21:25 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Wed, 1 Jul 2009 21:25:28 +0000 (21:25 +0000)
LICENSE MIT

On Windows there is no chown or chgrp command that can be used to
change the owner or group of an object in AFS.   Therefore we
add them to the fs command.

Usage: fs chown -owner <user name or id> [-path <dir/file path>+] [-literal] [-help]
Where: -literal  literal evaluation of mountpoints and symlinks

Usage: fs chgrp -group <user/group name or id> [-path <dir/file path>+] [-literal] [-help]
Where: -literal  literal evaluation of mountpoints and symlinks

src/WINNT/afsd/cm_ioctl.c
src/WINNT/afsd/cm_ioctl.h
src/WINNT/afsd/fs.c
src/WINNT/afsd/smb_iocons.h
src/WINNT/afsd/smb_ioctl.c
src/WINNT/afsd/smb_ioctl.h

index bf3c9f44df61f51fb0968ccc6b15ea70914d67f4..251107b5d08b1869ded1771e407d2b474d9c16c5 100644 (file)
@@ -882,6 +882,84 @@ cm_IoctlGetOwner(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *sc
 }
 
 
+/* 
+ * VIOC_SETOWNER internals.
+ * 
+ * Assumes that pioctl path has been parsed or skipped
+ * and that cm_ioctlQueryOptions_t have been parsed and skipped.
+ * 
+ * scp is held but not locked.
+ *
+ */
+afs_int32 
+cm_IoctlSetOwner(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp, cm_req_t *reqp)
+{
+    afs_int32 code = 0;
+    char *cp;
+
+    lock_ObtainWrite(&scp->rw);
+    code = cm_SyncOp(scp, NULL, userp, reqp, 0,
+                      CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+    if (code == 0)
+        cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+    lock_ReleaseWrite(&scp->rw);
+
+    if (code == 0) {
+        afs_uint32 owner;
+        cm_attr_t attr;
+
+        memset(&attr, 0, sizeof(attr));
+
+        cp = ioctlp->inDatap;
+        memcpy((char *)&owner, cp, sizeof(afs_uint32));
+
+        attr.mask = CM_ATTRMASK_OWNER;
+        attr.owner = owner;
+
+        code = cm_SetAttr(scp, &attr, userp, reqp);
+    }
+    return code;
+}
+
+
+/* 
+ * VIOC_SETGROUP internals.
+ * 
+ * Assumes that pioctl path has been parsed or skipped
+ * and that cm_ioctlQueryOptions_t have been parsed and skipped.
+ * 
+ */
+afs_int32 
+cm_IoctlSetGroup(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp, cm_req_t *reqp)
+{
+    afs_int32 code = 0;
+    char *cp;
+
+    lock_ObtainWrite(&scp->rw);
+    code = cm_SyncOp(scp, NULL, userp, reqp, 0,
+                      CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+    if (code == 0)
+        cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+    lock_ReleaseWrite(&scp->rw);
+
+    if (code == 0) {
+        afs_uint32 group;
+        cm_attr_t attr;
+
+        memset(&attr, 0, sizeof(attr));
+
+        cp = ioctlp->inDatap;
+        memcpy((char *)&group, cp, sizeof(afs_uint32));
+
+        attr.mask = CM_ATTRMASK_GROUP;
+        attr.group = group;
+
+        code = cm_SetAttr(scp, &attr, userp, reqp);
+    }
+    return code;
+}
+
+
 /* 
  * VIOCWHEREIS internals.
  * 
@@ -1732,9 +1810,9 @@ cm_IoctlGetSPrefs(struct cm_ioctl *ioctlp, struct cm_user *userp)
             continue;    /* catch up to where we left off */
         }
 
-        if ( vlonly && (tsp->type == CM_SERVER_FILE) )
+        if ( vlonly && (tsp->type != CM_SERVER_VLDB) )
             continue;   /* ignore fileserver for -vlserver option*/
-        if ( !vlonly && (tsp->type == CM_SERVER_VLDB) )
+        if ( !vlonly && (tsp->type != CM_SERVER_FILE) )
             continue;   /* ignore vlservers */
 
         srvout->host = tsp->addr.sin_addr;
index 66c7cc2e7594864c35bfe00f3b88dfdf8457dd93..d0827f3cab3b95d1bdeb5b8d72358e6362e11f61 100644 (file)
@@ -176,6 +176,10 @@ extern afs_int32 cm_IoctlGetFid(cm_ioctl_t *ioctlp, cm_user_t *userp, cm_scache_
 
 extern afs_int32 cm_IoctlGetOwner(cm_ioctl_t *ioctlp, cm_user_t *userp, cm_scache_t *scp, cm_req_t *reqp);
 
+extern afs_int32 cm_IoctlSetOwner(cm_ioctl_t *ioctlp, cm_user_t *userp, cm_scache_t *scp, cm_req_t *reqp);
+
+extern afs_int32 cm_IoctlSetGroup(cm_ioctl_t *ioctlp, cm_user_t *userp, cm_scache_t *scp, cm_req_t *reqp);
+
 extern afs_int32 cm_IoctlWhereIs(cm_ioctl_t *ioctlp, cm_user_t *userp, cm_scache_t *scp, cm_req_t *reqp);
 
 extern afs_int32 cm_IoctlStatMountPoint(cm_ioctl_t *ioctlp, cm_user_t *userp, cm_scache_t *scp, cm_req_t *reqp);
index 5ebadde47749aa3157441b9a411d25a6b1b30ab0..547234c1f8584b196e9264c31fd0334e437298e3 100644 (file)
@@ -1653,6 +1653,7 @@ ExamineCmd(struct cmd_syndesc *as, void *arock)
         blob.out = (char *) &owner;
        if (0 == pioctl_utf8(ti->data, VIOCGETOWNER, &blob, 1)) {
            char oname[PR_MAXNAMELEN] = "(unknown)";
+           char gname[PR_MAXNAMELEN] = "(unknown)";
             char confDir[257];
 
            /* Go to the PRDB and see if this all number username is valid */
@@ -1660,7 +1661,8 @@ ExamineCmd(struct cmd_syndesc *as, void *arock)
 
             pr_Initialize(1, confDir, cell);
            pr_SIdToName(owner[0], oname);
-           printf("Owner %s (%u) Group %u\n", oname, owner[0], owner[1]);
+           pr_SIdToName(owner[1], gname);
+           printf("Owner %s (%u) Group %s (%u)\n", oname, owner[0], gname, owner[1]);
         }
 
        blob.out = space;
@@ -3802,7 +3804,6 @@ GetFidCmd(struct cmd_syndesc *as, void *arock)
     for(ti=as->parms[0].items; ti; ti=ti->next) {
         cm_fid_t fid;
         afs_uint32 filetype;
-       afs_uint32 owner[2];
        char cell[CELL_MAXNAMELEN];
 
         /* once per file */
@@ -4711,6 +4712,188 @@ TestVolStatCmd(struct cmd_syndesc *as, void *arock)
     return 0;
 }
 
+static int 
+ChOwnCmd(struct cmd_syndesc *as, void *arock)
+{
+    afs_int32 code;
+    struct ViceIoctl blob;
+    struct cmd_item *ti;
+    int error = 0;
+    int literal = 0;
+    struct { 
+        cm_ioctlQueryOptions_t options;
+        afs_uint32 owner;
+    } inData;
+    afs_uint32 ownerId;
+    char * ownerStr;
+    char confDir[257];
+
+    cm_GetConfigDir(confDir, sizeof(confDir));
+
+    if (as->parms[2].items)
+        literal = 1;
+
+    ownerStr = as->parms[0].items->data;
+    ownerId = atoi(ownerStr);
+
+    SetDotDefault(&as->parms[1].items);
+    for(ti=as->parms[1].items; ti; ti=ti->next) {
+        cm_fid_t fid;
+        afs_uint32 filetype;
+       char cell[CELL_MAXNAMELEN];
+
+        /* once per file */
+        memset(&fid, 0, sizeof(fid));
+        memset(&inData, 0, sizeof(inData));
+        filetype = 0;
+        inData.options.size = sizeof(inData.options);
+        inData.options.field_flags |= CM_IOCTL_QOPTS_FIELD_LITERAL;
+        inData.options.literal = literal;
+       blob.in_size = inData.options.size;    /* no variable length data */
+        blob.in = &inData;
+
+        blob.out_size = sizeof(cm_fid_t);
+        blob.out = (char *) &fid;
+        if (0 == pioctl_utf8(ti->data, VIOCGETFID, &blob, 1)) {
+            inData.options.field_flags |= CM_IOCTL_QOPTS_FIELD_FID;
+            inData.options.fid = fid;
+        } else {
+           Die(errno, ti->data);
+           error = 1;
+           continue;
+        }
+
+        /* 
+         * if the owner was specified as a numeric value,
+         * then we can just use it.  Otherwise, we need 
+         * to know the cell of the path to determine which
+         * ptserver to contact in order to convert the name
+         * to a numeric value.
+         */
+        if (ownerId == 0) {
+            blob.out_size = CELL_MAXNAMELEN;
+            blob.out = cell;
+
+            code = pioctl_utf8(ti->data, VIOC_FILE_CELL_NAME, &blob, 1);
+            /* 
+             * We now know the cell for the target and we need to
+             * convert the ownerStr to the Id for this user 
+             */
+            pr_Initialize(1, confDir, cell);
+            code = pr_SNameToId(ownerStr, &inData.owner);
+            pr_End();
+
+            if (code || inData.owner == ANONYMOUSID ) {
+                Die(ECHILD, ti->data);
+                error = 1;
+                continue;
+            }
+        } else {
+            inData.owner = ownerId;
+        }
+
+        blob.in_size = sizeof(inData);
+       blob.out = NULL;
+       blob.out_size = 0;
+       code = pioctl_utf8(ti->data, VIOC_SETOWNER, &blob, 1);
+       if (code) {
+            Die(errno, ti->data);
+        }
+    }
+    return error;
+}
+
+static int 
+ChGrpCmd(struct cmd_syndesc *as, void *arock)
+{
+    afs_int32 code;
+    struct ViceIoctl blob;
+    struct cmd_item *ti;
+    int error = 0;
+    int literal = 0;
+    struct { 
+        cm_ioctlQueryOptions_t options;
+        afs_uint32 group;
+    } inData;
+    afs_uint32 groupId;
+    char * groupStr;
+    char confDir[257];
+
+    cm_GetConfigDir(confDir, sizeof(confDir));
+
+    if (as->parms[2].items)
+        literal = 1;
+
+    groupStr = as->parms[0].items->data;
+    groupId = atoi(groupStr);
+
+    SetDotDefault(&as->parms[1].items);
+    for(ti=as->parms[1].items; ti; ti=ti->next) {
+        cm_fid_t fid;
+        afs_uint32 filetype;
+       char cell[CELL_MAXNAMELEN];
+
+        /* once per file */
+        memset(&fid, 0, sizeof(fid));
+        memset(&inData, 0, sizeof(inData));
+        filetype = 0;
+        inData.options.size = sizeof(inData.options);
+        inData.options.field_flags |= CM_IOCTL_QOPTS_FIELD_LITERAL;
+        inData.options.literal = literal;
+       blob.in_size = inData.options.size;    /* no variable length data */
+        blob.in = &inData;
+
+        blob.out_size = sizeof(cm_fid_t);
+        blob.out = (char *) &fid;
+        if (0 == pioctl_utf8(ti->data, VIOCGETFID, &blob, 1)) {
+            inData.options.field_flags |= CM_IOCTL_QOPTS_FIELD_FID;
+            inData.options.fid = fid;
+        } else {
+           Die(errno, ti->data);
+           error = 1;
+           continue;
+        }
+
+        /* 
+         * if the group was specified as a numeric value,
+         * then we can just use it.  Otherwise, we need 
+         * to know the cell of the path to determine which
+         * ptserver to contact in order to convert the name
+         * to a numeric value.
+         */
+        if (groupId == 0) {
+            blob.out_size = CELL_MAXNAMELEN;
+            blob.out = cell;
+
+            code = pioctl_utf8(ti->data, VIOC_FILE_CELL_NAME, &blob, 1);
+            /* 
+             * We now know the cell for the target and we need to
+             * convert the groupStr to the Id for this user 
+             */
+            pr_Initialize(1, confDir, cell);
+            code = pr_SNameToId(groupStr, &inData.group);
+            pr_End();
+
+            if (code || inData.group == ANONYMOUSID ) {
+                Die(ECHILD, ti->data);
+                error = 1;
+                continue;
+            }
+        } else {
+            inData.group = groupId;
+        }
+
+        blob.in_size = sizeof(inData);
+       blob.out = NULL;
+       blob.out_size = 0;
+       code = pioctl_utf8(ti->data, VIOC_SETGROUP, &blob, 1);
+       if (code) {
+            Die(errno, ti->data);
+        }
+    }
+    return error;
+}
+
 #ifndef WIN32
 #include "AFS_component_version_number.c"
 #endif
@@ -5071,6 +5254,16 @@ int wmain(int argc, wchar_t **wargv)
     cmd_AddParm(ts, "-path", CMD_LIST, CMD_OPTIONAL, "dir/file path");
     cmd_AddParm(ts, "-literal", CMD_FLAG, CMD_OPTIONAL, "literal evaluation of mountpoints and symlinks");
 
+    ts = cmd_CreateSyntax("chown", ChOwnCmd, NULL, "set owner for object(s) in afs");
+    cmd_AddParm(ts, "-owner", CMD_SINGLE, 0, "user name or id");
+    cmd_AddParm(ts, "-path", CMD_LIST, CMD_OPTIONAL, "dir/file path");
+    cmd_AddParm(ts, "-literal", CMD_FLAG, CMD_OPTIONAL, "literal evaluation of mountpoints and symlinks");
+
+    ts = cmd_CreateSyntax("chgrp", ChGrpCmd, NULL, "set owner for object(s) in afs");
+    cmd_AddParm(ts, "-group", CMD_SINGLE, 0, "user/group name or id");
+    cmd_AddParm(ts, "-path", CMD_LIST, CMD_OPTIONAL, "dir/file path");
+    cmd_AddParm(ts, "-literal", CMD_FLAG, CMD_OPTIONAL, "literal evaluation of mountpoints and symlinks");
+
     code = cmd_Dispatch(argc, argv);
 
     if (rxInitDone) 
@@ -5141,6 +5334,12 @@ Die(int code, char *filename)
        else 
             fprintf(stderr,"%s: All servers are down\n", pn);
     } 
+    else if (code == ECHILD) {  /* hack */
+       if (filename) 
+            fprintf(stderr,"%s: Invalid owner specified for '%s'\n", pn, filename);
+       else 
+            fprintf(stderr,"%s: Invalid owner specified\n", pn);
+    } 
     else {
        if (filename) 
             fprintf(stderr,"%s:'%s'", pn, filename);
index f44d8a2ae908d0729e5943d5de48f9439f21a013..d0601977ac6a187c75a1b0e2f946e46309cac855 100644 (file)
@@ -95,6 +95,8 @@ struct sbstruct {
 #define VIOC_PATH_AVAILABILITY          0x31
 #define VIOC_GETFILETYPE                0x32
 #define VIOC_UNICODECTL                 0x33
+#define VIOC_SETOWNER                   0x34
+#define VIOC_SETGROUP                   0x35
 
 #define VIOC_VOLSTAT_TEST               0x3F
 
index 87be3219acf0470567e2625709cabada9ff12ec6..c2c339af4f811f5477a016fae60f3cad57f8bc69 100644 (file)
@@ -87,6 +87,8 @@ smb_InitIoctl(void)
     smb_ioctlProcsp[VIOC_GETFILETYPE] = smb_IoctlGetFileType;
     smb_ioctlProcsp[VIOC_VOLSTAT_TEST] = smb_IoctlVolStatTest;
     smb_ioctlProcsp[VIOC_UNICODECTL] = smb_IoctlUnicodeControl;
+    smb_ioctlProcsp[VIOC_SETOWNER] = smb_IoctlSetOwner;
+    smb_ioctlProcsp[VIOC_SETGROUP] = smb_IoctlSetGroup;
 }       
 
 /* called to make a fid structure into an IOCTL fid structure */
@@ -1102,6 +1104,7 @@ smb_IoctlGetACL(smb_ioctl_t *ioctlp, cm_user_t *userp)
     } else {
         code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
     }
+
     if (code) 
         return code;
 
@@ -1825,3 +1828,94 @@ smb_IoctlVolStatTest(struct smb_ioctl *ioctlp, struct cm_user *userp)
 
     return cm_IoctlVolStatTest(&ioctlp->ioctl, userp, &req);
 }
+
+/* 
+ * VIOC_SETOWNER
+ * 
+ * This pioctl requires the use of the cm_ioctlQueryOptions_t structure.
+ *
+ */
+afs_int32 
+smb_IoctlSetOwner(struct smb_ioctl *ioctlp, struct cm_user *userp)
+{
+    afs_int32 code;
+    cm_scache_t *scp;
+    cm_req_t req;
+    cm_ioctlQueryOptions_t *optionsp;
+    afs_uint32 flags = 0;
+
+    smb_InitReq(&req);
+
+    optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
+    if (optionsp) {
+        if (CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
+            flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
+
+        if (CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
+            cm_fid_t fid;
+            cm_SkipIoctlPath(&ioctlp->ioctl);
+            cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
+                       optionsp->fid.vnode, optionsp->fid.unique);
+            code = cm_GetSCache(&fid, &scp, userp, &req);
+        } else {
+            code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
+        }
+        if (code) 
+            return code;
+
+        cm_IoctlSkipQueryOptions(&ioctlp->ioctl, userp);
+    }
+
+    code = cm_IoctlSetOwner(&ioctlp->ioctl, userp, scp, &req);
+
+    cm_ReleaseSCache(scp);
+
+    return code;
+}
+
+/* 
+ * VIOC_GETOWNER
+ * 
+ * This pioctl requires the use of the cm_ioctlQueryOptions_t structure.
+ *
+ */
+afs_int32 
+smb_IoctlSetGroup(struct smb_ioctl *ioctlp, struct cm_user *userp)
+{
+    afs_int32 code;
+    cm_scache_t *scp;
+    cm_req_t req;
+    cm_ioctlQueryOptions_t *optionsp;
+    afs_uint32 flags = 0;
+
+    smb_InitReq(&req);
+
+    optionsp = cm_IoctlGetQueryOptions(&ioctlp->ioctl, userp);
+    if (optionsp) {
+        if (CM_IOCTL_QOPTS_HAVE_LITERAL(optionsp))
+            flags |= (optionsp->literal ? CM_PARSE_FLAG_LITERAL : 0);
+
+        if (CM_IOCTL_QOPTS_HAVE_FID(optionsp)) {
+            cm_fid_t fid;
+            cm_SkipIoctlPath(&ioctlp->ioctl);
+            cm_SetFid(&fid, optionsp->fid.cell, optionsp->fid.volume,
+                       optionsp->fid.vnode, optionsp->fid.unique);
+            code = cm_GetSCache(&fid, &scp, userp, &req);
+        } else {
+            code = smb_ParseIoctlPath(ioctlp, userp, &req, &scp, flags);
+        }
+        if (code) 
+            return code;
+
+        cm_IoctlSkipQueryOptions(&ioctlp->ioctl, userp);
+    }
+
+    code = cm_IoctlSetGroup(&ioctlp->ioctl, userp, scp, &req);
+
+    cm_ReleaseSCache(scp);
+
+    return code;
+}
+
+
+
index 202f5dcf7ee3fa5827a4fedcc8c9e21d97689ba7..033533f60bd8a24840e97a5d678d93830adb77b1 100644 (file)
@@ -200,4 +200,8 @@ extern afs_int32 smb_IoctlVolStatTest(struct smb_ioctl *ioctlp, struct cm_user *
 
 extern afs_int32 smb_IoctlUnicodeControl(struct smb_ioctl *ioctlp, struct cm_user * userp);
 
+extern afs_int32 smb_IoctlSetOwner(struct smb_ioctl *ioctlp, struct cm_user *userp);
+
+extern afs_int32 smb_IoctlSetGroup(struct smb_ioctl *ioctlp, struct cm_user *userp);
+
 #endif /*  __SMB_IOCTL_H_ENV__ */