Beispiel #1
0
/*int strlenn(const char *s)
{
	int a = 0;
	
	while((s != NULL) && (*s != '\0'))
	{
		s++;
		a++;	
	}

	return a;
} */
int main(int argc, char *argv[]) 
{
	printf("strlenn = %d\n", strlenn("ABSDS"));
	printf("strlen(NULL) = %d\n", strlenn(NULL));
	printf("strlen(\"\") = %d\n", strlenn(""));
	return 0;
}
Beispiel #2
0
/**
 * Get kmalloc'd array for full path name.
 */
static char * format_fpath(struct fatfs_inode * indir, const char * name)
{
    char * fpath;
    size_t fpath_size;

#ifdef configFATFS_DEBUG
    KERROR(KERROR_DEBUG,
             "format_fpath(indir \"%s\", name \"%s\")\n",
             indir->in_fpath, name);
#endif

    fpath_size = strlenn(name, NAME_MAX + 1) +
                 strlenn(indir->in_fpath, NAME_MAX + 1) + 6;
    fpath = kmalloc(fpath_size);
    if (!fpath)
        return NULL;

    ksprintf(fpath, fpath_size, "%s/%s", indir->in_fpath, name);

#ifdef configFATFS_DEBUG
    KERROR(KERROR_DEBUG, "Formatted \"%s\" as \"%s\"\n",
           name, fpath);
#endif

    return fpath;
}
Beispiel #3
0
void * main(void * arg)
{
    int r0, r1, r2;
    const char tty_path[] = "/dev/ttyS0";
//    char buf[80];

    mkdir("/dev", S_IRWXU | S_IRGRP | S_IXGRP);
    mount("", "/dev", "devfs", 0, "");

    close(STDIN_FILENO);
    close(STDOUT_FILENO);
    close(STDERR_FILENO);
    r0 = open(tty_path, O_RDONLY);
    r1 = open(tty_path, O_WRONLY);
    r2 = open(tty_path, O_WRONLY);

#if 0
    ksprintf(buf, sizeof(buf), "fd: %i, %i, %i\n", r0, r1, r2);
    write(STDOUT_FILENO, buf, strlenn(buf, sizeof(buf)));
#endif

    write(STDOUT_FILENO, banner, sizeof(banner));
    write(STDOUT_FILENO, msg, sizeof(msg));

#if configTISH != 0
    tish();
#endif
    while(1) {
        write(STDOUT_FILENO, "init\n", 5);
        sleep(10);
    }
}
Beispiel #4
0
	veryLong veryLong::operator+(veryLong n1)
	{
		veryLong n;
		unsigned char *del;
		if (!binary)
		{
			turn(&number);
			turn(&n1.number);
			del=n.number;
			if ((znak=='+')&&(n1.znak=='+'))
			{
				n.number = summ(&number,&n1.number);
				n.znak='+';
			}
			if ((znak=='-')&&(n1.znak=='-'))
			{
				n.number = summ(&number,&n1.number);
				n.znak='-';
			}
			if ((znak=='+')&&(n1.znak=='-'))
			{
				if (cmp(&number,&n1.number) == 1)
					{
						n.number = sub(&number,&n1.number);
						n.znak='+';
					}
					else
					{
						n.number = sub(&n1.number,&number);
						n.znak='-';
					}
			}
			if ((znak=='-')&&(n1.znak=='+'))
			{
				if (cmp(&number,&n1.number) == 1)
					{
						n.number = sub(&number,&n1.number);
						n.znak='-';
					}
					else
					{
						n.number = sub(&n1.number,&number);
						n.znak='+';
					}
			}
			n.lenght = strlenn(&n.number);
			n.binary=binary;
			turn(&number);
			turn(&n1.number);
			turn(&n.number);
			if (del != NULL)
				free(del);
		}
		else
		{
			n.number = summb(&number,&n1.number,lenght,n1.lenght,&n.lenght);
			n.binary=binary;
		}
		return n;
	}
Beispiel #5
0
/************************************************
**递归方式实现测量
****************************************/ 
int strlenn(const char *s)
{	
	static int a = 0;
	
	if(s == NULL)
	{
		return -1;
	}
	else
	{
		if(*s == '\0')
		{
			printf("%s \n", "end");
			return 0;
		}
		else
		{
			
			s++;
			printf("%s \n", s);
			strlenn(s);
			
			printf("%s \n", s);
			a++;
			return a;
		}	
	}
} 
Beispiel #6
0
	veryLong veryLong::operator/(veryLong n1)
	{
		veryLong n;
		unsigned char *ostatok;
		int lenOst;
		if (!binary)
		{
			if (((znak=='+')&&(n1.znak=='+'))||((znak=='-')&&(n1.znak=='-')))
			{
				n.number = divv(&number,&n1.number,&ostatok);
				n.znak='+';
			}
			else
			{
				n.number = divv(&number,&n1.number,&ostatok);
				n.znak='-';
			}
			n.lenght = strlenn(&n.number);
			n.binary=binary;
		}
		else
		{
			turnb(&number,lenght);
			turnb(&n1.number,n1.lenght);
			n.number = divvb(&number,&n1.number,lenght,n1.lenght,&n.lenght,&ostatok,&lenOst);
			n.binary=binary;
			turnb(&number,lenght);
			turnb(&n1.number,n1.lenght);
			turnb(&n.number,n.lenght);
		}
		return n;
	}
Beispiel #7
0
int parsenames(const char * pathname, char ** path, char ** name)
{
    char * path_act;
    char * fname;
    size_t i, j;

    KASSERT(pathname != NULL, "pathname should be set\n");

    path_act = kstrdup(pathname, PATH_MAX);
    fname = kmalloc(NAME_MAX);
    if (!path_act || !fname) {
        kfree(path_act);
        kfree(fname);

        return -ENOMEM;
    }

    i = strlenn(path_act, PATH_MAX);
    if (path_act[i] != '\0')
        goto fail;

    while (path_act[i] != '/') {
        path_act[i--] = '\0';
        if ((i == 0) &&
            (!(path_act[0] == '/') ||
             !(path_act[0] == '.' && path_act[1] == '/'))) {
            path_act[0] = '.';
            path_act[1] = '/';
            path_act[2] = '\0';
            i--; /* little trick */
            break;
        }
    }

    for (j = 0; j < NAME_MAX;) {
        i++;
        if (pathname[i] == '/')
            continue;

        fname[j] = pathname[i];
        if (fname[j] == '\0')
            break;
        j++;
    }

    if (fname[j] != '\0')
        goto fail;

    if (path)
        *path = path_act;
    if (name)
        *name = fname;

    return 0;

fail:
    kfree(path_act);
    kfree(fname);
    return -ENAMETOOLONG;
}
Beispiel #8
0
	veryLong veryLong::operator*(veryLong n1)
	{
		veryLong n;
		if (!binary)
		{
			turn(&number);
			if (&number != &n1.number)
				turn(&n1.number);
			if (((znak=='+')&&(n1.znak=='+'))||((znak=='-')&&(n1.znak=='-')))
			{
				n.number = mul(&number,&n1.number);
				n.znak='+';
			}
			else
			{
				n.number = mul(&number,&n1.number);
				n.znak='-';
			}
			n.lenght = strlenn(&n.number);
			n.binary=binary;
			turn(&number);
			if (&number != &n1.number)
				turn(&n1.number);
			turn(&n.number);
		}
		else
		{
			n.number = mulb(&number,&n1.number,lenght,n1.lenght,&n.lenght);
			n.binary=binary;
		}
		return n;
	}
Beispiel #9
0
	veryLong veryLong::operator-(veryLong n1)
	{
		veryLong n;
		if (!binary)
		{
			turn(&number);
			turn(&n1.number);
			if ((znak=='+')&&(n1.znak=='+'))
			{
				if (cmp(&number,&n1.number) == 1)
					{
						n.number = sub(&number,&n1.number);
						n.znak='+';
					}
					else
					{
						n.number = sub(&n1.number,&number);
						n.znak='-';
					}
			}
			if ((znak=='-')&&(n1.znak=='+'))
			{
				if (cmp(&number,&n1.number) == 1)
					{
						n.number = sub(&number,&n1.number);
						n.znak='-';
					}
					else
					{
						n.number = sub(&n1.number,&number);
						n.znak='+';
					}
			}
			if ((znak=='+')&&(n1.znak=='-'))
			{
				n.number = summ(&number,&n1.number);
				n.znak='+';
			}
			if ((znak=='-')&&(n1.znak=='+'))
			{
				n.number = summ(&number,&n1.number);
				n.znak='-';
			}
			n.lenght = strlenn(&n.number);
			n.binary=binary;
			turn(&number);
			turn(&n1.number);
			turn(&n.number);
		}
		else
		{
			n.number = subb(&number,&n1.number,lenght,n1.lenght,&n.lenght);
			n.binary=binary;
		}
		return n;
	}
Beispiel #10
0
	veryLong veryLong::operator=(const char* str)
	{
		int i;
		(*this).number=(unsigned char*)malloc(block);
		for (i=0;i<strlen(str);i++)
			(*this).number[i]=str[i];
		(*this).number[i]='\0';
		(*this).lenght=strlenn(&(*this).number);
		return *this;
	}
Beispiel #11
0
I getdelim_(S *s,I *n,I d,FILE *f)
{
  I m; S z;size_t o=*n;
  if(getdelim(s,&o,d,f)==-1){*n=0; R -1;}
  *n=o;
  m=strlenn(*s,*n);
  if(1<m && '\n'==(*s)[m-1] && '\r'==(*s)[m-2]) {
    (*s)[--m]='\0'; (*s)[m-1]='\n'; }
  z=strdupn(*s,m);
  free(*s);
  *s=z;
  R *n=m;
}
size_t asccpyn(wchar_t* buffer, size_t buflen,
               const char* source, size_t srclen) {
  if (buflen <= 0)
    return 0;

  if (srclen == SIZE_UNKNOWN) {
    srclen = strlenn(source, buflen - 1);
  } else if (srclen >= buflen) {
    srclen = buflen - 1;
  }
#if _DEBUG
  // Double check that characters are not UTF-8
  for (size_t pos = 0; pos < srclen; ++pos)
    ASSERT(static_cast<unsigned char>(source[pos]) < 128);
#endif  // _DEBUG
  std::copy(source, source + srclen, buffer);
  buffer[srclen] = 0;
  return srclen;
}
Beispiel #13
0
	veryLong veryLong::operator^(veryLong n1)
	{
		veryLong n;
		if (!binary)
		{
			turn(&number);
			turn(&n1.number);
			n.znak=znak;
			n.number = stepen(&number,&n1.number,&n.znak);
			n.lenght = strlenn(&n.number);
			n.binary=binary;
			turn(&number);
			turn(&n1.number);
			turn(&n.number);
		}
		else
		{
			n.number = stepenb(&number,&n1.number,lenght,n1.lenght,&n.lenght);
			n.binary=binary;
		}
		return n;
	}
Beispiel #14
0
	veryLong veryLong::operator%(veryLong n1)
	{
		veryLong n;
		unsigned char *ostatok;
		int lenOst;
		if (!binary)
		{
			divv(&number,&n1.number,&n.number);
			n.lenght = strlenn(&n.number);
			n.binary=binary;
		}
		else
		{
			turnb(&number,lenght);
			turnb(&n1.number,n1.lenght);
			divvb(&number,&n1.number,lenght,n1.lenght,&lenOst,&n.number,&n.lenght);
			n.binary=binary;
			turnb(&number,lenght);
			turnb(&n1.number,n1.lenght);
			turnb(&n.number,n.lenght);
		}
		return n;
	}
Beispiel #15
0
void start_kernel(struct params_t *params, int choice)
{
	/* we use var[] instead of *var because sizeof(var) using */
#ifdef USE_HOST_DEBUG
	const char kexec_path[] = "/bin/echo";
#else
	const char kexec_path[] = KEXEC_PATH;
#endif
	const char mount_point[] = MOUNTPOINT;

	const char str_cmdline_start[] = "--command-line=root=";
	const char str_rootfstype[] = " rootfstype=";
	const char str_rootwait[] = " rootwait";
	const char str_ubirootdev[] = "ubi0";
	const char str_ubimtd[] = " ubi.mtd="; /* max ' ubi.mtd=15' len 11 +1 = 12 */

#ifdef UBI_VID_HDR_OFFSET
	const char str_ubimtd_off[] = UBI_VID_HDR_OFFSET;
#else
	const char str_ubimtd_off[] = "";
#endif

	char mount_dev[16];
	char mount_fstype[16];
	char str_mtd_id[3];

	/* Tags passed from host kernel cmdline to kexec'ed kernel */
	const char str_mtdparts[] = " mtdparts=";
	const char str_fbcon[] = " fbcon=";

	const char str_initrd_start[] = "--initrd=";

	/* empty environment */
	char *const envp[] = { NULL };

	const char *load_argv[] = { NULL, "-l", NULL, NULL, NULL, NULL };
	const char *exec_argv[] = { NULL, "-e", NULL, NULL};

	char *cmdline_arg = NULL, *initrd_arg = NULL;
	int n, idx, u;
	struct stat sinfo;
	struct boot_item_t *item;

	item = params->bootcfg->list[choice];

	exec_argv[0] = kexec_path;
	load_argv[0] = kexec_path;

	/* --command-line arg generation */
	idx = 2;	/* load_argv current option index */

	/* fill '--command-line' option */
	if (item->device) {
		/* default device to mount */
		strcpy(mount_dev, item->device);

		/* allocate space */
		n = sizeof(str_cmdline_start) + strlen(item->device) +
				sizeof(str_ubirootdev) + 2 +
				sizeof(str_ubimtd) + 2 + sizeof(str_ubimtd_off) + 1 +
				sizeof(str_rootwait) +
				sizeof(str_rootfstype) + strlen(item->fstype) + 2 +
				sizeof(str_mtdparts) + strlenn(params->cfg->mtdparts) +
				sizeof(str_fbcon) + strlenn(params->cfg->fbcon) +
				sizeof(char) + strlenn(item->cmdline);

		cmdline_arg = (char *)malloc(n);
		if (NULL == cmdline_arg) {
			perror("Can't allocate memory for cmdline_arg");
		} else {

			strcpy(cmdline_arg, str_cmdline_start);	/* --command-line=root= */

			if (item->fstype) {

				/* default fstype to mount */
				strcpy(mount_fstype, item->fstype);

				/* extra tags when we detect UBI */
				if (!strncmp(item->fstype,"ubi",3)) {

					/* mtd id [0-15] - one or two digits */
					if(isdigit(atoi(item->device+strlen(item->device)-2))) {
						strcpy(str_mtd_id, item->device+strlen(item->device)-2);
						strcat(str_mtd_id, item->device+strlen(item->device)-1);
					} else {
						strcpy(str_mtd_id, item->device+strlen(item->device)-1);
					}
					/* get corresponding ubi dev to mount */
					u = find_attached_ubi_device(str_mtd_id);

					sprintf(mount_dev, "/dev/ubi%d", u);
					 /* FIXME: first volume is hardcoded */
					strcat(mount_dev, "_0");

					/* HARDCODED: we assume it's ubifs */
					strcpy(mount_fstype,"ubifs");

					/* extra cmdline tags when we detect ubi */
					strcat(cmdline_arg, str_ubirootdev);
					 /* FIXME: first volume is hardcoded */
					strcat(cmdline_arg, "_0");

					strcat(cmdline_arg, str_ubimtd);
					strcat(cmdline_arg, str_mtd_id);
#ifdef UBI_VID_HDR_OFFSET
					strcat(cmdline_arg, ",");
					strcat(cmdline_arg, str_ubimtd_off);
#endif
				} else {
					strcat(cmdline_arg, item->device); /* root=item->device */
				}
				strcat(cmdline_arg, str_rootfstype);
				strcat(cmdline_arg, mount_fstype);
			}
			strcat(cmdline_arg, str_rootwait);

			if (params->cfg->mtdparts) {
				strcat(cmdline_arg, str_mtdparts);
				strcat(cmdline_arg, params->cfg->mtdparts);
			}

			if (params->cfg->fbcon) {
				strcat(cmdline_arg, str_fbcon);
				strcat(cmdline_arg, params->cfg->fbcon);
			}

			if (item->cmdline) {
				strcat(cmdline_arg, " ");
				strcat(cmdline_arg, item->cmdline);
			}
			load_argv[idx] = cmdline_arg;
			++idx;
		}
	}

	/* fill '--initrd' option */
	if (item->initrd) {
		/* allocate space */
		n = sizeof(str_initrd_start) + strlen(item->initrd);

		initrd_arg = (char *)malloc(n);
		if (NULL == initrd_arg) {
			perror("Can't allocate memory for initrd_arg");
		} else {
			strcpy(initrd_arg, str_initrd_start);	/* --initrd= */
			strcat(initrd_arg, item->initrd);
			load_argv[idx] = initrd_arg;
			++idx;
		}
	}

	/* Append kernelpath as last arg of kexec */
	load_argv[idx] = item->kernelpath;

	DPRINTF("load_argv: %s, %s, %s, %s, %s", load_argv[0],
			load_argv[1], load_argv[2],
			load_argv[3], load_argv[4]);

	/* Mount boot device */
	if ( -1 == mount(mount_dev, mount_point, mount_fstype,
			MS_RDONLY, NULL) ) {
		perror("Can't mount boot device");
		exit(-1);
	}

	/* Load kernel */
	n = fexecw(kexec_path, (char *const *)load_argv, envp);
	if (-1 == n) {
		perror("Kexec can't load kernel");
		exit(-1);
	}

	umount(mount_point);

	dispose(cmdline_arg);
	dispose(initrd_arg);

	/* Check /proc/sys/net presence */
	if ( -1 == stat("/proc/sys/net", &sinfo) ) {
		if (ENOENT == errno) {
			/* We have no network, don't issue ifdown() while kexec'ing */
			exec_argv[2] = "-x";
			DPRINTF("No network is detected, disabling ifdown()");
		} else {
			perror("Can't stat /proc/sys/net");
		}
	}

	DPRINTF("exec_argv: %s, %s, %s", exec_argv[0],
			exec_argv[1], exec_argv[2]);

	/* Boot new kernel */
	execve(kexec_path, (char *const *)exec_argv, envp);
}
Beispiel #16
0
/**
 *  gnet_vunpack
 *  @format: unpack data format
 *  @buffer: buffer to unpack from
 *  @length: length of @buffer
 *  @args: var args
 *
 *  Var arg interface to gnet_unpack().  See gnet_unpack() for more
 *  information.
 *
 *  Returns: number of bytes packed; -1 on error.
 *
 **/
gint 
gnet_vunpack (const gchar * format, const gchar * buffer, gint length,
    va_list args)
{
  gint n = 0;
  gchar* p = (gchar*) format;
  guint mult = 0;
  gint sizemode = 0;	/* 1 = little, 2 = big */

  g_return_val_if_fail (format, -1);
  g_return_val_if_fail (buffer, -1);

  switch (*p)
    {
    case '@':					++p;	break;
    case '<':	sizemode = 1;			++p;	break;
    case '>':	
    case '!':	sizemode = 2;			++p;	break;
    }

  for (; *p; ++p)
    {
      switch (*p)
	{
	case 'x': 
	  {	
	    mult = mult? mult:1;
	    g_return_val_if_fail (n + mult <= length, FALSE);

	    buffer += mult;
	    n += mult;

	    mult = 0;
	    break; 
	  }

	case 'b':  { UNPACK(gint8); 			break;	}
	case 'B':  { UNPACK(guint8);			break;	}

	case 'h':  { UNPACK2(short, gint16); 		break;  }
	case 'H':  { UNPACK2(unsigned short, guint16);	break;  }

	case 'i':  { UNPACK2(int, gint32); 		break;  }
	case 'I':  { UNPACK2(unsigned int, guint32); 	break;  }

	case 'l':  { UNPACK2(long, gint32); 		break;  }
	case 'L':  { UNPACK2(unsigned long, guint32);	break;  }

	case 'f':  { UNPACK(float);			break;  }
	case 'd':  { UNPACK(double);			break;  }

	case 'v':  { UNPACK2(void*, void*); 		break;	}

	case 's':
	  { 
	    for (mult=(mult?mult:1); mult; --mult)
	      {
		gchar** sp; 
		gsize slen;

		sp = va_arg (args, gchar**);
		g_return_val_if_fail (sp, -1);

		slen = strlenn(buffer, length - n);
		g_return_val_if_fail (n + slen <= length, FALSE);

		*sp = g_new(gchar, slen + 1);
		memcpy (*sp, buffer, slen);
		(*sp)[slen] = 0;
		buffer += slen + 1;
		n += slen + 1;
	      }

	    mult = 0; 
	    break;
	  }

	case 'S':
	  { 
	    gchar** sp; 
	    gsize slen;

	    g_return_val_if_fail (mult, -1);

	    sp = va_arg (args, gchar**);
	    g_return_val_if_fail (sp, -1);

	    slen = MIN(mult, strlenn(buffer, length - n));
	    g_return_val_if_fail ((n + slen) <= length, -1);

	    *sp = g_new(gchar, mult + 1);

	    memcpy (*sp, buffer, slen);
	    while (slen < (mult + 1)) (*sp)[slen++] = '\0';
	    buffer += mult;
	    n += mult;

	    mult = 0; break;
	  }

	case 'r':  /* r is the same as s, in this case. */
	  { 
	    for (mult=(mult?mult:1); mult; --mult)
	      {
		gchar** sp; 
		guint ln;

		sp = va_arg (args, gchar**);
		ln = va_arg (args, guint);

		g_return_val_if_fail (sp, -1);
		g_return_val_if_fail (n + ln <= length, FALSE);

		*sp = g_new(char, ln);
		memcpy(*sp, buffer, ln);
		buffer += ln;
		n += ln;
	      }

	    mult = 0; break;
	  }

	case 'R':  
	  { 
	    gchar** sp; 

	    sp = va_arg (args, gchar**);
	    g_return_val_if_fail (sp, -1);

	    g_return_val_if_fail (mult, -1);
	    g_return_val_if_fail (n + mult <= length, -1);

	    *sp = g_new(char, mult);
	    memcpy(*sp, buffer, mult);
	    buffer += mult;
	    n += mult;
	    mult = 0; 
	    break;
	  }

	case 'p':  
	  { 
	    for (mult=(mult?mult:1); mult; --mult)
	      {
		gchar** sp;
		guint slen;

		sp = va_arg (args, gchar**);
		g_return_val_if_fail (sp, -1);
		g_return_val_if_fail (n + 1 <= length, FALSE);

		slen = *buffer++; 
		++n;
		g_return_val_if_fail (n + slen <= length, FALSE);

		*sp = g_new(gchar, slen + 1);
		memcpy (*sp, buffer, slen); 
		(*sp)[slen] = 0;
		buffer += slen;
		n += slen;
	      }

	    mult = 0;
	    break;
	  }

	case '0':  case '1': case '2': case '3': case '4':
	case '5':  case '6': case '7': case '8': case '9':
	  {
	    mult *= 10;
	    mult += (*p - '0');
	    break;
	  }

	case ' ': case '\t': case '\n': break;

	default: g_return_val_if_fail (FALSE, -1);
	}
    }

  return n;
}
Beispiel #17
0
/**
 * Lookup for a vnode (file/dir) in FatFs.
 * First lookup form vfs_hash and if not found then read it from ff which will
 * probably read it via devfs interface. After the vnode has been created it
 * will be added to the vfs hashmap. In ff terminology all files and directories
 * that are in hashmap are also open on a file/dir handle, thus we'll have to
 * make sure we don't have too many vnodes in cache that have no references, to
 * avoid hitting any ff hard limits.
 */
static int fatfs_lookup(vnode_t * dir, const char * name, vnode_t ** result)
{
    struct fatfs_inode * indir = get_inode_of_vnode(dir);
    struct fatfs_sb * sb = get_ffsb_of_sb(dir->sb);
    char * in_fpath;
    long vn_hash;
    struct vnode * vn = NULL;
    int err, retval = 0;

    KASSERT(dir != NULL, "dir must be set");

    /* Format full path */
    in_fpath = format_fpath(indir, name);
    if (!in_fpath)
        return -ENOMEM;

    /*
     * Emulate . and ..
     */
    if (name[0] == '.' && name[1] != '.') {
#ifdef configFATFS_DEBUG
        KERROR(KERROR_DEBUG, "Lookup emulating \".\"\n");
#endif
        (void)vref(dir);
        *result = dir;

        kfree(in_fpath);
        return 0;
    } else if (name[0] == '.' && name[1] == '.' && name[2] != '.') {
#ifdef configFATFS_DEBUG
        KERROR(KERROR_DEBUG, "Lookup emulating \"..\"\n");
#endif
        if (VN_IS_FSROOT(dir)) {
            *result = dir->sb->mountpoint;

            kfree(in_fpath);
            return -EDOM;
        } else {
            size_t i = strlenn(in_fpath, NAME_MAX) - 4;

            while (in_fpath[i] != '/') {
                i--;
            }
            in_fpath[i] = '\0';
        }
    }

    /*
     * Lookup from vfs_hash
     */
    vn_hash = hash32_str(in_fpath, 0);
    err = vfs_hash_get(
            dir->sb,        /* FS superblock */
            vn_hash,        /* Hash */
            &vn,            /* Retval */
            fatfs_vncmp,    /* Comparator */
            in_fpath        /* Compared fpath */
          );
    if (err) {
        retval = -EIO;
        goto fail;
    }
    if (vn) { /* found it in vfs_hash */
#ifdef configFATFS_DEBUG
        KERROR(KERROR_DEBUG, "vn found in vfs_hash (%p)\n", vn);
#endif

        *result = vn;
        retval = 0;
    } else { /* not cached */
        struct fatfs_inode * in;

#ifdef configFATFS_DEBUG
        KERROR(KERROR_DEBUG, "vn not in vfs_hash\n");
#endif

        /*
         * Create a inode and fetch data from the device.
         * This also vrefs.
         */
        err = create_inode(&in, sb, in_fpath, vn_hash, O_RDWR);
        if (err) {
            retval = err;
            goto fail;
        }

        in_fpath = NULL; /* shall not be freed. */
        *result = &in->in_vnode;
        retval = 0;
    }

fail:
    kfree(in_fpath);
    return retval;
}