/** Get cluster from the first FAT. * * @param bs Buffer holding the boot sector for the file system. * @param service_id Service ID for the file system. * @param clst Cluster which to get. * @param value Output argument holding the value of the cluster. * * @return EOK or a negative error code. */ static int fat_get_cluster_fat12(fat_bs_t *bs, service_id_t service_id, unsigned fatno, fat_cluster_t clst, fat_cluster_t *value) { block_t *b, *b1; uint16_t byte1, byte2; aoff64_t offset; int rc; offset = (clst + clst / 2); if (offset / BPS(bs) >= SF(bs)) return ERANGE; rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno + offset / BPS(bs), BLOCK_FLAGS_NONE); if (rc != EOK) return rc; byte1 = ((uint8_t *) b->data)[offset % BPS(bs)]; /* This cluster access spans a sector boundary. Check only for FAT12 */ if ((offset % BPS(bs)) + 1 == BPS(bs)) { /* Is this the last sector of FAT? */ if (offset / BPS(bs) < SF(bs)) { /* No, read the next sector */ rc = block_get(&b1, service_id, 1 + RSCNT(bs) + SF(bs) * fatno + offset / BPS(bs), BLOCK_FLAGS_NONE); if (rc != EOK) { block_put(b); return rc; } /* * Combining value with last byte of current sector and * first byte of next sector */ byte2 = ((uint8_t*) b1->data)[0]; rc = block_put(b1); if (rc != EOK) { block_put(b); return rc; } } else { /* Yes. This is the last sector of FAT */ block_put(b); return ERANGE; } } else byte2 = ((uint8_t *) b->data)[(offset % BPS(bs)) + 1]; *value = uint16_t_le2host(byte1 | (byte2 << 8)); if (IS_ODD(clst)) *value = (*value) >> 4; else
void print_inode_data(ext2_filesystem_t *fs, ext2_inode_t *inode, uint32_t data) { int rc; uint32_t data_block_index; block_t *block; rc = ext2_filesystem_get_inode_data_block_index(fs, inode, data, &data_block_index); if (rc != EOK) { printf("Failed getting data block #%u\n", data); return; } printf("Data for inode contents block #%u is located in filesystem " "block %u\n", data, data_block_index); printf("Data preview (only printable characters):\n"); rc = block_get(&block, fs->device, data_block_index, 0); if (rc != EOK) { printf("Failed reading filesystem block %u\n", data_block_index); return; } print_data(block->data, block->size); printf("\n"); rc = block_put(block); if (rc != EOK) { printf("Failed putting filesystem block\n"); } }
/* **************************************************************** * Encerra o uso das entradas da tabela "disktb" * **************************************************************** */ int disktb_close_entry (dev_t dev) { DISKTB *up; int i; BHEAD *bp; /* * Obtém a partição inicial do dispositivo */ if ((up = disktb_get_first_entry (dev)) == NODISKTB) return (-1); /* * Força a releitura da tabela de partições */ bp = block_get (up->p_dev, 0, 0); #ifdef DEBUG printf ("%v: O bloco 0 == %d\n", up->p_dev, EVENTTEST (&bp->b_done)); #endif DEBUG EVENTCLEAR (&bp->b_done); block_put (bp); /* * Encerra as entradas */ for (i = 0; i < 2; i++, up++) { /*** up->p_name = ...; ***/ up->p_offset = 0; up->p_size = BL4SZ / BLSZ; /* Provisório, para ler a "parttb" */ /*** up->p_dev = ...; ***/ /*** up->p_unit = ...; ***/ /*** up->p_target = ...; ***/ up->p_type = 0; up->p_flags = 0; up->p_head = 0; up->p_sect = 0; up->p_cyl = 0; if (up->p_nopen != 0) { printf ( "%s: p_nopen residual: %d\n", up->p_name, up->p_nopen ); } up->p_nopen = 0; up->p_lock = 0; } return (0); } /* end disktb_close_entry */
static int fat_node_sync(fat_node_t *node) { block_t *b; fat_bs_t *bs; fat_dentry_t *d; int rc; assert(node->dirty); bs = block_bb_get(node->idx->service_id); /* Read the block that contains the dentry of interest. */ rc = _fat_block_get(&b, bs, node->idx->service_id, node->idx->pfc, NULL, (node->idx->pdi * sizeof(fat_dentry_t)) / BPS(bs), BLOCK_FLAGS_NONE); if (rc != EOK) return rc; d = ((fat_dentry_t *)b->data) + (node->idx->pdi % DPS(bs)); d->firstc = host2uint16_t_le(node->firstc); if (node->type == FAT_FILE) { d->size = host2uint32_t_le(node->size); } else if (node->type == FAT_DIRECTORY) { d->attr = FAT_ATTR_SUBDIR; } /* TODO: update other fields? (e.g time fields) */ b->dirty = true; /* need to sync block */ rc = block_put(b); return rc; }
static int fat_directory_block_load(fat_directory_t *di) { uint32_t i; int rc; i = (di->pos * sizeof(fat_dentry_t)) / BPS(di->bs); if (i < di->blocks) { if (di->b && di->bnum != i) { block_put(di->b); di->b = NULL; } if (!di->b) { rc = fat_block_get(&di->b, di->bs, di->nodep, i, BLOCK_FLAGS_NONE); if (rc != EOK) { di->b = NULL; return rc; } di->bnum = i; } return EOK; } return ENOENT; }
/* **************************************************************** * Certifica-se de que o sistema de arquivos é V7 * **************************************************************** */ int v7_authen (dev_t dev) { BHEAD *bp; int status = -1; DISKTB *up; /* * Confere a assinatura mágica */ u.u_error = NOERR; bp = bread (dev, V7_SBNO, 0); if (u.u_error) /* vazio */; elif (ENDIAN_LONG (((V7SB *)bp->b_addr)->s_magic) != V7_SBMAGIC) u.u_error = ENOTFS; elif (status = 0, (up = disktb_get_entry (dev)) != NODISKTB && up->p_type == 0) up->p_type = PAR_TROPIX_V7; block_put (bp); return (status); } /* end v7_authen */
int exfat_bitmap_set_cluster(exfat_bs_t *bs, service_id_t service_id, exfat_cluster_t clst) { fs_node_t *fn; block_t *b = NULL; exfat_node_t *bitmapp; uint8_t *bitmap; int rc; clst -= EXFAT_CLST_FIRST; rc = exfat_bitmap_get(&fn, service_id); if (rc != EOK) return rc; bitmapp = EXFAT_NODE(fn); aoff64_t offset = clst / 8; rc = exfat_block_get(&b, bs, bitmapp, offset / BPS(bs), BLOCK_FLAGS_NONE); if (rc != EOK) { (void) exfat_node_put(fn); return rc; } bitmap = (uint8_t *)b->data; bitmap[offset % BPS(bs)] |= (1 << (clst % 8)); b->dirty = true; rc = block_put(b); if (rc != EOK) { (void) exfat_node_put(fn); return rc; } return exfat_node_put(fn); }
static ssize_t block_write(struct cdev *cdev, const void *buf, size_t count, unsigned long offset, ulong flags) { struct block_device *blk = cdev->priv; unsigned long mask = BLOCKSIZE(blk) - 1; unsigned long block = offset >> blk->blockbits; size_t icount = count; int blocks; if (offset & mask) { size_t now = BLOCKSIZE(blk) - (offset & mask); void *iobuf = block_get(blk, block); now = min(count, now); if (IS_ERR(iobuf)) return PTR_ERR(iobuf); memcpy(iobuf + (offset & mask), buf, now); block_put(blk, iobuf, block); buf += now; count -= now; block++; } blocks = count >> blk->blockbits; while (blocks) { block_put(blk, buf, block); buf += BLOCKSIZE(blk); blocks--; block++; count -= BLOCKSIZE(blk); } if (count) { void *iobuf = block_get(blk, block); if (IS_ERR(iobuf)) return PTR_ERR(iobuf); memcpy(iobuf, buf, count); block_put(blk, iobuf, block); } return icount; }
int fat_directory_close(fat_directory_t *di) { int rc = EOK; if (di->b) rc = block_put(di->b); return rc; }
/** Fill the gap between EOF and a new file position. * * @param bs Buffer holding the boot sector for nodep. * @param nodep FAT node with the gap. * @param mcl First cluster in an independent cluster chain that will * be later appended to the end of the node's own cluster * chain. If pos is still in the last allocated cluster, * this argument is ignored. * @param pos Position in the last node block. * * @return EOK on success or a negative error code. */ int fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, aoff64_t pos) { block_t *b; aoff64_t o, boundary; int rc; boundary = ROUND_UP(nodep->size, BPS(bs) * SPC(bs)); /* zero out already allocated space */ for (o = nodep->size; o < pos && o < boundary; o = ALIGN_DOWN(o + BPS(bs), BPS(bs))) { int flags = (o % BPS(bs) == 0) ? BLOCK_FLAGS_NOREAD : BLOCK_FLAGS_NONE; rc = fat_block_get(&b, bs, nodep, o / BPS(bs), flags); if (rc != EOK) return rc; memset(b->data + o % BPS(bs), 0, BPS(bs) - o % BPS(bs)); b->dirty = true; /* need to sync node */ rc = block_put(b); if (rc != EOK) return rc; } if (o >= pos) return EOK; /* zero out the initial part of the new cluster chain */ for (o = boundary; o < pos; o += BPS(bs)) { rc = _fat_block_get(&b, bs, nodep->idx->service_id, mcl, NULL, (o - boundary) / BPS(bs), BLOCK_FLAGS_NOREAD); if (rc != EOK) return rc; memset(b->data, 0, min(BPS(bs), pos - o)); b->dirty = true; /* need to sync node */ rc = block_put(b); if (rc != EOK) return rc; } return EOK; }
/* if the added stuff does not fit on current page, write it out after page break and change buffer handling mode to pass though */ void buffer_eob(int eot) { block_put(); if (epsf) { if (epsf == 3) write_eps(); /* close the image */ return; } if (remy + bposy >= 0 || multicol_start != 0) return; // page full if (!in_page) { if ((cfmt.splittune == 2 && !(nbpages & 1)) || (cfmt.splittune == 3 && (nbpages & 1))) { // wrong odd/even page if (remy + maxy + bposy < 0) { // 2nd overflow init_page(); close_page(); write_buffer(); return; } if (eot) write_buffer(); return; } } else { close_page(); } if ((cfmt.splittune == 2 && !(nbpages & 1)) || (cfmt.splittune == 3 && (nbpages & 1))) use_buffer = 1; // if wrong odd/even page else write_buffer(); #if 0 --- old if (use_buffer && !eot && ((cfmt.splittune == 2 && !(nbpages & 1)) || (cfmt.splittune == 3 && (nbpages & 1)))) { init_page(); // 8.7.4 use_buffer = 1; } else { // 8.7.5 - required to avoid buffer overflow write_buffer(); } //8.7.0 // write_buffer(); //8.6.2 // use_buffer = 0; #endif }
static int udf_match(fs_node_t **rfn, fs_node_t *pfn, const char *component) { char *name = malloc(MAX_FILE_NAME_LEN + 1); if (name == NULL) return ENOMEM; block_t *block = NULL; udf_file_identifier_descriptor_t *fid = NULL; size_t pos = 0; while (udf_get_fid(&fid, &block, UDF_NODE(pfn), pos) == EOK) { udf_long_ad_t long_ad = fid->icb; udf_to_unix_name(name, MAX_FILE_NAME_LEN, (char *) fid->implementation_use + FLE16(fid->lenght_iu), fid->lenght_file_id, &UDF_NODE(pfn)->instance->charset); if (stricmp(name, component) == 0) { int rc = udf_node_get(rfn, udf_service_get(pfn), udf_long_ad_to_pos(UDF_NODE(pfn)->instance, &long_ad)); if (block != NULL) block_put(block); free(name); return rc; } if (block != NULL) { int rc = block_put(block); if (rc != EOK) return rc; } pos++; } free(name); return ENOENT; }
/** Set cluster in FAT. * * @param bs Buffer holding the boot sector for the file system. * @param service_id Service ID for the file system. * @param clst Cluster which is to be set. * @param value Value to set the cluster with. * * @return EOK on success or a negative error code. */ int exfat_set_cluster(exfat_bs_t *bs, service_id_t service_id, exfat_cluster_t clst, exfat_cluster_t value) { block_t *b; aoff64_t offset; int rc; offset = clst * sizeof(exfat_cluster_t); rc = block_get(&b, service_id, FAT_FS(bs) + offset / BPS(bs), BLOCK_FLAGS_NONE); if (rc != EOK) return rc; *(uint32_t *)(b->data + offset % BPS(bs)) = host2uint32_t_le(value); b->dirty = true; /* need to sync block */ rc = block_put(b); return rc; }
/** Get cluster from the FAT. * * @param bs Buffer holding the boot sector for the file system. * @param service_id Service ID for the file system. * @param clst Cluster which to get. * @param value Output argument holding the value of the cluster. * * @return EOK or a negative error code. */ int exfat_get_cluster(exfat_bs_t *bs, service_id_t service_id, exfat_cluster_t clst, exfat_cluster_t *value) { block_t *b; aoff64_t offset; int rc; offset = clst * sizeof(exfat_cluster_t); rc = block_get(&b, service_id, FAT_FS(bs) + offset / BPS(bs), BLOCK_FLAGS_NONE); if (rc != EOK) return rc; *value = uint32_t_le2host(*(uint32_t *)(b->data + offset % BPS(bs))); rc = block_put(b); return rc; }
int exfat_zero_cluster(exfat_bs_t *bs, service_id_t service_id, exfat_cluster_t c) { size_t i; block_t *b; int rc; for (i = 0; i < SPC(bs); i++) { rc = exfat_block_get_by_clst(&b, bs, service_id, false, c, NULL, i, BLOCK_FLAGS_NOREAD); if (rc != EOK) return rc; memset(b->data, 0, BPS(bs)); b->dirty = true; rc = block_put(b); if (rc != EOK) return rc; } return EOK; }
int exfat_read_uctable(exfat_bs_t *bs, exfat_node_t *nodep, uint8_t *uctable) { size_t i, blocks, count; block_t *b; int rc; blocks = ROUND_UP(nodep->size, BPS(bs))/BPS(bs); count = BPS(bs); for (i = 0; i < blocks; i++) { rc = exfat_block_get(&b, bs, nodep, i, BLOCK_FLAGS_NOREAD); if (rc != EOK) return rc; if (i == blocks - 1) count = nodep->size - i * BPS(bs); memcpy(uctable, b->data, count); uctable += count; rc = block_put(b); if (rc != EOK) return rc; } return EOK; }
static int udf_read(service_id_t service_id, fs_index_t index, aoff64_t pos, size_t *rbytes) { udf_instance_t *instance; int rc = fs_instance_get(service_id, (void **) &instance); if (rc != EOK) return rc; fs_node_t *rfn; rc = udf_node_get(&rfn, service_id, index); if (rc != EOK) return rc; udf_node_t *node = UDF_NODE(rfn); ipc_callid_t callid; size_t len = 0; if (!async_data_read_receive(&callid, &len)) { async_answer_0(callid, EINVAL); udf_node_put(rfn); return EINVAL; } if (node->type == NODE_FILE) { if (pos >= node->data_size) { *rbytes = 0; async_data_read_finalize(callid, NULL, 0); udf_node_put(rfn); return EOK; } size_t read_len = 0; if (node->data == NULL) rc = udf_read_file(&read_len, callid, node, pos, len); else { /* File in allocation descriptors area */ read_len = (len < node->data_size) ? len : node->data_size; async_data_read_finalize(callid, node->data + pos, read_len); rc = EOK; } *rbytes = read_len; (void) udf_node_put(rfn); return rc; } else { block_t *block = NULL; udf_file_identifier_descriptor_t *fid = NULL; if (udf_get_fid(&fid, &block, node, pos) == EOK) { char *name = malloc(MAX_FILE_NAME_LEN + 1); // FIXME: Check for NULL return value udf_to_unix_name(name, MAX_FILE_NAME_LEN, (char *) fid->implementation_use + FLE16(fid->lenght_iu), fid->lenght_file_id, &node->instance->charset); async_data_read_finalize(callid, name, str_size(name) + 1); *rbytes = 1; free(name); udf_node_put(rfn); if (block != NULL) return block_put(block); return EOK; } else { *rbytes = 0; udf_node_put(rfn); async_answer_0(callid, ENOENT); return ENOENT; } } }
} } else { /* Yes. This is the last sector of FAT */ block_put(b); return ERANGE; } } else byte2 = ((uint8_t *) b->data)[(offset % BPS(bs)) + 1]; *value = uint16_t_le2host(byte1 | (byte2 << 8)); if (IS_ODD(clst)) *value = (*value) >> 4; else *value = (*value) & FAT12_MASK; rc = block_put(b); return rc; } /** Get cluster from the first FAT. * * @param bs Buffer holding the boot sector for the file system. * @param service_id Service ID for the file system. * @param clst Cluster which to get. * @param value Output argument holding the value of the cluster. * * @return EOK or a negative error code. */ static int fat_get_cluster_fat16(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
/* **************************************************************** * Operação de MOUNT * **************************************************************** */ int v7_mount (SB *sp) { BHEAD *bp; V7SB *v7sp; /* * Aloca a parte específica do V7SB */ if ((v7sp = malloc_byte (sizeof (V7SB))) == NOV7SB) { u.u_error = ENOMEM; return (-1); } bp = bread (sp->sb_dev, V7_SBNO, 0); if (u.u_error) { block_put (bp); goto out_6; } memmove (v7sp, bp->b_addr, sizeof (V7SB)); block_put (bp); #ifdef LITTLE_ENDIAN /* * Se for o caso, converte, ... */ v7_sb_endian_conversion (v7sp); #endif LITTLE_ENDIAN #define MOUNTCHK #ifdef MOUNTCHK /* * Verifica se é realmente um SB de um sistema de arquivos */ if (v7sp->s_magic != V7_SBMAGIC) { u.u_error = ENOTFS; goto out_6; } #endif MOUNTCHK /* * Verifica a validade das listas livres do SB */ if ((unsigned)v7sp->s_nfblk > V7_SBFBLK || (unsigned)v7sp->s_nfdino > V7_SBFDINO) { printf ("%g: Dispositivo \"%v\" com lista livre inválida\n", sp->sb_dev); u.u_error = ENOTFS; goto out_6; } /* * Atualiza as entradas do SB */ strcpy (sp->sb_fname, v7sp->s_fname); strcpy (sp->sb_fpack, v7sp->s_fpack); sp->sb_code = FS_V7; sp->sb_ptr = v7sp; sp->sb_root_ino = V7_ROOT_INO; /* * Inicializa as variáveis da V7 */ SLEEPCLEAR (&v7sp->s_flock); SLEEPCLEAR (&v7sp->s_ilock); return (0); /* * Em caso de ERRO */ out_6: free_byte (v7sp); return (-1); } /* end v7_mount */
/* **************************************************************** * Le as partições do volume e atualiza a "disktb" * **************************************************************** */ int disktb_open_entries (dev_t dev, const SCSI *sp) { DISKTB *up; BHEAD *bp; const PARTTB *reg_pp; HDINFO hdinfo; int reg_index; /* * Obtém a partição inicial do dispositivo */ if ((up = disktb_get_first_entry (dev)) == NODISKTB) return (-1); /* * Le o Bloco 0 do volume */ bp = bread (up->p_dev, 0, 0); if (bp->b_flags & B_ERROR) { block_put (bp); return (-1); } if (*(ushort *)(bp->b_addr + MAGIC_OFF) != 0xAA55) { printf ( "%s: O bloco 0 NÃO contém a assinatura \"0x55AA\"\n", up->p_name ); } /* * Tenta obter a geometria do disco */ geo_get_parttb_geo (up->p_name, bp->b_addr, &hdinfo, sp->scsi_disksz); /* * Processa (por enquanto) somente a primeira partição regular */ for ( reg_index = 0, reg_pp = (PARTTB *)(bp->b_addr + PARTB_OFF); /* abaixo */; reg_index++, reg_pp++ ) { if (reg_index >= NPART) { printf ( "%s: Volume NÃO tem partição regular\n", up->p_name ); u.u_error = ENXIO; block_put (bp); return (-1); } if (reg_pp->pt_size == 0) continue; if (!IS_EXT (reg_pp->pt_type)) break; printf ( "%s: Partição ESTENDIDA ignorada\n", up->p_name ); } /* * Completa a entrada do disco inteiro */ /*** up->p_offset = ...; ***/ up->p_size = sp->scsi_disksz; /*** up->p_type = 0; ***/ /*** up->p_flags = 0; ***/ /*** up->p_lock = 0; ***/ up->p_blshift = sp->scsi_blshift; /*** up->p_dev = ...; ***/ /*** up->p_unit = ...; ***/ /*** up->p_target = ...; ***/ up->p_head = hdinfo.h_head; up->p_sect = hdinfo.h_sect; up->p_cyl = hdinfo.h_cyl; /*** up->p_nopen = 0; ***/ /* * Prepara a entrada da partição regular */ up++; up->p_offset = reg_pp->pt_offset; up->p_size = reg_pp->pt_size; up->p_type = reg_pp->pt_type; up->p_flags = (reg_pp->pt_active == 0x80) ? DISK_ACTIVE : 0; /*** up->p_lock = 0; ***/ up->p_blshift = sp->scsi_blshift; /*** up->p_dev = ...; ***/ /*** up->p_unit = ...; ***/ /*** up->p_target = ...; ***/ up->p_head = hdinfo.h_head; up->p_sect = hdinfo.h_sect; up->p_cyl = hdinfo.h_cyl; /*** up->p_nopen = 0; ***/ block_put (bp); return (0); } /* end disktb_open_entries */
/* **************************************************************** * Lê as partições do volume e atualiza a "disktb" * **************************************************************** */ DISKTB * disktb_create_partitions (DISKTB *base_up) { DISKTB *up, *slot_up = NODISKTB; const DISKTB *end_up; dev_t dev; BHEAD *bp; const PARTTB *reg_pp, *log_pp; daddr_t log_offset, ext_begin, ext_end; int reg_index, log_index, minor_index = 1; int slot_sz, dec; HDINFO hdinfo; char area[BLSZ]; /* * A partição global do volume acabou de ser criada * * ("base_up" é idêntico a "next_disktb") * * Lê o Bloco 0 do volume e extrai a tabela de partições */ up = base_up; dev = up->p_dev; bp = bread (dev, 0, 0); if (bp->b_flags & B_ERROR) { block_put (bp); return (NODISKTB); } if (*(ushort *)(bp->b_addr + MAGIC_OFF) != 0xAA55) printf ("%s: O bloco 0 NÃO contém a assinatura \"0x55AA\"\n", up->p_name); memmove (area, bp->b_addr, BLSZ); block_put (bp); bp = NOBHEAD; /* * Tenta obter a geometria do volume */ geo_get_parttb_geo (up->p_name, area, &hdinfo, up->p_size); /* * Completa a entrada para o volume inteiro */ /*** up->p_name = ...; ***/ /*** up->p_offset = 0; ***/ /*** up->p_size = ...; ***/ /*** up->p_type = 0; ***/ /*** up->p_flags = 0; ***/ /*** up->p_lock = 0; ***/ /*** up->p_blshift = ...; ***/ /*** up->p_dev = ...; ***/ /*** up->p_unit = ...; ***/ /*** up->p_target = ...; ***/ up->p_head = hdinfo.h_head; up->p_sect = hdinfo.h_sect; up->p_cyl = hdinfo.h_cyl; /*** up->p_nopen = 0; ***/ /*** up->p_sb = NOSB; ***/ /*** up->p_inode = NOINODE; ***/ up++; /* * Processa todas as partições */ for (reg_pp = (PARTTB *)(area + PARTB_OFF), reg_index = 1; reg_index <= NPART; reg_index++, reg_pp++) { if (reg_pp->pt_size == 0) continue; /* Encontrou uma partição regular/estendida válida */ if (up >= end_disktb - 1) { printf ("%s: DISKTB cheia\n", base_up->p_name); break; } sprintf (up->p_name, "%s%d", base_up->p_name, reg_index); up->p_offset = reg_pp->pt_offset; up->p_size = reg_pp->pt_size; up->p_type = reg_pp->pt_type; up->p_flags = (reg_pp->pt_active == 0x80) ? DISK_ACTIVE : 0; /*** up->p_lock = 0; ***/ up->p_blshift = base_up->p_blshift; up->p_dev = dev + minor_index++; /* incrementa o MINOR */ up->p_unit = base_up->p_unit; up->p_target = base_up->p_target; up->p_head = hdinfo.h_head; up->p_sect = hdinfo.h_sect; up->p_cyl = hdinfo.h_cyl; /*** up->p_nopen = 0; ***/ /*** up->p_sb = NOSB; ***/ /*** up->p_inode = NOINODE; ***/ up++; if (!IS_EXT (reg_pp->pt_type)) continue; /* * Temos uma partição estendida */ ext_begin = reg_pp->pt_offset; ext_end = reg_pp->pt_offset + reg_pp->pt_size; log_offset = ext_begin; /* * Percorre a cadeia de partições lógicas */ for (log_index = 0; /* abaixo */; log_index++) { if (log_offset < ext_begin || log_offset >= ext_end) { printf ( "%s: Deslocamento %d inválido na partição estendida %d\n", base_up->p_name, log_offset, reg_index ); break; } if (bp != NOBHEAD) block_put (bp); bp = bread (dev, log_offset, 0); if (bp->b_flags & B_ERROR) { block_put (bp); bp = NOBHEAD; break; } if (*(ushort *)(bp->b_addr + MAGIC_OFF) != 0xAA55) { printf ( "%s: O bloco %d da partição estendida %d " "NÃO contém a assinatura \"0x55AA\"\n", base_up->p_name, log_offset, reg_index ); } log_pp = (PARTTB *)(bp->b_addr + PARTB_OFF); if (log_pp[0].pt_size == 0) /* Primeiro método de EOF */ break; /* Encontrou uma partição lógica válida */ if (up >= end_disktb - 1) { printf ("%s: DISKTB cheia\n", base_up->p_name); goto out; } sprintf (up->p_name, "%s%d%c", base_up->p_name, reg_index, 'a' + log_index); up->p_offset = log_offset + log_pp->pt_offset; up->p_size = log_pp->pt_size; up->p_type = log_pp->pt_type; up->p_flags = (log_pp->pt_active == 0x80) ? DISK_ACTIVE : 0; /*** up->p_lock = 0; ***/ up->p_blshift = base_up->p_blshift; up->p_dev = dev + minor_index++; /* incrementa o MINOR */ up->p_unit = base_up->p_unit; up->p_target = base_up->p_target; up->p_head = hdinfo.h_head; up->p_sect = hdinfo.h_sect; up->p_cyl = hdinfo.h_cyl; /*** up->p_nopen = 0; ***/ /*** up->p_sb = NOSB; ***/ /*** up->p_inode = NOINODE; ***/ up++; /* * Procura a partição seguinte */ if (log_pp[1].pt_size == 0) /* Segundo método de EOF */ break; log_offset = ext_begin + log_pp[1].pt_offset; } /* end for (cadeia de partições lógicas) */ } /* end for (partições regulares/estendeidas) */ out: if (bp != NOBHEAD) block_put (bp); /* * Atualiza o final da "disktb" */ next_disktb = up; up->p_name[0] = '\0'; /* * Neste ponto, "minor_index" contém o número de entradas total * * Procura um grupo de "minor_index" entradas vagas contíguas */ for (slot_sz = 0, up = disktb; /* abaixo */; up++) { if (up >= base_up) return (base_up); if (up->p_name[0] != '*') { slot_sz = 0; continue; } if (slot_sz++ == 0) slot_up = up; if (slot_sz >= minor_index) break; } /* * Encontrou um grupo adequado */ memmove (slot_up, base_up, minor_index * sizeof (DISKTB)); dec = base_up - slot_up; for (up = slot_up, end_up = up + minor_index; up < end_up; up++) up->p_dev -= dec; /* Supondo que o MINOR esteja na parte baixa */ memclr (base_up, minor_index * sizeof (DISKTB)); next_disktb = base_up; return (slot_up); } /* end disktb_create_partitions */