block_run parseBlockRun(Disk &disk, char *first, char *last) { char *comma; if (last) { return block_run::Run(atol(first), atol(last), 1); } else if ((comma = strchr(first, ',')) != NULL) { *comma++ = '\0'; return block_run::Run(atol(first), atol(comma)); } return disk.ToBlockRun(atoll(first)); }
void checkIndexForNonExistingFiles(Disk &disk,BPlusTree &tree) { char name[B_FILE_NAME_LENGTH]; uint16 length; off_t offset; while (tree.GetNextEntry(name,&length,B_FILE_NAME_LENGTH,&offset) == B_OK) { name[length] = 0; block_run run = disk.ToBlockRun(offset); if (!gHashtable.Contains(&run)) { printf(" inode at (%ld, %d), offset %Ld, doesn't exist!",run.allocation_group,run.start,offset); switch (tree.Type()) { case BPLUSTREE_STRING_TYPE: printf(" (string = \"%s\")",name); break; case BPLUSTREE_INT32_TYPE: printf(" (int32 = %ld)",*(int32 *)&name); break; case BPLUSTREE_UINT32_TYPE: printf(" (uint32 = %lu)",*(uint32 *)&name); break; case BPLUSTREE_INT64_TYPE: printf(" (int64 = %Ld)",*(int64 *)&name); break; case BPLUSTREE_UINT64_TYPE: printf(" (uint64 = %Lu)",*(uint64 *)&name); break; case BPLUSTREE_FLOAT_TYPE: printf(" (float = %g)",*(float *)&name); break; case BPLUSTREE_DOUBLE_TYPE: printf(" (double = %g)",*(double *)&name); break; } putchar('\n'); } } }
void checkFiles(Disk &disk,BPlusTree &tree,char *attribute) { block_run *runs = (block_run *)malloc(gCount * sizeof(block_run)); if (runs == NULL) { fprintf(stderr," Not enough memory!\n"); return; } // copy hashtable to array block_run *run = NULL; int32 index = 0; gHashtable.Rewind(); while (gHashtable.GetNextEntry((void **)&run) == B_OK) { runs[index++] = *run; } // sort array to speed up disk access qsort(runs,index,sizeof(block_run),(int (*)(const void *,const void *))compareBlockRuns); bool sizeIndex = !strcmp(attribute,"size"); bool nameIndex = !strcmp(attribute,"name"); bool modifiedIndex = !strcmp(attribute,"last_modified"); char key[B_FILE_NAME_LENGTH]; uint16 keyLength = 0; Inode *inode = NULL; for (int32 i = 0;i < index;i++) { if (i % 50 == 0) printf(" %7ld%s1A\n",i,gEscape); delete inode; inode = Inode::Factory(&disk,runs[i]); if (inode == NULL || inode->InitCheck() < B_OK) { fprintf(stderr," inode at (%ld, %d) is corrupt!\n",runs[i].allocation_group,runs[i].start); delete inode; continue; } // check indices not based on standard attributes if (sizeIndex) { if (inode->IsDirectory()) continue; memcpy(key,&inode->InodeBuffer()->data.size,sizeof(off_t)); keyLength = sizeof(off_t); } else if (nameIndex) { strcpy(key,inode->Name()); keyLength = strlen(key); } else if (modifiedIndex) { if (inode->IsDirectory()) continue; memcpy(key,&inode->InodeBuffer()->last_modified_time,sizeof(off_t)); keyLength = sizeof(off_t); } else // iterate through all attributes to find the right one (damn slow, sorry...) { inode->RewindAttributes(); char name[B_FILE_NAME_LENGTH]; uint32 type; void *data; size_t length; bool found = false; while (inode->GetNextAttribute(name,&type,&data,&length) == B_OK) { if (!strcmp(name,attribute)) { strncpy(key,(char *)data,B_FILE_NAME_LENGTH - 1); key[B_FILE_NAME_LENGTH - 1] = '\0'; keyLength = length > B_FILE_NAME_LENGTH ? B_FILE_NAME_LENGTH : length; found = true; break; } } if (!found) continue; } off_t value; if (tree.Find((uint8 *)key,keyLength,&value) < B_OK) { if (*inode->Name()) fprintf(stderr," inode at (%ld, %d) name \"%s\" is not in index!\n",runs[i].allocation_group,runs[i].start,inode->Name()); else { // inode is obviously deleted! block_run parent = inode->Parent(); Directory *directory = (Directory *)Inode::Factory(&disk,parent); if (directory != NULL && directory->InitCheck() == B_OK) { BPlusTree *parentTree; if (directory->GetTree(&parentTree) == B_OK) { char name[B_FILE_NAME_LENGTH]; uint16 length; off_t offset,searchOffset = disk.ToBlock(runs[i]); bool found = false; while (parentTree->GetNextEntry(name,&length,B_FILE_NAME_LENGTH,&offset) == B_OK) { if (offset == searchOffset) { fprintf(stderr," inode at (%ld, %d) name \"%s\" was obviously deleted, but the parent \"%s\" still contains it!\n",runs[i].allocation_group,runs[i].start,name,directory->Name()); found = true; break; } } if (!found) fprintf(stderr," inode at (%ld, %d) was obviously deleted, and the parent \"%s\" obviously doesn't contain it anymore!\n",runs[i].allocation_group,runs[i].start,directory->Name()); } else fprintf(stderr," inode at (%ld, %d) was obviously deleted, but the parent \"%s\" is invalid and still contains it!\n",runs[i].allocation_group,runs[i].start,directory->Name()); } else { // not that this would be really possible... - but who knows fprintf(stderr," inode at (%ld, %d) is not in index and has invalid parent!\n",runs[i].allocation_group,runs[i].start); } delete directory; } } else { if (bplustree_node::LinkType(value) == BPLUSTREE_NODE) { if (disk.ToBlockRun(value) != runs[i]) fprintf(stderr," offset in index and inode offset doesn't match for inode \"%s\" at (%ld, %d)\n",inode->Name(),runs[i].allocation_group,runs[i].start); } else { // search duplicates char name[B_FILE_NAME_LENGTH]; uint16 length; off_t offset; bool found = false,duplicates = false; //puts("++"); tree.Rewind(); while (tree.GetNextEntry(name,&length,B_FILE_NAME_LENGTH,&offset) == B_OK) { //printf("search for = %ld, key = %ld -> value = %Ld (%ld, %d)\n",*(int32 *)&key,*(int32 *)&name,offset,disk.ToBlockRun(offset).allocation_group,disk.ToBlockRun(offset).start); if (keyLength == length && !memcmp(key,name,keyLength)) { duplicates = true; if (disk.ToBlockRun(offset) == runs[i]) { found = true; break; } } //else if (duplicates) // break; } if (!found) { printf(" inode \"%s\" at (%ld, %d) not found in duplicates!\n",inode->Name(),runs[i].allocation_group,runs[i].start); // return; } } } } delete inode; printf(" %7Ld files processed.\n",gCount); }