std::string Graph::nextName(std::string prefix) const { unsigned i=0; while(1) { auto n = prefix + std::to_string(i++); if (isNameUnique(n)) return n; } }
void Viewport::onPaste() { auto data = QApplication::clipboard()->mimeData(); if (data->hasFormat("sb::viewport")) { auto g = App::instance()->getGraph(); const uint64_t new_uid = g->getUIDs(1).front(); // Update this node's UID and store the change in uid_map auto n = QJsonDocument::fromJson( data->data("sb::viewport")).object(); n["uid"] = int(new_uid); auto name = n["name"].toString(); if (!g->isNameUnique(name.toStdString())) { // Trim trailing numbers from the node's name while (name.at(name.size() - 1).isNumber()) name = name.left(name.size() - 1); if (name.isEmpty()) name = "n"; // Then use the remaining string as a prefix n["name"] = QString::fromStdString(g->nextName(name.toStdString())); } // Deserialize this node SceneDeserializer::Info ds; SceneDeserializer::deserializeNode(n, g, &ds); // Update the inspector positions by shifting a bit down and over for (auto& i : ds.inspectors) i += QPointF(10, 10); App::instance()->getGraphScene()->setInspectorPositions(ds.inspectors); App::instance()->pushStack( new UndoAddNodeCommand(g->childNodes().back(), "'paste'")); } }
// int cffsd_fsupdate_directory (u_int sn, int action, struct embdirent *dirent, u_int param2, u_int param3, u_int param4, u_int param5) int serv_fsupdate_directory (u_int client_eid, int action, struct cffsd_fsupdate_directory_arg *arg) { struct embdirent *dirent; u_int param2 = arg->param2; u_int param3 = arg->uint_param3; // u_int param4 = arg->uint_param4; u_int param5 = arg->param5; u_int param1; /* XXX % */ // char *dirBlock = (char *) translate_address ((param1 - (param1 % BLOCK_SIZE)), BLOCK_SIZE); char *dirBlock; debug_request = 3; dirent = translate_address (&arg->dirent); param1 = (u_int) dirent; dirBlock = (char *)((param1 - (param1 % BLOCK_SIZE))); if (dirBlock == NULL) { return (-E_INVAL); } /* XXX % */ dirent = (embdirent_t *) (dirBlock + (param1 % BLOCK_SIZE)); /* GROK -- need to check for write permission on directory. The relevant */ /* inode should be provided automatically by base disk protection software */ if (!isValidDirent(dirBlock, dirent)) { printf ("sys_fsupdate_directory (%d): invalid dirent specified (%x)\n", action, param1); return (-E_INVAL); } /************************** CFFS_DIRECTORY_INITDIRBLOCK ***********************/ if (action == CFFS_DIRECTORY_INITDIRBLOCK) { int i; dinode_t *dinode; /* XXX */ if ((u_int)dirent % BLOCK_SIZE) { printf ("sys_fsupdate_directory (%d): dirent not start of block (%p)\n", action, dirent); return (-E_INVAL); } bzero ((char *)dirent, BLOCK_SIZE); for (i=0; i<(BLOCK_SIZE/CFFS_EMBDIR_SECTOR_SIZE); i++) { dirent->type = (char) 0; dirent->entryLen = CFFS_EMBDIR_SECTOR_SPACEFORNAMES; dirent->preventryLen = 0; dinode = (dinode_t *) ((char *)dirent + CFFS_DINODE_SIZE); dinode->dinodeNum = 0; dinode = (dinode_t *) ((char *)dirent + (2*CFFS_DINODE_SIZE)); dinode->dinodeNum = 0; dinode = (dinode_t *) ((char *)dirent + (3*CFFS_DINODE_SIZE)); dinode->dinodeNum = 0; dirent = (embdirent_t *) ((char *) dirent + CFFS_EMBDIR_SECTOR_SIZE); } /*************************** CFFS_DIRECTORY_SPLITENTRY ************************/ } else if (action == CFFS_DIRECTORY_SPLITENTRY) { embdirent_t *newDirent; int splitspace = param2; int extraspace; extraspace = (dirent->type == (char)0) ? dirent->entryLen : (dirent->entryLen - embdirentsize(dirent)); if ((extraspace < SIZEOF_EMBDIRENT_T) || (extraspace < splitspace)) { printf ("sys_fsupdate_directory (%d): not enough extra space (%d) (wanted %d)\n", action, extraspace, splitspace); return (-E_INVAL); } if (splitspace == 0) { printf ("sys_fsupdate_directory (%d): bad splitspace (%d) (extraspace %d)\n", action, splitspace, extraspace); return (-E_INVAL); } dirent->entryLen -= splitspace; newDirent = (embdirent_t *) ((u_int)dirent + dirent->entryLen); if (newDirent != dirent) { newDirent->preventryLen = dirent->entryLen; } newDirent->entryLen = splitspace; newDirent->type = 0; newDirent->nameLen = 0; newDirent->name[0] = (char) 0; if (((u_int)newDirent + newDirent->entryLen) % CFFS_EMBDIR_SECTOR_SPACEFORNAMES) { dirent = (embdirent_t *) ((char *)newDirent + newDirent->entryLen); dirent->preventryLen = splitspace; } /* XXX % */ // ret = (param1 - (param1 % BLOCK_SIZE)) + ((u_int)newDirent - (u_int)dirBlock); return ((u_int )newDirent); /*************************** CFFS_DIRECTORY_SETNAME ************************/ } else if (action == CFFS_DIRECTORY_SETNAME) { // char *name = (char *) trup(param2); /* XXX */ char name[256]; u_int namelen = param3; dinode_t *dirDInode = translate_address (&arg->ref_param4); /* XXX -- I thought we only reserved < 128 bytes for names? */ if (namelen > 256) { printf ("sys_fsupdate_directory (%d): name too long (%d)\n", action, namelen); return (-E_INVAL); } if (cffsd_copyin (client_eid, param2, (uint )name, namelen) == -1) return (-E_INVAL); if ((dirDInode == NULL) || (dirDInode->dinodeNum == 0)) { return (-E_INVAL); } /* Note: param5 is fsdev in this case, which should be discoverable */ /* from the dinode's identity... */ if ((dirent->type != 0) && (!isNameUnique(param5, dirDInode, name, namelen))) { printf ("sys_fsupdate_directory (%d): non-unique name specified (%d)\n", action, namelen); return (-E_INVAL); } bcopy(name, dirent->name, namelen); // dirent->name[namelen] = (char) 0; dirent->nameLen = namelen; /*************************** CFFS_DIRECTORY_MERGEENTRY ************************/ } else if (action == CFFS_DIRECTORY_MERGEENTRY) { embdirent_t *next = NULL; int maxleft = CFFS_EMBDIR_SECTOR_SPACEFORNAMES - (param1 % CFFS_EMBDIR_SECTOR_SIZE); int extraspace = 0; while ((extraspace < param2) && (extraspace < maxleft)) { next = (embdirent_t *) ((char *)dirent + dirent->entryLen); if (next->type != 0) { break; } extraspace += next->entryLen; } if (extraspace != param2) { printf ("sys_fsupdate_directory (%d): mismatched extraspaces (%d != %d) (maxleft %d)\n", action, extraspace, param2, maxleft); printf ("next %p, next->entryLen %d\n", next, ((next) ? (next->entryLen) : -1)); return (-E_INVAL); } dirent->entryLen += extraspace; next = (embdirent_t *) ((char *)dirent + dirent->entryLen); if ((u_int) next % CFFS_EMBDIR_SECTOR_SPACEFORNAMES) { next->preventryLen = dirent->entryLen; } /*************************** CFFS_DIRECTORY_SHIFTENTRY ************************/ } else if (action == CFFS_DIRECTORY_SHIFTENTRY) { /********* Not currently supported! ************/ assert (0); #if 0 embdirent_t *tmp; int extraspace; if ((-param2 > (param1 % CFFS_EMBDIR_SECTOR_SIZE)) || ((param2 + (param1 % CFFS_EMBDIR_SECTOR_SIZE)) >= (CFFS_EMBDIR_SECTOR_SPACEFORNAMES - SIZEOF_EMBDIRENT_T))) { printf ("sys_fsupdate_directory (%d): sizes don't work (currOff %d, move %d)\n", action, (param1 % BLOCK_SIZE), param2); return (-E_INVAL); } if (param2 <= 0) { tmp = (embdirent_t *) ((char *)dirent - dirent->preventryLen); extraspace = (tmp->type == (char)0) ? tmp->entryLen : tmp->entryLen - embdirentsize(tmp); if (extraspace < (-param2)) { printf ("sys_fsupdate_directory (%d): not enough extra space (%d < %d)\n", action, extraspace, param2); return (-E_INVAL); } tmp->entryLen -= (-param2); dirent->preventryLen = tmp->entryLen; dirent->entryLen += (-param2); bcopy ((char *) dirent, ((char *)dirent - (-param2)), embdirentsize(dirent)); tmp = (embdirent_t *) ((char *)dirent + dirent->entryLen); if ((u_int) tmp % CFFS_EMBDIR_SECTOR_SPACEFORNAMES) { tmp->preventryLen = dirent->entryLen; } } else { tmp = (embdirent_t *) ((char *)dirent - dirent->preventryLen); extraspace = dirent->entryLen - embdirentsize(dirent); if (extraspace < param2) { printf ("sys_fsupdate_directory (%d): not enough extra space (%d < %d)\n", action, extraspace, param2); return (-E_INVAL); } tmp->entryLen += param2; dirent->preventryLen = tmp->entryLen; dirent->entryLen -= param2; bcopy ((char *)dirent, ((char *)dirent + param2), embdirentsize(dirent)); dirent = (embdirent_t *) ((char *)dirent + tmp->entryLen); tmp = (embdirent_t *) ((char *)dirent + dirent->entryLen); if ((u_int) tmp % CFFS_EMBDIR_SECTOR_SPACEFORNAMES) { tmp->preventryLen = dirent->entryLen; } } #endif /*************************** CFFS_DIRECTORY_SETINODENUM ***********************/ } else if (action == CFFS_DIRECTORY_SETINODENUM) { u_int inodeNum = param2; /* no restrictions is directory entry is not currently live */ if (dirent->type == 0) { dirent->inodeNum = inodeNum; /* this case causes a change in which inode a dirent points to. */ /* because the dirent is live, it must always point to a live inode. */ } else { dinode_t *olddinode; dinode_t *newdinode; if (inodeNum == 0) { printf ("sys_fsupdate_directory (%d): can't set inodeNum to 0 is live dirent\n", action); return (-E_INVAL); } /* if ((param3 == 0) || (param4 == 0)) { printf ("sys_fsupdate_directory (%d): passed NULL for a cheat variable (%d, %d)\n", action, param3, param4); return (-E_INVAL); } */ /* it is a bug in FS code to have valid dirent with 0 for an inodeNum */ assert (dirent->inodeNum != 0); /* this should be retrievable from dirent->inodeNum, which identifies */ /* the containing disk block -- which must be a directory block. */ olddinode = translate_address (&arg->ref_param3); if (olddinode->dinodeNum != dirent->inodeNum) { printf ("sys_fsupdate_directory (%d): mismatching old inodeNums (%d != %d)\n", action, olddinode->dinodeNum, dirent->inodeNum); return (-E_INVAL); } /* this should be retrievable from inodeNum, which identifies the */ /* containing disk block -- which must be a directory block. */ newdinode = translate_address (&arg->ref_param4); if (newdinode->dinodeNum != inodeNum) { printf ("sys_fsupdate_directory (%d): mismatching old inodeNums (%d != %d)\n", action, newdinode->dinodeNum, inodeNum); return (-E_INVAL); } if ((olddinode->type != newdinode->type) && ((cffs_dinode_isDir(olddinode)) || (cffs_dinode_isDir(newdinode)))) { printf ("sys_fsupdate_directory (%d): can't interchange a directory and non-directory (%x != %x)\n", action, olddinode->type, newdinode->type); return (-E_INVAL); } /* this rule helps get us around an ordering requirement!! */ /* (i.e., if we handle ordering in some other way, it can */ /* go away... */ if (newdinode->linkCount < (cffs_dinode_isDir(newdinode) ? 2 : 1)) { printf ("sys_fsupdate_directory (%d): can't link up to disowned inode\n", action); return (-E_INVAL); } /* the big stickler here is that we need to be able to check whether */ /* the caller has the ability to look at newdinode. In particular, */ /* this requires execute permission on a directory that already */ /* contains an existing link. */ if ((olddinode) && (cffs_dinode_isDir(olddinode))) { /* must check that directory is actually empty... */ } /* GROK - I'm pretty sure I've designed away all need for ordering here */ olddinode->linkCount--; newdinode->linkCount++; dirent->inodeNum = inodeNum; dirent->type = newdinode->type >> 8; } /**************************** CFFS_DIRECTORY_SETTYPE **************************/ } else if (action == CFFS_DIRECTORY_SETTYPE) {