/* 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;
}
Example #2
0
/* 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;
}
Example #4
0
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;
}
Example #5
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;
}