/* * Remove a temporary symlink entry from /afs. */ int afs_DynrootVOPRemove(struct vcache *avc, afs_ucred_t *acred, char *aname) { struct afs_dynSymlink **tpps; struct afs_dynSymlink *tps; int found = 0; #if defined(AFS_SUN510_ENV) if (crgetruid(acred)) #else if (afs_cr_uid(acred)) #endif return EPERM; ObtainWriteLock(&afs_dynSymlinkLock, 97); tpps = &afs_dynSymlinkBase; while (*tpps) { tps = *tpps; if (afs_strcasecmp(aname, tps->name) == 0) { afs_osi_Free(tps->name, strlen(tps->name) + 1); afs_osi_Free(tps->target, strlen(tps->target) + 1); *tpps = tps->next; afs_osi_Free(tps, sizeof(*tps)); afs_dynSymlinkIndex++; found = 1; break; } tpps = &(tps->next); } ReleaseWriteLock(&afs_dynSymlinkLock); if (found) { afs_DynrootInvalidate(); return 0; } if (afs_CellOrAliasExists(aname)) return EROFS; else return ENOENT; }
/*! * Create new cell alias entry and update dynroot vnode. * \param alias * \param cell * \return */ afs_int32 afs_NewCellAlias(char *alias, char *cell) { struct cell_alias *tc; ObtainSharedLock(&afs_xcell, 681); if (afs_CellOrAliasExists_nl(alias)) { ReleaseSharedLock(&afs_xcell); return EEXIST; } UpgradeSToWLock(&afs_xcell, 682); tc = (struct cell_alias *)afs_osi_Alloc(sizeof(struct cell_alias)); tc->alias = afs_strdup(alias); tc->cell = afs_strdup(cell); tc->next = afs_cellalias_head; tc->index = afs_cellalias_index++; afs_cellalias_head = tc; ReleaseWriteLock(&afs_xcell); afs_DynrootInvalidate(); return 0; }
/* * Create a temporary symlink entry in /afs. */ int afs_DynrootVOPSymlink(struct vcache *avc, afs_ucred_t *acred, char *aname, char *atargetName) { struct afs_dynSymlink *tps; if (afs_cr_uid(acred)) return EPERM; if (afs_CellOrAliasExists(aname)) return EEXIST; /* Check if it's already a symlink */ ObtainWriteLock(&afs_dynSymlinkLock, 91); tps = afs_dynSymlinkBase; while (tps) { if (afs_strcasecmp(aname, tps->name) == 0) { ReleaseWriteLock(&afs_dynSymlinkLock); return EEXIST; } tps = tps->next; } /* Doesn't already exist -- go ahead and create it */ tps = afs_osi_Alloc(sizeof(*tps)); tps->index = afs_dynSymlinkIndex++; tps->next = afs_dynSymlinkBase; tps->name = afs_osi_Alloc(strlen(aname) + 1); strcpy(tps->name, aname); tps->target = afs_osi_Alloc(strlen(atargetName) + 1); strcpy(tps->target, atargetName); afs_dynSymlinkBase = tps; ReleaseWriteLock(&afs_dynSymlinkLock); afs_DynrootInvalidate(); return 0; }
/*! * Create or update a cell entry. * \param acellName Name of cell. * \param acellHosts Array of hosts that this cell has. * \param aflags Cell flags. * \param linkedcname * \param fsport File server port. * \param vlport Volume server port. * \param timeout Cell timeout value, 0 means static AFSDB entry. * \return */ afs_int32 afs_NewCell(char *acellName, afs_int32 * acellHosts, int aflags, char *linkedcname, u_short fsport, u_short vlport, int timeout) { struct cell *tc, *tcl = 0; afs_int32 i, newc = 0, code = 0; AFS_STATCNT(afs_NewCell); ObtainWriteLock(&afs_xcell, 103); tc = afs_FindCellByName_nl(acellName, READ_LOCK); if (tc) { aflags &= ~CNoSUID; } else { tc = afs_osi_Alloc(sizeof(struct cell)); osi_Assert(tc != NULL); memset(tc, 0, sizeof(*tc)); tc->cellName = afs_strdup(acellName); tc->fsport = AFS_FSPORT; tc->vlport = AFS_VLPORT; AFS_MD5_String(tc->cellHandle, tc->cellName, strlen(tc->cellName)); AFS_RWLOCK_INIT(&tc->lock, "cell lock"); newc = 1; aflags |= CNoSUID; } ObtainWriteLock(&tc->lock, 688); /* If the cell we've found has the correct name but no timeout, * and we're called with a non-zero timeout, bail out: never * override static configuration entries with AFSDB ones. * One exception: if the original cell entry had no servers, * it must get servers from AFSDB. */ if (timeout && !tc->timeout && tc->cellHosts[0]) { code = EEXIST; /* This code is checked for in afs_LookupAFSDB */ goto bad; } /* we don't want to keep pinging old vlservers which were down, * since they don't matter any more. It's easier to do this than * to remove the server from its various hash tables. */ for (i = 0; i < AFS_MAXCELLHOSTS; i++) { if (!tc->cellHosts[i]) break; tc->cellHosts[i]->flags &= ~SRVR_ISDOWN; tc->cellHosts[i]->flags |= SRVR_ISGONE; } if (fsport) tc->fsport = fsport; if (vlport) tc->vlport = vlport; if (aflags & CLinkedCell) { if (!linkedcname) { code = EINVAL; goto bad; } tcl = afs_FindCellByName_nl(linkedcname, READ_LOCK); if (!tcl) { code = ENOENT; goto bad; } if (tcl->lcellp) { /* XXX Overwriting if one existed before! XXX */ tcl->lcellp->lcellp = (struct cell *)0; tcl->lcellp->states &= ~CLinkedCell; } tc->lcellp = tcl; tcl->lcellp = tc; } tc->states |= aflags; tc->timeout = timeout; memset(tc->cellHosts, 0, sizeof(tc->cellHosts)); for (i = 0; i < AFS_MAXCELLHOSTS; i++) { /* Get server for each host and link this cell in.*/ struct server *ts; afs_uint32 temp = acellHosts[i]; if (!temp) break; ts = afs_GetServer(&temp, 1, 0, tc->vlport, WRITE_LOCK, NULL, 0); ts->cell = tc; ts->flags &= ~SRVR_ISGONE; /* Set the server as a host of the new cell. */ tc->cellHosts[i] = ts; afs_PutServer(ts, WRITE_LOCK); } afs_SortServers(tc->cellHosts, AFS_MAXCELLHOSTS); /* randomize servers */ /* New cell: Build and add to LRU cell queue. */ if (newc) { struct cell_name *cn; cn = afs_cellname_lookup_name(acellName); if (!cn) cn = afs_cellname_new(acellName, 0); tc->cnamep = cn; tc->cellNum = cn->cellnum; tc->cellIndex = afs_cellindex++; afs_stats_cmperf.numCellsVisible++; QAdd(&CellLRU, &tc->lruq); } ReleaseWriteLock(&tc->lock); ReleaseWriteLock(&afs_xcell); afs_PutCell(tc, 0); if (!(aflags & CHush)) afs_DynrootInvalidate(); return 0; bad: if (newc) { afs_osi_FreeStr(tc->cellName); afs_osi_Free(tc, sizeof(struct cell)); } ReleaseWriteLock(&tc->lock); ReleaseWriteLock(&afs_xcell); return code; }