diff --git a/src/WINNT/afsd/cm_ioctl.c b/src/WINNT/afsd/cm_ioctl.c index d493b46af1..c5da5ad6eb 100644 --- a/src/WINNT/afsd/cm_ioctl.c +++ b/src/WINNT/afsd/cm_ioctl.c @@ -902,6 +902,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. * @@ -1776,9 +1854,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; diff --git a/src/WINNT/afsd/cm_ioctl.h b/src/WINNT/afsd/cm_ioctl.h index 9e82755271..35ef628c31 100644 --- a/src/WINNT/afsd/cm_ioctl.h +++ b/src/WINNT/afsd/cm_ioctl.h @@ -177,6 +177,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); diff --git a/src/WINNT/afsd/fs.c b/src/WINNT/afsd/fs.c index 5ebadde477..547234c1f8 100644 --- a/src/WINNT/afsd/fs.c +++ b/src/WINNT/afsd/fs.c @@ -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); diff --git a/src/WINNT/afsd/smb_iocons.h b/src/WINNT/afsd/smb_iocons.h index f44d8a2ae9..d0601977ac 100644 --- a/src/WINNT/afsd/smb_iocons.h +++ b/src/WINNT/afsd/smb_iocons.h @@ -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 diff --git a/src/WINNT/afsd/smb_ioctl.c b/src/WINNT/afsd/smb_ioctl.c index 87be3219ac..c2c339af4f 100644 --- a/src/WINNT/afsd/smb_ioctl.c +++ b/src/WINNT/afsd/smb_ioctl.c @@ -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; +} + + + diff --git a/src/WINNT/afsd/smb_ioctl.h b/src/WINNT/afsd/smb_ioctl.h index 202f5dcf7e..033533f60b 100644 --- a/src/WINNT/afsd/smb_ioctl.h +++ b/src/WINNT/afsd/smb_ioctl.h @@ -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__ */