/* msdos_find_node_by_cluster_num_in_fat_file -- * Find node with specified number of cluster in fat-file. * * PARAMETERS: * mt_entry - mount table entry * fat_fd - fat-file descriptor * cl4find - number of cluster to find * paux - identify a node location on the disk - * cluster num and offset inside the cluster * dir_entry - placeholder for found node * * RETURNS: * RC_OK on success, or error code if error occured * */ int msdos_find_node_by_cluster_num_in_fat_file( rtems_filesystem_mount_table_entry_t *mt_entry, fat_file_fd_t *fat_fd, uint32_t cl4find, fat_auxiliary_t *paux, char *dir_entry ) { int rc = RC_OK; ssize_t ret = 0; msdos_fs_info_t *fs_info = mt_entry->fs_info; uint32_t bts2rd = 0; uint32_t i = 0, j = 0; if (FAT_FD_OF_ROOT_DIR(fat_fd) && (fs_info->fat.vol.type & (FAT_FAT12 | FAT_FAT16))) bts2rd = fat_fd->fat_file_size; else bts2rd = fs_info->fat.vol.bpc; while ((ret = fat_file_read(mt_entry, fat_fd, j * bts2rd, bts2rd, fs_info->cl_buf)) != FAT_EOF) { if ( ret < MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE ) set_errno_and_return_minus_one( EIO ); assert(ret == bts2rd); for (i = 0; i < bts2rd; i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE) { /* if this and all rest entries are empty - return not-found */ if ((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) == MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY) return MSDOS_NAME_NOT_FOUND_ERR; /* have to look at the DIR_NAME as "raw" 8-bit data */ /* if this entry is empty - skip it */ if ((*(uint8_t *)MSDOS_DIR_NAME(fs_info->cl_buf + i)) == MSDOS_THIS_DIR_ENTRY_EMPTY) continue; /* if get a non-empty entry - compare clusters num */ if (MSDOS_EXTRACT_CLUSTER_NUM((fs_info->cl_buf + i)) == cl4find) { /* on success fill aux structure and copy all 32 bytes */ rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM, j * bts2rd, &paux->cln); if (rc != RC_OK) return rc; paux->ofs = i; memcpy(dir_entry, fs_info->cl_buf + i, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE); return RC_OK; } } j++; } return MSDOS_NAME_NOT_FOUND_ERR; }
/* fat_init_clusters_chain -- * Zeroing contents of all clusters in the chain * * PARAMETERS: * mt_entry - mount table entry * start_cluster_num - num of first cluster in the chain * * RETURNS: * RC_OK on success, or -1 if error occured * and errno set appropriately */ int fat_init_clusters_chain( rtems_filesystem_mount_table_entry_t *mt_entry, uint32_t start_cln ) { int rc = RC_OK; ssize_t ret = 0; register fat_fs_info_t *fs_info = mt_entry->fs_info; uint32_t cur_cln = start_cln; char *buf; buf = calloc(fs_info->vol.bpc, sizeof(char)); if ( buf == NULL ) set_errno_and_return_minus_one( EIO ); while ((cur_cln & fs_info->vol.mask) < fs_info->vol.eoc_val) { ret = fat_cluster_write(mt_entry, cur_cln, buf); if ( ret == -1 ) { free(buf); return -1; } rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln); if ( rc != RC_OK ) { free(buf); return rc; } } free(buf); return rc; }
/* msdos_find_name_in_fat_file -- * This routine is used in two ways: for a new mode creation (a) or for * search the node which correspondes to the 'name' parameter (b). * In case (a) name should be set up to NULL and 'name_dir_entry' should * point to initialized 32 bytes structure described a new node. * In case (b) 'name' should contain a valid string. * * (a): reading fat-file corresponded to directory we are going to create * node in. If found free slot write contents of name_dir_entry into * it. * * (b): reading fat-file corresponded to directory and trying to find slot * with the name field == name parameter * * PARAMETERS: * mt_entry - mount table entry * fat_fd - fat-file descriptor * name - NULL or name to find * paux - identify a node location on the disk - * number of cluster and offset inside the cluster * name_dir_entry - node to create/placeholder for found node * * RETURNS: * RC_OK on success, or error code if error occured (errno set * appropriately) * */ int msdos_find_name_in_fat_file( rtems_filesystem_mount_table_entry_t *mt_entry, fat_file_fd_t *fat_fd, char *name, fat_auxiliary_t *paux, char *name_dir_entry ) { int rc = RC_OK; ssize_t ret = 0; msdos_fs_info_t *fs_info = mt_entry->fs_info; uint32_t i = 0, j = 0; uint32_t bts2rd = 0; if (FAT_FD_OF_ROOT_DIR(fat_fd) && (fs_info->fat.vol.type & (FAT_FAT12 | FAT_FAT16))) bts2rd = fat_fd->fat_file_size; else bts2rd = fs_info->fat.vol.bpc; while ((ret = fat_file_read(mt_entry, fat_fd, (j * bts2rd), bts2rd, fs_info->cl_buf)) != FAT_EOF) { if (ret < MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE) set_errno_and_return_minus_one(EIO); assert(ret == bts2rd); /* have to look at the DIR_NAME as "raw" 8-bit data */ for (i = 0; i < bts2rd; i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE) { /* is the entry empty ? */ if (((*(uint8_t *)MSDOS_DIR_NAME(fs_info->cl_buf + i)) == MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY) || ((*(uint8_t *)MSDOS_DIR_NAME(fs_info->cl_buf + i)) == MSDOS_THIS_DIR_ENTRY_EMPTY)) { /* whether we are looking for an empty entry */ if (name == NULL) { /* get current cluster number */ rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM, j * bts2rd, &paux->cln); if (rc != RC_OK) return rc; /* offset is computed in bytes */ paux->ofs = i; /* write new node entry */ ret = fat_file_write(mt_entry, fat_fd, j * bts2rd + i, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE, (uint8_t *)name_dir_entry); if (ret != MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE) return -1; /* * we don't update fat_file_size here - it should not * increase */ return RC_OK; } /* * if name != NULL and there is no more entries in the * directory - return name-not-found */ if (((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) == MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY)) return MSDOS_NAME_NOT_FOUND_ERR; } else { /* entry not empty and name != NULL -> compare names */ if (name != NULL) { if (strncmp(MSDOS_DIR_NAME((fs_info->cl_buf + i)), name, MSDOS_SHORT_NAME_LEN) == 0) { /* * we get the entry we looked for - fill auxiliary * structure and copy all 32 bytes of the entry */ rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM, j * bts2rd, &paux->cln); if (rc != RC_OK) return rc; /* offset is computed in bytes */ paux->ofs = i; memcpy(name_dir_entry,(fs_info->cl_buf + i), MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE); return RC_OK; } } } } j++; } return MSDOS_NAME_NOT_FOUND_ERR; }
int _POSIX_Message_queue_Create_support( const char *name, int pshared, unsigned int oflag, struct mq_attr *attr_ptr, POSIX_Message_queue_Control **message_queue ) { POSIX_Message_queue_Control *the_mq; CORE_message_queue_Attributes *the_mq_attr; struct mq_attr attr; _Thread_Disable_dispatch(); /* * There is no real basis for the default values. They will work * but were not compared against any existing implementation for * compatibility. See README.mqueue for an example program we * think will print out the defaults. Report anything you find with it. */ if ( attr_ptr == NULL ) { attr.mq_maxmsg = 10; attr.mq_msgsize = 16; } else { if ( attr_ptr->mq_maxmsg < 0 ){ _Thread_Enable_dispatch(); set_errno_and_return_minus_one( EINVAL ); } if ( attr_ptr->mq_msgsize < 0 ){ _Thread_Enable_dispatch(); set_errno_and_return_minus_one( EINVAL ); } attr = *attr_ptr; } #if 0 && defined(RTEMS_MULTIPROCESSING) if ( pshared == PTHREAD_PROCESS_SHARED && !( _Objects_MP_Allocate_and_open( &_POSIX_Message_queue_Information, 0, the_mq->Object.id, FALSE ) ) ) { _POSIX_Message_queue_Free( the_mq ); _Thread_Enable_dispatch(); set_errno_and_return_minus_one( ENFILE ); } #endif the_mq = _POSIX_Message_queue_Allocate(); if ( !the_mq ) { _Thread_Enable_dispatch(); set_errno_and_return_minus_one( ENFILE ); } the_mq->process_shared = pshared; the_mq->oflag = oflag; the_mq->named = TRUE; the_mq->open_count = 1; the_mq->linked = TRUE; /* XXX * * Note that thread blocking discipline should be based on the * current scheduling policy. */ the_mq_attr = &the_mq->Message_queue.Attributes; the_mq_attr->discipline = CORE_MESSAGE_QUEUE_DISCIPLINES_FIFO; if ( ! _CORE_message_queue_Initialize( &the_mq->Message_queue, OBJECTS_POSIX_MESSAGE_QUEUES, the_mq_attr, attr.mq_maxmsg, attr.mq_msgsize, #if 0 && defined(RTEMS_MULTIPROCESSING) _POSIX_Message_queue_MP_Send_extract_proxy #else NULL #endif ) ) { #if 0 && defined(RTEMS_MULTIPROCESSING) if ( pshared == PTHREAD_PROCESS_SHARED ) _Objects_MP_Close( &_POSIX_Message_queue_Information, the_mq->Object.id ); #endif _POSIX_Message_queue_Free( the_mq ); _Thread_Enable_dispatch(); set_errno_and_return_minus_one( ENOSPC ); } _Objects_Open( &_POSIX_Message_queue_Information, &the_mq->Object, (char *) name ); *message_queue = the_mq; #if 0 && defined(RTEMS_MULTIPROCESSING) if ( pshared == PTHREAD_PROCESS_SHARED ) _POSIX_Message_queue_MP_Send_process_packet( POSIX_MESSAGE_QUEUE_MP_ANNOUNCE_CREATE, the_mq->Object.id, (char *) name, 0 /* Not used */ ); #endif _Thread_Enable_dispatch(); return 0; }
/* fat_init_volume_info -- * Get inforamtion about volume on which filesystem is mounted on * * PARAMETERS: * mt_entry - mount table entry * * RETURNS: * RC_OK on success, or -1 if error occured * and errno set appropriately */ int fat_init_volume_info(rtems_filesystem_mount_table_entry_t *mt_entry) { int rc = RC_OK; fat_fs_info_t *fs_info = mt_entry->fs_info; register fat_vol_t *vol = &fs_info->vol; uint32_t data_secs = 0; char boot_rec[FAT_MAX_BPB_SIZE]; char fs_info_sector[FAT_USEFUL_INFO_SIZE]; ssize_t ret = 0; int fd; struct stat stat_buf; int i = 0; rc = stat(mt_entry->dev, &stat_buf); if (rc == -1) return rc; /* rtmes feature: no block devices, all are character devices */ if (!S_ISCHR(stat_buf.st_mode)) set_errno_and_return_minus_one(ENOTBLK); /* check that device is registred as block device and lock it */ vol->dd = rtems_disk_lookup(stat_buf.st_dev); if (vol->dd == NULL) set_errno_and_return_minus_one(ENOTBLK); vol->dev = stat_buf.st_dev; fd = open(mt_entry->dev, O_RDONLY); if (fd == -1) { rtems_disk_release(vol->dd); return -1; } ret = read(fd, (void *)boot_rec, FAT_MAX_BPB_SIZE); if ( ret != FAT_MAX_BPB_SIZE ) { close(fd); rtems_disk_release(vol->dd); set_errno_and_return_minus_one( EIO ); } close(fd); vol->bps = FAT_GET_BR_BYTES_PER_SECTOR(boot_rec); if ( (vol->bps != 512) && (vol->bps != 1024) && (vol->bps != 2048) && (vol->bps != 4096)) { rtems_disk_release(vol->dd); set_errno_and_return_minus_one( EINVAL ); } for (vol->sec_mul = 0, i = (vol->bps >> FAT_SECTOR512_BITS); (i & 1) == 0; i >>= 1, vol->sec_mul++); for (vol->sec_log2 = 0, i = vol->bps; (i & 1) == 0; i >>= 1, vol->sec_log2++); vol->spc = FAT_GET_BR_SECTORS_PER_CLUSTER(boot_rec); /* * "sectors per cluster" of zero is invalid * (and would hang the following loop) */ if (vol->spc == 0) { rtems_disk_release(vol->dd); set_errno_and_return_minus_one(EINVAL); } for (vol->spc_log2 = 0, i = vol->spc; (i & 1) == 0; i >>= 1, vol->spc_log2++); /* * "bytes per cluster" value greater than 32K is invalid */ if ((vol->bpc = vol->bps << vol->spc_log2) > MS_BYTES_PER_CLUSTER_LIMIT) { rtems_disk_release(vol->dd); set_errno_and_return_minus_one(EINVAL); } for (vol->bpc_log2 = 0, i = vol->bpc; (i & 1) == 0; i >>= 1, vol->bpc_log2++); vol->fats = FAT_GET_BR_FAT_NUM(boot_rec); vol->fat_loc = FAT_GET_BR_RESERVED_SECTORS_NUM(boot_rec); vol->rdir_entrs = FAT_GET_BR_FILES_PER_ROOT_DIR(boot_rec); /* calculate the count of sectors occupied by the root directory */ vol->rdir_secs = ((vol->rdir_entrs * FAT_DIRENTRY_SIZE) + (vol->bps - 1)) / vol->bps; vol->rdir_size = vol->rdir_secs << vol->sec_log2; if ( (FAT_GET_BR_SECTORS_PER_FAT(boot_rec)) != 0) vol->fat_length = FAT_GET_BR_SECTORS_PER_FAT(boot_rec); else vol->fat_length = FAT_GET_BR_SECTORS_PER_FAT32(boot_rec); vol->data_fsec = vol->fat_loc + vol->fats * vol->fat_length + vol->rdir_secs; /* for FAT12/16 root dir starts at(sector) */ vol->rdir_loc = vol->fat_loc + vol->fats * vol->fat_length; if ( (FAT_GET_BR_TOTAL_SECTORS_NUM16(boot_rec)) != 0) vol->tot_secs = FAT_GET_BR_TOTAL_SECTORS_NUM16(boot_rec); else vol->tot_secs = FAT_GET_BR_TOTAL_SECTORS_NUM32(boot_rec); data_secs = vol->tot_secs - vol->data_fsec; vol->data_cls = data_secs / vol->spc; /* determine FAT type at least */ if ( vol->data_cls < FAT_FAT12_MAX_CLN) { vol->type = FAT_FAT12; vol->mask = FAT_FAT12_MASK; vol->eoc_val = FAT_FAT12_EOC; } else { if ( vol->data_cls < FAT_FAT16_MAX_CLN) { vol->type = FAT_FAT16; vol->mask = FAT_FAT16_MASK; vol->eoc_val = FAT_FAT16_EOC; } else { vol->type = FAT_FAT32; vol->mask = FAT_FAT32_MASK; vol->eoc_val = FAT_FAT32_EOC; } } if (vol->type == FAT_FAT32) { vol->rdir_cl = FAT_GET_BR_FAT32_ROOT_CLUSTER(boot_rec); vol->mirror = FAT_GET_BR_EXT_FLAGS(boot_rec) & FAT_BR_EXT_FLAGS_MIRROR; if (vol->mirror) vol->afat = FAT_GET_BR_EXT_FLAGS(boot_rec) & FAT_BR_EXT_FLAGS_FAT_NUM; else vol->afat = 0; vol->info_sec = FAT_GET_BR_FAT32_FS_INFO_SECTOR(boot_rec); if( vol->info_sec == 0 ) { rtems_disk_release(vol->dd); set_errno_and_return_minus_one( EINVAL ); } else { ret = _fat_block_read(mt_entry, vol->info_sec , 0, FAT_FSI_LEADSIG_SIZE, fs_info_sector); if ( ret < 0 ) { rtems_disk_release(vol->dd); return -1; } if (FAT_GET_FSINFO_LEAD_SIGNATURE(fs_info_sector) != FAT_FSINFO_LEAD_SIGNATURE_VALUE) { rtems_disk_release(vol->dd); set_errno_and_return_minus_one( EINVAL ); } else { ret = _fat_block_read(mt_entry, vol->info_sec , FAT_FSI_INFO, FAT_USEFUL_INFO_SIZE, fs_info_sector); if ( ret < 0 ) { rtems_disk_release(vol->dd); return -1; } vol->free_cls = FAT_GET_FSINFO_FREE_CLUSTER_COUNT(fs_info_sector); vol->next_cl = FAT_GET_FSINFO_NEXT_FREE_CLUSTER(fs_info_sector); rc = fat_fat32_update_fsinfo_sector(mt_entry, 0xFFFFFFFF, 0xFFFFFFFF); if ( rc != RC_OK ) { rtems_disk_release(vol->dd); return rc; } } } } else { vol->rdir_cl = 0; vol->mirror = 0; vol->afat = 0; vol->free_cls = 0xFFFFFFFF; vol->next_cl = 0xFFFFFFFF; } vol->afat_loc = vol->fat_loc + vol->fat_length * vol->afat; /* set up collection of fat-files fd */ fs_info->vhash = calloc(FAT_HASH_SIZE, sizeof(Chain_Control)); if ( fs_info->vhash == NULL ) { rtems_disk_release(vol->dd); set_errno_and_return_minus_one( ENOMEM ); } for (i = 0; i < FAT_HASH_SIZE; i++) _Chain_Initialize_empty(fs_info->vhash + i); fs_info->rhash = calloc(FAT_HASH_SIZE, sizeof(Chain_Control)); if ( fs_info->rhash == NULL ) { rtems_disk_release(vol->dd); free(fs_info->vhash); set_errno_and_return_minus_one( ENOMEM ); } for (i = 0; i < FAT_HASH_SIZE; i++) _Chain_Initialize_empty(fs_info->rhash + i); fs_info->uino_pool_size = FAT_UINO_POOL_INIT_SIZE; fs_info->uino_base = (vol->tot_secs << vol->sec_mul) << 4; fs_info->index = 0; fs_info->uino = (char *)calloc(fs_info->uino_pool_size, sizeof(char)); if ( fs_info->uino == NULL ) { rtems_disk_release(vol->dd); free(fs_info->vhash); free(fs_info->rhash); set_errno_and_return_minus_one( ENOMEM ); } fs_info->sec_buf = (uint8_t *)calloc(vol->bps, sizeof(uint8_t)); if (fs_info->sec_buf == NULL) { rtems_disk_release(vol->dd); free(fs_info->vhash); free(fs_info->rhash); free(fs_info->uino); set_errno_and_return_minus_one( ENOMEM ); } return RC_OK; }