Back to index

avfs  1.0.1
Defines | Typedefs | Functions | Variables
redir.c File Reference
#include <linux/version.h>
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/unistd.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <linux/coda_psdev.h>

Go to the source code of this file.

Defines

#define DEB(X)
#define REDIR_VERSION   "0.93"
#define NEWVFS   1
#define AVFS_MAGIC_CHAR   '#'
#define OVERLAY_DIR   "/overlay"
#define OVERLAY_DIR_LEN   8
#define PF_AVFS   0x00008000
#define path_ok(pwd)   (pwd->d_parent == pwd || !list_empty(&pwd->d_hash))
#define cwd_virtual()   (current->fs->pwd->d_sb->s_magic == CODA_SUPER_MAGIC)

Typedefs

typedef asmlinkage int(* chdir_func )(const char *)
typedef asmlinkage int(* stat_func )(const char *, struct stat *)
typedef asmlinkage int(* access_func )(const char *, int)
typedef asmlinkage int(* open_func )(const char *, int, int)
typedef asmlinkage int(* readlink_func )(const char *, char *, int)
typedef asmlinkage int(* getcwd_func )(char *, unsigned long)
typedef asmlinkage long(* stat64_func )(const char *, struct stat64 *, long)

Functions

static char * path_pwd (char *page)
static int a_path_walk (const char *pathname, int flags, struct nameidata *nd)
static void a_path_release (struct nameidata *nd)
static char * resolv_virt (const char *pathname, int must_exist, int flags)
static char * get_abs_path (const char *filename)
static char * resolve_name (const char *kfilename, int must_exist, int flags)
asmlinkage int virt_chdir (const char *filename)
static int do_orig_stat (stat_func sfunc, const char *filename, struct stat *statbuf)
asmlinkage int virt_stat (const char *filename, struct stat *statbuf)
asmlinkage int virt_lstat (const char *filename, struct stat *statbuf)
asmlinkage int virt_access (const char *filename, int mode)
asmlinkage int virt_open (const char *filename, int flags, int mode)
asmlinkage int virt_readlink (const char *filename, char *buf, int bufsiz)
asmlinkage int virt_getcwd (char *buf, unsigned long size)
static long do_orig_stat64 (stat64_func sfunc, const char *filename, struct stat64 *statbuf, long flags)
asmlinkage long virt_stat64 (char *filename, struct stat64 *statbuf, long flags)
asmlinkage long virt_lstat64 (char *filename, struct stat64 *statbuf, long flags)
void * replace_syscall (int index, void *new_syscall)
int init_module (void)
void cleanup_module (void)

Variables

void * sys_call_table []
static chdir_func orig_chdir
static stat_func orig_stat
static stat_func orig_lstat
static access_func orig_access
static open_func orig_open
static readlink_func orig_readlink
static getcwd_func orig_getcwd
static stat64_func orig_stat64
static stat64_func orig_lstat64

Define Documentation

#define AVFS_MAGIC_CHAR   '#'

Definition at line 63 of file redir.c.

#define cwd_virtual ( )    (current->fs->pwd->d_sb->s_magic == CODA_SUPER_MAGIC)

Definition at line 299 of file redir.c.

#define DEB (   X)

Definition at line 22 of file redir.c.

#define NEWVFS   1

Definition at line 28 of file redir.c.

#define OVERLAY_DIR   "/overlay"

Definition at line 64 of file redir.c.

#define OVERLAY_DIR_LEN   8

Definition at line 65 of file redir.c.

#define path_ok (   pwd)    (pwd->d_parent == pwd || !list_empty(&pwd->d_hash))

Definition at line 69 of file redir.c.

#define PF_AVFS   0x00008000

Definition at line 67 of file redir.c.

#define REDIR_VERSION   "0.93"

Definition at line 25 of file redir.c.


Typedef Documentation

typedef asmlinkage int(* access_func)(const char *, int)

Definition at line 37 of file redir.c.

typedef asmlinkage int(* chdir_func)(const char *)

Definition at line 35 of file redir.c.

typedef asmlinkage int(* getcwd_func)(char *, unsigned long)

Definition at line 40 of file redir.c.

typedef asmlinkage int(* open_func)(const char *, int, int)

Definition at line 38 of file redir.c.

typedef asmlinkage int(* readlink_func)(const char *, char *, int)

Definition at line 39 of file redir.c.

typedef asmlinkage long(* stat64_func)(const char *, struct stat64 *, long)

Definition at line 51 of file redir.c.

typedef asmlinkage int(* stat_func)(const char *, struct stat *)

Definition at line 36 of file redir.c.


Function Documentation

static void a_path_release ( struct nameidata *  nd) [static]

Definition at line 88 of file redir.c.

{
       dput(nd->dentry);
       mntput(nd->mnt);
}

Here is the caller graph for this function:

static int a_path_walk ( const char *  pathname,
int  flags,
struct nameidata *  nd 
) [static]

Definition at line 77 of file redir.c.

{
       int error;

       error = 0;
       if (path_init(pathname, flags, nd))
              error = path_walk(pathname, nd);

       return error;
}

Here is the caller graph for this function:

void cleanup_module ( void  )

Definition at line 891 of file redir.c.

{
       printk(KERN_INFO "redir cleanup\n");
   
       replace_syscall(__NR_chdir,    orig_chdir);
       replace_syscall(__NR_stat,     orig_stat);
       replace_syscall(__NR_lstat,    orig_lstat);
       replace_syscall(__NR_access,   orig_access);
       replace_syscall(__NR_open,     orig_open);
       replace_syscall(__NR_readlink, orig_readlink);
       replace_syscall(__NR_getcwd,   orig_getcwd);

#if NEWVFS
       replace_syscall(__NR_stat64,   orig_stat64);
       replace_syscall(__NR_lstat64,  orig_lstat64);
#endif

#ifdef __i386__
       replace_syscall(__NR_execve,   orig_execve);
#endif

}

Here is the call graph for this function:

static int do_orig_stat ( stat_func  sfunc,
const char *  filename,
struct stat statbuf 
) [static]

Definition at line 431 of file redir.c.

{
       int ret;
       mm_segment_t old_fs;
       struct stat locbuf;

       old_fs = get_fs();
       set_fs(get_ds());
       ret =  (*sfunc)(filename, &locbuf);
       set_fs(old_fs);

       if(ret == 0)
              ret = (copy_to_user(statbuf, &locbuf, sizeof(locbuf)) ? 
                     -EFAULT : 0);

       return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static long do_orig_stat64 ( stat64_func  sfunc,
const char *  filename,
struct stat64 *  statbuf,
long  flags 
) [static]

Definition at line 694 of file redir.c.

{
       long ret;
       mm_segment_t old_fs;
       struct stat64 locbuf;

       old_fs = get_fs();
       set_fs(get_ds());
       ret =  (*sfunc)(filename, &locbuf, flags);
       set_fs(old_fs);

       if(ret == 0)
              ret = (copy_to_user(statbuf, &locbuf, sizeof(locbuf)) ? 
                     -EFAULT : 0);

       return ret;
}

Here is the caller graph for this function:

static char* get_abs_path ( const char *  filename) [static]

Definition at line 302 of file redir.c.

{
       char *cwd;
       int cwdlen, fnamelen;
       char *abspath, *s;
       char *page;

       if(!path_ok(current->fs->pwd))
              return NULL;

       page = (char *) __get_free_page(GFP_USER);
       if(!page)
              return NULL;

       cwd = path_pwd(page);
       cwdlen = (unsigned int) page + PAGE_SIZE - (unsigned int) cwd - 1;
       if(cwd_virtual() && cwdlen > OVERLAY_DIR_LEN) {
              cwd += OVERLAY_DIR_LEN;
              cwdlen -= OVERLAY_DIR_LEN;
       }
              

       fnamelen = strlen(filename);

       abspath = kmalloc(cwdlen + 1 + fnamelen + 1, GFP_USER);
       if(abspath) {
              s = abspath;
              strncpy(s, cwd, cwdlen);
              s += cwdlen;
              *s++ = '/';
              strncpy(s, filename, fnamelen + 1);
       }
       free_page((unsigned long) page);
       
       return abspath;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int init_module ( void  )

Definition at line 866 of file redir.c.

{
       printk(KERN_INFO "redir init (version %s)\n", REDIR_VERSION);

       orig_chdir    = replace_syscall(__NR_chdir,    virt_chdir);
       orig_stat     = replace_syscall(__NR_stat,     virt_stat);
       orig_lstat    = replace_syscall(__NR_lstat,    virt_lstat);
       orig_access   = replace_syscall(__NR_access,   virt_access);
       orig_open     = replace_syscall(__NR_open,     virt_open);
       orig_readlink = replace_syscall(__NR_readlink, virt_readlink);
       orig_getcwd   = replace_syscall(__NR_getcwd,   virt_getcwd);

#if NEWVFS
       orig_stat64   = replace_syscall(__NR_stat64,   virt_stat64);
       orig_lstat64  = replace_syscall(__NR_lstat64,  virt_lstat64);
#endif

#ifdef __i386__
       orig_execve   = replace_syscall(__NR_execve,   virt_execve);
#endif

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* path_pwd ( char *  page) [static]

Definition at line 72 of file redir.c.

{
       return d_path(current->fs->pwd, current->fs->pwdmnt, page, PAGE_SIZE);
}

Here is the caller graph for this function:

void* replace_syscall ( int  index,
void *  new_syscall 
)

Definition at line 855 of file redir.c.

{
       void *orig_syscall = sys_call_table[index];

       printk(KERN_INFO "replacing syscall nr. %3i [%p] with [%p]\n", 
              index, orig_syscall, new_syscall);
       sys_call_table[index] = new_syscall;
       
       return orig_syscall;
}

Here is the caller graph for this function:

static char* resolv_virt ( const char *  pathname,
int  must_exist,
int  flags 
) [static]

Definition at line 94 of file redir.c.

{
       struct nameidata root;
       struct nameidata nd;
       struct dentry *origroot;
       struct vfsmount *origrootmnt;
       char *newpathname = NULL;
       char *page = NULL;
       char *path = NULL;
       int pathlen = 0;
       int error;
       int newflags;

       lock_kernel();

       DEB((KERN_INFO "resolve_virt pathname: '%s'\n", 
            pathname ? pathname : "(null)"));

       error = a_path_walk(OVERLAY_DIR, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &root);
       if(error)
              goto out;

       origroot = current->fs->root;
       origrootmnt = current->fs->rootmnt;

       current->fs->root = root.dentry;
       current->fs->rootmnt = root.mnt;
       
       newflags = flags;
       if(must_exist)
              newflags |= LOOKUP_POSITIVE;

       error  = a_path_walk(pathname, newflags, &nd);
       if(!error) {
              if(path_ok(nd.dentry)) {
                     page = (char *) __get_free_page(GFP_USER);
                     if(page) {
                            path = d_path(nd.dentry, nd.mnt, page,
                                         PAGE_SIZE);
                            DEB((KERN_INFO "resolve_virt path = '%s'\n",
                                 path));
                            pathlen = (unsigned int) page + PAGE_SIZE - 
                                   (unsigned int) path;
                     }
              }
              a_path_release(&nd);
       }

       current->fs->root = origroot;
       current->fs->rootmnt = origrootmnt;

       a_path_release(&root);

       if(path) {
              int isvirtual;

              error  = a_path_walk(path, flags, &nd);
              if(!error) {
                     if(nd.dentry->d_inode)
                            isvirtual = 0;
                     else if(must_exist)
                            isvirtual = 1;
                     else if(strchr(path, AVFS_MAGIC_CHAR))
                            isvirtual = 1;
                     else 
                            isvirtual = 0;

                     a_path_release(&nd);
              }
              else {
                     isvirtual = 1;
              }

              if(!isvirtual) {
                     newpathname = kmalloc(pathlen + 1, GFP_USER);
                     if(newpathname)
                            strncpy(newpathname, path, pathlen);
              }
              else {
                     newpathname = kmalloc(OVERLAY_DIR_LEN + pathlen + 1,
                                         GFP_USER);

                     if(newpathname) {
                            strcpy(newpathname, OVERLAY_DIR);
                            strncat(newpathname, path, pathlen);
                     }
              }
       }

       if(page)
              free_page((unsigned long) page);


       DEB((KERN_INFO "resolve_virt newpathname: '%s'\n", 
            newpathname ? newpathname : "(null)"));

 out:
       unlock_kernel();
       return newpathname;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* resolve_name ( const char *  kfilename,
int  must_exist,
int  flags 
) [static]

Definition at line 339 of file redir.c.

{
       char *tmp;
       char *newfilename;          

       tmp = getname(kfilename);
       if(IS_ERR(tmp))
              return tmp;


       if((tmp[0] != '/' && cwd_virtual()) || strchr(tmp, AVFS_MAGIC_CHAR)) {
              DEB((KERN_INFO "resolve_name: %s (%i/%s)\n", tmp, 
                   current->pid,
                   (current->flags & PF_AVFS) ? "on" : "off"));

              if(strcmp(tmp, "/#avfs-on") == 0) {
                     printk(KERN_INFO "AVFS ON  (pid: %i)\n",
                            current->pid);
                     current->flags |= PF_AVFS;
                     newfilename = ERR_PTR(-EEXIST);
              }
              else if(!(current->flags & PF_AVFS))
                     newfilename = NULL;
              else if(strcmp(tmp, "/#avfs-off") == 0) {
                     printk(KERN_INFO "AVFS OFF (pid: %i)\n",
                            current->pid);
                     current->flags &= ~PF_AVFS;
                     newfilename = ERR_PTR(-EEXIST);
              }
              else {
                     if(tmp[0] == '/') {
                            newfilename = resolv_virt(tmp, must_exist, flags);
                     }
                     else {
                            char *abspath;

                            abspath = get_abs_path(tmp);
                            if(abspath) {
                                   newfilename = resolv_virt(abspath, must_exist, flags);
                                   kfree(abspath);
                            }
                            else
                                   newfilename = NULL;
                     }
              }
       }
       else 
              newfilename = NULL;
       
       putname(tmp);
       
       return newfilename;
}

Here is the call graph for this function:

Here is the caller graph for this function:

asmlinkage int virt_access ( const char *  filename,
int  mode 
)

Definition at line 517 of file redir.c.

{
       int ret;
       mm_segment_t old_fs;
       char *newfilename;
       
       if(!cwd_virtual()) {
              ret = (*orig_access)(filename, mode);
              if(ret != -ENOENT) 
                     return ret;
       }
       else 
              ret = 0;

       newfilename = resolve_name(filename, 1, 1);
       if(!newfilename) {
              if(ret)
                     return ret;
              else
                     return (*orig_access)(filename, mode);
       }
       if(IS_ERR(newfilename))
              return PTR_ERR(newfilename);

       DEB((KERN_INFO "ACCESS: trying '%s'\n", newfilename));
              
       old_fs = get_fs();
       set_fs(get_ds());
       ret = (*orig_access)(newfilename, mode);
       set_fs(old_fs);
       kfree(newfilename);

       DEB((KERN_INFO "ACCESS: result %i\n", ret));
       
       return ret;
}

Here is the caller graph for this function:

asmlinkage int virt_chdir ( const char *  filename)

Definition at line 393 of file redir.c.

{
       int ret;
       mm_segment_t old_fs;
       char *newfilename;
       
       if(!cwd_virtual()) {
              ret = (*orig_chdir)(filename);
              if(ret != -ENOENT) 
                     return ret;
       }
       else 
              ret = 0;

       newfilename = resolve_name(filename, 1, 1);
       if(!newfilename) {
              if(ret)
                     return ret;
              else
                     return (*orig_chdir)(filename);
       }
       if(IS_ERR(newfilename))
              return PTR_ERR(newfilename);


       DEB((KERN_INFO "CHDIR: trying '%s'\n", newfilename));
              
       old_fs = get_fs();
       set_fs(get_ds());
       ret =  (*orig_chdir)(newfilename);
       set_fs(old_fs);
       kfree(newfilename);

       DEB((KERN_INFO "CHDIR: result %i\n", ret));
       
       return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

asmlinkage int virt_getcwd ( char *  buf,
unsigned long  size 
)

Definition at line 645 of file redir.c.

{
       int ret;
       char *cwd;
       unsigned long cwdlen;
       char *page;
       char *newcwd;
       unsigned long newlen;
       
       ret = (*orig_getcwd)(buf, size);

       if(!cwd_virtual() || ret < 0)
              return ret;
              
       if(!path_ok(current->fs->pwd))
              return -ENOENT;
       
       page = (char *) __get_free_page(GFP_USER);
       if(!page)
              return -ENOMEM;
       
       cwd = path_pwd(page);
       cwdlen = PAGE_SIZE + (page - cwd) - 1;
       
       if(cwdlen >= OVERLAY_DIR_LEN && 
          strncmp(cwd, OVERLAY_DIR, OVERLAY_DIR_LEN) == 0) {
              if(cwdlen == OVERLAY_DIR_LEN) {
                     newcwd = "/";
                     newlen = 1;
              }
              else {
                     newcwd = cwd + OVERLAY_DIR_LEN;
                     newlen = cwdlen - OVERLAY_DIR_LEN;
              }

              ret = -ERANGE;
              if(newlen + 1 <= size) {
                     ret = newlen + 1;
                     if(copy_to_user(buf, newcwd, newlen + 1))
                            ret = -EFAULT;
              }
       }
       free_page((unsigned long) page);

       return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

asmlinkage int virt_lstat ( const char *  filename,
struct stat statbuf 
)

Definition at line 483 of file redir.c.

{
       int ret;
       char *newfilename;

       if(!cwd_virtual()) {
              ret = (*orig_lstat)(filename, statbuf);
              if(ret != -ENOENT) 
                     return ret;
       }
       else 
              ret = 0;

       newfilename = resolve_name(filename, 1, 0);
       if(!newfilename) {
              if(ret)
                     return ret;
              else
                     return (*orig_lstat)(filename, statbuf);
       }
       if(IS_ERR(newfilename))
              return PTR_ERR(newfilename);

       DEB((KERN_INFO "LSTAT: trying '%s'\n", newfilename));

       ret = do_orig_stat(orig_lstat, newfilename, statbuf);
       kfree(newfilename);

       DEB((KERN_INFO "LSTAT: result %i\n", ret));

       return ret;
}

Here is the caller graph for this function:

asmlinkage long virt_lstat64 ( char *  filename,
struct stat64 *  statbuf,
long  flags 
)

Definition at line 746 of file redir.c.

{
       long ret;
       char *newfilename;

       if(!cwd_virtual()) {
              ret = (*orig_lstat64)(filename, statbuf, flags);
              if(ret != -ENOENT) 
                     return ret;
       }
       else 
              ret = 0;

       newfilename = resolve_name(filename, 1, 0);
       if(!newfilename) {
              if(ret)
                     return ret;
              else
                     return (*orig_lstat64)(filename, statbuf, flags);
       }
       if(IS_ERR(newfilename))
              return PTR_ERR(newfilename);

       DEB((KERN_INFO "LSTAT64: trying '%s'\n", newfilename));

       ret = do_orig_stat64(orig_lstat64, newfilename, statbuf, flags);
       kfree(newfilename);

       DEB((KERN_INFO "LSTAT64: result %li\n", ret));

       return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

asmlinkage int virt_open ( const char *  filename,
int  flags,
int  mode 
)

Definition at line 554 of file redir.c.

{
       int ret;
       mm_segment_t old_fs;
       char *newfilename;
       
       if(!cwd_virtual()) {
              ret = (*orig_open)(filename, flags, mode);
              if(ret != -ENOENT) 
                     return ret;
       }
       else 
              ret = 0;

       newfilename = resolve_name(filename, 1, 1);
       if(!newfilename) {
              if(ret)
                     return ret;
              else
                     return (*orig_open)(filename, flags, mode);
       }
       if(IS_ERR(newfilename))
              return PTR_ERR(newfilename);

       DEB((KERN_INFO "OPEN: trying '%s'\n", newfilename));
              
       old_fs = get_fs();
       set_fs(get_ds());
       ret = (*orig_open)(newfilename, flags, mode);
       set_fs(old_fs);
       kfree(newfilename);

       DEB((KERN_INFO "OPEN: result %i\n", ret));
       
       return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

asmlinkage int virt_readlink ( const char *  filename,
char *  buf,
int  bufsiz 
)

Definition at line 591 of file redir.c.

{
       int ret;
       mm_segment_t old_fs;
       char *newfilename;
       char *locbuf;
       int len;
       
       if(!cwd_virtual()) {
              ret = (*orig_readlink)(filename, buf, bufsiz);
              if(ret != -ENOENT) 
                     return ret;
       }
       else 
              ret = 0;

       newfilename = resolve_name(filename, 1, 0);
       if(!newfilename) {
              if(ret)
                     return ret;
              else
                     return (*orig_readlink)(filename, buf, bufsiz);
       }
       if(IS_ERR(newfilename))
              return PTR_ERR(newfilename);

       DEB((KERN_INFO "READLINK: trying '%s'\n", newfilename));

       /* bufsiz is legal (already checked by sys_readlink) */
       len = bufsiz;
       if(bufsiz > PAGE_SIZE)
              len = PAGE_SIZE;
                     
       locbuf = (char *) __get_free_page(GFP_USER);
                     
       ret = -ENOMEM;
       if(locbuf) {
              old_fs = get_fs();
              set_fs(get_ds());
              ret =  (*orig_readlink)(newfilename, locbuf, len);
              set_fs(old_fs);

              if(ret >= 0)
                     if(copy_to_user(buf, locbuf, len))
                            ret = -EFAULT;
              free_page((unsigned long) locbuf);
       }
       kfree(newfilename);

       DEB((KERN_INFO "READLINK: result %i\n", ret));
       
       return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

asmlinkage int virt_stat ( const char *  filename,
struct stat statbuf 
)

Definition at line 450 of file redir.c.

{
       int ret;
       char *newfilename;

       if(!cwd_virtual()) {
              ret = (*orig_stat)(filename, statbuf);
              if(ret != -ENOENT) 
                     return ret;
       }
       else 
              ret = 0;

       newfilename = resolve_name(filename, 1, 1);
       if(!newfilename) {
              if(ret)
                     return ret;
              else
                     return (*orig_stat)(filename, statbuf);
       }
       if(IS_ERR(newfilename))
              return PTR_ERR(newfilename);

       DEB((KERN_INFO "STAT: trying '%s'\n", newfilename));

       ret = do_orig_stat(orig_stat, newfilename, statbuf);
       kfree(newfilename);

       DEB((KERN_INFO "STAT: result %i\n", ret));

       return ret;
}

Here is the caller graph for this function:

asmlinkage long virt_stat64 ( char *  filename,
struct stat64 *  statbuf,
long  flags 
)

Definition at line 713 of file redir.c.

{
       long ret;
       char *newfilename;

       if(!cwd_virtual()) {
              ret = (*orig_stat64)(filename, statbuf, flags);
              if(ret != -ENOENT) 
                     return ret;
       }
       else 
              ret = 0;

       newfilename = resolve_name(filename, 1, 1);
       if(!newfilename) {
              if(ret)
                     return ret;
              else
                     return (*orig_stat64)(filename, statbuf, flags);
       }
       if(IS_ERR(newfilename))
              return PTR_ERR(newfilename);

       DEB((KERN_INFO "STAT64: trying '%s'\n", newfilename));

       ret = do_orig_stat64(orig_stat64, newfilename, statbuf, flags);
       kfree(newfilename);

       DEB((KERN_INFO "STAT64: result %li\n", ret));

       return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Definition at line 45 of file redir.c.

Definition at line 42 of file redir.c.

Definition at line 48 of file redir.c.

Definition at line 44 of file redir.c.

Definition at line 54 of file redir.c.

open_func orig_open [static]

Definition at line 46 of file redir.c.

Definition at line 47 of file redir.c.

stat_func orig_stat [static]

Definition at line 43 of file redir.c.

Definition at line 53 of file redir.c.

void* sys_call_table[]