Back to index

avfs  1.0.1
Defines | Functions | Variables
child.c File Reference
#include "virtual.h"
#include "avfscoda.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/stat.h>

Go to the source code of this file.

Defines

#define MULTITHREADED   1
#define MAXPMSGLEN   8192
#define MAXMSGLEN   1045
#define COPYBUF   16384

Functions

static int st2type (struct stat *s)
static void st2attr (struct stat *s, struct coda_vattr *a, ViceFid *id)
static int set_attr (const char *path, struct coda_vattr *a)
static int create_empty_dir (const char *tmpname)
static int copy_dir (const char *path, const char *tmpname)
static int copy_file (const char *name, const char *tmpname)
static int write_file (const char *tmpname, const char *name)
static int create_empty_file (const char *tmpname)
void * process_request (void *arg)
void child_process (int infd, int outfd)

Variables

static int child_outfd

Define Documentation

#define COPYBUF   16384

Definition at line 205 of file child.c.

#define MAXMSGLEN   1045

Definition at line 28 of file child.c.

#define MAXPMSGLEN   8192

Definition at line 27 of file child.c.

#define MULTITHREADED   1

Definition at line 25 of file child.c.


Function Documentation

void child_process ( int  infd,
int  outfd 
)

Definition at line 526 of file child.c.

{
    int res;
    int insize;
    int numread;
    char ibuf[MAXPMSGLEN];
    char *bufcpy;
    pthread_attr_t attr;
    pthread_t thrid;

    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

    child_outfd = outfd;

#if 0
    pid_t pid = getpid();
    uid_t uid = getuid();
    gid_t gid = getgid();
       

    fprintf(stderr, "My pid: %i\n", pid);
    sleep(15);
#endif
    
    while(1) {
        numread = read(infd, &insize, sizeof(insize));
        if(numread == -1) {
            fprintf(stderr, "Error reading from device: %s\n",
                    strerror(errno));
            exit(1);
        }
        if(insize > MAXPMSGLEN || insize <= 0) {
            fprintf(stderr, "Error: illegal size");
            exit(1);
        }
              
        numread = read(infd, ibuf, insize);
        if(numread == -1) {
            fprintf(stderr, "Error reading from device: %s\n", 
                    strerror(errno));
            exit(1);
        }
       
       bufcpy = malloc(numread);
       if(bufcpy == NULL) {
           fprintf(stderr, "Out of memory\n");
           exit(1);
       }
       
       memcpy(bufcpy, ibuf, numread);


#if MULTITHREADED
       res = pthread_create(&thrid, &attr, process_request, bufcpy);
       if(res != 0) {
           fprintf(stderr, "Error creating thread: %s\n", strerror(errno));
           exit(1);
       }
#else
        process_request(bufcpy);
#endif
       
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int copy_dir ( const char *  path,
const char *  tmpname 
) [static]

Definition at line 147 of file child.c.

{
    struct venus_dirent vd;
    int res;
    DIR *dirp;
    int outfd;
    struct dirent *ent;
       
    dirp = virt_opendir(path);
    if(dirp == NULL)
        return -errno;
       
    outfd = open(tmpname, O_WRONLY | O_TRUNC);
    if(outfd == -1) {
        fprintf(stderr, "open(%s, O_WRONLY | O_TRUNC) failed (%s)\n", tmpname, 
                strerror(errno));
        virt_closedir(dirp);
        return -EIO;
    }

    while(1) {
        errno = 0;
        ent = virt_readdir(dirp);
        if(ent == NULL) {
            if(errno != 0)
                res = -errno;
            else
                res = 0;
            break;
        }

        vd.d_fileno = 1; /* We don't know the inode number */
        vd.d_type   = CDT_UNKNOWN;
        strncpy(vd.d_name, ent->d_name, CODA_MAXNAMLEN);
        vd.d_name[CODA_MAXNAMLEN] = '\0';
        vd.d_namlen = strlen(vd.d_name);
        vd.d_reclen = DIRSIZ(&vd);
        
        res = write(outfd, &vd, vd.d_reclen);
        if(res == -1) {
            fprintf(stderr, "write failed (%s)\n", strerror(errno));
            res = -EIO;
            break;
        }
    } while(ent != NULL);
       
    close(outfd);
    if(res == 0) {
        res = virt_closedir(dirp);
        if(res == -1)
            return -errno;
    }
    else
        virt_closedir(dirp);

    return res;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int copy_file ( const char *  name,
const char *  tmpname 
) [static]

Definition at line 207 of file child.c.

{
    char buf[COPYBUF];
    int infd;
    int outfd;
    int res;
       
    infd = virt_open(name, O_RDONLY, 0);
    if(infd == -1)
        return -errno;
       
    outfd = open(tmpname, O_WRONLY | O_TRUNC);
    if(outfd == -1) {
        fprintf(stderr, "open(%s) failed (%s)\n", tmpname, strerror(errno));
        virt_close(infd);
        return -EIO;
    }
       
    do {
        res = virt_read(infd, buf, COPYBUF);
        if(res == -1) {
            res = -errno;
            break;
        }
        if (res > 0) {
            res = write(outfd, buf, res);
            if(res == -1) {
                fprintf(stderr, "write failed (%s)\n", strerror(errno));
                res = -EIO;
                break;
            }
        }
    } while(res > 0);

    close(outfd);
    if(res == 0) {
        res = virt_close(infd);
        if(res == -1)
            return -errno;
    }
    else
        virt_close(infd);

    return res;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int create_empty_dir ( const char *  tmpname) [static]

Definition at line 132 of file child.c.

{
    int outfd;

    outfd = open(tmpname, O_WRONLY | O_TRUNC);
    if(outfd == -1) {
        fprintf(stderr, "open(%s, O_WRONLY | O_TRUNC) failed (%s)\n", tmpname, 
                strerror(errno));
        return -EIO;
    }

    close(outfd);
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int create_empty_file ( const char *  tmpname) [static]

Definition at line 297 of file child.c.

{
    int fd;

    fprintf(stderr, "create_empty_file: %s\n", tmpname);

    fd = open(tmpname, O_WRONLY | O_TRUNC);
    if(fd == -1) {
        fprintf(stderr, "open(%s, O_WRONLY | O_TRUNC) failed (%s)\n", tmpname,
                strerror(errno));
        
        return -EIO;
    }

    close(fd);
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void* process_request ( void *  arg)

Definition at line 316 of file child.c.

{
    char *ibuf = (char *) arg;
    int ret;
    struct child_message *msg = (struct child_message *) ibuf;
    union inputArgs *req;
    char obuf[MAXMSGLEN + sizeof(int)];
    union outputArgs *rep = (union outputArgs *) (obuf + sizeof(int));
    int size, noff;
    char *path1;
    char *path2;
    int offset = sizeof(struct child_message);
    struct stat stbuf;
    int outfd = child_outfd;

    req = (union inputArgs *)  (ibuf + offset);

    if(msg->path1size != 0)
       path1 = ibuf + offset + msg->reqsize;
    else
       path1 = NULL;
    
    if(msg->path2size != 0)
       path2 = ibuf + offset + msg->reqsize + msg->path1size;
    else
       path2 = NULL;
    
    
#if 0
    fprintf(stderr, 
           "- %i/%i [%i] ---------------------------------------------------\n", 
           uid, gid, pid);
    fprintf(stderr, 
           "%i (%i (%i)) bytes: opcode: %li, unique: %li\n", 
           msg->reqsize, numread, insize, req->ih.opcode, 
           req->ih.unique);
    fprintf(stderr, "ibuf: %p, req: %p msg: %p\n", ibuf, req, msg);
#endif
    
    size = sizeof(rep->oh);
    rep->oh.opcode = req->ih.opcode;
    rep->oh.unique = req->ih.unique;
    rep->oh.result = 0;
    
    switch (req->ih.opcode) {
    case CODA_GETATTR:
       size = sizeof(rep->coda_getattr);
       
       ret = virt_lstat(path1, &stbuf);
       if(ret == -1) 
           rep->oh.result = errno;
       else 
           st2attr(&stbuf, &rep->coda_getattr.attr, 
                  &req->coda_getattr.VFid);
       break;
                     
    case CODA_ACCESS:
       size = sizeof(rep->oh);
                     
       ret = virt_access(path1, req->coda_access.flags & 0x7);
       if(ret == -1) 
           rep->oh.result = errno;
       break;
                     
#ifdef CODA_OPEN_BY_FD
    case CODA_OPEN_BY_FD:
#endif
    case CODA_OPEN:
       size = sizeof(rep->oh);
       if(strcmp(path1, "/") == 0)
           ret = create_empty_dir(path2);
       else {
           if((req->coda_open.flags & C_O_TRUNC) != 0)
              ret = create_empty_file(path2);
           else {
              ret = virt_stat(path1, &stbuf);
              if(ret == -1)
                    ret = -errno;
              else {
                  if(S_ISDIR(stbuf.st_mode))
                     ret = copy_dir(path1, path2);
                  else 
                     ret = copy_file(path1, path2);
              }
           }
        }
        if(ret < 0)
            rep->oh.result = -ret;
       break;

    case CODA_CREATE:
       size = sizeof(rep->coda_create);
       if((req->coda_create.mode & S_IFMT) == S_IFREG) {
           ret = virt_open(path1, O_WRONLY | O_CREAT | O_TRUNC, 
                         req->coda_create.mode & 07777);
           if(ret != -1) 
              ret = virt_close(ret);
       }
       else {
           ret = virt_mknod(path1, req->coda_create.mode,
                          req->coda_create.attr.va_rdev);
       }
       if(ret == -1)
           rep->oh.result = errno;
       break;


    case CODA_CLOSE:
       size = sizeof(rep->oh);
       ret = write_file(path2, path1);
       if(ret < 0)
           rep->oh.result = -ret;
       break;
                     
    case CODA_LOOKUP:
       size = sizeof(rep->coda_lookup);
                     
       ret = virt_lstat(path1, &stbuf);
       if(ret == -1) 
           rep->oh.result = errno;
       else {
           /* We don't know these */
           rep->coda_lookup.VFid.Volume = 0;
           rep->coda_lookup.VFid.Vnode  = 0;
           rep->coda_lookup.VFid.Unique = 0; 
           rep->coda_lookup.vtype = st2type(&stbuf);
       }
       break;
                     
    case CODA_READLINK:
       size = sizeof(rep->coda_readlink);
       noff = size;
                     
       ret = virt_readlink(path1, (char *) rep + noff,
                         MAXMSGLEN - noff);
       if(ret == -1) 
           rep->oh.result = errno;
       else {
           rep->coda_readlink.data = (void *) noff;
           rep->coda_readlink.count = ret;
           size += ret;
       }
       break;

    case CODA_SETATTR:
       size = sizeof(rep->oh);
       ret = set_attr(path1, &req->coda_setattr.attr);
       if(ret == -1)
           rep->oh.result = errno;
       break;

    case CODA_REMOVE:
       size = sizeof(rep->oh);
       ret = virt_unlink(path1);
       if(ret == -1)
           rep->oh.result = errno;
       break;

    case CODA_RMDIR:
       size = sizeof(rep->oh);
       ret = virt_rmdir(path1);
       if(ret == -1)
           rep->oh.result = errno;
       break;

    case CODA_MKDIR:
       size = sizeof(rep->coda_mkdir);
       ret = virt_mkdir(path1, req->coda_mkdir.attr.va_mode & 07777);
       if(ret == -1)
           rep->oh.result = errno;
       break;

    case CODA_RENAME:
       size = sizeof(rep->oh);
       ret = virt_rename(path1, path2);
       if(ret == -1)
           rep->oh.result = errno;
       break;

    case CODA_SYMLINK:
       size = sizeof(rep->oh);
       ret = virt_symlink(path2, path1);
       if(ret == -1)
           rep->oh.result = errno;
       break;

    case CODA_LINK:
       size = sizeof(rep->oh);
       ret = virt_link(path2, path1);
       if(ret == -1)
           rep->oh.result = errno;
       break;

    default:
       rep->oh.result = EOPNOTSUPP;
    }
              
    *(int *) obuf = size;
    size += sizeof(int);
    ret = write(outfd, obuf, size);
    if(ret == -1 || ret != size) {
       fprintf(stderr, "Error writing to parent: %s\n", strerror(errno));
       exit(1);
    }
    
    free(ibuf);

    return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int set_attr ( const char *  path,
struct coda_vattr *  a 
) [static]

Definition at line 100 of file child.c.

{
    
    if(a->va_mode != (u_short) -1) {
        if(virt_chmod(path, a->va_mode & 07777) == -1)
            return -1;
    }
    
    if(a->va_uid != (vuid_t) -1 || a->va_gid != (vuid_t) -1) {
        if(virt_lchown(path, a->va_uid, a->va_gid) == -1)
            return -1;
    }

    if(a->va_size != (u_quad_t) -1) {
        if(virt_truncate(path, a->va_size) == -1)
            return -1;
    }

    if(a->va_atime.tv_sec != (time_t) -1 ||
       a->va_mtime.tv_sec != (time_t) -1) {
        struct utimbuf utbuf;

        utbuf.actime = a->va_atime.tv_sec;
        utbuf.modtime = a->va_mtime.tv_sec;

        if(virt_utime(path, &utbuf) == -1)
            return -1;
    }

    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void st2attr ( struct stat s,
struct coda_vattr *  a,
ViceFid *  id 
) [static]

Definition at line 62 of file child.c.

{
    memset(a, 0, sizeof(struct coda_vattr));
    a->va_type = st2type(s);
       
    a->va_mode = s->st_mode & 07777;
       
    /* File type handling in linux-coda is a mess */
    a->va_mode |= (s->st_mode  & S_IFMT);
       
    a->va_nlink = s->st_nlink;
    a->va_uid = s->st_uid;
    a->va_gid = s->st_gid;
    a->va_fileid = coda_f2i(id);
    a->va_size = s->st_size;
    a->va_blocksize = 1024; /* s->st_blksize */
    a->va_atime.tv_nsec = a->va_ctime.tv_nsec = a->va_mtime.tv_nsec = 0;
    a->va_atime.tv_sec = s->st_atime;
    a->va_mtime.tv_sec = s->st_mtime;
    a->va_ctime.tv_sec = s->st_ctime;
    a->va_gen = 0;
    a->va_flags = 0;
    a->va_rdev = s->st_rdev;
       
    a->va_bytes = s->st_blocks * s->st_blksize;
    a->va_filerev = 0;
       
#ifdef HAVE_FIFO_BUG
    /* Make a char device (255/255) out of pipes */
    if(S_ISFIFO(s->st_mode)) {
        a->va_mode = (s->st_mode & 07777) | S_IFCHR;
        a->va_type = C_VCHR;
        a->va_rdev = ~0;
    }
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int st2type ( struct stat s) [static]

Definition at line 34 of file child.c.

{
    if (S_ISDIR(s->st_mode))
        return C_VDIR;

    if (S_ISREG(s->st_mode))
        return C_VREG;

    if (S_ISBLK(s->st_mode))
        return C_VBLK;

    if (S_ISCHR(s->st_mode))
        return C_VCHR;

    if (S_ISLNK(s->st_mode))
        return C_VLNK;

    if (S_ISSOCK(s->st_mode))
        return C_VSOCK;

    if (S_ISFIFO(s->st_mode))
        return C_VFIFO;

    fprintf(stderr, "Unknown type\n");
    return C_VNON;
}

Here is the caller graph for this function:

static int write_file ( const char *  tmpname,
const char *  name 
) [static]

Definition at line 253 of file child.c.

{
    char buf[COPYBUF];
    int infd;
    int outfd;
    int res;
       
    outfd = virt_open(name, O_WRONLY | O_TRUNC, 0);
    if(outfd == -1)
        return -errno;
       
    infd = open(tmpname, O_RDONLY, 0);
    if(infd == -1) {
        fprintf(stderr, "open(%s) failed (%s)\n", tmpname, strerror(errno));
        virt_close(outfd);
        return -EIO;
    }
       
    do {
        res = read(infd, buf, COPYBUF);
        if(res == -1) {
            fprintf(stderr, "read failed (%s)\n", strerror(errno));
            res = -EIO;
            break;
        }
        if (res > 0) {
            res = virt_write(outfd, buf, res);
            if(res == -1) {
                res = -errno;
                break;
            }
        }
    } while(res > 0);

    close(infd);
    if(res == 0) {
        res = virt_close(outfd);
        if(res == -1)
            return -errno;
    }
    
    return res;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

int child_outfd [static]

Definition at line 32 of file child.c.