Esempio n. 1
0
static int proc_readdir(struct fs_dirent_s *dir)
{
  FAR struct proc_dir_s *procdir;
  FAR const struct proc_node_s *node = NULL;
  FAR struct tcb_s *tcb;
  unsigned int index;
  irqstate_t flags;
  pid_t pid;
  int ret;

  DEBUGASSERT(dir != NULL && dir->u.procfs != NULL);
  procdir = dir->u.procfs;

  /* Have we reached the end of the directory */

  index = procdir->base.index;
  if (index >= procdir->base.nentries)
    {
      /* We signal the end of the directory by returning the special
       * error -ENOENT
       */

      finfo("Entry %d: End of directory\n", index);
      ret = -ENOENT;
    }

  /* No, we are not at the end of the directory */

  else
    {
      /* Verify that the pid still refers to an active task/thread */

      pid = procdir->pid;

      flags = enter_critical_section();
      tcb = sched_gettcb(pid);
      leave_critical_section(flags);

      if (tcb == NULL)
        {
          ferr("ERROR: PID %d is no longer valid\n", (int)pid);
          return -ENOENT;
        }

      /* The TCB is still valid (or at least was when we entered this function) */
      /* Handle the directory listing by the node type */

      switch (procdir->node->node)
        {
         case PROC_LEVEL0: /* Top level directory */
           DEBUGASSERT(procdir->base.level == 1);
           node = g_level0info[index];
           break;

         case PROC_GROUP:  /* Group sub-directory */
           DEBUGASSERT(procdir->base.level == 2);
           node = g_groupinfo[index];
           break;

         default:
           return -ENOENT;
        }

      /* Save the filename and file type */

      dir->fd_dir.d_type = node->dtype;
      strncpy(dir->fd_dir.d_name, node->name, NAME_MAX+1);

      /* Set up the next directory entry offset.  NOTE that we could use the
       * standard f_pos instead of our own private index.
       */

      procdir->base.index = index + 1;
      ret = OK;
    }

  return ret;
}
Esempio n. 2
0
File: debug.c Progetto: spott/dmd
void WReqn(elem *e)
{ static int nest;

  if (!e)
        return;
  if (OTunary(e->Eoper))
  {
        WROP(e->Eoper);
        if (OTbinary(e->E1->Eoper))
        {       nest++;
                ferr("(");
                WReqn(e->E1);
                ferr(")");
                nest--;
        }
        else
                WReqn(e->E1);
  }
  else if (e->Eoper == OPcomma && !nest)
  {     WReqn(e->E1);
        dbg_printf(";\n\t");
        WReqn(e->E2);
  }
  else if (OTbinary(e->Eoper))
  {
        if (OTbinary(e->E1->Eoper))
        {       nest++;
                ferr("(");
                WReqn(e->E1);
                ferr(")");
                nest--;
        }
        else
                WReqn(e->E1);
        ferr(" ");
        WROP(e->Eoper);
        if (e->Eoper == OPstreq)
            dbg_printf("%ld",(long)type_size(e->ET));
        ferr(" ");
        if (OTbinary(e->E2->Eoper))
        {       nest++;
                ferr("(");
                WReqn(e->E2);
                ferr(")");
                nest--;
        }
        else
                WReqn(e->E2);
  }
  else
  {
        switch (e->Eoper)
        {   case OPconst:
                switch (tybasic(e->Ety))
                {
                    case TYfloat:
                        dbg_printf("%g <float> ",e->EV.Vfloat);
                        break;
                    case TYdouble:
                        dbg_printf("%g ",e->EV.Vdouble);
                        break;
                    case TYldouble:
                        dbg_printf("%Lg ",e->EV.Vldouble);
                        break;
                    case TYcent:
                    case TYucent:
                        dbg_printf("%lld+%lld ", e->EV.Vcent.msw, e->EV.Vcent.lsw);
                        break;
                    default:
                        dbg_printf("%lld ",el_tolong(e));
                        break;
                }
                break;
            case OPrelconst:
                ferr("#");
                /* FALL-THROUGH */
            case OPvar:
                dbg_printf("%s",e->EV.sp.Vsym->Sident);
                if (e->EV.sp.Vsym->Ssymnum != -1)
                    dbg_printf("(%d)",e->EV.sp.Vsym->Ssymnum);
                if (e->Eoffset != 0)
                {
                    if (sizeof(e->Eoffset) == 8)
                        dbg_printf(".x%llx", e->Eoffset);
                    else
                        dbg_printf(".%ld",(long)e->Eoffset);
                }
                break;
            case OPasm:
            case OPstring:
                dbg_printf("\"%s\"",e->EV.ss.Vstring);
                if (e->EV.ss.Voffset)
                    dbg_printf("+%ld",(long)e->EV.ss.Voffset);
                break;
            case OPmark:
            case OPgot:
            case OPframeptr:
            case OPhalt:
                WROP(e->Eoper);
                break;
            case OPstrthis:
                break;
            default:
                WROP(e->Eoper);
                assert(0);
        }
  }
}
Esempio n. 3
0
int pipecommon_open(FAR struct file *filep)
{
  FAR struct inode      *inode = filep->f_inode;
  FAR struct pipe_dev_s *dev   = inode->i_private;
  int                    sval;
  int                    ret;

  DEBUGASSERT(dev != NULL);

  /* Make sure that we have exclusive access to the device structure.  The
   * sem_wait() call should fail only if we are awakened by a signal.
   */

  ret = sem_wait(&dev->d_bfsem);
  if (ret != OK)
    {
      ferr("ERROR: sem_wait failed: %d\n", get_errno());
      DEBUGASSERT(get_errno() > 0);
      return -get_errno();
    }

  /* If this the first reference on the device, then allocate the buffer.
   * In the case of policy 1, the buffer already be present when the pipe
   * is first opened.
   */

  if (dev->d_refs == 0 && dev->d_buffer == NULL)
    {
      dev->d_buffer = (FAR uint8_t *)kmm_malloc(dev->d_bufsize);
      if (!dev->d_buffer)
        {
          (void)sem_post(&dev->d_bfsem);
          return -ENOMEM;
        }
    }

  /* Increment the reference count on the pipe instance */

  dev->d_refs++;

  /* If opened for writing, increment the count of writers on the pipe instance */

  if ((filep->f_oflags & O_WROK) != 0)
    {
      dev->d_nwriters++;

      /* If this this is the first writer, then the read semaphore indicates the
       * number of readers waiting for the first writer.  Wake them all up.
       */

      if (dev->d_nwriters == 1)
        {
          while (sem_getvalue(&dev->d_rdsem, &sval) == 0 && sval < 0)
            {
              sem_post(&dev->d_rdsem);
            }
        }
    }

  /* If opened for reading, increment the count of reader on on the pipe instance */

  if ((filep->f_oflags & O_RDOK) != 0)
    {
      dev->d_nreaders++;
    }

  /* If opened for read-only, then wait for either (1) at least one writer
   * on the pipe (policy == 0), or (2) until there is buffered data to be
   * read (policy == 1).
   */

  sched_lock();
  (void)sem_post(&dev->d_bfsem);

  if ((filep->f_oflags & O_RDWR) == O_RDONLY &&  /* Read-only */
      dev->d_nwriters < 1 &&                     /* No writers on the pipe */
      dev->d_wrndx == dev->d_rdndx)              /* Buffer is empty */
    {
      /* NOTE: d_rdsem is normally used when the read logic waits for more
       * data to be written.  But until the first writer has opened the
       * pipe, the meaning is different: it is used prevent O_RDONLY open
       * calls from returning until there is at least one writer on the pipe.
       * This is required both by spec and also because it prevents
       * subsequent read() calls from returning end-of-file because there is
       * no writer on the pipe.
       */

      ret = sem_wait(&dev->d_rdsem);
      if (ret != OK)
        {
          /* The sem_wait() call should fail only if we are awakened by
           * a signal.
           */

          ferr("ERROR: sem_wait failed: %d\n", get_errno());
          DEBUGASSERT(get_errno() > 0);
          ret = -get_errno();

          /* Immediately close the pipe that we just opened */

          (void)pipecommon_close(filep);
        }
    }

  sched_unlock();
  return ret;
}
Esempio n. 4
0
File: ftl.c Progetto: a1ien/nuttx
static ssize_t ftl_flush(FAR void *priv, FAR const uint8_t *buffer,
                         off_t startblock, size_t nblocks)
{
  struct ftl_struct_s *dev = (struct ftl_struct_s *)priv;
  off_t  alignedblock;
  off_t  mask;
  off_t  rwblock;
  off_t  eraseblock;
  off_t  offset;
  size_t remaining;
  size_t nxfrd;
  int    nbytes;
  int    ret;

  /* Get the aligned block.  Here is is assumed: (1) The number of R/W blocks
   * per erase block is a power of 2, and (2) the erase begins with that same
   * alignment.
   */

  mask         = dev->blkper - 1;
  alignedblock = (startblock + mask) & ~mask;

  /* Handle partial erase blocks before the first unaligned block */

  remaining = nblocks;
  if (alignedblock > startblock)
    {
      /* Check if the write is shorter than to the end of the erase block */

      bool short_write = (remaining < (alignedblock - startblock));

      /* Read the full erase block into the buffer */

      rwblock = startblock & ~mask;
      nxfrd   = MTD_BREAD(dev->mtd, rwblock, dev->blkper, dev->eblock);
      if (nxfrd != dev->blkper)
        {
          ferr("ERROR: Read erase block %d failed: %d\n", rwblock, nxfrd);
          return -EIO;
        }

      /* Then erase the erase block */

      eraseblock = rwblock / dev->blkper;
      ret        = MTD_ERASE(dev->mtd, eraseblock, 1);
      if (ret < 0)
        {
          ferr("ERROR: Erase block=%d failed: %d\n", eraseblock, ret);
          return ret;
        }

      /* Copy the user data at the end of the buffered erase block */

      offset = (startblock & mask) * dev->geo.blocksize;

      if (short_write)
        {
          nbytes = remaining * dev->geo.blocksize;
        }
      else
        {
          nbytes = dev->geo.erasesize - offset;
        }

      finfo("Copy %d bytes into erase block=%d at offset=%d\n",
             nbytes, eraseblock, offset);

      memcpy(dev->eblock + offset, buffer, nbytes);

      /* And write the erase block back to flash */

      nxfrd = MTD_BWRITE(dev->mtd, rwblock, dev->blkper, dev->eblock);
      if (nxfrd != dev->blkper)
        {
          ferr("ERROR: Write erase block %d failed: %d\n", rwblock, nxfrd);
          return -EIO;
        }

      /* Then update for amount written */

      if (short_write)
        {
          remaining = 0;
        }
      else
        {
          remaining -= dev->blkper - (startblock & mask);
        }

      buffer += nbytes;
    }

  /* How handle full erase pages in the middle */

  while (remaining >= dev->blkper)
    {
      /* Erase the erase block */

      eraseblock = alignedblock / dev->blkper;
      ret        = MTD_ERASE(dev->mtd, eraseblock, 1);
      if (ret < 0)
        {
          ferr("ERROR: Erase block=%d failed: %d\n", eraseblock, ret);
          return ret;
        }

      /* Write a full erase back to flash */

      finfo("Write %d bytes into erase block=%d at offset=0\n",
             dev->geo.erasesize, alignedblock);

      nxfrd = MTD_BWRITE(dev->mtd, alignedblock, dev->blkper, buffer);
      if (nxfrd != dev->blkper)
        {
          ferr("ERROR: Write erase block %d failed: %d\n", alignedblock, nxfrd);
          return -EIO;
        }

      /* Then update for amount written */

      alignedblock += dev->blkper;
      remaining    -= dev->blkper;
      buffer       += dev->geo.erasesize;
    }

  /* Finally, handle any partial blocks after the last full erase block */

  if (remaining > 0)
    {
      /* Read the full erase block into the buffer */

     nxfrd = MTD_BREAD(dev->mtd, alignedblock, dev->blkper, dev->eblock);
      if (nxfrd != dev->blkper)
        {
          ferr("ERROR: Read erase block %d failed: %d\n", alignedblock, nxfrd);
          return -EIO;
        }

      /* Then erase the erase block */

      eraseblock = alignedblock / dev->blkper;
      ret        = MTD_ERASE(dev->mtd, eraseblock, 1);
      if (ret < 0)
        {
          ferr("ERROR: Erase block=%d failed: %d\n", eraseblock, ret);
          return ret;
        }

      /* Copy the user data at the beginning the buffered erase block */

      nbytes = remaining * dev->geo.blocksize;
      finfo("Copy %d bytes into erase block=%d at offset=0\n",
             nbytes, alignedblock);
      memcpy(dev->eblock, buffer, nbytes);

      /* And write the erase back to flash */

      nxfrd = MTD_BWRITE(dev->mtd, alignedblock, dev->blkper, dev->eblock);
      if (nxfrd != dev->blkper)
        {
          ferr("ERROR: Write erase block %d failed: %d\n", alignedblock, nxfrd);
          return -EIO;
        }
    }

  return nblocks;
}
Esempio n. 5
0
int stm32_at24_automount(int minor)
{
  FAR struct i2c_master_s *i2c;
  FAR struct mtd_dev_s *mtd;
  static bool initialized = false;
  int ret;

  /* Have we already initialized? */

  if (!initialized)
    {
      /* No.. Get the I2C bus driver */

      finfo("Initialize I2C%d\n", AT24_I2C_BUS);
      i2c = stm32_i2cbus_initialize(AT24_I2C_BUS);
      if (!i2c)
        {
          ferr("ERROR: Failed to initialize I2C%d\n", AT24_I2C_BUS);
          return -ENODEV;
        }

      /* Now bind the I2C interface to the AT24 I2C EEPROM driver */

      finfo("Bind the AT24 EEPROM driver to I2C%d\n", AT24_I2C_BUS);
      mtd = at24c_initialize(i2c);
      if (!mtd)
        {
          ferr("ERROR: Failed to bind TWI%d to the AT24 EEPROM driver\n",
               AT24_I2C_BUS);
          return -ENODEV;
        }

#if defined(CONFIG_STM32F103MINIMUM_AT24_FTL)
      /* And finally, use the FTL layer to wrap the MTD driver as a block driver */

      finfo("Initialize the FTL layer to create /dev/mtdblock%d\n", AT24_MINOR);
      ret = ftl_initialize(AT24_MINOR, mtd);
      if (ret < 0)
        {
          ferr("ERROR: Failed to initialize the FTL layer: %d\n", ret);
          return ret;
        }

#elif defined(CONFIG_STM32F103MINIMUM_AT24_NXFFS)
      /* Initialize to provide NXFFS on the MTD interface */

      finfo("Initialize the NXFFS file system\n");
      ret = nxffs_initialize(mtd);
      if (ret < 0)
        {
          ferr("ERROR: NXFFS initialization failed: %d\n", ret);
          return ret;
        }

      /* Mount the file system at /mnt/at24 */

      finfo("Mount the NXFFS file system at /dev/at24\n");
      ret = mount(NULL, "/mnt/at24", "nxffs", 0, NULL);
      if (ret < 0)
        {
          ferr("ERROR: Failed to mount the NXFFS volume: %d\n", errno);
          return ret;
        }
#endif
      /* Now we are initialized */

      initialized = true;
    }

  return OK;
}
Esempio n. 6
0
static int procfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
{
  FAR struct procfs_dir_priv_s *priv;
  FAR struct procfs_level0_s *level0;
  FAR struct tcb_s *tcb;
  FAR const char *name = NULL;
  unsigned int index;
  irqstate_t flags;
  pid_t pid;
  int ret = -ENOENT;

  DEBUGASSERT(mountpt && dir && dir->u.procfs);
  priv = dir->u.procfs;

  /* Are we reading the 1st directory level with dynamic PID and static
   * entries?
   */

  if (priv->level == 0)
    {
      level0 = (FAR struct procfs_level0_s *)priv;

      /* Have we reached the end of the PID information */

      index = priv->index;
      if (index >= priv->nentries)
        {
          /* We must report the next static entry ... no more PID entries.
           * skip any entries with wildcards in the first segment of the
           * directory name.
           */

          while (index < priv->nentries + g_procfs_entrycount)
            {
              name = g_procfs_entries[index - priv->nentries].pathpattern;
              while (*name != '/' && *name != '\0')
                {
                  if (*name == '*' || *name == '[' || *name == '?')
                    {
                      /* Wildcard found.  Skip this entry */

                      index++;
                      name = NULL;
                      break;
                    }

                  name++;
                }

              /* Test if we skipped this entry */

              if (name != NULL)
                {
                  /* This entry is okay to report. Test if it has a duplicate
                   * first level name as the one we just reported.  This could
                   * happen in the event of procfs_entry_s such as:
                   *
                   *    fs/smartfs
                   *    fs/nfs
                   *    fs/nxffs
                   */

                  name = g_procfs_entries[index - priv->nentries].pathpattern;
                  if (!level0->lastlen || (strncmp(name, level0->lastread,
                      level0->lastlen) != 0))
                    {
                      /* Not a duplicate, return the first segment of this
                       * entry
                       */

                      break;
                    }
                  else
                    {
                      /* Skip this entry ... duplicate 1st level name found */

                      index++;
                    }
                }
            }

          /* Test if we are at the end of the directory */

          if (index >= priv->nentries + g_procfs_entrycount)
            {
              /* We signal the end of the directory by returning the special
               * error -ENOENT
               */

              finfo("Entry %d: End of directory\n", index);
              ret = -ENOENT;
            }
          else
            {
              /* Report the next static entry */

              level0->lastlen = strcspn(name, "/");
              level0->lastread = name;
              strncpy(dir->fd_dir.d_name, name, level0->lastlen);
              dir->fd_dir.d_name[level0->lastlen] = '\0';

              if (name[level0->lastlen] == '/')
                {
                  dir->fd_dir.d_type = DTYPE_DIRECTORY;
                }
              else
                {
                  dir->fd_dir.d_type = DTYPE_FILE;
                }

              /* Advance to next entry for the next read */

              priv->index = index;
              ret = OK;
            }
        }
#ifndef CONFIG_FS_PROCFS_EXCLUDE_PROCESS
      else
        {
          /* Verify that the pid still refers to an active task/thread */

          pid = level0->pid[index];

          flags = enter_critical_section();
          tcb = sched_gettcb(pid);
          leave_critical_section(flags);

          if (!tcb)
            {
              ferr("ERROR: PID %d is no longer valid\n", (int)pid);
              return -ENOENT;
            }

          /* Save the filename=pid and file type=directory */

          dir->fd_dir.d_type = DTYPE_DIRECTORY;
          snprintf(dir->fd_dir.d_name, NAME_MAX+1, "%d", (int)pid);

          /* Set up the next directory entry offset.  NOTE that we could use the
           * standard f_pos instead of our own private index.
           */

          level0->base.index = index + 1;
          ret = OK;
        }
#endif /* CONFIG_FS_PROCFS_EXCLUDE_PROCESS */
    }

    /* Are we reading an intermediate subdirectory? */

  else if (priv->level > 0 && priv->procfsentry == NULL)
    {
      FAR struct procfs_level1_s *level1;

      level1 = (FAR struct procfs_level1_s *) priv;

      /* Test if this entry matches.  We assume all entries of the same
       * subdirectory are listed in order in the procfs_entry array.
       */

      if (strncmp(g_procfs_entries[level1->base.index].pathpattern,
                  g_procfs_entries[level1->firstindex].pathpattern,
                  level1->subdirlen) == 0)
        {
          /* This entry matches.  Report the subdir entry */

          name = &g_procfs_entries[level1->base.index].pathpattern[
                    level1->subdirlen + 1];
          level1->lastlen = strcspn(name, "/");
          level1->lastread = name;
          strncpy(dir->fd_dir.d_name, name, level1->lastlen);

          /* Some of the search entries contain '**' wildcards.  When we
           * report the entry name, we must remove this wildcard search
           * specifier.
           */

          while (dir->fd_dir.d_name[level1->lastlen - 1] == '*')
            {
              level1->lastlen--;
            }

          dir->fd_dir.d_name[level1->lastlen] = '\0';

          if (name[level1->lastlen] == '/')
            {
              dir->fd_dir.d_type = DTYPE_DIRECTORY;
            }
          else
            {
              dir->fd_dir.d_type = DTYPE_FILE;
            }

          level1->base.index++;
          ret = OK;
        }
      else
        {
          /* No more entries in the subdirectory */

          ret = -ENOENT;
        }
    }
  else
    {
      /* We are performing a directory search of one of the subdirectories
       * and we must let the handler perform the read.
       */

      DEBUGASSERT(priv->procfsentry && priv->procfsentry->ops->readdir);
      ret = priv->procfsentry->ops->readdir(dir);
    }

  return ret;
}
Esempio n. 7
0
int nxffs_blockstats(FAR struct nxffs_volume_s *volume,
                     FAR struct nxffs_blkstats_s *stats)
{
#ifndef CONFIG_NXFFS_NAND
  FAR uint8_t *bptr;     /* Pointer to next block data */
  int lblock;            /* Logical block index */
#endif
  off_t ioblock;         /* I/O block number */
  int ret;

  /* Process each erase block */

  memset(stats, 0, sizeof(struct nxffs_blkstats_s));

#ifndef CONFIG_NXFFS_NAND
  for (ioblock = 0; ioblock < volume->nblocks; ioblock += volume->blkper)
    {
      /* Read the full erase block */

      ret = MTD_BREAD(volume->mtd, ioblock, volume->blkper, volume->pack);
      if (ret < volume->blkper)
        {
          ferr("ERROR: Failed to read erase block %d: %d\n",
               ioblock / volume->blkper, ret);
          return ret;
        }

      /* Then examine each logical block in the erase block */

      for (bptr = volume->pack, lblock = 0;
           lblock < volume->blkper;
           bptr += volume->geo.blocksize, lblock++)
        {
          /* We read the block successfully, now check for errors tagged
           * in the NXFFS data.
           */

          FAR struct nxffs_block_s *blkhdr = (FAR struct nxffs_block_s *)bptr;

          /* Increment the total count of blocks examined */

          stats->nblocks++;

          /* Collect statistics */
          /* Check if this is a block that should be recognized by NXFFS */

          if (memcmp(blkhdr->magic, g_blockmagic, NXFFS_MAGICSIZE) != 0)
            {
              /* Nope.. block must not be formatted */

              stats->nunformat++;
            }
          else if (blkhdr->state == BLOCK_STATE_BAD)
            {
              /* The block is marked as bad */

               stats->nbad++;
            }
          else if (blkhdr->state == BLOCK_STATE_GOOD)
            {
              /* The block is marked as good */

              stats-> ngood++;
            }
          else
            {
              /* The good/bad mark is not recognized.  Let's call this
               * corrupt (vs. unformatted).
               */

              stats->ncorrupt++;
            }
        }
    }

  finfo("Number blocks:        %d\n", stats->nblocks);
  finfo("  Good blocks:        %d\n", stats->ngood);
  finfo("  Bad blocks:         %d\n", stats->nbad);
  finfo("  Unformatted blocks: %d\n", stats->nunformat);
  finfo("  Corrupt blocks:     %d\n", stats->ncorrupt);

#else
  for (ioblock = 0; ioblock < volume->nblocks; ioblock++)
    {
      /* Increment the total count of blocks examined */

      stats->nblocks++;

      /* Read each logical block, one at a time.  We could read all of the
       * blocks in the erase block into volume->pack at once.  But this would
       * be a problem for NAND which may generate read errors due to bad ECC
       * on individual blocks.
       */

      ret = MTD_BREAD(volume->mtd, ioblock, 1, volume->pack);
      if (ret < 1)
        {
          /* This should not happen at all on most kinds of FLASH.  But a
           * bad read will happen normally with a NAND device that has
           * uncorrectable blocks.  So, just for NAND, we keep the count
           * of unreadable blocks.
           */

          ferr("ERROR: Failed to read block %d: %d\n", ioblock, ret);

          /* Increment the count of un-readable blocks */

          stats->nbadread++;
        }
      else
        {
          /* We read the block successfully, now check for errors tagged
           * in the NXFFS data.
           */

          FAR struct nxffs_block_s *blkhdr = (FAR struct nxffs_block_s *)volume->pack;

          /* Collect statistics */
          /* Check if this is a block that should be recognized by NXFFS */

          if (memcmp(blkhdr->magic, g_blockmagic, NXFFS_MAGICSIZE) != 0)
            {
              /* Nope.. block must not be formatted */

              stats->nunformat++;
            }
          else if (blkhdr->state == BLOCK_STATE_BAD)
            {
              /* The block is marked as bad */

              stats->nbad++;
            }
          else if (blkhdr->state == BLOCK_STATE_GOOD)
            {
              /* The block is marked as good */

              stats-> ngood++;
            }
          else
            {
              /* The good/bad mark is not recognized.  Let's call this
               * corrupt (vs. unformatted).
               */

              stats->ncorrupt++;
            }
        }
    }

  finfo("Number blocks:        %d\n", stats->nblocks);
  finfo("  Good blocks:        %d\n", stats->ngood);
  finfo("  Bad blocks:         %d\n", stats->nbad);
  finfo("  Unformatted blocks: %d\n", stats->nunformat);
  finfo("  Corrupt blocks:     %d\n", stats->ncorrupt);
  finfo("  Unreadable blocks:  %d\n", stats->nbadread);

#endif
  return OK;
}
Esempio n. 8
0
FAR struct mtd_dev_s *blockmtd_initialize(FAR const char *path, size_t offset,
                                          size_t mtdlen, int16_t sectsize,
                                          int32_t erasesize)
{
  FAR struct file_dev_s *priv;
  size_t nblocks;
  int mode;
  int ret;
  int fd;

  /* Create an instance of the FILE MTD device state structure */

  priv = (FAR struct file_dev_s *)kmm_zalloc(sizeof(struct file_dev_s));
  if (!priv)
    {
      ferr("ERROR: Failed to allocate the FILE MTD state structure\n");
      return NULL;
    }

  /* Determine the file open mode */

  mode  = O_RDOK;
#ifdef CONFIG_FS_WRITABLE
  mode |= O_WROK;
#endif

  /* Try to open the file.  NOTE that block devices will use a character
   * driver proxy.
   */

  fd = open(path, mode);
  if (fd <0)
    {
      ferr("ERROR: Failed to open the FILE MTD file %s\n", path);
      kmm_free(priv);
      return NULL;
    }

  /* Detach the file descriptor from the open file */

  ret = file_detach(fd, &priv->mtdfile);
  if (ret < 0)
    {
      ferr("ERROR: Failed to detail the FILE MTD file %s\n", path);
      close(fd);
      kmm_free(priv);
      return NULL;
    }

  /* Set the block size based on the provided sectsize parameter */

  if (sectsize <= 0)
    {
      priv->blocksize = CONFIG_FILEMTD_BLOCKSIZE;
    }
  else
    {
      priv->blocksize = sectsize;
    }

  /* Set the erase size based on the provided erasesize parameter */

  if (erasesize <= 0)
    {
      priv->erasesize = CONFIG_FILEMTD_ERASESIZE;
    }
  else
    {
      priv->erasesize = erasesize;
    }

  /* Force the size to be an even number of the erase block size */

  nblocks = mtdlen / priv->erasesize;
  if (nblocks < 3)
    {
      ferr("ERROR: Need to provide at least three full erase block\n");
      file_close_detached(&priv->mtdfile);
      kmm_free(priv);
      return NULL;
    }

  /* Perform initialization as necessary. (unsupported methods were
   * nullified by kmm_zalloc).
   */

  priv->mtd.erase  = filemtd_erase;
  priv->mtd.bread  = filemtd_bread;
  priv->mtd.bwrite = filemtd_bwrite;
  priv->mtd.read   = filemtd_byteread;
#ifdef CONFIG_MTD_BYTE_WRITE
  priv->mtd.write  = file_bytewrite;
#endif
  priv->mtd.ioctl  = filemtd_ioctl;
  priv->offset     = offset;
  priv->nblocks    = nblocks;

#ifdef CONFIG_MTD_REGISTRATION
  /* Register the MTD with the procfs system if enabled */

  mtd_register(&priv->mtd, "filemtd");
#endif

  return &priv->mtd;
}
Esempio n. 9
0
int nxffs_dump(FAR struct mtd_dev_s *mtd, bool verbose)
{
#if defined(CONFIG_DEBUG_FEATURES) && defined(CONFIG_DEBUG_FS)
  struct nxffs_blkinfo_s blkinfo;
  int ret;

  /* Get the volume geometry. (casting to uintptr_t first eliminates
   * complaints on some architectures where the sizeof long is different
   * from the size of a pointer).
   */

  memset(&blkinfo, 0, sizeof(struct nxffs_blkinfo_s));
  ret = MTD_IOCTL(mtd, MTDIOC_GEOMETRY, (unsigned long)((uintptr_t)&blkinfo.geo));
  if (ret < 0)
    {
      ferr("ERROR: MTD ioctl(MTDIOC_GEOMETRY) failed: %d\n", -ret);
      return ret;
    }

  /* Save the verbose output indication */

  blkinfo.verbose = verbose;

  /* Allocate a buffer to hold one block */

  blkinfo.buffer = (FAR uint8_t *)kmm_malloc(blkinfo.geo.blocksize);
  if (!blkinfo.buffer)
    {
      ferr("ERROR: Failed to allocate block cache\n");
      return -ENOMEM;
    }

  /* Now read every block on the device */

  syslog(LOG_NOTICE, "NXFFS Dump:\n");
  syslog(LOG_NOTICE, g_hdrformat);

  blkinfo.nblocks = blkinfo.geo.erasesize * blkinfo.geo.neraseblocks / blkinfo.geo.blocksize;
  for (blkinfo.block = 0, blkinfo.offset = 0;
       blkinfo.block < blkinfo.nblocks;
       blkinfo.block++, blkinfo.offset += blkinfo.geo.blocksize)
    {
      /* Read the next block */

      ret = MTD_BREAD(mtd, blkinfo.block, 1, blkinfo.buffer);
      if (ret < 0)
        {
#ifndef CONFIG_NXFFS_NAND
          /* Read errors are fatal */

          ferr("ERROR: Failed to read block %d\n", blkinfo.block);
          kmm_free(blkinfo.buffer);
          return ret;
#else
          /* A read error is probably fatal on all media but NAND.
           * On NAND, the read error probably just signifies a block
           * with an uncorrectable ECC failure.  So, to handle NAND,
           * just report the read error and continue.
           */

          syslog(LOG_NOTICE, g_format, blkinfo.block, 0, "BLOCK", "RD FAIL",
               blkinfo.geo.blocksize);
#endif
        }
      else
        {
          /* Analyze the block that we just read */

          nxffs_analyze(&blkinfo);
        }
    }

  syslog(LOG_NOTICE, "%d blocks analyzed\n", blkinfo.nblocks);

  kmm_free(blkinfo.buffer);
  return OK;

#else
  return -ENOSYS;
#endif
}
Esempio n. 10
0
void WReqn(elem *e)
{ static int nest;

  if (!e)
        return;
  if (OTunary(e->Eoper))
  {
        WROP(e->Eoper);
        if (OTbinary(e->E1->Eoper))
        {       nest++;
                ferr("(");
                WReqn(e->E1);
                ferr(")");
                nest--;
        }
        else
                WReqn(e->E1);
  }
  else if (e->Eoper == OPcomma && !nest)
  {     WReqn(e->E1);
        dbg_printf(";\n\t");
        WReqn(e->E2);
  }
  else if (OTbinary(e->Eoper))
  {
        if (OTbinary(e->E1->Eoper))
        {       nest++;
                ferr("(");
                WReqn(e->E1);
                ferr(")");
                nest--;
        }
        else
                WReqn(e->E1);
        ferr(" ");
        WROP(e->Eoper);
        if (e->Eoper == OPstreq)
            dbg_printf("%ld",e->Enumbytes);
        ferr(" ");
        if (OTbinary(e->E2->Eoper))
        {       nest++;
                ferr("(");
                WReqn(e->E2);
                ferr(")");
                nest--;
        }
        else
                WReqn(e->E2);
  }
  else
  {
        switch (e->Eoper)
        {   case OPconst:
                switch (tybasic(e->Ety))
                {
                    case TYfloat:
                        dbg_printf("%g <float> ",e->EV.Vfloat);
                        break;
                    case TYdouble:
                        dbg_printf("%g ",e->EV.Vdouble);
                        break;
                    default:
                        dbg_printf("%lld ",el_tolong(e));
                        break;
                }
                break;
            case OPrelconst:
                ferr("#");
                /* FALL-THROUGH */
            case OPvar:
                dbg_printf("%s",e->EV.sp.Vsym->Sident);
                if (e->EV.sp.Vsym->Ssymnum != -1)
                    dbg_printf("(%d)",e->EV.sp.Vsym->Ssymnum);
                if (e->Eoffset != 0)
                        dbg_printf(".%ld",e->Eoffset);
                break;
            case OPasm:
#if TARGET_MAC
                if (e->Eflags & EFsmasm)
                    {
                    if (e->EV.mac.Vasmdat[1])
                        dbg_printf("\"%c%c\"",e->EV.mac.Vasmdat[0],e->EV.mac.Vasmdat[1]);
                    else
                        dbg_printf("\"%c\"",e->EV.mac.Vasmdat[0]);
                    break;
                    };
#endif
            case OPstring:
                dbg_printf("\"%s\"",e->EV.ss.Vstring);
                if (e->EV.ss.Voffset)
                    dbg_printf("+%ld",e->EV.ss.Voffset);
                break;
            case OPmark:
            case OPgot:
            case OPframeptr:
                WROP(e->Eoper);
                break;
            case OPstrthis:
                break;
            default:
                WROP(e->Eoper);
                assert(0);
        }
  }
}
Esempio n. 11
0
static ssize_t filemtd_write(FAR struct file_dev_s *priv, size_t offset,
                             FAR const void *src, size_t len)
{
  FAR const uint8_t *pin  = (FAR const uint8_t *)src;
  FAR uint8_t       *pout;
  char               buf[128];
  int                buflen = 0;
  uint8_t            oldvalue;
  uint8_t            srcvalue;
  uint8_t            newvalue;
  size_t             seekpos;

  /* Set the starting location in the file */

  seekpos = priv->offset + offset;

  while (len-- > 0)
    {
      if (buflen == 0)
        {
          /* Read more data from the file */

          file_seek(&priv->mtdfile, seekpos, SEEK_SET);
          buflen = file_read(&priv->mtdfile, buf, sizeof(buf));
          pout   = (FAR uint8_t *) buf;
        }

      /* Get the source and destination values */

      oldvalue = *pout;
      srcvalue = *pin++;

      /* Get the new destination value, accounting for bits that cannot be
       * changes because they are not in the erased state.
       */

#if CONFIG_FILEMTD_ERASESTATE == 0xff
      newvalue = oldvalue & srcvalue; /* We can only clear bits */
#else /* CONFIG_FILEMTD_ERASESTATE == 0x00 */
      newvalue = oldvalue | srcvalue; /* We can only set bits */
#endif

      /* Report any attempt to change the value of bits that are not in the
       * erased state.
       */

#ifdef CONFIG_DEBUG_FEATURES
      if (newvalue != srcvalue)
        {
          ferr("ERROR: Bad write: source=%02x dest=%02x result=%02x\n",
              srcvalue, oldvalue, newvalue);
        }
#endif

      /* Write the modified value to simulated FLASH */

      *pout++ = newvalue;
      buflen--;

      /* If our buffer is full, then seek back to beginning of
       * the file and write the buffer contents
       */

      if (buflen == 0)
        {
          file_seek(&priv->mtdfile, seekpos, SEEK_SET);
          (void)file_write(&priv->mtdfile, buf, sizeof(buf));
          seekpos += sizeof(buf);
        }
    }

  /* Write remaining bytes */

  if (buflen != 0)
    {
      file_seek(&priv->mtdfile, seekpos, SEEK_SET);
      (void)file_write(&priv->mtdfile, buf, sizeof(buf));
    }

  return len;
}
Esempio n. 12
0
static off_t  mtdconfig_consolidate(FAR struct mtdconfig_struct_s *dev)
{
  off_t       src_block, dst_block;
  off_t       src_offset, dst_offset;
  uint16_t    blkper, x, bytes, bytes_left_in_block;
  struct mtdconfig_header_s hdr;
  int         ret;
  uint8_t     sig[CONFIGDATA_BLOCK_HDR_SIZE];
  uint8_t     *pBuf;

  /* Prepare to copy block 0 to the last block (erase blocks) */

  src_block = 0;
  dst_block = dev->neraseblocks - 1;

  /* Ensure the last block is erased */

  MTD_ERASE(dev->mtd, dst_block, 1);
  blkper = dev->erasesize / dev->blocksize;
  dst_block *= blkper;            /* Convert to read/write blocks */

  /* Allocate a small buffer for moving data */

  pBuf = (uint8_t *)kmm_malloc(dev->blocksize);
  if (pBuf == NULL)
    {
      return 0;
    }

  /* Now copy block zero to last block */

  for (x = 0; x < blkper; x++)
    {
      ret = MTD_BREAD(dev->mtd, src_block++, 1, dev->buffer);
      if (ret < 0)
        {
          /* I/O Error! */

          goto errout;
        }

      ret = MTD_BWRITE(dev->mtd, dst_block++, 1, dev->buffer);
      if (ret < 0)
        {
          /* I/O Error! */

          goto errout;
        }
    }

  /* Erase block zero and write a format signature. */

  MTD_ERASE(dev->mtd, 0, 1);
  sig[0] = 'C';
  sig[1] = 'D';
  sig[2] = CONFIGDATA_FORMAT_VERSION;

  ret = mtdconfig_writebytes(dev, 0, sig, sizeof(sig));
  if (ret != sizeof(sig))
    {
      /* Cannot write even the signature. */

      ret = -EIO;
      goto errout;
    }

  /* Now consolidate entries. */

  src_block = 1;
  dst_block = 0;
  src_offset = src_block * dev->erasesize + CONFIGDATA_BLOCK_HDR_SIZE;
  dst_offset = CONFIGDATA_BLOCK_HDR_SIZE;

  while (src_block < dev->neraseblocks)
    {
      /* Scan all headers and move them to the src_offset */

retry_relocate:
      bytes = MTD_READ(dev->mtd, src_offset, sizeof(hdr), (uint8_t *) &hdr);
      if (bytes != sizeof(hdr))
        {
          /* I/O Error! */

          ret = -EIO;
          goto errout;
        }

      if (hdr.flags == MTD_ERASED_FLAGS)
        {
          /* Test if the source entry is active or if we are at the end
           * of data for this erase block.
           */

          if (hdr.id == MTD_ERASED_ID)
            {
              /* No more data in this erase block.  Advance to the
               * next one.
               */

              src_offset = (src_block + 1) * dev->erasesize + CONFIGDATA_BLOCK_HDR_SIZE;
            }
          else
            {
              /* Test if this entry will fit in the current destination block */

              bytes_left_in_block = (dst_block + 1) * dev->erasesize - dst_offset;
              if (hdr.len + sizeof(hdr) > bytes_left_in_block)
                {
                  /* Item doesn't fit in the block.  Advance to the next one */

                  /* Update control variables */

                  dst_block++;
                  dst_offset = dst_block * dev->erasesize + CONFIGDATA_BLOCK_HDR_SIZE;

                  DEBUGASSERT(dst_block != src_block);

                  /* Retry the relocate */

                  goto retry_relocate;
                }

              /* Copy this entry to the destination */

              ret = mtdconfig_writebytes(dev, dst_offset, (uint8_t *) &hdr, sizeof(hdr));
              if (ret != sizeof(hdr))
                {
                  /* I/O Error! */

                  ret = -EIO;
                  goto errout;
                }

              src_offset += sizeof(hdr);
              dst_offset += sizeof(hdr);

              /* Now copy the data */

              while (hdr.len)
                {
                  bytes = hdr.len;
                  if (bytes > dev->blocksize)
                    {
                      bytes = dev->blocksize;
                    }

                  /* Move the data. */

                  ret = mtdconfig_readbytes(dev, src_offset, pBuf, bytes);
                  if (ret != OK)
                    {
                      /* I/O Error! */

                      ret = -EIO;
                      goto errout;
                    }

                  ret = mtdconfig_writebytes(dev, dst_offset, pBuf, bytes);
                  if (ret != bytes)
                    {
                      /* I/O Error! */

                      ret = -EIO;
                      goto errout;
                    }

                  /* Update control variables */

                  hdr.len -= bytes;
                  src_offset += bytes;
                  dst_offset += bytes;
                }
            }
        }
      else
        {
          /* This item has been released.  Skip it! */

          src_offset += sizeof(hdr) + hdr.len;
          if (src_offset + sizeof(hdr) >= (src_block + 1) * dev->erasesize ||
              src_offset == (src_block + 1) * dev->erasesize)
            {
              /* No room left at end of source block */

              src_offset = (src_block + 1) * dev->erasesize + CONFIGDATA_BLOCK_HDR_SIZE;
            }
        }

      /* Test if we are out of space in the src block */

      if (src_offset + sizeof(hdr) >= (src_block + 1) * dev->erasesize)
        {
          /* No room at end of src block for another header.  Go to next
           * source block.
           */

          src_offset = (src_block + 1) * dev->erasesize + CONFIGDATA_BLOCK_HDR_SIZE;
        }

      /* Test if we advanced to the next block.  If we did, then erase the
       * old block.
       */

      if (src_block != src_offset / dev->erasesize)
        {
          /* Erase the block ... we have emptied it */

          MTD_ERASE(dev->mtd, src_block, 1);
          src_block++;
        }

      /* Test if we are out of space in the dst block */

      if (dst_offset + sizeof(hdr) >= (dst_block + 1) * dev->erasesize)
        {
          /* No room at end of dst block for another header.  Go to next block. */

          dst_block++;
          dst_offset = dst_block * dev->erasesize + CONFIGDATA_BLOCK_HDR_SIZE;
          DEBUGASSERT(dst_block != src_block);
        }
    }

  kmm_free(pBuf);
  return dst_offset;

errout:
  kmm_free(pBuf);
  ferr("ERROR: fail consolidate: %d\n", ret);
  return 0;
}
Esempio n. 13
0
static off_t mtdconfig_ramconsolidate(FAR struct mtdconfig_struct_s *dev)
{
  FAR uint8_t *pBuf;
  FAR struct  mtdconfig_header_s *phdr;
  struct      mtdconfig_header_s  hdr;
  uint16_t    src_block = 0, dst_block = 0, blkper;
  off_t       dst_offset = CONFIGDATA_BLOCK_HDR_SIZE;
  off_t       src_offset = CONFIGDATA_BLOCK_HDR_SIZE;
  off_t       bytes_left_in_block;
  uint8_t     sig[CONFIGDATA_BLOCK_HDR_SIZE];
  int         ret;

  /* Allocate a consolidation buffer */

  pBuf = (uint8_t *)kmm_malloc(dev->erasesize);
  if (pBuf == NULL)
    {
      /* Unable to allocate buffer, can't consolidate! */

      return 0;
    }

  /* Loop for all blocks and consolidate them */

  blkper = dev->erasesize / dev->blocksize;
  while (src_block < dev->neraseblocks)
    {
      /* Point to beginning of pBuf and read the next erase block */

      ret = MTD_BREAD(dev->mtd, src_block * blkper, blkper, pBuf);
      if (ret < 0)
        {
          /* Error doing block read */

          goto errout;
        }

      /* Now erase the block */

      ret = MTD_ERASE(dev->mtd, src_block, 1);
      if (ret < 0)
        {
          /* Error erasing the block */

          goto errout;
        }

      /* If this is block zero, then write a format signature */

      if (src_block == 0)
        {
          sig[0] = 'C';
          sig[1] = 'D';
          sig[2] = CONFIGDATA_FORMAT_VERSION;

          ret = mtdconfig_writebytes(dev, 0, sig, sizeof(sig));
          if (ret != sizeof(sig))
            {
              /* Cannot write even the signature. */

              ret = -EIO;
              goto errout;
            }
        }

      /* Copy active items back to the MTD device. */

      while (src_offset < dev->erasesize)
        {
          phdr = (FAR struct mtdconfig_header_s *) &pBuf[src_offset];
          if (phdr->id == MTD_ERASED_ID)
            {
              /* No more data in this erase block. */

              src_offset = dev->erasesize;
              continue;
            }

          if (phdr->flags == MTD_ERASED_FLAGS)
            {
              /* This is an active entry.  Copy it.  Check if it
               * fits in the current destination block.
               */

              bytes_left_in_block = (dst_block + 1) * dev->erasesize -
                dst_offset;
              if (bytes_left_in_block < sizeof(*phdr) + phdr->len)
                {
                  /* Item won't fit in the destination block.  Move to
                   * the next block.
                   */

                  dst_block++;
                  dst_offset = dst_block * dev->erasesize + CONFIGDATA_BLOCK_HDR_SIZE;

                  /* Test for program bug.  We shouldn't ever overflow
                   * even if no entries were inactive.
                   */

                  DEBUGASSERT(dst_block != dev->neraseblocks);
                }

              /* Now write the item to the current dst_offset location. */

              ret = mtdconfig_writebytes(dev, dst_offset, (uint8_t *) phdr,
                                         sizeof(hdr));
              if (ret != sizeof(hdr))
                {
                  /* I/O Error! */

                  ret = -EIO;
                  goto errout;
                }

              dst_offset += sizeof(hdr);
              ret = mtdconfig_writebytes(dev, dst_offset,
                                         &pBuf[src_offset + sizeof(hdr)], phdr->len);
              if (ret != phdr->len)
                {
                  /* I/O Error! */

                  ret = -EIO;
                  goto errout;
                }

              dst_offset += phdr->len;

              /* Test if enough space in dst block for another header */

              if (dst_offset + sizeof(hdr) >= (dst_block + 1) * dev->erasesize ||
                  dst_offset == (dst_block + 1) * dev->erasesize)
                {
                  dst_block++;
                  dst_offset = dst_block * dev->erasesize + CONFIGDATA_BLOCK_HDR_SIZE;
                }
            }

          /* Increment past the current source item */

          src_offset += sizeof(hdr) + phdr->len;
          if (src_offset + sizeof(hdr) > dev->erasesize)
            {
              src_offset = dev->erasesize;
            }

          DEBUGASSERT(src_offset <= dev->erasesize);
        }

      /* Increment to next source block */

      src_block++;
      src_offset = CONFIGDATA_BLOCK_HDR_SIZE;
    }

  kmm_free(pBuf);
  return dst_offset;

errout:
  kmm_free(pBuf);
  ferr("ERROR: fail ram consolidate: %d\n", ret);
  return 0;
}
Esempio n. 14
0
static int proc_stat(const char *relpath, struct stat *buf)
{
  FAR const struct proc_node_s *node;
  FAR struct tcb_s *tcb;
  unsigned long tmp;
  FAR char *ptr;
  irqstate_t flags;
  pid_t pid;

  /* Two path forms are accepted:
   *
   * "<pid>" - If <pid> refers to a currently active task/thread, then it
   *   is a directory
   * "<pid>/<node>" - If <node> is a recognized node then, then it
   *   is a file or directory.
   */

  ptr = NULL;

  if (strncmp(relpath, "self", 4) == 0)
    {
      tmp = (unsigned long)getpid();    /* Get the PID of the calling task */
      ptr = (FAR char *)relpath + 4;    /* Discard const */
    }
  else
    {
      tmp = strtoul(relpath, &ptr, 10); /* Extract the PID from path */
    }

  if (ptr == NULL)
    {
      ferr("ERROR: Invalid path \"%s\"\n", relpath);
      return -ENOENT;
   }

  /* A valid PID would be in the range of 0-32767 (0 is reserved for the
   * IDLE thread).
   */

  if (tmp >= 32768)
    {
      ferr("ERROR: Invalid PID %ld\n", tmp);
      return -ENOENT;
    }

  /* Now verify that a task with this task/thread ID exists */

  pid = (pid_t)tmp;

  flags = enter_critical_section();
  tcb = sched_gettcb(pid);
  leave_critical_section(flags);

  if (tcb == NULL)
    {
      ferr("ERROR: PID %d is no longer valid\n", (int)pid);
      return -ENOENT;
    }

  /* Was the <pid> the final element of the path? */

  memset(buf, 0, sizeof(struct stat));
  if (*ptr == '\0' || strcmp(ptr, "/") == 0)
    {
      /* Yes ... It's a read-only directory */

      buf->st_mode = S_IFDIR | S_IROTH | S_IRGRP | S_IRUSR;
    }

  /* Verify that the process ID is followed by valid path segment delimiter */

  else if (*ptr != '/')
    {
      /* We are required to return -ENOENT all all invalid paths */

      ferr("ERROR: Bad delimiter '%c' in relpath '%s'\n", *ptr, relpath);
      return -ENOENT;
    }
  else
    {
      /* Otherwise, the second segment of the relpath should be a well
       * known node of the task/thread directory structure.
       */

      /* Skip over the path segment delimiter */

      ptr++;

      /* Lookup the well-known node associated with the relative path. */

      node = proc_findnode(ptr);
      if (node == NULL)
        {
          ferr("ERROR: Invalid path \"%s\"\n", relpath);
          return -ENOENT;
        }

      /* If the node exists, it is the name for a read-only file or
       * directory.
       */

      if (node->dtype == DTYPE_FILE)
        {
          buf->st_mode = S_IFREG | S_IROTH | S_IRGRP | S_IRUSR;
        }
      else
        {
          buf->st_mode = S_IFDIR | S_IROTH | S_IRGRP | S_IRUSR;
        }
    }

  return OK;
}
Esempio n. 15
0
int board_app_initialize(uintptr_t arg)
{
  int ret;

#ifdef CONFIG_FS_PROCFS
  /* Mount the procfs file system */

  ret = mount(NULL, STM32_PROCFS_MOUNTPOINT, "procfs", 0, NULL);
  if (ret < 0)
    {
      syslog(LOG_ERR, "ERROR: Failed to mount procfs at %s: %d\n",
             STM32_PROCFS_MOUNTPOINT, ret);
    }
#endif

#if !defined(CONFIG_ARCH_LEDS) && defined(CONFIG_USERLED_LOWER)
  /* Register the LED driver */

  ret = userled_lower_initialize(LED_DRIVER_PATH);
  if (ret < 0)
    {
      syslog(LOG_ERR, "ERROR: userled_lower_initialize() failed: %d\n", ret);
    }
#endif

#ifdef CONFIG_ADC
  /* Initialize ADC and register the ADC driver. */

  ret = stm32_adc_setup();
  if (ret < 0)
    {
      syslog(LOG_ERR, "ERROR: stm32_adc_setup failed: %d\n", ret);
    }
#endif

#ifdef CONFIG_STM32F7_BBSRAM
  /* Initialize battery-backed RAM */

  (void)stm32_bbsram_int();
#endif

#if defined(CONFIG_FAT_DMAMEMORY)
  if (stm32_dma_alloc_init() < 0)
    {
      syslog(LOG_ERR, "DMA alloc FAILED");
    }
#endif

#if defined(CONFIG_NUCLEO_SPI_TEST)
  /* Create SPI interfaces */

  ret = stm32_spidev_bus_test();
  if (ret != OK)
    {
      syslog(LOG_ERR, "ERROR: Failed to initialize SPI interfaces: %d\n", ret);
      return ret;
    }
#endif

#if defined(CONFIG_MMCSD)
  /* Configure SDIO */
  /* Initialize the SDIO block driver */

  ret = stm32_sdio_initialize();
  if (ret != OK)
    {
      ferr("ERROR: Failed to initialize MMC/SD driver: %d\n", ret);
      return ret;
    }
#endif

  UNUSED(ret);
  return OK;
}
Esempio n. 16
0
File: acme.c Progetto: Jedzia/acm3
// Tidy up before exiting by saving label dump
int ACME_finalize(int exit_code) {
	FILE*	fd;

	if(labeldump_filename) {
#if defined(USE_FOPEN_S)
		errno_t err = fopen_s(&fd,labeldump_filename, FILE_WRITETEXT);
		if(ferr(fd,err)) {
#else
		fd = fopen(labeldump_filename, FILE_WRITETEXT);
		if(fd) {
#endif
			Label_dump_all(fd);
			fclose(fd);
		} else {
			fprintf(stderr,
				"Error: Cannot open label dump file \"%s\".\n",
				labeldump_filename);
			exit_code = EXIT_FAILURE;
		}
	}

	if(vicelabeldump_filename) {
#if defined(USE_FOPEN_S)
		errno_t err = fopen_s(&fd,vicelabeldump_filename, FILE_WRITETEXT);
		if(ferr(fd,err)) {
#else
		fd = fopen(vicelabeldump_filename, FILE_WRITETEXT);
		if(fd) {
#endif
			Label_dump_all_vice(fd);
			fclose(fd);
		} else {
			fprintf(stderr,
				"Error: Cannot open label dump file \"%s\".\n",
				vicelabeldump_filename);
			exit_code = EXIT_FAILURE;
		}
	}

	return(exit_code);
}

// Save output file
static void save_output_file(void) {
	FILE*	fd;
#if defined(USE_FOPEN_S)
 	errno_t err;
#endif

	// if no output file chosen, tell user and do nothing
	if(output_filename == NULL) {
		fputs("No output file specified (use the \"-o\" option or the \"!to\" pseudo opcode).", stderr);
		return;
	}

#if defined(USE_FOPEN_S)
		err = fopen_s(&fd,output_filename, FILE_WRITETEXT);
		if((fd == NULL) | (err != NULL)) {
#else
		fd = fopen(output_filename, FILE_WRITEBINARY);
		if(fd == NULL) {
#endif
		fprintf(stderr, "Error: Cannot open output file \"%s\".\n",
			output_filename);
		return;
	}
	Output_save_file(fd);
	fclose(fd);
}

// Perform a single pass. Returns number of "NeedValue" type errors.
static int perform_pass(void) {
	FILE*	fd;
	int	i;

	// call modules' "pass init" functions
	CPU_passinit(default_cpu);// set default cpu values (PC undefined)
	Output_passinit(start_addr);// call after CPU_passinit(), to define PC
	Encoding_passinit();	// set default encoding
	Section_passinit();	// set initial zone (untitled)
	// init variables
	pass_undefined_count = 0;	// no "NeedValue" errors yet
	pass_real_errors = 0;	// no real errors yet
	// Process toplevel files
	for(i = 0; i<toplevel_src_count; i++) {
#if defined(USE_FOPEN_S)
		errno_t err = fopen_s(&fd,toplevel_sources[i], FILE_READBINARY);
		if(ferr(fd,err))
#else
		fd = fopen(toplevel_sources[i], FILE_READBINARY);
		if(fd)
#endif
			Parse_and_close_file(fd, toplevel_sources[i]);
		else {
			fprintf(stderr, "Error: Cannot open toplevel file \"%s\".\n", toplevel_sources[i]);
			pass_real_errors++;
		}
	}
	if(pass_real_errors)
		exit(ACME_finalize(EXIT_FAILURE));
	else
		Output_end_segment();
	return(pass_undefined_count);
}

// do passes until done (or errors occured). Return whether output is ready.
static bool do_actual_work(void) {
	int	undefined_prev,	// "NeedValue" errors of previous pass
		undefined_curr;	// "NeedValue" errors of current pass

	if(Process_verbosity > 1)
		puts("First pass.");
	pass_count = 0;
	undefined_curr = perform_pass();	// First pass
	// now pretend there has been a pass before the first one
	undefined_prev = undefined_curr + 1;
	// As long as the number of "NeedValue" errors is decreasing but
	// non-zero, keep doing passes.
	while(undefined_curr && (undefined_curr < undefined_prev)) {
		pass_count++;
		undefined_prev = undefined_curr;
		if(Process_verbosity > 1)
			puts("Further pass.");
		undefined_curr = perform_pass();
	}
	// If still errors (unsolvable by doing further passes),
	// perform additional pass to find and show them
	if(undefined_curr == 0)
		return(TRUE);
	if(Process_verbosity > 1)
		puts("Further pass needed to find error.");
	ALU_throw_errors();	// activate error output (CAUTION - one-way!)
	pass_count++;
	perform_pass();	// perform pass, but now show "value undefined"
	return(FALSE);
}
Esempio n. 17
0
static int procfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
                          FAR struct fs_dirent_s *dir)
{
  FAR struct procfs_level0_s *level0;
  FAR struct procfs_dir_priv_s *dirpriv;
  FAR void *priv = NULL;
  irqstate_t flags;

  finfo("relpath: \"%s\"\n", relpath ? relpath : "NULL");
  DEBUGASSERT(mountpt && relpath && dir && !dir->u.procfs);

  /* The relative must be either:
   *
   * ""      - The top level directory of task/thread IDs
   * "<pid>" - The sub-directory of task/thread attributes
   */

  if (!relpath || relpath[0] == '\0')
    {
      /* The path refers to the top level directory.  Allocate the level0
       * dirent structure.
       */

      level0 = (FAR struct procfs_level0_s *)
         kmm_zalloc(sizeof(struct procfs_level0_s));

      if (!level0)
        {
          ferr("ERROR: Failed to allocate the level0 directory structure\n");
          return -ENOMEM;
        }

      /* Take a snapshot of all currently active tasks.  Any new tasks
       * added between the opendir() and closedir() call will not be
       * visible.
       *
       * NOTE that interrupts must be disabled throughout the traversal.
       */

#ifndef CONFIG_FS_PROCFS_EXCLUDE_PROCESS
      flags = enter_critical_section();
      sched_foreach(procfs_enum, level0);
      leave_critical_section(flags);
#else
      level0->base.index = 0;
      level0->base.nentries = 0;
#endif

      /* Initialize lastread entries */

      level0->lastread = "";
      level0->lastlen = 0;
      level0->base.procfsentry = NULL;

      priv = (FAR void *)level0;
    }
  else
    {
      int x, ret;
      int len = strlen(relpath);

      /* Search the static array of procfs_entries */

      for (x = 0; x < g_procfs_entrycount; x++)
        {
          /* Test if the path matches this entry's specification */

          if (match(g_procfs_entries[x].pathpattern, relpath))
            {
              /* Match found!  Call the handler's opendir routine.  If successful,
               * this opendir routine will create an entry derived from struct
               * procfs_dir_priv_s as dir->u.procfs.
               */

              DEBUGASSERT(g_procfs_entries[x].ops && g_procfs_entries[x].ops->opendir);
              ret = g_procfs_entries[x].ops->opendir(relpath, dir);

              if (ret == OK)
                {
                  DEBUGASSERT(dir->u.procfs);

                  /* Set the procfs_entry handler */

                  dirpriv = (FAR struct procfs_dir_priv_s *)dir->u.procfs;
                  dirpriv->procfsentry = &g_procfs_entries[x];
                }

              return ret;
            }

            /* Test for a sub-string match (e.g. "ls /proc/fs") */

          else if (strncmp(g_procfs_entries[x].pathpattern, relpath, len) == 0)
            {
              FAR struct procfs_level1_s *level1;

              /* Doing an intermediate directory search */

              /* The path refers to the top level directory.  Allocate the level1
               * dirent structure.
               */

              level1 = (FAR struct procfs_level1_s *)
                 kmm_zalloc(sizeof(struct procfs_level1_s));

              if (!level1)
                {
                  ferr("ERROR: Failed to allocate the level0 directory structure\n");
                  return -ENOMEM;
                }

              level1->base.level = 1;
              level1->base.index = x;
              level1->firstindex = x;
              level1->subdirlen = len;
              level1->lastread = "";
              level1->lastlen = 0;
              level1->base.procfsentry = NULL;

              priv = (FAR void *)level1;
              break;
            }
        }
    }

  dir->u.procfs = priv;
  return OK;
}
Esempio n. 18
0
int main(int argc, char** argv){
	if(argc==1)usage(help_str);
	for(filenum=0;filenum<argc;++filenum)if(unlink(argv[filenum])!=0)ferr();
	_exit(0);
}
Esempio n. 19
0
int onfi_read(uintptr_t cmdaddr, uintptr_t addraddr, uintptr_t dataaddr,
              FAR struct onfi_pgparam_s *onfi)
{
  uint8_t parmtab[ONFI_PARAM_TABLE_SIZE];
  int i;

  finfo("cmdaddr=%08x addraddr=%08x dataaddr=%08x\n",
        (int)cmdaddr, (int)addraddr, (int)dataaddr);

  if (!onfi_compatible(cmdaddr, addraddr, dataaddr))
    {
      ferr("ERROR: No ONFI compatible device detected\n");
      return -ENODEV;
    }

  /* Initialize the ONFI parameter table */

  memset(parmtab, 0xff, ONFI_PARAM_TABLE_SIZE);

  /* Perform Read Parameter Page command */

  WRITE_NAND_COMMAND(NAND_CMD_READ_PARAM_PAGE, cmdaddr);
  WRITE_NAND_ADDRESS(0x0, addraddr);

  /* Wait NF ready */

  onfi_readstatus(cmdaddr, dataaddr);

  /* Re-enable data output mode required after Read Status command */

  WRITE_NAND_COMMAND(NAND_CMD_READ0, cmdaddr);

  /* Read the parameter table */

  for (i = 0; i < ONFI_PARAM_TABLE_SIZE; i++)
    {
      parmtab[i] = READ_NAND(dataaddr);
    }

  for (i = 0; i < ONFI_PARAM_TABLE_SIZE; i++)
    {
      if (parmtab[i] != 0xff)
        {
          break;
        }
    }

  if (i == ONFI_PARAM_TABLE_SIZE)
    {
      ferr("ERROR: Failed to read ONFI parameter table\n");
      return -EIO;
   }

  /* JEDEC manufacturer ID */

  onfi->manufacturer = *(FAR uint8_t *)(parmtab + 64);

  /* Bus width */

  onfi->buswidth = (*(FAR uint8_t *)(parmtab + 6)) & 0x01;

  /* Get number of data bytes per page (bytes 80-83 in the param table) */

  onfi->pagesize =  *(FAR uint32_t *)(FAR void *)(parmtab + 80);

  /* Get number of spare bytes per page (bytes 84-85 in the param table) */

  onfi->sparesize =  *(FAR uint16_t *)(FAR void *)(parmtab + 84);

  /* Number of pages per block. */

  onfi->pagesperblock = *(FAR uint32_t *)(FAR void *)(parmtab + 92);

  /* Number of blocks per logical unit (LUN). */

  onfi->blocksperlun = *(FAR uint32_t *)(FAR void *)(parmtab + 96);

  /* Number of logical units. */

  onfi->luns = *(FAR uint8_t *)(parmtab + 100);

  /* Number of bits of ECC correction */

  onfi->eccsize = *(FAR uint8_t *)(parmtab + 112);

  /* Device model */

  onfi->model = *(FAR uint8_t *)(parmtab + 49);

  finfo("Returning:\n");
  finfo("  manufacturer:  0x%02x\n", onfi->manufacturer);
  finfo("  buswidth:      %d\n",     onfi->buswidth);
  finfo("  luns:          %d\n",     onfi->luns);
  finfo("  eccsize:       %d\n",     onfi->eccsize);
  finfo("  model:         0x%02s\n", onfi->model);
  finfo("  sparesize:     %d\n",     onfi->sparesize);
  finfo("  pagesperblock: %d\n",     onfi->pagesperblock);
  finfo("  blocksperlun:  %d\n",     onfi->blocksperlun);
  finfo("  pagesize:      %d\n",     onfi->pagesize);
  return OK;
}
Esempio n. 20
0
int board_app_initialize(uintptr_t arg)
{
#if defined(CONFIG_STM32_SPI4)
  FAR struct spi_dev_s *spi;
  FAR struct mtd_dev_s *mtd;
  FAR struct mtd_geometry_s geo;
#endif

#if defined(CONFIG_MTD_PARTITION_NAMES)
  FAR const char *partname = CONFIG_STM32F429I_DISCO_FLASH_PART_NAMES;
#endif

#if defined(CONFIG_MTD) && defined(CONFIG_MTD_SST25XX)
  int ret;
#elif defined(HAVE_USBHOST) || defined(HAVE_USBMONITOR)
  int ret;
#endif

  /* Configure SPI-based devices */

#ifdef CONFIG_STM32_SPI4
  /* Get the SPI port */

  syslog(LOG_INFO, "Initializing SPI port 4\n");

  spi = stm32_spibus_initialize(4);
  if (!spi)
    {
      syslog(LOG_ERR, "ERROR: Failed to initialize SPI port 4\n");
      return -ENODEV;
    }

  syslog(LOG_INFO, "Successfully initialized SPI port 4\n");

  /* Now bind the SPI interface to the SST25F064 SPI FLASH driver.  This
   * is a FLASH device that has been added external to the board (i.e.
   * the board does not ship from STM with any on-board FLASH.
   */

#if defined(CONFIG_MTD) && defined(CONFIG_MTD_SST25XX)
  syslog(LOG_INFO, "Bind SPI to the SPI flash driver\n");

  mtd = sst25xx_initialize(spi);
  if (!mtd)
    {
      syslog(LOG_ERR, "ERROR: Failed to bind SPI port 4 to the SPI FLASH driver\n");
    }
  else
    {
      syslog(LOG_INFO, "Successfully bound SPI port 4 to the SPI FLASH driver\n");

      /* Get the geometry of the FLASH device */

      ret = mtd->ioctl(mtd, MTDIOC_GEOMETRY, (unsigned long)((uintptr_t)&geo));
      if (ret < 0)
        {
          ferr("ERROR: mtd->ioctl failed: %d\n", ret);
          return ret;
        }

#ifdef CONFIG_STM32F429I_DISCO_FLASH_PART
      {
        int partno;
        int partsize;
        int partoffset;
        int partszbytes;
        int erasesize;
        const char *partstring = CONFIG_STM32F429I_DISCO_FLASH_PART_LIST;
        const char *ptr;
        FAR struct mtd_dev_s *mtd_part;
        char  partref[4];

        /* Now create a partition on the FLASH device */

        partno = 0;
        ptr = partstring;
        partoffset = 0;

        /* Get the Flash erase size */

        erasesize = geo.erasesize;

        while (*ptr != '\0')
          {
            /* Get the partition size */

            partsize = atoi(ptr);
            partszbytes = (partsize << 10); /* partsize is defined in KB */

            /* Check if partition size is bigger then erase block */

            if (partszbytes < erasesize)
              {
                ferr("ERROR: Partition size is lesser than erasesize!\n");
                return -1;
              }

            /* Check if partition size is multiple of erase block */

            if ((partszbytes % erasesize) != 0)
              {
                ferr("ERROR: Partition size is not multiple of erasesize!\n");
                return -1;
              }

            mtd_part    = mtd_partition(mtd, partoffset, partszbytes / erasesize);
            partoffset += partszbytes / erasesize;

#ifdef CONFIG_STM32F429I_DISCO_FLASH_CONFIG_PART
            /* Test if this is the config partition */

            if (CONFIG_STM32F429I_DISCO_FLASH_CONFIG_PART_NUMBER == partno)
              {
                /* Register the partition as the config device */

                mtdconfig_register(mtd_part);
              }
            else
#endif
              {
                /* Now initialize a SMART Flash block device and bind it
                 * to the MTD device.
                 */

#if defined(CONFIG_MTD_SMART) && defined(CONFIG_FS_SMARTFS)
                sprintf(partref, "p%d", partno);
                smart_initialize(CONFIG_STM32F429I_DISCO_FLASH_MINOR, mtd_part, partref);
#endif
              }

#if defined(CONFIG_MTD_PARTITION_NAMES)
            /* Set the partition name */

            if (mtd_part == NULL)
              {
                ferr("ERROR: failed to create partition %s\n", partname);
                return -1;
              }

            mtd_setpartitionname(mtd_part, partname);

            /* Now skip to next name.  We don't need to split the string here
             * because the MTD partition logic will only display names up to
             * the comma, thus allowing us to use a single static name
             * in the code.
             */

            while (*partname != ',' && *partname != '\0')
              {
                /* Skip to next ',' */

                partname++;
              }

            if (*partname == ',')
              {
                partname++;
              }
#endif

            /* Update the pointer to point to the next size in the list */

            while ((*ptr >= '0') && (*ptr <= '9'))
              {
                ptr++;
              }

            if (*ptr == ',')
              {
                ptr++;
              }

            /* Increment the part number */

            partno++;
          }
      }
#else /* CONFIG_STM32F429I_DISCO_FLASH_PART */

      /* Configure the device with no partition support */

      smart_initialize(CONFIG_STM32F429I_DISCO_FLASH_MINOR, mtd, NULL);

#endif /* CONFIG_STM32F429I_DISCO_FLASH_PART */
    }

#endif /* CONFIG_MTD */
#endif /* CONFIG_STM32_SPI4 */

  /* Create a RAM MTD device if configured */

#if defined(CONFIG_RAMMTD) && defined(CONFIG_STM32F429I_DISCO_RAMMTD)
  {
    uint8_t *start = (uint8_t *) kmm_malloc(CONFIG_STM32F429I_DISCO_RAMMTD_SIZE * 1024);
    mtd = rammtd_initialize(start, CONFIG_STM32F429I_DISCO_RAMMTD_SIZE * 1024);
    mtd->ioctl(mtd, MTDIOC_BULKERASE, 0);

    /* Now initialize a SMART Flash block device and bind it to the MTD device */

#if defined(CONFIG_MTD_SMART) && defined(CONFIG_FS_SMARTFS)
    smart_initialize(CONFIG_STM32F429I_DISCO_RAMMTD_MINOR, mtd, NULL);
#endif
  }

#endif /* CONFIG_RAMMTD && CONFIG_STM32F429I_DISCO_RAMMTD */

#ifdef HAVE_USBHOST
  /* Initialize USB host operation.  stm32_usbhost_initialize() starts a thread
   * will monitor for USB connection and disconnection events.
   */

  ret = stm32_usbhost_initialize();
  if (ret != OK)
    {
      syslog(LOG_ERR, "ERROR: Failed to initialize USB host: %d\n", ret);
      return ret;
    }
#endif

#ifdef HAVE_USBMONITOR
  /* Start the USB Monitor */

  ret = usbmonitor_start();
  if (ret != OK)
    {
      syslog(LOG_ERR, "ERROR: Failed to start USB monitor: %d\n", ret);
    }
#endif

#if defined(CONFIG_I2C) && defined(CONFIG_MPU6050)
	stm32_mpu6050_initialize("/dev/mpu6050");
#endif

  return OK;
}
Esempio n. 21
0
  /*
   *
   *  @param   file    Pointer to the file
   *  @param   debug   Turn on debug printing
   *
   *  @ingroup inputfiles
   */
  void ct2ctml(const char* file, const int debug) {

#ifdef HAS_NO_PYTHON
    /*
     *  Section to bomb out if python is not
     *  present in the computation environment.
     */
    string ppath = file;
    throw CanteraError("ct2ctml", 
		       "python cti to ctml conversion requested for file, " + ppath +
		       ", but not available in this computational environment");
#endif

    time_t aclock;
    time( &aclock );
    int ia = static_cast<int>(aclock);
    string path =  tmpDir()+"/.cttmp"+int2str(ia)+".pyw";
    ofstream f(path.c_str());
    if (!f) {
      throw CanteraError("ct2ctml","cannot open "+path+" for writing.");
    }

    f << "from ctml_writer import *\n"
      << "import sys, os, os.path\n"
      << "file = \"" << file << "\"\n"
      << "base = os.path.basename(file)\n"
      << "root, ext = os.path.splitext(base)\n"
      << "dataset(root)\n"
      << "execfile(file)\n"
      << "write()\n";
    f.close();
    string logfile = tmpDir()+"/ct2ctml.log";
#ifdef WIN32
    string cmd = pypath() + " " + "\"" + path + "\"" + "> " + logfile + " 2>&1";
#else
    string cmd = "sleep " + sleep() + "; " + "\"" + pypath() + "\"" + 
      " " + "\"" + path + "\"" + " &> " + logfile;
#endif
#ifdef DEBUG_PATHS
    writelog("ct2ctml: executing the command " + cmd + "\n");
#endif
    if (debug > 0) {
      writelog("ct2ctml: executing the command " + cmd + "\n");
      writelog("ct2ctml: the Python command is: " + pypath() + "\n");
    }

    int ierr = 0;
    try {
      ierr = system(cmd.c_str());
    }
    catch (...) {
      ierr = -10;
	  if (debug > 0) {
	    writelog("ct2ctml: command execution failed.\n");
	  }
    }

    /*
     * This next section may seem a bit weird. However, it is in
     * response to an issue that arises when running cantera with
     * cygwin, using cygwin's python intepreter. Basically, the
     * xml file is written to the local directory by the last
     * system command. Then, the xml file is read immediately
     * after by an ifstream() c++ command. Unfortunately, it seems
     * that the directory info is not being synched fast enough so
     * that the ifstream() read fails, even though the file is
     * actually there. Putting in a sleep system call here fixes
     * this problem. Also, having the xml file pre-existing fixes
     * the problem as well. There may be more direct ways to fix
     * this bug; however, I am not aware of them.
     * HKM -> During the solaris port, I found the same thing.
     *        It probably has to do with NFS syncing problems.
     *        3/3/06
     */
#ifndef WIN32
    string sss = sleep();
    if (debug > 0) {
      writelog("sleeping for " + sss + " secs+\n");
    }
    cmd = "sleep " + sss;
    try {
      ierr = system(cmd.c_str());
    }
    catch (...) {
      ierr = -10;
      writelog("ct2ctml: command execution failed.\n");
    }
#else
    // This command works on windows machines if Windows.h and Winbase.h are included
    // Sleep(5000);
#endif
    // show the contents of the log file on the screen
    try {
      char ch=0;
      string s = "";
      ifstream ferr("ct2ctml.log");
      if (ferr) {
	    while (!ferr.eof()) {
	      ferr.get(ch);
	      s += ch;
	      if (ch == '\n') {
	        writelog(s);
	        s = "";
	      }
	    }
	    ferr.close();
      }
      else {
            if (debug > 0) {
	      writelog("cannot open ct2ctml.log for reading.\n");
	    }
      }
    }
    catch (...) {
      writelog("ct2ctml: caught something \n");; 
    }
    if (ierr != 0) {
      string msg = cmd;
	  writelog("ct2ctml: throw cantera error \n");; 
      throw CanteraError("ct2ctml", 
			 "could not convert input file to CTML.\n "
			 "Command line was: \n" + msg);
    }

    // if the conversion succeeded and DEBUG_PATHS is not defined,
    // then clean up by deleting the temporary Python file.
#ifndef DEBUG_PATHS
    //#ifdef WIN32
    //cmd = "cmd /C rm " + path;
    if (debug == 0)
      remove(path.c_str());
    else {
      writelog("ct2ctml: retaining temporary file "+path+"\n");
    }
#else
    if (debug > 0) {
      writelog("ct2ctml: retaining temporary file "+path+"\n");
    }
#endif
  }
Esempio n. 22
0
File: ls.c Progetto: Dorif/escu
void ls(DIR *d){
	struct stat fs;
	struct dirent *ent;
	while(ent=readdir(d)){
	if(stat(ent->d_name,&fs))ferr(progname);
	if(!shh & !strncmp(ent->d_name, ".",1))continue;
	if(!shdd & (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")))continue;
	if(shr){
		if(fs.st_mode & S_IFDIR)putchar('d');
		else putchar('-');
		if(fs.st_mode & S_IRUSR)putchar('r');
		else putchar('-');
		if(fs.st_mode & S_IWUSR)putchar('w');
		else putchar('-');
		if(fs.st_mode & S_IXUSR){
			if(fs.st_mode & S_ISUID)putchar('s');
			else putchar('x');
		}
		else {
			if(fs.st_mode & S_ISUID)putchar('S');
			else putchar('-');
		}
		if(fs.st_mode & S_IRGRP)putchar('r');
		else putchar('-');
		if(fs.st_mode & S_IWGRP)putchar('w');
		else putchar('-');
		if(fs.st_mode & S_IXGRP){
			if(fs.st_mode & S_ISUID)putchar('s');
			else putchar('x');
		}
		else {
			if(fs.st_mode & S_ISUID)putchar('S');
			else putchar('-');
		}
		if(fs.st_mode & S_IROTH)putchar('r');
		else putchar('-');
		if(fs.st_mode & S_IWOTH)putchar('w');
		else putchar('-');
		if(fs.st_mode & S_IXOTH){
			if((fs.st_mode & S_IFDIR) & (fs.st_mode & S_ISVTX))putchar('t');
			else putchar('x');
		}
		else {
			if((fs.st_mode & S_IFDIR) & (fs.st_mode & S_ISVTX))putchar('T');
			else putchar('-');
		}
		putchar(' ');
	}
	if(!nsu&shu){
		struct passwd *pw;
		pw=getpwuid(fs.st_uid);
		printf("%s ",pw->pw_name);
		}
	if(!nsg&shg){
		struct group *grp;
		grp=getgrgid(fs.st_gid);
		printf("%s ",grp->gr_name);
		}
	if(!nsu&sui)printf("%i ",fs.st_uid);
	if(!nsg&sgi)printf("%i ",fs.st_gid);
	if(shs)printf("%li ",fs.st_size);
	if(shi)printf("%li ",fs.st_ino);
	if(smt){
		char *mt, mtn;
		if(shc)mt=ctime(&fs.st_ctime);
		else if(sat) mt=ctime(&fs.st_atime);
			else mt=ctime(&fs.st_mtime);
		strncat(&mtn, mt, strlen(mt)-1);
		printf("%s ",&mtn);
	}
	printf("%s", ent->d_name);
	if((sht || shd) & S_ISDIR(fs.st_mode))putchar('/');
	if(sht){
	if(S_ISLNK(fs.st_mode))putchar('@');
	if(S_ISFIFO(fs.st_mode))putchar('|');
	if(S_IXUSR & fs.st_mode)putchar('*');
	if(S_IFSOCK & fs.st_mode)putchar('=');
	}
	struct dirent *chk;
	if(chk=readdir(d)){
		if(wre)putchar('\n');
		else if(wrc)printf(", ");
			else putchar('\t');
	}
	}
}
Esempio n. 23
0
File: ftl.c Progetto: a1ien/nuttx
int ftl_initialize(int minor, FAR struct mtd_dev_s *mtd)
{
  struct ftl_struct_s *dev;
  char devname[16];
  int ret = -ENOMEM;

  /* Sanity check */

#ifdef CONFIG_DEBUG_FEATURES
  if (minor < 0 || minor > 255 || !mtd)
    {
      return -EINVAL;
    }
#endif

  /* Allocate a FTL device structure */

  dev = (struct ftl_struct_s *)kmm_malloc(sizeof(struct ftl_struct_s));
  if (dev)
    {
      /* Initialize the FTL device structure */

      dev->mtd = mtd;

      /* Get the device geometry. (casting to uintptr_t first eliminates
       * complaints on some architectures where the sizeof long is different
       * from the size of a pointer).
       */

      ret = MTD_IOCTL(mtd, MTDIOC_GEOMETRY, (unsigned long)((uintptr_t)&dev->geo));
      if (ret < 0)
        {
          ferr("ERROR: MTD ioctl(MTDIOC_GEOMETRY) failed: %d\n", ret);
          kmm_free(dev);
          return ret;
        }

      /* Allocate one, in-memory erase block buffer */

#ifdef CONFIG_FS_WRITABLE
      dev->eblock  = (FAR uint8_t *)kmm_malloc(dev->geo.erasesize);
      if (!dev->eblock)
        {
          ferr("ERROR: Failed to allocate an erase block buffer\n");
          kmm_free(dev);
          return -ENOMEM;
        }
#endif

      /* Get the number of R/W blocks per erase block */

      dev->blkper = dev->geo.erasesize / dev->geo.blocksize;
      DEBUGASSERT(dev->blkper * dev->geo.blocksize == dev->geo.erasesize);

      /* Configure read-ahead/write buffering */

#ifdef FTL_HAVE_RWBUFFER
      dev->rwb.blocksize   = dev->geo.blocksize;
      dev->rwb.nblocks     = dev->geo.neraseblocks * dev->blkper;
      dev->rwb.dev         = (FAR void *)dev;

#if defined(CONFIG_FS_WRITABLE) && defined(CONFIG_FTL_WRITEBUFFER)
      dev->rwb.wrmaxblocks = dev->blkper;
      dev->rwb.wrflush     = ftl_flush;
#endif

#ifdef CONFIG_FTL_READAHEAD
      dev->rwb.rhmaxblocks = dev->blkper;
      dev->rwb.rhreload    = ftl_reload;
#endif

      ret = rwb_initialize(&dev->rwb);
      if (ret < 0)
        {
          ferr("ERROR: rwb_initialize failed: %d\n", ret);
          kmm_free(dev);
          return ret;
        }
#endif

      /* Create a MTD block device name */

      snprintf(devname, 16, "/dev/mtdblock%d", minor);

      /* Inode private data is a reference to the FTL device structure */

      ret = register_blockdriver(devname, &g_bops, 0, dev);
      if (ret < 0)
        {
          ferr("ERROR: register_blockdriver failed: %d\n", -ret);
          kmm_free(dev);
        }
    }

  return ret;
}
Esempio n. 24
0
File: sstrip.c Progetto: deater/tb1
/* readelfheader() reads the ELF header into our global variable, and
 * checks to make sure that this is in fact a file that we should be
 * munging.
 */
static int readelfheader(int fd, Elf_Ehdr *ehdr) {
    errno = 0;
    if (read(fd, ehdr, sizeof *ehdr) != sizeof *ehdr) {
	return ferr("missing or incomplete ELF header.");
    }
   
    /* Check the ELF signature.
     */
    if (!(ehdr->e_ident[EI_MAG0] == ELFMAG0 &&
	  ehdr->e_ident[EI_MAG1] == ELFMAG1 &&
	  ehdr->e_ident[EI_MAG2] == ELFMAG2 &&
	  ehdr->e_ident[EI_MAG3] == ELFMAG3)) {
	printf("missing ELF signature.");
        exit(0);
    }

    /* Compare the file's class and endianness with the program's.
     */

   if (ELF_DATA == ELFDATA2LSB) {         /* 2's complement, little endian */
      if (!little_endian) {
         fprintf(stderr,"Warning!  Host and target endianess don't match!\n");
	 swap_bytes=1;
      }
   }
   else if (ELF_DATA == ELFDATA2MSB) {    /* 2's complement, big endian */
      if (little_endian) {
         fprintf(stderr,"Warning!  Host and target endianess don't match!\n");
	 swap_bytes=1;
      }
   }
   else {
      err("Unknown endianess type.");
   }
   
   if (ELF_CLASS == ELFCLASS64) {
      if (sizeof(void *)!=8) err("host!=elf word size not supported");
   }
   else if (ELF_CLASS == ELFCLASS32) {
      if (sizeof(void *)!=4) err("host!=elf word size not supported");
   }
   else {
      err("Unknown word size");
   }
   
    if (ehdr->e_ident[EI_DATA] != ELF_DATA) {
       err("ELF file has different endianness.");
    }

    if (ehdr->e_ident[EI_CLASS] != ELF_CLASS) {
       err("ELF file has different word size.");
    }

    /* Check the target architecture.
     */
     { unsigned short machine;
       machine=ehdr->e_machine;
       if (swap_bytes) machine=bswap_16(machine);
	
       if (machine != ELF_ARCH) {
          fprintf(stderr, "Warning!  "
	       "ELF file created for different architecture: %d\n",
	       ehdr->e_machine);
       }
     }

    /* Verify the sizes of the ELF header and the program segment
     * header table entries.
     */
     { short ehsize;
	ehsize=ehdr->e_ehsize;
	if (swap_bytes) ehsize=bswap_16(ehsize);
    
	if (ehsize != sizeof(Elf_Ehdr)) {
           fprintf(stderr,"Warning! "
	       "unrecognized ELF header size: %d != %ld\n",
	       ehdr->e_ehsize,(long)sizeof(Elf_Ehdr));
	}
     }
   
     {
	short phentsize;
	phentsize=ehdr->e_phentsize;
	if (swap_bytes) phentsize=bswap_16(phentsize);
	
        if (phentsize != sizeof(Elf_Phdr)) {
           fprintf(stderr,"Warning! "
	      "unrecognized program segment header size: %d != %ld\n",
	      ehdr->e_phentsize,(long)sizeof(Elf_Phdr));
	}
     }
   
    /* Finally, check the file type.
     */
     {short e_type;
      e_type=ehdr->e_type;
      if (swap_bytes) e_type=bswap_16(e_type);
	
      if (e_type != ET_EXEC && e_type != ET_DYN) {
	return err("not an executable or shared-object library.");
      }
     }
   
    return 1;
}
Esempio n. 25
0
/* main() loops over the cmdline arguments, leaving all the real work
 * to the other functions.
 */
int main(int argc, char *argv[])
{
	int				fd;
	union {
		Elf32_Ehdr	ehdr32;
		Elf64_Ehdr	ehdr64;
	} e;
	union {
		Elf32_Phdr	*phdrs32;
		Elf64_Phdr	*phdrs64;
	} p;
	unsigned long	newsize;
	char			**arg;
	int				failures = 0;

	if (argc < 2 || argv[1][0] == '-') {
		printf("Usage: sstrip FILE...\n"
			   "sstrip discards all nonessential bytes from an executable.\n\n"
			   "Version 2.0-X Copyright (C) 2000,2001 Brian Raiter.\n"
			   "Cross-devel hacks Copyright (C) 2004 Manuel Novoa III.\n"
			   "This program is free software, licensed under the GNU\n"
			   "General Public License. There is absolutely no warranty.\n");
		return EXIT_SUCCESS;
	}

	progname = argv[0];

	for (arg = argv + 1 ; *arg != NULL ; ++arg) {
		filename = *arg;

		fd = open(*arg, O_RDWR);
		if (fd < 0) {
			ferr("can't open");
			++failures;
			continue;
		}

		switch (readelfheaderident(fd, &e.ehdr32)) {
			case ELFCLASS32:
				if (!(readelfheader32(fd, &e.ehdr32)					&&
					  readphdrtable32(fd, &e.ehdr32, &p.phdrs32)		&&
					  getmemorysize32(&e.ehdr32, p.phdrs32, &newsize)	&&
					  truncatezeros(fd, &newsize)						&&
					  modifyheaders32(&e.ehdr32, p.phdrs32, newsize)	&&
					  commitchanges32(fd, &e.ehdr32, p.phdrs32, newsize)))
					++failures;
				break;
			case ELFCLASS64:
				if (!(readelfheader64(fd, &e.ehdr64)					&&
					  readphdrtable64(fd, &e.ehdr64, &p.phdrs64)		&&
					  getmemorysize64(&e.ehdr64, p.phdrs64, &newsize)	&&
					  truncatezeros(fd, &newsize)						&&
					  modifyheaders64(&e.ehdr64, p.phdrs64, newsize)	&&
					  commitchanges64(fd, &e.ehdr64, p.phdrs64, newsize)))
					++failures;
				break;
			default:
				++failures;
				break;
		}
		close(fd);
	}

	return failures ? EXIT_FAILURE : EXIT_SUCCESS;
}
Esempio n. 26
0
static ssize_t part_procfs_read(FAR struct file *filep, FAR char *buffer,
                                size_t buflen)
{
  FAR struct part_procfs_file_s *attr;
  FAR struct mtd_geometry_s geo;
  ssize_t total = 0;
  ssize_t blkpererase;
  ssize_t ret;
#ifdef CONFIG_MTD_PARTITION_NAMES
  char partname[11];
  FAR const char *ptr;
  uint8_t x;
#endif

  finfo("buffer=%p buflen=%d\n", buffer, (int)buflen);

  /* Recover our private data from the struct file instance */

  attr = (FAR struct part_procfs_file_s *)filep->f_priv;
  DEBUGASSERT(attr);

  /* If we are at the end of the list, then return 0 signifying the
   * end-of-file.  This also handles the special case when there are
   * no registered MTD partitions.
   */

  if (attr->nextpart)
    {
      /* Output a header before the first entry */

      if (attr->nextpart == g_pfirstpartition)
        {
#ifdef CONFIG_MTD_PARTITION_NAMES
          total = snprintf(buffer, buflen, "Name        Start    Size");
#else
          total = snprintf(buffer, buflen, "  Start    Size");
#endif

#ifndef CONFIG_FS_PROCFS_EXCLUDE_MTD
          total += snprintf(&buffer[total], buflen - total, "   MTD\n");
#else
          total += snprintf(&buffer[total], buflen - total, "\n");
#endif
        }

      /* Provide the requested data */

      do
        {
          /* Get the geometry of the FLASH device */

          ret = attr->nextpart->parent->ioctl(attr->nextpart->parent,
                  MTDIOC_GEOMETRY, (unsigned long)((uintptr_t)&geo));
          if (ret < 0)
            {
              ferr("ERROR: mtd->ioctl failed: %d\n", ret);
              return 0;
            }

          /* Get the number of blocks per erase.  There must be an even number
           * of blocks in one erase blocks.
           */

          blkpererase = geo.erasesize / geo.blocksize;

          /* Copy data from the next known partition */

#ifdef CONFIG_MTD_PARTITION_NAMES
          if (attr->nextpart->name == NULL)
            {
              strcpy(partname, "(noname)  ");
            }
          else
            {
              ptr = attr->nextpart->name;
              for (x = 0; x < sizeof(partname) - 1; x++)
                {
                  /* Test for end of partition name */

                  if (*ptr == ',' || *ptr == '\0')
                    {
                      /* Perform space fill for alignment */

                      partname[x] = ' ';
                    }
                  else
                    {
                      /* Copy next byte of partition name */

                      partname[x] = *ptr++;
                    }
                }

              partname[x] = '\0';
            }

          /* Terminate the partition name and add to output buffer */

          ret = snprintf(&buffer[total], buflen - total, "%s%7d %7d",
                  partname, attr->nextpart->firstblock / blkpererase,
                  attr->nextpart->neraseblocks);
#else
          ret = snprintf(&buffer[total], buflen - total, "%7d %7d",
                  attr->nextpart->firstblock / blkpererase,
                  attr->nextpart->neraseblocks);
#endif

#ifndef CONFIG_FS_PROCFS_EXCLUDE_MTD
          if (ret + total < buflen)
            {
              ret += snprintf(&buffer[total + ret], buflen - (total + ret),
                        "   %s\n", attr->nextpart->parent->name);
            }
#else
          if (ret + total < buflen)
            {
              ret += snprintf(&buffer[total + ret], buflen - (total + ret),
                        "\n");
            }
#endif

          if (ret + total < buflen)
            {
              /* It fit in the buffer totally.  Advance total and move to
               * next partition.
               */

              total += ret;
              attr->nextpart = attr->nextpart->pnext;
            }
          else
            {
              /* This one didn't fit completely.  Truncate the partial
               * entry and break the loop.
               */

              buffer[total] = '\0';
              break;
            }
        }
      while (attr->nextpart);
    }

  /* Update the file offset */

  if (total > 0)
    {
      filep->f_pos += total;
    }

  return total;
}
Esempio n. 27
0
File: debug.c Progetto: spott/dmd
void WRblock(block *b)
{
    if (OPTIMIZER)
    {
        if (b && b->Bweight)
                dbg_printf("B%d: (%p), weight=%d",b->Bdfoidx,b,b->Bweight);
        else
                dbg_printf("block %p",b);
        if (!b)
        {       ferr("\n");
                return;
        }
        dbg_printf(" flags=x%x weight=%d",b->Bflags,b->Bweight);
#if 0
        dbg_printf("\tfile %p, line %d",b->Bfilptr,b->Blinnum);
#endif
        dbg_printf(" ");
        WRBC(b->BC);
        dbg_printf(" Btry=%p Bindex=%d",b->Btry,b->Bindex);
#if SCPP
        if (b->BC == BCtry)
            dbg_printf(" catchvar = %p",b->catchvar);
#endif
        dbg_printf("\n");
        dbg_printf("\tBpred: "); WRblocklist(b->Bpred);
        dbg_printf("\tBsucc: "); WRblocklist(b->Bsucc);
        if (b->Belem)
        {       if (debugf)                     /* if full output       */
                        elem_print(b->Belem);
                else
                {       ferr("\t");
                        WReqn(b->Belem);
                        dbg_printf(";\n");
                }
        }
        if (b->Bcode)
            b->Bcode->print();
        ferr("\n");
    }
    else
    {
        targ_llong *pu;
        int ncases;
        list_t bl;

        assert(b);
        dbg_printf("********* Basic Block %p ************\n",b);
        if (b->Belem) elem_print(b->Belem);
        dbg_printf("block: ");
        WRBC(b->BC);
        dbg_printf(" Btry=%p Bindex=%d",b->Btry,b->Bindex);
        dbg_printf("\n");
        dbg_printf("\tBpred:\n");
        for (bl = b->Bpred; bl; bl = list_next(bl))
            dbg_printf("\t%p\n",list_block(bl));
        bl = b->Bsucc;
        switch (b->BC)
        {
            case BCswitch:
                pu = b->BS.Bswitch;
                assert(pu);
                ncases = *pu;
                dbg_printf("\tncases = %d\n",ncases);
                dbg_printf("\tdefault: %p\n",list_block(bl));
                while (ncases--)
                {   bl = list_next(bl);
                    dbg_printf("\tcase %lld: %p\n",*++pu,list_block(bl));
                }
                break;
            case BCiftrue:
            case BCgoto:
            case BCasm:
#if SCPP
            case BCtry:
            case BCcatch:
#endif
            case BCjcatch:
            case BC_try:
            case BC_filter:
            case BC_finally:
            case BC_ret:
            case BC_except:

            Lsucc:
                dbg_printf("\tBsucc:\n");
                for ( ; bl; bl = list_next(bl))
                    dbg_printf("\t%p\n",list_block(bl));
                break;
            case BCret:
            case BCretexp:
            case BCexit:
                break;
            default:
                assert(0);
        }
    }
}
Esempio n. 28
0
FAR struct mtd_dev_s *mtd_partition(FAR struct mtd_dev_s *mtd, off_t firstblock,
                                    off_t nblocks)
{
  FAR struct mtd_partition_s *part;
  FAR struct mtd_geometry_s geo;
  unsigned int blkpererase;
  off_t erasestart;
  off_t eraseend;
  off_t devblocks;
  int ret;

  DEBUGASSERT(mtd);

  /* Get the geometry of the FLASH device */

  ret = mtd->ioctl(mtd, MTDIOC_GEOMETRY, (unsigned long)((uintptr_t)&geo));
  if (ret < 0)
    {
      ferr("ERROR: mtd->ioctl failed: %d\n", ret);
      return NULL;
    }

  /* Get the number of blocks per erase.  There must be an even number of
   * blocks in one erase blocks.
   */

  blkpererase = geo.erasesize / geo.blocksize;
  DEBUGASSERT(blkpererase * geo.blocksize == geo.erasesize);

  /* Adjust the offset and size if necessary so that they are multiples of
   * the erase block size (making sure that we do not go outside of the
   * requested sub-region).  NOTE that 'eraseend' is the first erase block
   * beyond the sub-region.
   */

  erasestart = (firstblock + blkpererase - 1) / blkpererase;
  eraseend   = (firstblock + nblocks) / blkpererase;

  if (erasestart >= eraseend)
    {
      ferr("ERROR: sub-region too small\n");
      return NULL;
    }

  /* Verify that the sub-region is valid for this geometry */

  devblocks = blkpererase * geo.neraseblocks;
  if (eraseend > devblocks)
    {
      ferr("ERROR: sub-region too big\n");
      return NULL;
    }

  /* Allocate a partition device structure */

  part = (FAR struct mtd_partition_s *)kmm_zalloc(sizeof(struct mtd_partition_s));
  if (!part)
    {
      ferr("ERROR: Failed to allocate memory for the partition device\n");
      return NULL;
    }

  /* Initialize the partition device structure. (unsupported methods were
   * nullified by kmm_zalloc).
   */

  part->child.erase  = part_erase;
  part->child.bread  = part_bread;
  part->child.bwrite = part_bwrite;
  part->child.read   = mtd->read ? part_read : NULL;
  part->child.ioctl  = part_ioctl;
#ifdef CONFIG_MTD_BYTE_WRITE
  part->child.write  = mtd->write ? part_write : NULL;
#endif

  part->parent       = mtd;
  part->firstblock   = erasestart * blkpererase;
  part->neraseblocks = eraseend - erasestart;
  part->blocksize    = geo.blocksize;
  part->blkpererase  = blkpererase;

#ifdef CONFIG_MTD_PARTITION_NAMES
  part->name         = NULL;
#endif

#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_PROCFS_EXCLUDE_PARTITIONS)
  /* Add this partition to the list of known partitions */

  if (g_pfirstpartition == NULL)
    {
      g_pfirstpartition = part;
    }
  else
    {
      struct mtd_partition_s *plast;

      /* Add the partition to the end of the list */
      part->pnext = NULL;

      plast = g_pfirstpartition;
      while (plast->pnext != NULL)
        {
          /* Get pointer to next partition */
          plast = plast->pnext;
        }

      plast->pnext = part;
    }
#endif

  /* Return the implementation-specific state structure as the MTD device */

  return &part->child;
}
Esempio n. 29
0
int block_proxy(FAR const char *blkdev, int oflags)
{
  FAR char *chardev;
  bool readonly;
  int ret;
  int fd;

  DEBUGASSERT(blkdev);

  /* Create a unique temporary file name for the character device */

  chardev = unique_chardev();
  if (chardev == NULL)
    {
      ferr("ERROR: Failed to create temporary device name\n");
      return -ENOMEM;
    }

  /* Should this character driver be read-only? */

  readonly = ((oflags & O_WROK) == 0);

  /* Wrap the block driver with an instance of the BCH driver */

  ret = bchdev_register(blkdev, chardev, readonly);
  if (ret < 0)
    {
      ferr("ERROR: bchdev_register(%s, %s) failed: %d\n",
           blkdev, chardev, ret);

      goto errout_with_chardev;
    }

  /* Open the newly created character driver */

  oflags &= ~(O_CREAT | O_EXCL | O_APPEND | O_TRUNC);
  fd = open(chardev, oflags);
  if (fd < 0)
    {
      ret = -errno;
      ferr("ERROR: Failed to open %s: %d\n", chardev, ret);
      goto errout_with_bchdev;
    }

  /* Unlink the character device name.  The driver instance will persist,
   * provided that CONFIG_DISABLE_PSEUDOFS_OPERATIONS=y (otherwise, we have
   * a problem here!)
   */

  ret = unlink(chardev);
  if (ret < 0)
    {
      ret = -errno;
      ferr("ERROR: Failed to unlink %s: %d\n", chardev, ret);
    }

  /* Free the allocate character driver name and return the open file
   * descriptor.
   */

  kmm_free(chardev);
  return fd;

errout_with_bchdev:
  (void)unlink(chardev);

errout_with_chardev:
  kmm_free(chardev);
  return ret;
}
Esempio n. 30
0
static int proc_opendir(FAR const char *relpath, FAR struct fs_dirent_s *dir)
{
  FAR struct proc_dir_s *procdir;
  FAR const struct proc_node_s *node;
  FAR struct tcb_s *tcb;
  irqstate_t flags;
  unsigned long tmp;
  FAR char *ptr;
  pid_t pid;

  finfo("relpath: \"%s\"\n", relpath ? relpath : "NULL");
  DEBUGASSERT(relpath != NULL && dir != NULL && dir->u.procfs == NULL);

  /* The relative must be either:
   *
   *  (1) "<pid>" - The sub-directory of task/thread attributes,
   *  (2) "self"  - Which refers to the PID of the calling task, or
   *  (3) The name of a directory node under either of those
   */

  /* Otherwise, the relative path should be a valid task/thread ID */

  ptr = NULL;

  if (strncmp(relpath, "self", 4) == 0)
    {
      tmp = (unsigned long)getpid();    /* Get the PID of the calling task */
      ptr = (FAR char *)relpath + 4;    /* Discard const */
    }
  else
    {
      tmp = strtoul(relpath, &ptr, 10); /* Extract the PID from path */
    }

  if (ptr == NULL || (*ptr != '\0' && *ptr != '/'))
    {
      /* strtoul failed or there is something in the path after the pid */

      ferr("ERROR: Invalid path \"%s\"\n", relpath);
      return -ENOENT;
   }

  /* A valid PID would be in the range of 0-32767 (0 is reserved for the
   * IDLE thread).
   */

  if (tmp >= 32768)
    {
      ferr("ERROR: Invalid PID %ld\n", tmp);
      return -ENOENT;
    }

  /* Now verify that a task with this task/thread ID exists */

  pid = (pid_t)tmp;

  flags = enter_critical_section();
  tcb = sched_gettcb(pid);
  leave_critical_section(flags);

  if (tcb == NULL)
    {
      ferr("ERROR: PID %d is not valid\n", (int)pid);
      return -ENOENT;
    }

  /* Allocate the directory structure.  Note that the index and procentry
   * pointer are implicitly nullified by kmm_zalloc().  Only the remaining,
   * non-zero entries will need be initialized.
   */

  procdir = (FAR struct proc_dir_s *)kmm_zalloc(sizeof(struct proc_dir_s));
  if (procdir == NULL)
    {
      ferr("ERROR: Failed to allocate the directory structure\n");
      return -ENOMEM;
    }

  /* Was the <pid> the final element of the path? */

  if (*ptr != '\0' && strcmp(ptr, "/") != 0)
    {
      /* There is something in the path after the pid.  Skip over the path
       * segment delimiter and see if we can identify the node of interest.
       */

      ptr++;
      node = proc_findnode(ptr);
      if (node == NULL)
        {
          ferr("ERROR: Invalid path \"%s\"\n", relpath);
          kmm_free(procdir);
          return -ENOENT;
        }

      /* The node must be a directory, not a file */

      if (!DIRENT_ISDIRECTORY(node->dtype))
        {
          ferr("ERROR: Path \"%s\" is not a directory\n", relpath);
          kmm_free(procdir);
          return -ENOTDIR;
        }

      /* This is a second level directory */

      procdir->base.level    = 2;
      procdir->base.nentries = PROC_NGROUPNODES;
      procdir->node          = node;
    }
  else
    {
      /* Use the special level0 node */

      procdir->base.level    = 1;
      procdir->base.nentries = PROC_NLEVEL0NODES;
      procdir->node          = &g_level0node;
    }

   procdir->pid  = pid;
   dir->u.procfs = (FAR void *)procdir;
   return OK;
}