Exemple #1
0
long xgsdtof(int *buf, int h, int wrt)
{
        register OFD *f ;
        register int *b ;

        b = buf ;
        f = getofd(h) ;

        if ( !wrt )
        {
                b[0] = f->o_time ;
                b[1] = f->o_date ;
        }

        swpw(b[0]);
        swpw(b[1]);

        if ( wrt )
        {
                f->o_time = b[0] ;
                f->o_date = b[1] ;
                f->o_flag |= O_DIRTY;           /* M01.01.0918.01 */
                swpw(b[0]);                    /* M01.01.0918.01 */
                swpw(b[1]);                    /* M01.01.0918.01 */
        }

        return E_OK;
}
Exemple #2
0
static void makbuf(FCB *f, DTAINFO *dt)
{                                       /*  M01.01.03   */
    dt->dt_fattr = f->f_attrib ;
    dt->dt_time = f->f_time ;
    swpw(dt->dt_time) ;
    dt->dt_date = f->f_date ;
    swpw(dt->dt_date) ;
    dt->dt_fileln = f->f_fileln ;
    swpl( dt->dt_fileln ) ;
    
    if( f->f_attrib & FA_VOL ) {
        memcpy(&dt->dt_fname[0], &f->f_name[0], 11);
        dt->dt_fname[11] = '\0' ;
    } else {
        packit(&f->f_name[0],&dt->dt_fname[0]);
    }
}
Exemple #3
0
/*
**  ixdel - internal delete file.
**
**  Traverse the list of files open for this directory node.
**  If a file is found that has the same position in the directory as the one
**  we are to delete, then scan the system file table to see if this process is
**  then owner.  If so, then close it, otherwise abort.
**
**  NOTE:       both 'for' loops scan for the entire length of their
**              respective data structures, and do not drop out of the loop on
**              the first occurrence of a match.
**      Used by
**              ixcreat()
**              xunlink()
**              xrmdir()
**
*/
long ixdel(DND *dn, FCB *f, long pos)
{
    OFD *fd;
    DMD *dm;
    int n2;
    int n;
    char c;

    for (fd = dn->d_files; fd; fd = fd->o_link)
        if (fd->o_dirbyt == pos)
            for (n = 0; n < OPNFILES; n++)
                if (sft[n].f_ofd == fd)
                {
                    if (sft[n].f_own == run)
                        ixclose(fd,0);
                    else
                        return EACCDN;
                }

    /*
     * Traverse this file's chain of allocated clusters, freeing them.
     */
    dm = dn->d_drv;
    n = f->f_clust;
    swpw(n);

    while (n && !endofchain(n))
    {
        n2 = getrealcl(n,dm);
        clfix(n,FREECLUSTER,dm);
        n = n2;
    }

    /*
     * Mark the directory entry as erased.
     */
    fd = dn->d_ofd;
    ixlseek(fd,pos);
    c = (char)ERASE_MARKER;
    ixwrite(fd,1L,&c);
    ixclose(fd,CL_DIR);

    /*
     * NOTE that the preceding routines that do physical disk operations
     * will 'longjmp' on failure at the BIOS level, thereby allowing us to
     * simply return with E_OK.
     */
    return E_OK;
}
Exemple #4
0
/*
**  makopn - make an open file for sft handle h
**
*/
static long makopn(FCB *f, DND *dn, int h, int mod)
{
    OFD *p;
    OFD *p2;
    DMD *dm;                        /*  M01.01.03   */

    dm = dn->d_drv;

    p = MGET(OFD);                  /* MGET(OFD) only returns if it succeeds */

    p->o_mod = mod;                 /*  set mode                    */
    p->o_dmd = dm;                  /*  link OFD to media           */
    sft[h-NUMSTD].f_ofd = p;
    p->o_usecnt = 0;                /*  init usage                  */
    p->o_curcl = 0;                 /*  init file pointer info      */
    p->o_curbyt = 0;                /*  "                           */
    p->o_dnode = dn;                /*  link to directory           */
    p->o_dirfil = dn->d_ofd;        /*  link to dir's ofd           */
    p->o_dirbyt = dn->d_ofd->o_bytnum - 32; /*  offset of fcb in dir*/

    for (p2 = dn->d_files; p2; p2 = p2->o_link)
        if (p2->o_dirbyt == p->o_dirbyt)
            break;              /* same dir, same dcnt */

    p->o_link = dn->d_files;
    dn->d_files = p;

    if (p2)
    {       /* steal time/date,startcl,fileln (a bit clumsily) */
        memcpy(&p->o_td,&p2->o_td,sizeof(DOSTIME)+sizeof(CLNO)+sizeof(long));
        /* not used yet... TBA *********/
        p2->o_thread = p;
    }
    else
    {
        p->o_strtcl = f->f_clust;       /*  1st cluster of file */
        swpw(p->o_strtcl);
        p->o_fileln = f->f_fileln;      /*  init length of file */
        swpl(p->o_fileln);
        p->o_td.date = f->f_td.date;    /* note: OFD time/date are  */
        p->o_td.time = f->f_td.time;    /*  actually little-endian! */
    }

    return h;
}
Exemple #5
0
/*  name: path name of file
 *  attr: atttributes
 */
long ixcreat(char *name, char attr)
{
    DND *dn;
    OFD *fd;
    FCB *f;
    const char *s;
    char n[2], a[11];                       /*  M01.01.03   */
    int i, f2;                              /*  M01.01.03   */
    long pos, rc;

    n[0] = (char)ERASE_MARKER; n[1] = 0;

    /* first find path */

    if ((long)(dn = findit(name,&s,0)) < 0) /* M01.01.1212.01 */
        return (long)dn;
    if (!dn)                                /* M01.01.1214.01 */
        return EPTHNF;

    if (!*s || (*s == '.'))         /*  no file name || '.' || '..' */
        return EPTHNF;

    /*  M01.01.0721.01  */
    if (contains_illegal_characters(s))
        return EACCDN;

    /*
     * if the volume label attribute is set, no others are allowed
     */
    if ((attr&FA_VOL) && (attr != FA_VOL))
        return EACCDN;

    /*
     * volume labels may only be created in the root
     */
    if ((attr == FA_VOL) && dn->d_parent)
        return EACCDN;

    if (!(fd = dn->d_ofd))
        fd = makofd(dn);            /* makofd() also updates dn->d_ofd */

    /*
     * if a matching file already exists, we delete it first.  note
     * that the definition of matching, and the action taken, differs
     * depending on whether the file is a volume label or not:
     *  . for a volume label, *any* existing volume label matches
     *    and will be deleted (reference: Rainbow TOS Release Notes)
     *  . for other files, the name must match, and the existing
     *    file will be deleted unless (a) it's read-only or a folder
     *    or (b) the file being created is a folder.
     */
    pos = 0;
    if (attr == FA_VOL)
        f = scan(dn,"*.*",FA_VOL,&pos);
    else f = scan(dn,s,FA_NORM|FA_SUBDIR,&pos);

    if (f)                  /* found matching file / label */
    {
        if (attr != FA_VOL) /* for normal files, need to check more stuff */
        {
                                        /* M01.01.0730.01   */
            if ((f->f_attrib & (FA_SUBDIR | FA_RO)) || (attr == FA_SUBDIR))
                return EACCDN;          /*  subdir or read only  */
        }
        pos -= 32;
        ixdel(dn,f,pos);
    }
    else
        pos = 0;

    /* now scan for empty space */

    /*  M01.01.SCC.FS.02  */
    while( !( f = scan(dn,n,0xff,&pos) ) )
    {
        /*  not in current dir, need to grow  */
        if (!fd->o_dnode)           /*  but can't grow root  */
            return EACCDN;

        if ( nextcl(fd,1) )
            return EACCDN;

        f = dirinit(dn);
        pos = 0;
    }

    builds(s,a);
    pos -= 32;
    f->f_attrib = attr;
    for (i = 0; i < 10; i++)
        f->f_fill[i] = 0;
    f->f_td.time = current_time;
    swpw(f->f_td.time);
    f->f_td.date = current_date;
    swpw(f->f_td.date);
    f->f_clust = 0;
    f->f_fileln = 0;
    ixlseek(fd,pos);
    ixwrite(fd,11L,a);              /* write name, set dirty flag */
    ixclose(fd,CL_DIR);             /* partial close to flush */
    ixlseek(fd,pos);
    s = (char*) ixread(fd,32L,NULL);
    f2 = rc = opnfil((FCB*)s,dn,(f->f_attrib&FA_RO)?RO_MODE:RW_MODE);

    if (rc < 0)
        return rc;

    getofd(f2)->o_flag |= O_DIRTY;

    return f2;
}
Exemple #6
0
/*
**  ixclose -
**
**  Error returns   EINTRN
**
**  Last modified   SCC     10 Apr 85
**
**  NOTE:   I'm not sure that returning immediately upon an error from
**          ixlseek() is the right thing to do.  Some data structures may
**          not be updated correctly.  Watch out for this!
**          Also, I'm not sure that the EINTRN return is ok.
*/
long ixclose(OFD *fd, int part)
{                                   /*  M01.01.03                   */
    OFD *p, **q;
    int i;                          /*  M01.01.03                   */
    BCB *b;

    /*
     * if the file or folder has been modified, we need to make sure
     * that the date/time, starting cluster, and file length in the
     * directory entry are updated.  In addition, for files, we must
     * set the archive flag.
     *
     * The following code avoids multiple ixlseek()/ixlread()/ixlwrite()
     * sequences by just getting a pointer to a buffer containing the
     * FCB, and updating it directly.  We must do an ixwrite() at the
     * end so that the buffer is marked as dirty and is subsequently
     * written.
     */
    if (fd->o_flag & O_DIRTY)
    {
        FCB *fcb;
        UBYTE attr;

        ixlseek(fd->o_dirfil,fd->o_dirbyt); /* start of dir entry */
        fcb = (FCB *)ixread(fd->o_dirfil,32L,NULL);
        attr = fcb->f_attrib;               /* get attributes */
        memcpy(&fcb->f_td,&fd->o_td,10);    /* copy date/time, start, length */
        swpw(fcb->f_clust);                 /*  & fixup byte order */
        swpl(fcb->f_fileln);

        if (part & CL_DIR)
            fcb->f_fileln = 0L;             /* dir lengths on disk are zero */
        else
            attr |= FA_ARCHIVE;             /* set the archive flag for files */

        ixlseek(fd->o_dirfil,fd->o_dirbyt+11);  /* seek to attrib byte */
        ixwrite(fd->o_dirfil,1,&attr);          /*  & rewrite it       */
    }

    if ((!part) || (part & CL_FULL))
    {
        q = &fd->o_dnode->d_files;

        for (p = *q; p ; p = *(q = &p->o_link))
            if (p == fd)
                break;

        /* someone else has this file open **** TBA */

        if (p)
            *q = p->o_link;
        else
            return EINTRN;  /* some kind of internal error */
    }

    /* only flush to appropriate drive ***** TBA ******/

    for (i = 0; i < 2; i++)
        for (b = bufl[i]; b; b = b->b_link)
            flush(b);

    return E_OK;
}
Exemple #7
0
long xmkdir(char *s) 
{
        register OFD *f;
        register FCB *f2;
        OFD     *fd,*f0;
        FCB     *b;
        DND     *dn;
        int     h,cl,plen;
        long    rc;

        if ((h = rc = ixcreat(s,FA_SUBDIR)) < 0)
                return(rc);

        f = getofd(h);

        /* build a DND in the tree */

        fd = f->o_dirfil;

        ixlseek(fd,f->o_dirbyt);
        b = (FCB *) ixread(fd,32L,NULLPTR);

        /* is the total path length too long? */     /* M01.01.1107.01 */

        plen = namlen( b->f_name );
        for ( dn = f->o_dnode; dn; dn = dn->d_parent )
                plen += namlen( dn->d_name );
        if ( plen >= (LEN_ZPATH-3) )
        {
                ixdel( f->o_dnode, b, f->o_dirbyt );
                return ( EACCDN );
        }

        if( (dn = makdnd(f->o_dnode,b)) == NULLPTR )
        {
                ixdel( f->o_dnode, b, f->o_dirbyt );    /* M01.01.1103.01 */
                return (ENSMEM);
        }

        if( (dn->d_ofd = f0 = makofd(dn)) == (OFD*)NULLPTR )
        {
                ixdel( f->o_dnode, b, f->o_dirbyt );    /* M01.01.1103.01 */
                f->o_dnode->d_left = NULLPTR;            /* M01.01.1103.01 */
                xmfreblk((char *)dn);
                return (ENSMEM);
        }

        /* initialize dir cluster */

        if (nextcl(f0,1))
        {
                ixdel( f->o_dnode, b, f->o_dirbyt );    /* M01.01.1103.01 */
                f->o_dnode->d_left = NULLPTR;            /* M01.01.1103.01 */
                freednd(dn);                    /* M01.01.1031.02 */
                return(EACCDN);
        }

        f2 = dirinit(dn);                       /* pointer to dirty dir block */

        /* write identifier */

        memcpy(f2, dots, 22);
        f2->f_attrib = FA_SUBDIR;
        f2->f_time = time;
        swpw( f2->f_time ) ;           /*  M01.01.SCC.FS.04  */
        f2->f_date = date;
        swpw( f2->f_date ) ;           /*  M01.01.SCC.FS.04  */
        cl = f0->o_strtcl;
        swpw(cl);
        f2->f_clust = cl;
        f2->f_fileln = 0;
        f2++;

        /* write parent entry .. */

        memcpy(f2, dots, 22);
        f2->f_name[1] = '.';           /* This is .. */
        f2->f_attrib = FA_SUBDIR;
        f2->f_time = time;
        swpw( f2->f_time ) ;           /*  M01.01.SCC.FS.06  */
        f2->f_date = date;
        swpw( f2->f_date ) ;           /*  M01.01.SCC.FS.06  */
        cl = f->o_dirfil->o_strtcl;

        if (!fd->o_dnode)              /* if creating a folder in the root, the */
                cl = 0;                /*  cluster# of the .. entry must be 0   */

        swpw(cl);
        f2->f_clust = cl;
        f2->f_fileln = 0;
        memcpy(f, f0, sizeof(OFD));
        f->o_flag |= O_DIRTY;
        ixclose(f,CL_DIR | CL_FULL);    /* force flush and write */
        xmfreblk((char*)f);
        sft[h-NUMSTD].f_own = 0;
        sft[h-NUMSTD].f_ofd = 0;
        return(E_OK);
}
Exemple #8
0
static DND *makdnd(DND *p, FCB *b) 
{
        register DND *p1;
        register DND **prev;
        OFD     *fd;
        register int i;
        int     in_use;

        fd = p->d_ofd;

        /* 
        **  scavenge a DND at this level if we can find one that has not 
        **  d_left 
        */
        for (prev = &p->d_left; (p1 = *prev) ; prev = &p1->d_right)
        {
                if (!p1->d_left)
                {
                        /* check dirtbl[] to see if anyone is using this guy */

                        in_use = 0;
                        for (i = 1; i < NCURDIR; i++)
                                if (diruse[i] && dirtbl[i] == p1) {
                                    in_use = 1;
                                    break;
                                }

#if DBGFSDIR
                        kprintf("\n makdnd check dirtbl (%d)", in_use);
#endif
                        if( !in_use && p1->d_files == NULLPTR )
                        {       /*  M01.01.KTB.SCC.02  */
                                /* clean out this DND for reuse */

                                p1->d_flag = 0;
                                p1->d_scan = 0L;
                                p1->d_files = (OFD *) 0;
                                if (p1->d_ofd)
                                {
                                        xmfreblk((char *)p1->d_ofd);
                                }
                                break;
                        }
                }
        }

        /* we didn't find one that qualifies, so allocate a new one */

        if (!p1)
        {
#if DBGFSDIR
                kprintf("\n makdnd new");
#endif
                if (!(p1 = MGET(DND)))
                        return ( (DND *) 0 );   /* ran out of system memory */

                /* do this init only on a newly allocated DND */
                p1->d_right = p->d_left;
                p->d_left = p1;
                p1->d_parent = p;
        }

        /* complete the initialization */

        p1->d_ofd = (OFD *) 0;
        p1->d_strtcl = b->f_clust;
        swpw(p1->d_strtcl);
        p1->d_drv = p->d_drv;
        p1->d_dirfil = fd;
        p1->d_dirpos = fd->o_bytnum - 32;
        p1->d_time = b->f_time;
        p1->d_date = b->f_date;
        memcpy(p1->d_name, b->f_name, 11);

#if DBGFSDIR
        kprintf("\n makdnd(%08lx)", (long)p1);
#endif
        return(p1);
}