windows-freelance-symlink-20071018

More tweaking of the IoctlPathParsing code.

Add special handling for many more pioctl operations performed on
the Freelance root.afs volume.

Add informative error values for symlink freelance operations.
This commit is contained in:
Jeffrey Altman 2007-10-18 06:27:40 +00:00
parent 8598b81a69
commit 91855b82c7
3 changed files with 185 additions and 133 deletions

View File

@ -1192,22 +1192,22 @@ long cm_FreelanceAddSymlink(char *filename, char *destination, cm_fid_t *fidp)
osi_LogSaveString(afsd_logp,destination));
if ( filename[0] == '\0' || destination[0] == '\0' )
return -1;
return CM_ERROR_INVAL;
fullname[0] = '\0';
if (filename[0] == '.') {
cm_GetCell_Gen(&filename[1], fullname, CM_FLAG_CREATE);
if (stricmp(&filename[1],fullname) == 0)
return -1;
return CM_ERROR_EXISTS;
} else {
cm_GetCell_Gen(filename, fullname, CM_FLAG_CREATE);
if (stricmp(filename,fullname) == 0)
return -1;
return CM_ERROR_EXISTS;
}
if ( cm_FreelanceMountPointExists(filename) ||
cm_FreelanceSymlinkExists(filename) )
return -1;
return CM_ERROR_EXISTS;
lock_ObtainMutex(&cm_Freelance_Lock);

View File

@ -268,7 +268,7 @@ long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
}
lastComponent = strrchr(p, '\\');
if (lastComponent && (p - lastComponent) > 1 &&strlen(p) > 1) {
if (lastComponent && (lastComponent - p) > 1 &&strlen(lastComponent) > 1) {
*lastComponent = '\0';
lastComponent++;
@ -280,7 +280,7 @@ long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
if (iscp)
cm_ReleaseSCache(iscp);
} else {
code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_NOMOUNTCHASE,
code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD,
userp, NULL, reqp, scpp);
}
cm_ReleaseSCache(substRootp);
@ -315,7 +315,7 @@ long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
}
lastComponent = strrchr(p, '\\');
if (lastComponent && (p - lastComponent) > 1 &&strlen(p) > 1) {
if (lastComponent && (lastComponent - p) > 1 &&strlen(lastComponent) > 1) {
*lastComponent = '\0';
lastComponent++;
@ -327,7 +327,7 @@ long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
if (iscp)
cm_ReleaseSCache(iscp);
} else {
code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_NOMOUNTCHASE,
code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD,
userp, NULL, reqp, scpp);
}
@ -347,7 +347,7 @@ long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
}
lastComponent = strrchr(relativePath, '\\');
if (lastComponent && (relativePath - lastComponent) > 1 && strlen(relativePath) > 1) {
if (lastComponent && (lastComponent - relativePath) > 1 && strlen(lastComponent) > 1) {
*lastComponent = '\0';
lastComponent++;
@ -359,7 +359,7 @@ long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
if (iscp)
cm_ReleaseSCache(iscp);
} else {
code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | CM_FLAG_NOMOUNTCHASE,
code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD,
userp, NULL, reqp, scpp);
}
if (code) {
@ -565,25 +565,32 @@ long cm_IoctlGetACL(smb_ioctl_t *ioctlp, cm_user_t *userp)
if (code) return code;
/* now make the get acl call */
fid.Volume = scp->fid.volume;
fid.Vnode = scp->fid.vnode;
fid.Unique = scp->fid.unique;
do {
acl.AFSOpaque_val = ioctlp->outDatap;
acl.AFSOpaque_len = 0;
code = cm_ConnFromFID(&scp->fid, userp, &req, &connp);
if (code) continue;
#ifdef AFS_FREELANCE_CLIENT
if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
code = 0;
ioctlp->outDatap[0] ='\0';
} else
#endif
{
fid.Volume = scp->fid.volume;
fid.Vnode = scp->fid.vnode;
fid.Unique = scp->fid.unique;
do {
acl.AFSOpaque_val = ioctlp->outDatap;
acl.AFSOpaque_len = 0;
code = cm_ConnFromFID(&scp->fid, userp, &req, &connp);
if (code) continue;
callp = cm_GetRxConn(connp);
code = RXAFS_FetchACL(callp, &fid, &acl, &fileStatus, &volSync);
rx_PutConnection(callp);
callp = cm_GetRxConn(connp);
code = RXAFS_FetchACL(callp, &fid, &acl, &fileStatus, &volSync);
rx_PutConnection(callp);
} while (cm_Analyze(connp, userp, &req, &scp->fid, &volSync, NULL, NULL, code));
code = cm_MapRPCError(code, &req);
cm_ReleaseSCache(scp);
if (code) return code;
} while (cm_Analyze(connp, userp, &req, &scp->fid, &volSync, NULL, NULL, code));
code = cm_MapRPCError(code, &req);
cm_ReleaseSCache(scp);
if (code) return code;
}
/* skip over return data */
tlen = (int)strlen(ioctlp->outDatap) + 1;
ioctlp->outDatap += tlen;
@ -646,28 +653,34 @@ long cm_IoctlSetACL(struct smb_ioctl *ioctlp, struct cm_user *userp)
code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
if (code) return code;
/* now make the get acl call */
fid.Volume = scp->fid.volume;
fid.Vnode = scp->fid.vnode;
fid.Unique = scp->fid.unique;
do {
acl.AFSOpaque_val = ioctlp->inDatap;
acl.AFSOpaque_len = (u_int)strlen(ioctlp->inDatap)+1;
code = cm_ConnFromFID(&scp->fid, userp, &req, &connp);
if (code) continue;
#ifdef AFS_FREELANCE_CLIENT
if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
code = CM_ERROR_NOACCESS;
} else
#endif
{
/* now make the get acl call */
fid.Volume = scp->fid.volume;
fid.Vnode = scp->fid.vnode;
fid.Unique = scp->fid.unique;
do {
acl.AFSOpaque_val = ioctlp->inDatap;
acl.AFSOpaque_len = (u_int)strlen(ioctlp->inDatap)+1;
code = cm_ConnFromFID(&scp->fid, userp, &req, &connp);
if (code) continue;
callp = cm_GetRxConn(connp);
code = RXAFS_StoreACL(callp, &fid, &acl, &fileStatus, &volSync);
rx_PutConnection(callp);
callp = cm_GetRxConn(connp);
code = RXAFS_StoreACL(callp, &fid, &acl, &fileStatus, &volSync);
rx_PutConnection(callp);
} while (cm_Analyze(connp, userp, &req, &scp->fid, &volSync, NULL, NULL, code));
code = cm_MapRPCError(code, &req);
/* invalidate cache info, since we just trashed the ACL cache */
lock_ObtainMutex(&scp->mx);
cm_DiscardSCache(scp);
lock_ReleaseMutex(&scp->mx);
} while (cm_Analyze(connp, userp, &req, &scp->fid, &volSync, NULL, NULL, code));
code = cm_MapRPCError(code, &req);
/* invalidate cache info, since we just trashed the ACL cache */
lock_ObtainMutex(&scp->mx);
cm_DiscardSCache(scp);
lock_ReleaseMutex(&scp->mx);
}
cm_ReleaseSCache(scp);
return code;
@ -714,12 +727,18 @@ long cm_IoctlFlushVolume(struct smb_ioctl *ioctlp, struct cm_user *userp)
code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
if (code) return code;
volume = scp->fid.volume;
cell = scp->fid.cell;
cm_ReleaseSCache(scp);
code = cm_FlushVolume(userp, &req, cell, volume);
#ifdef AFS_FREELANCE_CLIENT
if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
code = CM_ERROR_NOACCESS;
} else
#endif
{
volume = scp->fid.volume;
cell = scp->fid.cell;
cm_ReleaseSCache(scp);
code = cm_FlushVolume(userp, &req, cell, volume);
}
return code;
}
@ -734,7 +753,14 @@ long cm_IoctlFlushFile(struct smb_ioctl *ioctlp, struct cm_user *userp)
code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
if (code) return code;
cm_FlushFile(scp, userp, &req);
#ifdef AFS_FREELANCE_CLIENT
if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
code = CM_ERROR_NOACCESS;
} else
#endif
{
cm_FlushFile(scp, userp, &req);
}
cm_ReleaseSCache(scp);
return 0;
@ -761,53 +787,60 @@ long cm_IoctlSetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
if (code) return code;
cellp = cm_FindCellByID(scp->fid.cell);
osi_assert(cellp);
#ifdef AFS_FREELANCE_CLIENT
if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
code = CM_ERROR_NOACCESS;
} else
#endif
{
cellp = cm_FindCellByID(scp->fid.cell);
osi_assert(cellp);
if (scp->flags & CM_SCACHEFLAG_RO) {
cm_ReleaseSCache(scp);
return CM_ERROR_READONLY;
if (scp->flags & CM_SCACHEFLAG_RO) {
cm_ReleaseSCache(scp);
return CM_ERROR_READONLY;
}
code = cm_GetVolumeByID(cellp, scp->fid.volume, userp, &req,
CM_GETVOL_FLAG_CREATE, &tvp);
if (code) {
cm_ReleaseSCache(scp);
return code;
}
cm_PutVolume(tvp);
/* Copy the junk out, using cp as a roving pointer. */
cp = ioctlp->inDatap;
memcpy((char *)&volStat, cp, sizeof(AFSFetchVolumeStatus));
cp += sizeof(AFSFetchVolumeStatus);
StringCbCopyA(volName, sizeof(volName), cp);
cp += strlen(volName)+1;
StringCbCopyA(offLineMsg, sizeof(offLineMsg), cp);
cp += strlen(offLineMsg)+1;
StringCbCopyA(motd, sizeof(motd), cp);
storeStat.Mask = 0;
if (volStat.MinQuota != -1) {
storeStat.MinQuota = volStat.MinQuota;
storeStat.Mask |= AFS_SETMINQUOTA;
}
if (volStat.MaxQuota != -1) {
storeStat.MaxQuota = volStat.MaxQuota;
storeStat.Mask |= AFS_SETMAXQUOTA;
}
do {
code = cm_ConnFromFID(&scp->fid, userp, &req, &tcp);
if (code) continue;
callp = cm_GetRxConn(tcp);
code = RXAFS_SetVolumeStatus(callp, scp->fid.volume,
&storeStat, volName, offLineMsg, motd);
rx_PutConnection(callp);
} while (cm_Analyze(tcp, userp, &req, &scp->fid, NULL, NULL, NULL, code));
code = cm_MapRPCError(code, &req);
}
code = cm_GetVolumeByID(cellp, scp->fid.volume, userp, &req,
CM_GETVOL_FLAG_CREATE, &tvp);
if (code) {
cm_ReleaseSCache(scp);
return code;
}
cm_PutVolume(tvp);
/* Copy the junk out, using cp as a roving pointer. */
cp = ioctlp->inDatap;
memcpy((char *)&volStat, cp, sizeof(AFSFetchVolumeStatus));
cp += sizeof(AFSFetchVolumeStatus);
StringCbCopyA(volName, sizeof(volName), cp);
cp += strlen(volName)+1;
StringCbCopyA(offLineMsg, sizeof(offLineMsg), cp);
cp += strlen(offLineMsg)+1;
StringCbCopyA(motd, sizeof(motd), cp);
storeStat.Mask = 0;
if (volStat.MinQuota != -1) {
storeStat.MinQuota = volStat.MinQuota;
storeStat.Mask |= AFS_SETMINQUOTA;
}
if (volStat.MaxQuota != -1) {
storeStat.MaxQuota = volStat.MaxQuota;
storeStat.Mask |= AFS_SETMAXQUOTA;
}
do {
code = cm_ConnFromFID(&scp->fid, userp, &req, &tcp);
if (code) continue;
callp = cm_GetRxConn(tcp);
code = RXAFS_SetVolumeStatus(callp, scp->fid.volume,
&storeStat, volName, offLineMsg, motd);
rx_PutConnection(callp);
} while (cm_Analyze(tcp, userp, &req, &scp->fid, NULL, NULL, NULL, code));
code = cm_MapRPCError(code, &req);
/* return on failure */
cm_ReleaseSCache(scp);
if (code) {
@ -990,7 +1023,8 @@ long cm_IoctlWhereIs(struct smb_ioctl *ioctlp, struct cm_user *userp)
return CM_ERROR_NOSUCHCELL;
code = cm_GetVolumeByID(cellp, volume, userp, &req, CM_GETVOL_FLAG_CREATE, &tvp);
if (code) return code;
if (code)
return code;
cp = ioctlp->outDatap;
@ -1163,7 +1197,8 @@ long cm_IoctlCheckServers(struct smb_ioctl *ioctlp, struct cm_user *userp)
if (haveCell) {
/* have cell name, too */
cellp = cm_GetCell(cp, 0);
if (!cellp) return CM_ERROR_NOSUCHCELL;
if (!cellp)
return CM_ERROR_NOSUCHCELL;
}
else cellp = (cm_cell_t *) 0;
if (!cellp && (temp & 2)) {
@ -1695,7 +1730,8 @@ long cm_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
cm_InitReq(&req);
code = cm_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
if (code) return code;
if (code)
return code;
/* Translate chars for the mount point name */
TranslateExtendedChars(leaf);
@ -1720,8 +1756,10 @@ long cm_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
if (code && cm_dnsEnabled)
code = cm_SearchCellByDNS(cell, fullCell, &ttl, 0, 0);
#endif
if (code)
if (code) {
cm_ReleaseSCache(dscp);
return CM_ERROR_NOSUCHCELL;
}
StringCbPrintfA(mpInfo, sizeof(mpInfo), "%c%s:%s", *ioctlp->inDatap, fullCell, volume);
} else {
@ -2111,7 +2149,8 @@ long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
/* cell name */
cellp = cm_GetCell(tp, CM_FLAG_CREATE);
if (!cellp) return CM_ERROR_NOSUCHCELL;
if (!cellp)
return CM_ERROR_NOSUCHCELL;
tp += strlen(tp) + 1;
/* user name */
@ -2369,7 +2408,8 @@ long cm_IoctlDelToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
/* cell name is right here */
cellp = cm_GetCell(ioctlp->inDatap, 0);
if (!cellp) return CM_ERROR_NOSUCHCELL;
if (!cellp)
return CM_ERROR_NOSUCHCELL;
lock_ObtainMutex(&userp->mx);
@ -2853,42 +2893,50 @@ long cm_IoctlPathAvailability(struct smb_ioctl *ioctlp, struct cm_user *userp)
if (code)
return code;
volume = scp->fid.volume;
#ifdef AFS_FREELANCE_CLIENT
if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
code = 0;
cm_ReleaseSCache(scp);
} else
#endif
{
volume = scp->fid.volume;
cellp = cm_FindCellByID(scp->fid.cell);
cellp = cm_FindCellByID(scp->fid.cell);
cm_ReleaseSCache(scp);
cm_ReleaseSCache(scp);
if (!cellp)
return CM_ERROR_NOSUCHCELL;
if (!cellp)
return CM_ERROR_NOSUCHCELL;
code = cm_GetVolumeByID(cellp, volume, userp, &req, CM_GETVOL_FLAG_CREATE, &tvp);
if (code)
return code;
code = cm_GetVolumeByID(cellp, volume, userp, &req, CM_GETVOL_FLAG_CREATE, &tvp);
if (code)
return code;
if (volume == tvp->rw.ID)
statep = &tvp->rw;
else if (volume == tvp->ro.ID)
statep = &tvp->ro;
else
statep = &tvp->bk;
if (volume == tvp->rw.ID)
statep = &tvp->rw;
else if (volume == tvp->ro.ID)
statep = &tvp->ro;
else
statep = &tvp->bk;
switch (statep->state) {
case vl_online:
case vl_unknown:
code = 0;
break;
case vl_busy:
code = CM_ERROR_ALLBUSY;
break;
case vl_offline:
code = CM_ERROR_ALLOFFLINE;
break;
case vl_alldown:
code = CM_ERROR_ALLDOWN;
break;
switch (statep->state) {
case vl_online:
case vl_unknown:
code = 0;
break;
case vl_busy:
code = CM_ERROR_ALLBUSY;
break;
case vl_offline:
code = CM_ERROR_ALLOFFLINE;
break;
case vl_alldown:
code = CM_ERROR_ALLDOWN;
break;
}
cm_PutVolume(tvp);
}
cm_PutVolume(tvp);
return code;
}

View File

@ -620,8 +620,12 @@ void Die(code, filename)
else fprintf(stderr,"%s: Invalid argument.\n", pn);
}
else if (code == ENOENT) {
if (filename) fprintf(stderr,"%s: File '%s' doesn't exist\n", pn, filename);
else fprintf(stderr,"%s: no such file returned\n", pn);
if (filename) fprintf(stderr,"%s: File '%s' doesn't exist.\n", pn, filename);
else fprintf(stderr,"%s: no such file returned.\n", pn);
}
else if (code == EEXIST) {
if (filename) fprintf(stderr,"%s: File '%s' already exists.\n", pn, filename);
else fprintf(stderr,"%s: the specified file already exists.\n", pn);
}
else if (code == EROFS) fprintf(stderr,"%s: You can not change a backup or readonly volume\n", pn);
else if (code == EACCES || code == EPERM) {