le32 LinnCreate::createInode(char *inputFile, struct stat *st) { LinnGroup *group; LinnInode *inode; BitArray inodeMap(super->inodesPerGroup); u32 gn, in; /* Loop all available LinnGroups. */ for (gn = 0; gn < LINN_GROUP_COUNT(super); gn++) { /* Point to the correct LinnGroup. */ group = BLOCKPTR(LinnGroup, super->groupsTable) + gn; /* Does it have any free inodes? */ if (!group->freeInodesCount) { group = ZERO; continue; } else break; } /* Did we find an appropriate group? */ if (!group) { printf("%s: no free inode available for `%s'\n", prog, inputFile); exit(EXIT_FAILURE); } /* Find an empty inode number. */ inodeMap.setArray(BLOCKPTR(u8, group->inodeMap), super->inodesPerGroup); in = inodeMap.setNext(); /* Instantiate the inode. */ inode = createInode(in, FILETYPE_FROM_ST(st), FILEMODE_FROM_ST(st), st->st_uid, st->st_gid); /* Insert file contents. */ if (S_ISREG(st->st_mode)) { insertFile(inputFile, inode, st); } /* Debug out. */ if (verbose) { printf("%s inode=%u size=%u\n", inputFile, in, inode->size); } return in; }
int LinnCreate::create(Size blockSize, Size blockNum, Size inodeNum) { LinnGroup *group; BitArray map(128); assert(image != ZERO); assert(prog != ZERO); assert(blockNum >= 2); assert(inodeNum > 0); /* Allocate blocks. */ blocks = new u8[blockSize * blockNum]; memset(blocks, 0, blockSize * blockNum); /* Create a superblock. */ super = (LinnSuperBlock *) (blocks + LINN_SUPER_OFFSET); super->magic0 = LINN_SUPER_MAGIC0; super->magic1 = LINN_SUPER_MAGIC1; super->majorRevision = LINN_SUPER_MAJOR; super->minorRevision = LINN_SUPER_MINOR; super->state = LINN_SUPER_VALID; super->blockSize = blockSize; super->blocksPerGroup = LINN_CREATE_BLOCKS_PER_GROUP; super->inodesCount = inodeNum; super->blocksCount = blockNum; super->inodesPerGroup = super->inodesCount / LINN_GROUP_COUNT(super); super->freeInodesCount = super->inodesCount; super->freeBlocksCount = blockNum - 3; super->creationTime = time(ZERO); super->mountTime = ZERO; super->mountCount = ZERO; super->lastCheck = ZERO; super->groupsTable = 2; /* Allocate LinnGroups. */ for (Size i = 0; i < LINN_GROUP_COUNT(super); i++) { /* Point to the correct LinnGroup. */ group = BLOCKPTR(LinnGroup, 2) + i; /* Fill the group. */ group->freeBlocksCount = super->blocksPerGroup; group->freeInodesCount = super->inodesPerGroup; group->blockMap = BLOCKS(super, LINN_GROUP_NUM_BLOCKMAP(super)); group->inodeMap = BLOCKS(super, LINN_GROUP_NUM_INODEMAP(super)); group->inodeTable = BLOCKS(super, LINN_GROUP_NUM_INODETAB(super)); } /* Create special inodes. */ createInode(LINN_INODE_ROOT, DirectoryFile, OwnerRWX | GroupRX | OtherRX); createInode(LINN_INODE_LOADER, RegularFile, OwnerRWX | GroupRX | OtherRX); createInode(LINN_INODE_BAD, RegularFile, OwnerRW | GroupR | OtherR); createInode(LINN_INODE_JOURNAL, RegularFile, OwnerRW | GroupR | OtherR); /* Insert into directory contents, if set. */ if (input) { insertDirectory(input, LINN_INODE_ROOT, LINN_INODE_ROOT); } /* Mark blocks used. */ for (le32 block = 0; block < super->freeBlocksCount; block++) { /* Point to group. */ group = BLOCKPTR(LinnGroup, super->groupsTable) + (block / super->blocksPerGroup); group->freeBlocksCount--; /* Mark the block used. */ map.setArray(BLOCKPTR(u8, group->blockMap), super->blocksPerGroup); map.set(block % super->blocksPerGroup); } /* Write the final image. */ return writeImage(); }
void LinnCreate::insertDirectory(char *inputDir, le32 inodeNum, le32 parentNum) { struct dirent *ent; struct stat st; DIR *dir; char path[255]; le32 child; bool skip = false; /* Create '.' and '..' */ insertEntry(inodeNum, inodeNum, ".", DirectoryFile); insertEntry(inodeNum, parentNum, "..", DirectoryFile); /* Open the input directory. */ if ((dir = opendir(inputDir)) == NULL) { printf("%s: failed to opendir() `%s': %s\n", prog, inputDir, strerror(errno)); exit(EXIT_FAILURE); } /* Read all it's entries. */ while ((ent = readdir(dir))) { /* Hidden files. */ skip = ent->d_name[0] == '.'; /* Excluded files. */ for (ListIterator<String *> e(&excludes); e.hasCurrent(); e++) { String dent = (const char *) ent->d_name; if (dent.match(**e.current())) { skip = true; break; } } /* Skip file? */ if (skip) continue; /* Construct local path. */ snprintf(path, sizeof(path), "%s/%s", inputDir, ent->d_name); /* Stat the file. */ if (stat(path, &st) != 0) { printf("%s: failed to stat() `%s': %s\n", prog, path, strerror(errno)); exit(EXIT_FAILURE); } /* Create an inode for the child. */ child = createInode(path, &st); /* Insert directory entry. */ insertEntry(inodeNum, child, ent->d_name, FILETYPE_FROM_ST(&st)); /* Traverse down. */ if (S_ISDIR(st.st_mode)) { insertDirectory(path, child, inodeNum); } } /* All done. */ closedir(dir); }
Inode* readInode(disk_t disk, int block){ char * databuf = malloc(sizeof(char) * disk->block_size); readblock(disk,block,databuf); int size; int i,j; char * name; bool gotsize = false; bool gotpointers = false; bool gotlink = false; bool gotname = false; int numberbufIndex = 0; char * numberbuf = malloc(sizeof(char) * 16); int * pointers = malloc(sizeof(int) * disk->size); int pointersIndex = 0; for(i = 0; databuf[i] != '\0' && i < disk->block_size;i+=1){ if(!gotsize){ if(databuf[i] == '\n'){ numberbuf[numberbufIndex] = '\0'; size = str2int(numberbuf); numberbufIndex = 0; gotsize = true; }else{ numberbuf[numberbufIndex] = databuf[i]; numberbufIndex +=1; } }else if(!gotpointers){ if(databuf[i] == '\n'){ gotpointers = true; numberbuf[0] = '\0'; numberbufIndex = 0; }else{ if(databuf[i] == ','){ numberbuf[numberbufIndex] = '\0'; pointers[pointersIndex] = str2int(numberbuf); numberbufIndex = 0; pointersIndex +=1; }else{ numberbuf[numberbufIndex] = databuf[i]; numberbufIndex +=1; } } }else if(!gotname){ if(databuf[i] == '\n'){ name = malloc(sizeof(char) * (numberbufIndex+1)); for(j = 0; j < numberbufIndex; j+=1){ name[j] = numberbuf[j]; } name[j] = '\0'; gotname = true; numberbufIndex = 0; }else{ numberbuf[numberbufIndex]= databuf[i]; numberbufIndex +=1; } } else{ gotlink = true; numberbuf[numberbufIndex] = databuf[i]; numberbufIndex +=1; } } int link; if(gotlink){ numberbuf[numberbufIndex] = '\0'; link = str2int(numberbuf); Inode * newinode = readInode(disk,link); for(i = 0; newinode->pointers[i] != '\0';i+=1){ pointers[pointersIndex] = newinode->pointers[i]; pointersIndex+=1; } freeInode(newinode); } int * pointersSmall = malloc(sizeof(int) * (pointersIndex+1)); for(i = 0; i < pointersIndex;i+=1){ pointersSmall[i] = pointers[i]; } pointersSmall[i] = '\0'; Inode * node = createInode(size,pointersSmall,(size ==0)? true : false, block,name); free(numberbuf); free(databuf); free(pointers); //free(pointersSmall); return node; }
//max name size = 15 //will modify block_map Inode* writeInode(disk_t disk, int block, int * gpointers,bool directory, char * nametemp){ int * blkmap = read_block_map(disk); blkmap[block] = 1; write_block_map(disk,blkmap); int size = arrayLength(gpointers); int maxsize = (disk->block_size-20-(ceil(log10(disk->size))*2)/(ceil(log10(disk->size))+1)); int * pointers = malloc(sizeof(int) * (size+1)); int i,j; int strlength = length(nametemp); char * name = malloc(sizeof(char)* 16); for(i = 0; i < 15 && nametemp[i] != '\0';i+=1){ name[i] = nametemp[i]; } name[i] = '\0'; int * wpointers = malloc(sizeof(int) * (size + 1)); for(i = 0; i < size; i+=1){ pointers[i] = gpointers[i]; wpointers[i] = gpointers[i]; } wpointers[i] = '\0'; pointers[i] = '\0'; char * potSize; if(size > (maxsize)){ //-4 for 3 \n and 1 \0 - 16 for name length int * newpointers = malloc(sizeof(int) * (maxsize+1)); int * extrapointers = malloc(sizeof(int) * (size-maxsize+1)); for(i = 0; i < maxsize;i+=1){ newpointers[i] = pointers[i]; } newpointers[i] = '\0'; free(wpointers); wpointers = newpointers; for(j = 0; j <size-maxsize;j+=1){ extrapointers[j] = pointers[i]; i+=1; } extrapointers[j] = '\0'; int newblk; for(i = 0; i < disk->size;i+=1){ if(blkmap[i] == 0){ newblk = i; break; } } freeInode(writeInode(disk,newblk,extrapointers,directory,name)); } unsigned char *strings[6]; potSize = int2str(size); strings[0] = (directory)? "0" : potSize; char * list = intArray2charArray(wpointers); char * pntrs = malloc(sizeof(char) * (length(list)+2)); pntrs[0] = '\n'; pntrs[1] = '\0'; strcat(pntrs,list); strings[1] = pntrs; strings[2] = "\n"; strings[3] = name; strings[4] = "\n"; strings[5] = NULL; unsigned char *databuf = calloc(disk->block_size, sizeof(unsigned char) ); copy2buf(databuf,strings,0); writeblock(disk,block,databuf); free(list); free(pntrs); free(databuf); //free(name); free(blkmap); free(potSize); free(wpointers); return createInode(size,pointers,directory,block,name); }
int serverCreate(int pinum, int type, char* name){ //take care of error cases if((type != MFS_DIRECTORY && type != MFS_REGULAR_FILE) || pinum > 4095 || pinum < 0) return -1; //if name is too long return -1 if(strlen(name) < 1 || strlen(name) > 28) return -1; //if pinum dne return -1 if(inodeMap.inodes[pinum] == -1) return -1; //if file already exists, return success if(serverLookup(pinum, name) >= 0) return 0; //get pinum address int pinumLocation = inodeMap.inodes[pinum]; //lseek to this location lseek(diskFD, pinumLocation, 0); //we have just lseeked to the inode, we need to read the inode MFS_Inode pInode; int bytesRead = read(diskFD,&pInode, sizeof(pInode)); //check if this is a directory or not if(pInode.stats.type != MFS_DIRECTORY){ return -1; } if(pInode.stats.size >= (MFS_BLOCK_SIZE * 14*128)){ return -1; } int newInum = createInode(pinum,type); //get the directoryBlockIndex in inode int inodeDirBlockIndex = (int) pInode.stats.size/(MFS_BLOCK_SIZE*128); //potential error case if(inodeDirBlockIndex < 0 ||inodeDirBlockIndex > 14){ return -1; } //this is the last full index int dirBlockIndex = (int) (pInode.stats.size/(MFS_BLOCK_SIZE) %128); pInode.stats.size += MFS_BLOCK_SIZE; if(dirBlockIndex < 0){ return -1; } //take care of case where directory index is full //need new directory block if(dirBlockIndex == 0){ pInode.blockPtrs[inodeDirBlockIndex] = ckptregion.endLog; MFS_Dir_Block freshDirBlock; int k; for(k = 0; k < 128; k++){ memcpy(freshDirBlock.dirEntries[k].name, "\0", sizeof("\0")); freshDirBlock.dirEntries[k].inum = -1; } lseek(diskFD, ckptregion.endLog, 0); write(diskFD, &freshDirBlock, sizeof(freshDirBlock)); //update endlog and write out the checkpoint ckptregion.endLog += MFS_BLOCK_SIZE; lseek(diskFD, 0, 0); write(diskFD, &ckptregion, sizeof(ckptregion)); } //IMPORTANT //write out the inode here. Either way, inode needs to be written out since size is updated //do it here because if we need to update the block ptrs, that happens just before this lseek(diskFD, pinumLocation, 0); write(diskFD, &pInode, sizeof(pInode)); memLoad(); lseek(diskFD, pInode.blockPtrs[inodeDirBlockIndex], 0); MFS_Dir_Block dirBlock; bytesRead = read(diskFD,&dirBlock, sizeof(dirBlock)); //set the name etc int newIndex = dirBlockIndex; memcpy(dirBlock.dirEntries[newIndex].name, "\0", sizeof("\0")); memcpy(dirBlock.dirEntries[newIndex].name, name, 28); dirBlock.dirEntries[newIndex].inum = newInum; //write out updated directory block to disk lseek(diskFD, pInode.blockPtrs[inodeDirBlockIndex], 0); write(diskFD, &dirBlock, sizeof(dirBlock)); /************************************************************************/ //fsync(diskFD); /************************************************************************/ memLoad(); return 0; }