Lines Matching +full:sc +full:- +full:partitions
30 #include "block/block-io.h"
41 #include "qemu/error-report.h"
55 /* MAYBE TODO: write block-visofs.c */
73 * https://jdebp.eu/FGA/volume-boot-block-oem-name-field.html
91 array->pointer = NULL; in array_init()
92 array->size=0; in array_init()
93 array->next=0; in array_init()
94 array->item_size=item_size; in array_init()
99 g_free(array->pointer); in array_free()
100 array->size=array->next=0; in array_free()
105 assert(index < array->next); in array_get()
106 assert(array->pointer); in array_get()
107 return array->pointer + index * array->item_size; in array_get()
112 if((index + 1) * array->item_size > array->size) { in array_ensure_allocated()
113 int new_size = (index + 32) * array->item_size; in array_ensure_allocated()
114 array->pointer = g_realloc(array->pointer, new_size); in array_ensure_allocated()
115 assert(array->pointer); in array_ensure_allocated()
116 memset(array->pointer + array->size, 0, new_size - array->size); in array_ensure_allocated()
117 array->size = new_size; in array_ensure_allocated()
118 array->next = index + 1; in array_ensure_allocated()
123 unsigned int next = array->next; in array_get_next()
126 array->next = next + 1; in array_get_next()
131 if((array->next+count)*array->item_size>array->size) { in array_insert()
132 int increment=count*array->item_size; in array_insert()
133 array->pointer=g_realloc(array->pointer,array->size+increment); in array_insert()
134 if(!array->pointer) in array_insert()
136 array->size+=increment; in array_insert()
138 memmove(array->pointer+(index+count)*array->item_size, in array_insert()
139 array->pointer+index*array->item_size, in array_insert()
140 (array->next-index)*array->item_size); in array_insert()
141 array->next+=count; in array_insert()
142 return array->pointer+index*array->item_size; in array_insert()
149 assert(index + count <= array->next); in array_remove_slice()
151 memmove(array->pointer + index * array->item_size, in array_remove_slice()
152 array->pointer + (index + count) * array->item_size, in array_remove_slice()
153 (array->next - index - count) * array->item_size); in array_remove_slice()
155 array->next -= count; in array_remove_slice()
167 size_t offset = (char*)pointer - array->pointer; in array_index()
168 assert((offset % array->item_size) == 0); in array_index()
169 assert(offset/array->item_size < array->next); in array_index()
170 return offset/array->item_size; in array_index()
263 /* as s->directory is growable, no pointer may be used here */
269 * - the offset in the file (in clusters) for a file, or
270 * - the next cluster of the directory for a directory
280 /* path contains the full path, i.e. it always starts with s->path */
354 chs->head = 0xFF; in sector2CHS()
355 chs->sector = 0xFF; in sector2CHS()
356 chs->cylinder = 0xFF; in sector2CHS()
359 chs->head = (uint8_t)head; in sector2CHS()
360 chs->sector = (uint8_t)( (sector+1) | ((spos>>8)<<6) ); in sector2CHS()
361 chs->cylinder = (uint8_t)spos; in sector2CHS()
368 mbr_t* real_mbr=(mbr_t*)s->first_sectors; in init_mbr()
369 partition_t* partition = &(real_mbr->partition[0]); in init_mbr()
372 memset(s->first_sectors,0,512); in init_mbr()
375 real_mbr->nt_id= cpu_to_le32(0xbe1afdfa); in init_mbr()
377 partition->attributes=0x80; /* bootable */ in init_mbr()
380 lba = sector2CHS(&partition->start_CHS, s->offset_to_bootsector, in init_mbr()
382 lba |= sector2CHS(&partition->end_CHS, s->bs->total_sectors - 1, in init_mbr()
385 /*LBA partitions are identified only by start/length_sector_long not by CHS*/ in init_mbr()
386 partition->start_sector_long = cpu_to_le32(s->offset_to_bootsector); in init_mbr()
387 partition->length_sector_long = cpu_to_le32(s->bs->total_sectors in init_mbr()
388 - s->offset_to_bootsector); in init_mbr()
393 partition->fs_type = s->fat_type == 12 ? 0x1 : in init_mbr()
394 s->fat_type == 16 ? (lba ? 0xe : 0x06) : in init_mbr()
395 /*s->fat_type == 32*/ (lba ? 0xc : 0x0b); in init_mbr()
397 real_mbr->magic[0]=0x55; real_mbr->magic[1]=0xaa; in init_mbr()
408 gunichar2 *longname = g_utf8_to_utf16(filename, -1, NULL, &length, NULL); in create_long_filename()
410 fprintf(stderr, "vvfat: invalid UTF-8 name: %s\n", filename); in create_long_filename()
417 entry=array_get_next(&(s->directory)); in create_long_filename()
418 entry->attributes=0xf; in create_long_filename()
419 entry->reserved[0]=0; in create_long_filename()
420 entry->begin=0; in create_long_filename()
421 entry->name[0]=(number_of_entries-i)|(i==0?0x40:0); in create_long_filename()
426 else if(offset<22) offset=14+offset-10; in create_long_filename()
427 else offset=28+offset-22; in create_long_filename()
428 entry=array_get(&(s->directory),s->directory.next-1-(i/26)); in create_long_filename()
430 entry->name[offset] = 0xff; in create_long_filename()
432 entry->name[offset] = longname[i / 2] & 0xff; in create_long_filename()
434 entry->name[offset] = longname[i / 2] >> 8; in create_long_filename()
438 return array_get(&(s->directory),s->directory.next-number_of_entries); in create_long_filename()
443 return direntry->name[0] == DIR_DELETED || direntry->name[0] == DIR_FREE; in is_free()
448 return direntry->attributes == 0x28; in is_volume_label()
453 return direntry->attributes == 0xf; in is_long_name()
464 return direntry->attributes & 0x10 && direntry->name[0] != DIR_DELETED; in is_directory()
469 return is_short_name(direntry) && direntry->name[0] == '.'; in is_dot()
479 return le16_to_cpu(direntry->begin)|(le16_to_cpu(direntry->begin_hi)<<16); in begin_of_direntry()
484 return le32_to_cpu(direntry->size); in filesize_of_direntry()
489 direntry->begin = cpu_to_le16(begin & 0xffff); in set_begin_of_direntry()
490 direntry->begin_hi = cpu_to_le16((begin >> 16) & 0xffff); in set_begin_of_direntry()
504 strchr(" $%'-_@~`!(){}^#&.+,;=[]", c) != NULL)) in valid_filename()
517 strchr("$%'-_@~`!(){}^#&", c) != NULL) { in to_valid_short_char()
529 direntry_t *entry = array_get_next(&(s->directory)); in create_short_filename()
538 memset(entry->name, 0x20, sizeof(entry->name)); in create_short_filename()
559 entry->name[j++] = v; in create_short_filename()
577 entry->name[8 + (j++)] = v; in create_short_filename()
585 if (entry->name[0] == DIR_KANJI) { in create_short_filename()
586 entry->name[0] = DIR_KANJI_FAKE; in create_short_filename()
589 /* numeric-tail generation */ in create_short_filename()
591 if (entry->name[j] == ' ') { in create_short_filename()
600 memcpy(entry->name + MIN(j, 8 - len), tail, len); in create_short_filename()
602 for (entry1 = array_get(&(s->directory), directory_start); in create_short_filename()
605 !memcmp(entry1->name, entry->name, 11)) { in create_short_filename()
624 for (i = 0; i < ARRAY_SIZE(entry->name); i++) { in fat_chksum()
626 ((chksum & 0x01) ? 0x80 : 0)) + entry->name[i]; in fat_chksum()
639 return cpu_to_le16((t->tm_sec/2)|(t->tm_min<<5)|(t->tm_hour<<11)); in fat_datetime()
640 return cpu_to_le16((t->tm_mday)|((t->tm_mon+1)<<5)|((t->tm_year-80)<<9)); in fat_datetime()
645 if(s->fat_type==32) { in fat_set()
646 uint32_t* entry=array_get(&(s->fat),cluster); in fat_set()
648 } else if(s->fat_type==16) { in fat_set()
649 uint16_t* entry=array_get(&(s->fat),cluster); in fat_set()
653 unsigned char* p = array_get(&(s->fat), offset); in fat_set()
669 if(s->fat_type==32) { in fat_get()
670 uint32_t* entry=array_get(&(s->fat),cluster); in fat_get()
672 } else if(s->fat_type==16) { in fat_get()
673 uint16_t* entry=array_get(&(s->fat),cluster); in fat_get()
676 const uint8_t* x=(uint8_t*)(s->fat.pointer)+cluster*3/2; in fat_get()
683 if(fat_entry>s->max_fat_value-8) in fat_eof()
684 return -1; in fat_eof()
690 if (s->fat_type == 12) { in init_fat()
691 array_init(&(s->fat),1); in init_fat()
692 array_ensure_allocated(&(s->fat), in init_fat()
693 s->sectors_per_fat * 0x200 * 3 / 2 - 1); in init_fat()
695 array_init(&(s->fat),(s->fat_type==32?4:2)); in init_fat()
696 array_ensure_allocated(&(s->fat), in init_fat()
697 s->sectors_per_fat * 0x200 / s->fat.item_size - 1); in init_fat()
699 memset(s->fat.pointer,0,s->fat.size); in init_fat()
701 switch(s->fat_type) { in init_fat()
702 case 12: s->max_fat_value=0xfff; break; in init_fat()
703 case 16: s->max_fat_value=0xffff; break; in init_fat()
704 case 32: s->max_fat_value=0x0fffffff; break; in init_fat()
705 default: s->max_fat_value=0; /* error... */ in init_fat()
713 int long_index = s->directory.next; in create_short_and_long_name()
718 entry=array_get_next(&(s->directory)); in create_short_and_long_name()
719 memset(entry->name, 0x20, sizeof(entry->name)); in create_short_and_long_name()
720 memcpy(entry->name,filename,strlen(filename)); in create_short_and_long_name()
732 entry_long=array_get(&(s->directory),long_index); in create_short_and_long_name()
734 entry_long->reserved[1]=chksum; in create_short_and_long_name()
747 mapping_t* mapping = array_get(&(s->mapping), mapping_index); in read_directory()
749 const char* dirname = mapping->path; in read_directory()
750 int first_cluster = mapping->begin; in read_directory()
751 int parent_index = mapping->info.dir.parent_mapping_index; in read_directory()
753 (parent_index >= 0 ? array_get(&(s->mapping), parent_index) : NULL); in read_directory()
754 int first_cluster_of_parent = parent_mapping ? parent_mapping->begin : -1; in read_directory()
760 assert(mapping->mode & MODE_DIRECTORY); in read_directory()
763 mapping->end = mapping->begin; in read_directory()
764 return -1; in read_directory()
767 i = mapping->info.dir.first_dir_index = in read_directory()
768 first_cluster == 0 ? 0 : s->directory.next; in read_directory()
778 unsigned int length=strlen(dirname)+2+strlen(entry->d_name); in read_directory()
781 int is_dot=!strcmp(entry->d_name,"."); in read_directory()
782 int is_dotdot=!strcmp(entry->d_name,".."); in read_directory()
784 if (first_cluster == 0 && s->directory.next >= s->root_entries - 1) { in read_directory()
787 return -2; in read_directory()
794 snprintf(buffer,length,"%s/%s",dirname,entry->d_name); in read_directory()
803 direntry = create_short_and_long_name(s, i, entry->d_name, 0); in read_directory()
805 direntry = array_get(&(s->directory), is_dot ? i : i + 1); in read_directory()
807 direntry->attributes=(S_ISDIR(st.st_mode)?0x10:0x20); in read_directory()
808 direntry->reserved[0]=direntry->reserved[1]=0; in read_directory()
809 direntry->ctime=fat_datetime(st.st_ctime,1); in read_directory()
810 direntry->cdate=fat_datetime(st.st_ctime,0); in read_directory()
811 direntry->adate=fat_datetime(st.st_atime,0); in read_directory()
812 direntry->begin_hi=0; in read_directory()
813 direntry->mtime=fat_datetime(st.st_mtime,1); in read_directory()
814 direntry->mdate=fat_datetime(st.st_mtime,0); in read_directory()
820 direntry->begin=0; /* do that later */ in read_directory()
825 return -2; in read_directory()
827 direntry->size=cpu_to_le32(S_ISDIR(st.st_mode)?0:st.st_size); in read_directory()
831 s->current_mapping = array_get_next(&(s->mapping)); in read_directory()
832 s->current_mapping->begin=0; in read_directory()
833 s->current_mapping->end=st.st_size; in read_directory()
838 s->current_mapping->dir_index=s->directory.next-1; in read_directory()
839 s->current_mapping->first_mapping_index = -1; in read_directory()
841 s->current_mapping->mode = MODE_DIRECTORY; in read_directory()
842 s->current_mapping->info.dir.parent_mapping_index = in read_directory()
845 s->current_mapping->mode = MODE_UNDEFINED; in read_directory()
846 s->current_mapping->info.file.offset = 0; in read_directory()
848 s->current_mapping->path=buffer; in read_directory()
849 s->current_mapping->read_only = in read_directory()
858 while(s->directory.next%(0x10*s->sectors_per_cluster)) { in read_directory()
859 direntry = array_get_next(&(s->directory)); in read_directory()
863 if (s->fat_type != 32 && in read_directory()
865 s->directory.next < s->root_entries) { in read_directory()
867 int cur = s->directory.next; in read_directory()
868 array_ensure_allocated(&(s->directory), s->root_entries - 1); in read_directory()
869 s->directory.next = s->root_entries; in read_directory()
870 memset(array_get(&(s->directory), cur), 0, in read_directory()
871 (s->root_entries - cur) * sizeof(direntry_t)); in read_directory()
874 /* re-get the mapping, since s->mapping was possibly realloc()ed */ in read_directory()
875 mapping = array_get(&(s->mapping), mapping_index); in read_directory()
876 first_cluster += (s->directory.next - mapping->info.dir.first_dir_index) in read_directory()
877 * 0x20 / s->cluster_size; in read_directory()
878 mapping->end = first_cluster; in read_directory()
880 direntry = array_get(&(s->directory), mapping->dir_index); in read_directory()
881 set_begin_of_direntry(direntry, mapping->begin); in read_directory()
888 return (sector_num - s->offset_to_root_dir) / s->sectors_per_cluster; in sector2cluster()
893 return s->offset_to_root_dir + s->sectors_per_cluster * cluster_num; in cluster2sector()
905 memset(&(s->first_sectors[0]),0,0x40*0x200); in init_directories()
907 s->cluster_size=s->sectors_per_cluster*0x200; in init_directories()
908 s->cluster_buffer=g_malloc(s->cluster_size); in init_directories()
911 * The formula: sc = spf+1+spf*spc*(512*8/fat_type), in init_directories()
912 * where sc is sector_count, in init_directories()
917 i = 1+s->sectors_per_cluster*0x200*8/s->fat_type; in init_directories()
918 s->sectors_per_fat=(s->sector_count+i)/i; /* round up */ in init_directories()
920 s->offset_to_fat = s->offset_to_bootsector + 1; in init_directories()
921 s->offset_to_root_dir = s->offset_to_fat + s->sectors_per_fat * 2; in init_directories()
923 array_init(&(s->mapping),sizeof(mapping_t)); in init_directories()
924 array_init(&(s->directory),sizeof(direntry_t)); in init_directories()
928 direntry_t* entry=array_get_next(&(s->directory)); in init_directories()
929 entry->attributes=0x28; /* archive | volume label */ in init_directories()
930 memcpy(entry->name, s->volume_label, sizeof(entry->name)); in init_directories()
937 s->root_entries = 0x02 * 0x10 * s->sectors_per_cluster; in init_directories()
938 s->cluster_count=sector2cluster(s, s->sector_count); in init_directories()
940 mapping = array_get_next(&(s->mapping)); in init_directories()
941 mapping->begin = 0; in init_directories()
942 mapping->dir_index = 0; in init_directories()
943 mapping->info.dir.parent_mapping_index = -1; in init_directories()
944 mapping->first_mapping_index = -1; in init_directories()
945 mapping->path = g_strdup(dirname); in init_directories()
946 i = strlen(mapping->path); in init_directories()
947 if (i > 0 && mapping->path[i - 1] == '/') in init_directories()
948 mapping->path[i - 1] = '\0'; in init_directories()
949 mapping->mode = MODE_DIRECTORY; in init_directories()
950 mapping->read_only = 0; in init_directories()
951 s->path = mapping->path; in init_directories()
953 for (i = 0, cluster = 0; i < s->mapping.next; i++) { in init_directories()
954 /* MS-DOS expects the FAT to be 0 for the root directory in init_directories()
958 mapping = array_get(&(s->mapping), i); in init_directories()
960 if (mapping->mode & MODE_DIRECTORY) { in init_directories()
961 char *path = mapping->path; in init_directories()
962 mapping->begin = cluster; in init_directories()
965 return -1; in init_directories()
967 mapping = array_get(&(s->mapping), i); in init_directories()
969 assert(mapping->mode == MODE_UNDEFINED); in init_directories()
970 mapping->mode=MODE_NORMAL; in init_directories()
971 mapping->begin = cluster; in init_directories()
972 if (mapping->end > 0) { in init_directories()
973 direntry_t* direntry = array_get(&(s->directory), in init_directories()
974 mapping->dir_index); in init_directories()
976 mapping->end = cluster + 1 + (mapping->end-1)/s->cluster_size; in init_directories()
977 set_begin_of_direntry(direntry, mapping->begin); in init_directories()
979 mapping->end = cluster + 1; in init_directories()
984 assert(mapping->begin < mapping->end); in init_directories()
987 cluster = mapping->end; in init_directories()
989 if(cluster > s->cluster_count) { in init_directories()
992 s->fat_type, s->sector_count / 2000.0); in init_directories()
993 return -1; in init_directories()
999 for(j = mapping->begin; j < mapping->end - 1; j++) in init_directories()
1001 fat_set(s, mapping->end - 1, s->max_fat_value); in init_directories()
1005 mapping = array_get(&(s->mapping), 0); in init_directories()
1006 s->last_cluster_of_root_directory = mapping->end; in init_directories()
1009 fat_set(s,0,s->max_fat_value); in init_directories()
1010 fat_set(s,1,s->max_fat_value); in init_directories()
1012 s->current_mapping = NULL; in init_directories()
1014 bootsector = (bootsector_t *)(s->first_sectors in init_directories()
1015 + s->offset_to_bootsector * 0x200); in init_directories()
1016 bootsector->jump[0]=0xeb; in init_directories()
1017 bootsector->jump[1]=0x3e; in init_directories()
1018 bootsector->jump[2]=0x90; in init_directories()
1019 memcpy(bootsector->name, BOOTSECTOR_OEM_NAME, 8); in init_directories()
1020 bootsector->sector_size=cpu_to_le16(0x200); in init_directories()
1021 bootsector->sectors_per_cluster=s->sectors_per_cluster; in init_directories()
1022 bootsector->reserved_sectors=cpu_to_le16(1); in init_directories()
1023 bootsector->number_of_fats=0x2; /* number of FATs */ in init_directories()
1024 bootsector->root_entries = cpu_to_le16(s->root_entries); in init_directories()
1025 bootsector->total_sectors16=s->sector_count>0xffff?0:cpu_to_le16(s->sector_count); in init_directories()
1027 bootsector->media_type = (s->offset_to_bootsector > 0 ? 0xf8 : 0xf0); in init_directories()
1028 s->fat.pointer[0] = bootsector->media_type; in init_directories()
1029 bootsector->sectors_per_fat=cpu_to_le16(s->sectors_per_fat); in init_directories()
1030 bootsector->sectors_per_track = cpu_to_le16(secs); in init_directories()
1031 bootsector->number_of_heads = cpu_to_le16(heads); in init_directories()
1032 bootsector->hidden_sectors = cpu_to_le32(s->offset_to_bootsector); in init_directories()
1033 bootsector->total_sectors=cpu_to_le32(s->sector_count>0xffff?s->sector_count:0); in init_directories()
1037 bootsector->u.fat16.drive_number = s->offset_to_bootsector == 0 ? 0 : 0x80; in init_directories()
1038 bootsector->u.fat16.signature=0x29; in init_directories()
1039 bootsector->u.fat16.id=cpu_to_le32(0xfabe1afd); in init_directories()
1041 memcpy(bootsector->u.fat16.volume_label, s->volume_label, in init_directories()
1042 sizeof(bootsector->u.fat16.volume_label)); in init_directories()
1043 memcpy(bootsector->u.fat16.fat_type, in init_directories()
1044 s->fat_type == 12 ? "FAT12 " : "FAT16 ", 8); in init_directories()
1045 bootsector->magic[0]=0x55; bootsector->magic[1]=0xaa; in init_directories()
1067 .name = "fat-type",
1121 i = strrchr(filename, ':') - filename; in vvfat_parse_filename()
1123 if (filename[i - 2] == ':' && qemu_isalpha(filename[i - 1])) { in vvfat_parse_filename()
1125 filename += i - 1; in vvfat_parse_filename()
1132 qdict_put_int(options, "fat-type", fat_type); in vvfat_parse_filename()
1140 BDRVVVFATState *s = bs->opaque; in vvfat_open()
1155 ret = -EINVAL; in vvfat_open()
1162 ret = -EINVAL; in vvfat_open()
1166 s->fat_type = qemu_opt_get_number(opts, "fat-type", 0); in vvfat_open()
1169 memset(s->volume_label, ' ', sizeof(s->volume_label)); in vvfat_open()
1175 ret = -EINVAL; in vvfat_open()
1178 memcpy(s->volume_label, label, label_length); in vvfat_open()
1180 memcpy(s->volume_label, "QEMU VVFAT", 10); in vvfat_open()
1185 if (!s->fat_type) { in vvfat_open()
1186 s->fat_type = 12; in vvfat_open()
1188 s->sectors_per_cluster = 2; in vvfat_open()
1190 secs = s->fat_type == 12 ? 18 : 36; in vvfat_open()
1191 s->sectors_per_cluster = 1; in vvfat_open()
1197 if (!s->fat_type) { in vvfat_open()
1198 s->fat_type = 16; in vvfat_open()
1200 s->offset_to_bootsector = 0x3f; in vvfat_open()
1201 cyls = s->fat_type == 12 ? 64 : 1024; in vvfat_open()
1206 switch (s->fat_type) { in vvfat_open()
1215 ret = -EINVAL; in vvfat_open()
1220 s->bs = bs; in vvfat_open()
1223 s->sectors_per_cluster=0x10; in vvfat_open()
1225 s->current_cluster=0xffffffff; in vvfat_open()
1227 s->qcow = NULL; in vvfat_open()
1228 s->qcow_filename = NULL; in vvfat_open()
1229 s->fat2 = NULL; in vvfat_open()
1230 s->downcase_short_names = 1; in vvfat_open()
1235 s->sector_count = cyls * heads * secs - s->offset_to_bootsector; in vvfat_open()
1236 bs->total_sectors = cyls * heads * secs; in vvfat_open()
1245 ret = -EPERM; in vvfat_open()
1247 "Unable to set VVFAT to 'rw' when drive is read-only"); in vvfat_open()
1258 ret = -EIO; in vvfat_open()
1262 s->sector_count = s->offset_to_root_dir in vvfat_open()
1263 + s->sectors_per_cluster * s->cluster_count; in vvfat_open()
1266 if (s->qcow) { in vvfat_open()
1267 error_setg(&s->migration_blocker, in vvfat_open()
1271 ret = migrate_add_blocker_normal(&s->migration_blocker, errp); in vvfat_open()
1277 if (s->offset_to_bootsector > 0) { in vvfat_open()
1281 qemu_co_mutex_init(&s->lock); in vvfat_open()
1288 g_free(s->qcow_filename); in vvfat_open()
1289 s->qcow_filename = NULL; in vvfat_open()
1290 g_free(s->cluster_buffer); in vvfat_open()
1291 s->cluster_buffer = NULL; in vvfat_open()
1292 g_free(s->used_clusters); in vvfat_open()
1293 s->used_clusters = NULL; in vvfat_open()
1301 bs->bl.request_alignment = BDRV_SECTOR_SIZE; /* No sub-sector I/O */ in vvfat_refresh_limits()
1306 if(s->current_mapping) { in vvfat_close_current_file()
1307 s->current_mapping = NULL; in vvfat_close_current_file()
1308 if (s->current_fd) { in vvfat_close_current_file()
1309 qemu_close(s->current_fd); in vvfat_close_current_file()
1310 s->current_fd = 0; in vvfat_close_current_file()
1313 s->current_cluster = -1; in vvfat_close_current_file()
1316 /* mappings between index1 and index2-1 are supposed to be ordered
1325 mapping=array_get(&(s->mapping),index3); in find_mapping_for_cluster_aux()
1326 assert(mapping->begin < mapping->end); in find_mapping_for_cluster_aux()
1327 if(mapping->begin>=cluster_num) { in find_mapping_for_cluster_aux()
1334 return mapping->end<=cluster_num ? index2 : index1; in find_mapping_for_cluster_aux()
1338 DLOG(mapping=array_get(&(s->mapping),index1); in find_mapping_for_cluster_aux()
1339 assert(mapping->begin<=cluster_num); in find_mapping_for_cluster_aux()
1340 assert(index2 >= s->mapping.next || in find_mapping_for_cluster_aux()
1341 ((mapping = array_get(&(s->mapping),index2)) && in find_mapping_for_cluster_aux()
1342 mapping->end>cluster_num))); in find_mapping_for_cluster_aux()
1348 int index=find_mapping_for_cluster_aux(s,cluster_num,0,s->mapping.next); in find_mapping_for_cluster()
1350 if(index>=s->mapping.next) in find_mapping_for_cluster()
1352 mapping=array_get(&(s->mapping),index); in find_mapping_for_cluster()
1353 if(mapping->begin>cluster_num) in find_mapping_for_cluster()
1355 assert(mapping->begin<=cluster_num && mapping->end>cluster_num); in find_mapping_for_cluster()
1362 return -1; in open_file()
1363 if(!s->current_mapping || in open_file()
1364 strcmp(s->current_mapping->path,mapping->path)) { in open_file()
1366 int fd = qemu_open_old(mapping->path, in open_file()
1369 return -1; in open_file()
1371 s->current_fd = fd; in open_file()
1374 s->current_mapping = mapping; in open_file()
1380 if(s->current_cluster != cluster_num) { in read_cluster()
1383 assert(!s->current_mapping || s->current_fd || (s->current_mapping->mode & MODE_DIRECTORY)); in read_cluster()
1384 if(!s->current_mapping in read_cluster()
1385 || s->current_mapping->begin>cluster_num in read_cluster()
1386 || s->current_mapping->end<=cluster_num) { in read_cluster()
1390 assert(!mapping || (cluster_num>=mapping->begin && cluster_num<mapping->end)); in read_cluster()
1392 if (mapping && mapping->mode & MODE_DIRECTORY) { in read_cluster()
1394 s->current_mapping = mapping; in read_cluster()
1396 offset = s->cluster_size*(cluster_num-s->current_mapping->begin); in read_cluster()
1397 s->cluster = (unsigned char*)s->directory.pointer+offset in read_cluster()
1398 + 0x20*s->current_mapping->info.dir.first_dir_index; in read_cluster()
1399 assert(((s->cluster-(unsigned char*)s->directory.pointer)%s->cluster_size)==0); in read_cluster()
1400 …assert((char*)s->cluster+s->cluster_size <= s->directory.pointer+s->directory.next*s->directory.it… in read_cluster()
1401 s->current_cluster = cluster_num; in read_cluster()
1406 return -2; in read_cluster()
1407 } else if (s->current_mapping->mode & MODE_DIRECTORY) in read_cluster()
1410 assert(s->current_fd); in read_cluster()
1412 offset = s->cluster_size * in read_cluster()
1413 ((cluster_num - s->current_mapping->begin) in read_cluster()
1414 + s->current_mapping->info.file.offset); in read_cluster()
1415 if(lseek(s->current_fd, offset, SEEK_SET)!=offset) in read_cluster()
1416 return -3; in read_cluster()
1417 s->cluster=s->cluster_buffer; in read_cluster()
1418 result=read(s->current_fd,s->cluster,s->cluster_size); in read_cluster()
1420 s->current_cluster = -1; in read_cluster()
1421 return -1; in read_cluster()
1423 s->current_cluster = cluster_num; in read_cluster()
1452 ADD_CHAR(direntry->name[i]); in print_direntry()
1456 direntry->attributes, in print_direntry()
1457 begin_of_direntry(direntry),le32_to_cpu(direntry->size)); in print_direntry()
1465 mapping, mapping->begin, mapping->end, mapping->dir_index, in print_mapping()
1466 mapping->first_mapping_index, mapping->path, mapping->mode); in print_mapping()
1468 if (mapping->mode & MODE_DIRECTORY) in print_mapping()
1469 …ent_mapping_index = %d, first_dir_index = %d\n", mapping->info.dir.parent_mapping_index, mapping->… in print_mapping()
1471 fprintf(stderr, "offset = %u\n", mapping->info.file.offset); in print_mapping()
1478 BDRVVVFATState *s = bs->opaque; in vvfat_read()
1482 if (sector_num >= bs->total_sectors) in vvfat_read()
1483 return -1; in vvfat_read()
1484 if (s->qcow) { in vvfat_read()
1487 ret = bdrv_co_is_allocated(s->qcow->bs, sector_num * BDRV_SECTOR_SIZE, in vvfat_read()
1488 (nb_sectors - i) * BDRV_SECTOR_SIZE, &n); in vvfat_read()
1496 if (bdrv_co_pread(s->qcow, sector_num * BDRV_SECTOR_SIZE, n, in vvfat_read()
1498 return -1; in vvfat_read()
1500 i += (n >> BDRV_SECTOR_BITS) - 1; in vvfat_read()
1501 sector_num += (n >> BDRV_SECTOR_BITS) - 1; in vvfat_read()
1507 if (sector_num < s->offset_to_root_dir) { in vvfat_read()
1508 if (sector_num < s->offset_to_fat) { in vvfat_read()
1510 &(s->first_sectors[sector_num * 0x200]), in vvfat_read()
1512 } else if (sector_num < s->offset_to_fat + s->sectors_per_fat) { in vvfat_read()
1514 &(s->fat.pointer[(sector_num in vvfat_read()
1515 - s->offset_to_fat) * 0x200]), in vvfat_read()
1517 } else if (sector_num < s->offset_to_root_dir) { in vvfat_read()
1519 &(s->fat.pointer[(sector_num - s->offset_to_fat in vvfat_read()
1520 - s->sectors_per_fat) * 0x200]), in vvfat_read()
1524 uint32_t sector = sector_num - s->offset_to_root_dir, in vvfat_read()
1525 sector_offset_in_cluster=(sector%s->sectors_per_cluster), in vvfat_read()
1526 cluster_num=sector/s->sectors_per_cluster; in vvfat_read()
1527 if(cluster_num > s->cluster_count || read_cluster(s, cluster_num) != 0) { in vvfat_read()
1528 /* LATER TODO: strict: return -1; */ in vvfat_read()
1532 memcpy(buf+i*0x200,s->cluster+sector_offset_in_cluster*0x200,0x200); in vvfat_read()
1543 BDRVVVFATState *s = bs->opaque; in vvfat_co_preadv()
1553 return -ENOMEM; in vvfat_co_preadv()
1556 qemu_co_mutex_lock(&s->lock); in vvfat_co_preadv()
1558 qemu_co_mutex_unlock(&s->lock); in vvfat_co_preadv()
1572 * new files and directories (in s->commits).
1605 DLOG(fprintf(stderr, "clear_commits (%u commits)\n", s->commits.next)); in clear_commits()
1606 for (i = 0; i < s->commits.next; i++) { in clear_commits()
1607 commit_t* commit = array_get(&(s->commits), i); in clear_commits()
1608 assert(commit->path || commit->action == ACTION_WRITEOUT); in clear_commits()
1609 if (commit->action != ACTION_WRITEOUT) { in clear_commits()
1610 assert(commit->path); in clear_commits()
1611 g_free(commit->path); in clear_commits()
1613 assert(commit->path == NULL); in clear_commits()
1615 s->commits.next = 0; in clear_commits()
1621 commit_t* commit = array_get_next(&(s->commits)); in schedule_rename()
1622 commit->path = new_path; in schedule_rename()
1623 commit->param.rename.cluster = cluster; in schedule_rename()
1624 commit->action = ACTION_RENAME; in schedule_rename()
1630 commit_t* commit = array_get_next(&(s->commits)); in schedule_writeout()
1631 commit->path = NULL; in schedule_writeout()
1632 commit->param.writeout.dir_index = dir_index; in schedule_writeout()
1633 commit->param.writeout.modified_offset = modified_offset; in schedule_writeout()
1634 commit->action = ACTION_WRITEOUT; in schedule_writeout()
1640 commit_t* commit = array_get_next(&(s->commits)); in schedule_new_file()
1641 commit->path = path; in schedule_new_file()
1642 commit->param.new_file.first_cluster = first_cluster; in schedule_new_file()
1643 commit->action = ACTION_NEW_FILE; in schedule_new_file()
1648 commit_t* commit = array_get_next(&(s->commits)); in schedule_mkdir()
1649 commit->path = path; in schedule_mkdir()
1650 commit->param.mkdir.cluster = cluster; in schedule_mkdir()
1651 commit->action = ACTION_MKDIR; in schedule_mkdir()
1668 lfn->sequence_number = lfn->len = 0; in lfn_init()
1669 lfn->checksum = 0x100; in lfn_init()
1684 lfn->sequence_number = pointer[0] & 0x3f; in parse_long_name()
1685 lfn->checksum = pointer[13]; in parse_long_name()
1686 lfn->name[0] = 0; in parse_long_name()
1687 lfn->name[lfn->sequence_number * 13] = 0; in parse_long_name()
1688 } else if ((pointer[0] & 0x3f) != --lfn->sequence_number) { in parse_long_name()
1690 return -1; in parse_long_name()
1691 } else if (pointer[13] != lfn->checksum) { in parse_long_name()
1693 return -2; in parse_long_name()
1696 return -3; in parse_long_name()
1699 offset = 13 * (lfn->sequence_number - 1); in parse_long_name()
1711 lfn->name2[offset + i] = c; in parse_long_name()
1716 lfn->len = offset + i; in parse_long_name()
1721 gchar *utf8 = g_utf16_to_utf8(lfn->name2, lfn->len, NULL, &olen, NULL); in parse_long_name()
1723 return -4; in parse_long_name()
1725 lfn->len = olen; in parse_long_name()
1726 memcpy(lfn->name, utf8, olen + 1); in parse_long_name()
1742 for (j = 7; j >= 0 && direntry->name[j] == ' '; j--); in parse_short_name()
1744 uint8_t c = direntry->name[i]; in parse_short_name()
1746 return -1; in parse_short_name()
1747 } else if (s->downcase_short_names) { in parse_short_name()
1748 lfn->name[i] = qemu_tolower(direntry->name[i]); in parse_short_name()
1750 lfn->name[i] = direntry->name[i]; in parse_short_name()
1754 for (j = 2; j >= 0 && direntry->name[8 + j] == ' '; j--) { in parse_short_name()
1757 lfn->name[i++] = '.'; in parse_short_name()
1758 lfn->name[i + j + 1] = '\0'; in parse_short_name()
1759 for (;j >= 0; j--) { in parse_short_name()
1760 uint8_t c = direntry->name[8 + j]; in parse_short_name()
1762 return -2; in parse_short_name()
1763 } else if (s->downcase_short_names) { in parse_short_name()
1764 lfn->name[i + j] = qemu_tolower(c); in parse_short_name()
1766 lfn->name[i + j] = c; in parse_short_name()
1770 lfn->name[i + j + 1] = '\0'; in parse_short_name()
1772 if (lfn->name[0] == DIR_KANJI_FAKE) { in parse_short_name()
1773 lfn->name[0] = DIR_KANJI; in parse_short_name()
1775 lfn->len = strlen((char*)lfn->name); in parse_short_name()
1783 if (cluster < s->last_cluster_of_root_directory) { in modified_fat_get()
1784 if (cluster + 1 == s->last_cluster_of_root_directory) in modified_fat_get()
1785 return s->max_fat_value; in modified_fat_get()
1790 if (s->fat_type==32) { in modified_fat_get()
1791 uint32_t* entry=((uint32_t*)s->fat2)+cluster; in modified_fat_get()
1793 } else if (s->fat_type==16) { in modified_fat_get()
1794 uint16_t* entry=((uint16_t*)s->fat2)+cluster; in modified_fat_get()
1797 const uint8_t* x=s->fat2+cluster*3/2; in modified_fat_get()
1808 if (s->qcow == NULL) { in cluster_was_modified()
1812 for (i = 0; !was_modified && i < s->sectors_per_cluster; i++) { in cluster_was_modified()
1813 was_modified = bdrv_co_is_allocated(s->qcow->bs, in cluster_was_modified()
1838 * The array s->used_clusters holds the states of the clusters. If it is
1865 * 15 -> 16, but now has 15 -> 32 -> 16), then the following happens: in get_cluster_count_for_direntry()
1867 * - do_commit will write the cluster into the file at the given in get_cluster_count_for_direntry()
1870 * - the cluster which is overwritten should be moved to a later in get_cluster_count_for_direntry()
1876 * contents of the clusters to-be-overwritten into the qcow. in get_cluster_count_for_direntry()
1894 if (s->qcow) { in get_cluster_count_for_direntry()
1902 assert(mapping->mode & MODE_DELETED); in get_cluster_count_for_direntry()
1903 mapping->mode &= ~MODE_DELETED; in get_cluster_count_for_direntry()
1905 basename = get_basename(mapping->path); in get_cluster_count_for_direntry()
1907 assert(mapping->mode & MODE_NORMAL); in get_cluster_count_for_direntry()
1922 if (s->qcow) { in get_cluster_count_for_direntry()
1925 mapping->begin > cluster_num || in get_cluster_count_for_direntry()
1926 mapping->end <= cluster_num) in get_cluster_count_for_direntry()
1931 (mapping->mode & MODE_DIRECTORY) == 0) { in get_cluster_count_for_direntry()
1934 if (offset != s->cluster_size in get_cluster_count_for_direntry()
1935 * ((cluster_num - mapping->begin) in get_cluster_count_for_direntry()
1936 + mapping->info.file.offset)) { in get_cluster_count_for_direntry()
1941 const char* basename = get_basename(mapping->path); in get_cluster_count_for_direntry()
1946 assert(mapping->first_mapping_index == -1 in get_cluster_count_for_direntry()
1947 || mapping->info.file.offset > 0); in get_cluster_count_for_direntry()
1952 schedule_writeout(s, mapping->dir_index, offset); in get_cluster_count_for_direntry()
1966 for (i = 0; i < s->sectors_per_cluster; i++) { in get_cluster_count_for_direntry()
1969 res = bdrv_co_is_allocated(s->qcow->bs, in get_cluster_count_for_direntry()
1973 return -1; in get_cluster_count_for_direntry()
1976 res = vvfat_read(s->bs, offs, s->cluster_buffer, 1); in get_cluster_count_for_direntry()
1978 return -1; in get_cluster_count_for_direntry()
1980 res = bdrv_co_pwrite(s->qcow, offs * BDRV_SECTOR_SIZE, in get_cluster_count_for_direntry()
1981 BDRV_SECTOR_SIZE, s->cluster_buffer, in get_cluster_count_for_direntry()
1984 return -2; in get_cluster_count_for_direntry()
1992 if (s->used_clusters[cluster_num] & USED_ANY) in get_cluster_count_for_direntry()
1994 s->used_clusters[cluster_num] = USED_FILE; in get_cluster_count_for_direntry()
2000 else if (cluster_num < 2 || cluster_num > s->max_fat_value - 16) in get_cluster_count_for_direntry()
2001 return -1; in get_cluster_count_for_direntry()
2003 offset += s->cluster_size; in get_cluster_count_for_direntry()
2016 unsigned char* cluster = g_malloc(s->cluster_size); in check_directory_consistency()
2030 const char* basename = get_basename(mapping->path); in check_directory_consistency()
2033 assert(mapping->mode & MODE_DIRECTORY); in check_directory_consistency()
2035 assert(mapping->mode & MODE_DELETED); in check_directory_consistency()
2036 mapping->mode &= ~MODE_DELETED; in check_directory_consistency()
2051 if (s->used_clusters[cluster_num] & USED_ANY) { in check_directory_consistency()
2055 s->used_clusters[cluster_num] = USED_DIRECTORY; in check_directory_consistency()
2058 subret = vvfat_read(s->bs, cluster2sector(s, cluster_num), cluster, in check_directory_consistency()
2059 s->sectors_per_cluster); in check_directory_consistency()
2067 for (i = 0; i < 0x10 * s->sectors_per_cluster; i++) { in check_directory_consistency()
2103 pstrcpy(path2 + path_len + 1, sizeof(path2) - path_len - 1, in check_directory_consistency()
2121 DIV_ROUND_UP(le32_to_cpu(direntries[i].size), s->cluster_size)) { in check_directory_consistency()
2147 * - get modified FAT in is_consistent()
2148 * - compare the two FATs (TODO) in is_consistent()
2149 * - get buffer for marking used clusters in is_consistent()
2150 * - recurse direntries from root (using bs->bdrv_pread to make in is_consistent()
2152 * - check that the FAT agrees with the size in is_consistent()
2153 * - count the number of clusters occupied by this directory and in is_consistent()
2155 * - check that the cumulative used cluster count agrees with the in is_consistent()
2157 * - if all is fine, return number of used clusters in is_consistent()
2159 if (s->fat2 == NULL) { in is_consistent()
2160 int size = 0x200 * s->sectors_per_fat; in is_consistent()
2161 s->fat2 = g_malloc(size); in is_consistent()
2162 memcpy(s->fat2, s->fat.pointer, size); in is_consistent()
2164 check = vvfat_read(s->bs, in is_consistent()
2165 s->offset_to_fat, s->fat2, s->sectors_per_fat); in is_consistent()
2170 assert (s->used_clusters); in is_consistent()
2171 for (i = 0; i < sector2cluster(s, s->sector_count); i++) in is_consistent()
2172 s->used_clusters[i] &= ~USED_ANY; in is_consistent()
2178 if (s->qcow) in is_consistent()
2179 for (i = 0; i < s->mapping.next; i++) { in is_consistent()
2180 mapping_t* mapping = array_get(&(s->mapping), i); in is_consistent()
2181 if (mapping->first_mapping_index < 0) in is_consistent()
2182 mapping->mode |= MODE_DELETED; in is_consistent()
2185 used_clusters_count = check_directory_consistency(s, 0, s->path); in is_consistent()
2191 check = s->last_cluster_of_root_directory; in is_consistent()
2192 for (i = check; i < sector2cluster(s, s->sector_count); i++) { in is_consistent()
2194 if(!s->used_clusters[i]) { in is_consistent()
2201 if (s->used_clusters[i] == USED_ALLOCATED) { in is_consistent()
2219 for (i = 0; i < s->mapping.next; i++) { in adjust_mapping_indices()
2220 mapping_t* mapping = array_get(&(s->mapping), i); in adjust_mapping_indices()
2223 if (mapping->name >= offset) \ in adjust_mapping_indices()
2224 mapping->name += adjust in adjust_mapping_indices()
2227 if (mapping->mode & MODE_DIRECTORY) in adjust_mapping_indices()
2237 * - find mapping where mapping->begin >= begin, in insert_mapping()
2238 * - if mapping->begin > begin: insert in insert_mapping()
2239 * - adjust all references to mappings! in insert_mapping()
2240 * - else: adjust in insert_mapping()
2241 * - replace name in insert_mapping()
2243 int index = find_mapping_for_cluster_aux(s, begin, 0, s->mapping.next); in insert_mapping()
2245 mapping_t* first_mapping = array_get(&(s->mapping), 0); in insert_mapping()
2247 if (index < s->mapping.next && (mapping = array_get(&(s->mapping), index)) in insert_mapping()
2248 && mapping->begin < begin) { in insert_mapping()
2249 mapping->end = begin; in insert_mapping()
2251 mapping = array_get(&(s->mapping), index); in insert_mapping()
2253 if (index >= s->mapping.next || mapping->begin > begin) { in insert_mapping()
2254 mapping = array_insert(&(s->mapping), index, 1); in insert_mapping()
2255 mapping->path = NULL; in insert_mapping()
2259 mapping->begin = begin; in insert_mapping()
2260 mapping->end = end; in insert_mapping()
2263 assert(index + 1 >= s->mapping.next || in insert_mapping()
2264 ((next_mapping = array_get(&(s->mapping), index + 1)) && in insert_mapping()
2265 next_mapping->begin >= end))); in insert_mapping()
2267 if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer) in insert_mapping()
2268 s->current_mapping = array_get(&(s->mapping), in insert_mapping()
2269 s->current_mapping - first_mapping); in insert_mapping()
2276 mapping_t* mapping = array_get(&(s->mapping), mapping_index); in remove_mapping()
2277 mapping_t* first_mapping = array_get(&(s->mapping), 0); in remove_mapping()
2280 if (mapping->first_mapping_index < 0) { in remove_mapping()
2281 g_free(mapping->path); in remove_mapping()
2284 /* remove from s->mapping */ in remove_mapping()
2285 array_remove(&(s->mapping), mapping_index); in remove_mapping()
2288 adjust_mapping_indices(s, mapping_index, -1); in remove_mapping()
2290 if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer) in remove_mapping()
2291 s->current_mapping = array_get(&(s->mapping), in remove_mapping()
2292 s->current_mapping - first_mapping); in remove_mapping()
2300 for (i = 0; i < s->mapping.next; i++) { in adjust_dirindices()
2301 mapping_t* mapping = array_get(&(s->mapping), i); in adjust_dirindices()
2302 if (mapping->dir_index >= offset) in adjust_dirindices()
2303 mapping->dir_index += adjust; in adjust_dirindices()
2304 if ((mapping->mode & MODE_DIRECTORY) && in adjust_dirindices()
2305 mapping->info.dir.first_dir_index >= offset) in adjust_dirindices()
2306 mapping->info.dir.first_dir_index += adjust; in adjust_dirindices()
2314 * make room in s->directory, in insert_direntries()
2317 direntry_t* result = array_insert(&(s->directory), dir_index, count); in insert_direntries()
2326 int ret = array_remove_slice(&(s->directory), dir_index, count); in remove_direntries()
2329 adjust_dirindices(s, dir_index, -count); in remove_direntries()
2336 * to the modified fat, and the corresponding entries in s->mapping are
2343 direntry_t* direntry = array_get(&(s->directory), dir_index); in commit_mappings()
2349 assert(mapping->begin == first_cluster); in commit_mappings()
2350 mapping->first_mapping_index = -1; in commit_mappings()
2351 mapping->dir_index = dir_index; in commit_mappings()
2352 mapping->mode = (dir_index <= 0 || is_directory(direntry)) ? in commit_mappings()
2362 if (c > mapping->end) { in commit_mappings()
2363 int index = array_index(&(s->mapping), mapping); in commit_mappings()
2364 int i, max_i = s->mapping.next - index; in commit_mappings()
2366 while (--i > 0) in commit_mappings()
2369 assert(mapping == array_get(&(s->mapping), s->mapping.next - 1) in commit_mappings()
2371 mapping->end = c; in commit_mappings()
2374 int i = find_mapping_for_cluster_aux(s, c1, 0, s->mapping.next); in commit_mappings()
2375 mapping_t* next_mapping = i >= s->mapping.next ? NULL : in commit_mappings()
2376 array_get(&(s->mapping), i); in commit_mappings()
2378 if (next_mapping == NULL || next_mapping->begin > c1) { in commit_mappings()
2379 int i1 = array_index(&(s->mapping), mapping); in commit_mappings()
2385 mapping = array_get(&(s->mapping), i1); in commit_mappings()
2388 next_mapping->dir_index = mapping->dir_index; in commit_mappings()
2389 next_mapping->first_mapping_index = in commit_mappings()
2390 mapping->first_mapping_index < 0 ? in commit_mappings()
2391 array_index(&(s->mapping), mapping) : in commit_mappings()
2392 mapping->first_mapping_index; in commit_mappings()
2393 next_mapping->path = mapping->path; in commit_mappings()
2394 next_mapping->mode = mapping->mode; in commit_mappings()
2395 next_mapping->read_only = mapping->read_only; in commit_mappings()
2396 if (mapping->mode & MODE_DIRECTORY) { in commit_mappings()
2397 next_mapping->info.dir.parent_mapping_index = in commit_mappings()
2398 mapping->info.dir.parent_mapping_index; in commit_mappings()
2399 next_mapping->info.dir.first_dir_index = in commit_mappings()
2400 mapping->info.dir.first_dir_index + in commit_mappings()
2401 0x10 * s->sectors_per_cluster * in commit_mappings()
2402 (mapping->end - mapping->begin); in commit_mappings()
2404 next_mapping->info.file.offset = mapping->info.file.offset + in commit_mappings()
2405 (mapping->end - mapping->begin); in commit_mappings()
2419 direntry_t* direntry = array_get(&(s->directory), dir_index); in commit_direntries()
2422 int factor = 0x10 * s->sectors_per_cluster; in commit_direntries()
2431 assert(mapping->begin == first_cluster); in commit_direntries()
2432 assert(mapping->info.dir.first_dir_index < s->directory.next); in commit_direntries()
2433 assert(mapping->mode & MODE_DIRECTORY); in commit_direntries()
2437 mapping->path, parent_mapping_index)); in commit_direntries()
2439 current_dir_index = mapping->info.dir.first_dir_index; in commit_direntries()
2441 mapping->info.dir.parent_mapping_index = parent_mapping_index; in commit_direntries()
2445 s->last_cluster_of_root_directory; in commit_direntries()
2459 factor * (new_cluster_count - old_cluster_count)) == NULL) in commit_direntries()
2460 return -1; in commit_direntries()
2464 factor * (old_cluster_count - new_cluster_count)); in commit_direntries()
2469 direntry = array_get(&(s->directory), current_dir_index); in commit_direntries()
2470 ret = vvfat_read(s->bs, cluster2sector(s, c), (uint8_t *)direntry, in commit_direntries()
2471 s->sectors_per_cluster); in commit_direntries()
2476 first_direntry = (direntry_t*) s->directory.pointer; in commit_direntries()
2477 assert(!memcmp(first_direntry->name, s->volume_label, 11)); in commit_direntries()
2488 direntry = array_get(&(s->directory), first_dir_index + i); in commit_direntries()
2492 return -1; in commit_direntries()
2494 assert(mapping->mode & MODE_DIRECTORY); in commit_direntries()
2496 array_index(&(s->mapping), mapping)); in commit_direntries()
2510 direntry_t* direntry = array_get(&(s->directory), dir_index); in commit_one_file()
2520 assert((offset % s->cluster_size) == 0); in commit_one_file()
2523 return -1; in commit_one_file()
2526 for (i = 0; i < offset; i += s->cluster_size) { in commit_one_file()
2530 fd = qemu_open_old(mapping->path, O_RDWR | O_CREAT | O_BINARY, 0666); in commit_one_file()
2532 fprintf(stderr, "Could not open %s... (%s, %d)\n", mapping->path, in commit_one_file()
2539 return -3; in commit_one_file()
2543 cluster = g_malloc(s->cluster_size); in commit_one_file()
2547 int rest_size = (size - offset > s->cluster_size ? in commit_one_file()
2548 s->cluster_size : size - offset); in commit_one_file()
2553 assert((size - offset == 0 && fat_eof(s, c)) || in commit_one_file()
2556 ret = vvfat_read(s->bs, cluster2sector(s, c), in commit_one_file()
2568 return -2; in commit_one_file()
2579 return -4; in commit_one_file()
2592 for (i = 0; i < s->mapping.next; i++) { in check1()
2593 mapping_t* mapping = array_get(&(s->mapping), i); in check1()
2594 if (mapping->mode & MODE_DELETED) { in check1()
2598 assert(mapping->dir_index < s->directory.next); in check1()
2599 direntry_t* direntry = array_get(&(s->directory), mapping->dir_index); in check1()
2600 assert(mapping->begin == begin_of_direntry(direntry) || mapping->first_mapping_index >= 0); in check1()
2601 if (mapping->mode & MODE_DIRECTORY) { in check1()
2602 …assert(mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster * (mapping->end - mapping… in check1()
2603 assert((mapping->info.dir.first_dir_index % (0x10 * s->sectors_per_cluster)) == 0); in check1()
2612 int first_mapping = -1; in check2()
2614 for (i = 0; i < s->directory.next; i++) { in check2()
2615 direntry_t* direntry = array_get(&(s->directory), i); in check2()
2620 assert(mapping->dir_index == i || is_dot(direntry)); in check2()
2621 assert(mapping->begin == begin_of_direntry(direntry) || is_dot(direntry)); in check2()
2624 if ((i % (0x10 * s->sectors_per_cluster)) == 0) { in check2()
2628 for (j = 0; j < s->mapping.next; j++) { in check2()
2629 mapping_t* mapping = array_get(&(s->mapping), j); in check2()
2630 if (mapping->mode & MODE_DELETED) in check2()
2632 if (mapping->mode & MODE_DIRECTORY) { in check2()
2633 …if (mapping->info.dir.first_dir_index <= i && mapping->info.dir.first_dir_index + 0x10 * s->sector… in check2()
2635 if (mapping->first_mapping_index == -1) in check2()
2636 first_mapping = array_index(&(s->mapping), mapping); in check2()
2638 assert(first_mapping == mapping->first_mapping_index); in check2()
2639 if (mapping->info.dir.parent_mapping_index < 0) in check2()
2642 … mapping_t* parent = array_get(&(s->mapping), mapping->info.dir.parent_mapping_index); in check2()
2643 assert(parent->mode & MODE_DIRECTORY); in check2()
2644 … assert(parent->info.dir.first_dir_index < mapping->info.dir.first_dir_index); in check2()
2650 first_mapping = -1; in check2()
2662 for (i = 0; i < s->commits.next; i++) { in handle_renames_and_mkdirs()
2663 commit_t* commit = array_get(&(s->commits), i); in handle_renames_and_mkdirs()
2665 commit->path ? commit->path : "(null)", in handle_renames_and_mkdirs()
2666 commit->param.rename.cluster, commit->action); in handle_renames_and_mkdirs()
2670 for (i = 0; i < s->commits.next;) { in handle_renames_and_mkdirs()
2671 commit_t* commit = array_get(&(s->commits), i); in handle_renames_and_mkdirs()
2672 if (commit->action == ACTION_RENAME) { in handle_renames_and_mkdirs()
2674 commit->param.rename.cluster); in handle_renames_and_mkdirs()
2678 return -1; in handle_renames_and_mkdirs()
2680 old_path = mapping->path; in handle_renames_and_mkdirs()
2681 assert(commit->path); in handle_renames_and_mkdirs()
2682 mapping->path = commit->path; in handle_renames_and_mkdirs()
2683 if (rename(old_path, mapping->path)) in handle_renames_and_mkdirs()
2684 return -2; in handle_renames_and_mkdirs()
2686 if (mapping->mode & MODE_DIRECTORY) { in handle_renames_and_mkdirs()
2687 int l1 = strlen(mapping->path); in handle_renames_and_mkdirs()
2689 int diff = l1 - l2; in handle_renames_and_mkdirs()
2690 direntry_t* direntry = array_get(&(s->directory), in handle_renames_and_mkdirs()
2691 mapping->info.dir.first_dir_index); in handle_renames_and_mkdirs()
2692 uint32_t c = mapping->begin; in handle_renames_and_mkdirs()
2706 return -1; in handle_renames_and_mkdirs()
2708 l = strlen(m->path); in handle_renames_and_mkdirs()
2711 assert(!strncmp(m->path, mapping->path, l2)); in handle_renames_and_mkdirs()
2713 pstrcpy(new_path, l + diff + 1, mapping->path); in handle_renames_and_mkdirs()
2714 pstrcpy(new_path + l1, l + diff + 1 - l1, in handle_renames_and_mkdirs()
2715 m->path + l2); in handle_renames_and_mkdirs()
2717 schedule_rename(s, m->begin, new_path); in handle_renames_and_mkdirs()
2720 } while (j % (0x10 * s->sectors_per_cluster) != 0); in handle_renames_and_mkdirs()
2726 array_remove(&(s->commits), i); in handle_renames_and_mkdirs()
2728 } else if (commit->action == ACTION_MKDIR) { in handle_renames_and_mkdirs()
2732 if (g_mkdir(commit->path, 0755)) { in handle_renames_and_mkdirs()
2733 return -5; in handle_renames_and_mkdirs()
2736 mapping = insert_mapping(s, commit->param.mkdir.cluster, in handle_renames_and_mkdirs()
2737 commit->param.mkdir.cluster + 1); in handle_renames_and_mkdirs()
2739 return -6; in handle_renames_and_mkdirs()
2741 mapping->mode = MODE_DIRECTORY; in handle_renames_and_mkdirs()
2742 mapping->read_only = 0; in handle_renames_and_mkdirs()
2743 mapping->path = commit->path; in handle_renames_and_mkdirs()
2744 j = s->directory.next; in handle_renames_and_mkdirs()
2746 insert_direntries(s, s->directory.next, in handle_renames_and_mkdirs()
2747 0x10 * s->sectors_per_cluster); in handle_renames_and_mkdirs()
2748 mapping->info.dir.first_dir_index = j; in handle_renames_and_mkdirs()
2750 parent_path_len = strlen(commit->path) in handle_renames_and_mkdirs()
2751 - strlen(get_basename(commit->path)) - 1; in handle_renames_and_mkdirs()
2752 for (j = 0; j < s->mapping.next; j++) { in handle_renames_and_mkdirs()
2753 mapping_t* m = array_get(&(s->mapping), j); in handle_renames_and_mkdirs()
2754 if (m->first_mapping_index < 0 && m != mapping && in handle_renames_and_mkdirs()
2755 !strncmp(m->path, mapping->path, parent_path_len) && in handle_renames_and_mkdirs()
2756 strlen(m->path) == parent_path_len) in handle_renames_and_mkdirs()
2759 assert(j < s->mapping.next); in handle_renames_and_mkdirs()
2760 mapping->info.dir.parent_mapping_index = j; in handle_renames_and_mkdirs()
2762 array_remove(&(s->commits), i); in handle_renames_and_mkdirs()
2780 for (i = 0; !fail && i < s->commits.next; i++) { in handle_commits()
2781 commit_t* commit = array_get(&(s->commits), i); in handle_commits()
2782 switch(commit->action) { in handle_commits()
2785 fail = -2; in handle_commits()
2788 direntry_t* entry = array_get(&(s->directory), in handle_commits()
2789 commit->param.writeout.dir_index); in handle_commits()
2794 assert(mapping->begin == begin); in handle_commits()
2795 assert(commit->path == NULL); in handle_commits()
2797 if (commit_one_file(s, commit->param.writeout.dir_index, in handle_commits()
2798 commit->param.writeout.modified_offset)) in handle_commits()
2799 fail = -3; in handle_commits()
2804 int begin = commit->param.new_file.first_cluster; in handle_commits()
2810 for (j = 0; j < s->directory.next; j++) { in handle_commits()
2811 entry = array_get(&(s->directory), j); in handle_commits()
2816 if (j >= s->directory.next) { in handle_commits()
2817 fail = -6; in handle_commits()
2822 if (mapping && mapping->begin != begin) { in handle_commits()
2823 mapping->end = begin; in handle_commits()
2830 assert(commit->path); in handle_commits()
2831 mapping->path = commit->path; in handle_commits()
2832 mapping->read_only = 0; in handle_commits()
2833 mapping->mode = MODE_NORMAL; in handle_commits()
2834 mapping->info.file.offset = 0; in handle_commits()
2837 fail = -7; in handle_commits()
2846 if (i > 0 && array_remove_slice(&(s->commits), 0, i)) in handle_commits()
2847 return -1; in handle_commits()
2856 /* handle DELETEs and unused mappings (modified_fat_get(s, mapping->begin) == 0) */ in handle_deletes()
2861 for (i = 1; i < s->mapping.next; i++) { in handle_deletes()
2862 mapping_t* mapping = array_get(&(s->mapping), i); in handle_deletes()
2863 if (mapping->mode & MODE_DELETED) { in handle_deletes()
2864 direntry_t* entry = array_get(&(s->directory), in handle_deletes()
2865 mapping->dir_index); in handle_deletes()
2869 if (mapping->mode & MODE_DIRECTORY) { in handle_deletes()
2870 int j, next_dir_index = s->directory.next, in handle_deletes()
2871 first_dir_index = mapping->info.dir.first_dir_index; in handle_deletes()
2873 if (rmdir(mapping->path) < 0) { in handle_deletes()
2878 return -5; in handle_deletes()
2881 for (j = 1; j < s->mapping.next; j++) { in handle_deletes()
2882 mapping_t* m = array_get(&(s->mapping), j); in handle_deletes()
2883 if (m->mode & MODE_DIRECTORY && in handle_deletes()
2884 m->info.dir.first_dir_index > in handle_deletes()
2886 m->info.dir.first_dir_index < in handle_deletes()
2889 m->info.dir.first_dir_index; in handle_deletes()
2892 next_dir_index - first_dir_index); in handle_deletes()
2897 if (unlink(mapping->path)) in handle_deletes()
2898 return -4; in handle_deletes()
2913 * - copy FAT (with bdrv_pread)
2914 * - mark all filenames corresponding to mappings as deleted
2915 * - recurse direntries from root (using bs->bdrv_pread)
2916 * - delete files corresponding to mappings marked as deleted
2923 if (s->commits.next == 0) in do_commit()
2936 memcpy(s->fat.pointer, s->fat2, 0x200 * s->sectors_per_fat); in do_commit()
2938 /* recurse direntries from root (using bs->bdrv_pread) */ in do_commit()
2939 ret = commit_direntries(s, 0, -1); in do_commit()
2960 bdrv_make_empty(s->qcow, NULL); in do_commit()
2962 memset(s->used_clusters, 0, sector2cluster(s, s->sector_count)); in do_commit()
2973 return -1; in try_commit()
2981 BDRVVVFATState *s = bs->opaque; in vvfat_write()
2987 /* Check if we're operating in read-only mode */ in vvfat_write()
2988 if (s->qcow == NULL) { in vvfat_write()
2989 return -EACCES; in vvfat_write()
2994 if (sector_num == s->offset_to_bootsector && nb_sectors == 1) { in vvfat_write()
2999 unsigned char *bootsector = s->first_sectors in vvfat_write()
3000 + s->offset_to_bootsector * 0x200; in vvfat_write()
3010 return -1; in vvfat_write()
3021 * - do not allow writing to the boot sector in vvfat_write()
3023 if (sector_num < s->offset_to_fat) in vvfat_write()
3024 return -1; in vvfat_write()
3031 last_cluster = sector2cluster(s, sector_num + nb_sectors - 1); in vvfat_write()
3041 if (mapping->read_only) { in vvfat_write()
3042 fprintf(stderr, "Tried to write to write-protected file %s\n", in vvfat_write()
3043 mapping->path); in vvfat_write()
3044 return -1; in vvfat_write()
3047 if (mapping->mode & MODE_DIRECTORY) { in vvfat_write()
3049 int end = begin + s->sectors_per_cluster, k; in vvfat_write()
3060 dir_index = mapping->dir_index + in vvfat_write()
3061 0x10 * (begin - mapping->begin * s->sectors_per_cluster); in vvfat_write()
3062 direntries = (direntry_t*)(buf + 0x200 * (begin - sector_num)); in vvfat_write()
3064 for (k = 0; k < (end - begin) * 0x10; k++) { in vvfat_write()
3065 /* no access to the direntry of a read-only file */ in vvfat_write()
3069 array_get(&(s->directory), dir_index + k), in vvfat_write()
3071 warn_report("tried to write to write-protected " in vvfat_write()
3073 return -1; in vvfat_write()
3078 i = mapping->end; in vvfat_write()
3088 ret = bdrv_co_pwrite(s->qcow, sector_num * BDRV_SECTOR_SIZE, in vvfat_write()
3097 s->used_clusters[i] |= USED_ALLOCATED; in vvfat_write()
3114 BDRVVVFATState *s = bs->opaque; in vvfat_co_pwritev()
3124 return -ENOMEM; in vvfat_co_pwritev()
3128 qemu_co_mutex_lock(&s->lock); in vvfat_co_pwritev()
3130 qemu_co_mutex_unlock(&s->lock); in vvfat_co_pwritev()
3160 BDRVVVFATState *s = bs->opaque; in enable_write_target()
3164 int size = sector2cluster(s, s->sector_count); in enable_write_target()
3167 s->used_clusters = g_malloc0(size); in enable_write_target()
3169 array_init(&(s->commits), sizeof(commit_t)); in enable_write_target()
3171 s->qcow_filename = create_tmp_file(errp); in enable_write_target()
3172 if (!s->qcow_filename) { in enable_write_target()
3173 ret = -ENOENT; in enable_write_target()
3180 ret = -ENOENT; in enable_write_target()
3184 opts = qemu_opts_create(bdrv_qcow->create_opts, NULL, 0, &error_abort); in enable_write_target()
3186 bs->total_sectors * BDRV_SECTOR_SIZE, &error_abort); in enable_write_target()
3189 ret = bdrv_create(bdrv_qcow, s->qcow_filename, opts, errp); in enable_write_target()
3196 qdict_put_str(options, "write-target.driver", "qcow"); in enable_write_target()
3197 s->qcow = bdrv_open_child(s->qcow_filename, options, "write-target", bs, in enable_write_target()
3202 if (!s->qcow) { in enable_write_target()
3203 ret = -EINVAL; in enable_write_target()
3208 unlink(s->qcow_filename); in enable_write_target()
3231 BDRVVVFATState *s = bs->opaque; in vvfat_close()
3234 array_free(&(s->fat)); in vvfat_close()
3235 array_free(&(s->directory)); in vvfat_close()
3236 array_free(&(s->mapping)); in vvfat_close()
3237 g_free(s->cluster_buffer); in vvfat_close()
3239 if (s->qcow) { in vvfat_close()
3240 migrate_del_blocker(&s->migration_blocker); in vvfat_close()
3246 "fat-type",
3284 assert(((mapping_t*)array_get(&(vvv->mapping), 0))->end == 2); in checkpoint()
3287 … assert(!vvv->current_mapping || vvv->current_fd || (vvv->current_mapping->mode & MODE_DIRECTORY)); in checkpoint()