Example #1
0
long xchmod(char *p, int wrt, char mod)
{
        OFD *fd;
        DND *dn;                                        /*  M01.01.03   */
        const char *s;
        long pos;

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

        pos = 0;


        if( ! scan( dn , s , FA_NORM , &pos )  )        /*  M01.01.03   */
                return( EFILNF ) ;


        pos -= 21;                           /* point at attribute in file */
        fd = dn->d_ofd;
        ixlseek(fd,pos);
        if (!wrt)
                ixread(fd,1L,&mod);
        else
        {
                ixwrite(fd,1L,&mod);
                ixclose(fd,CL_DIR); /* for flush */
        }
        return(mod);
}
Example #2
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;
}
Example #3
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;
}
Example #4
0
/*ARGSUSED*/
long xrename(int n, char *p1, char *p2)
{
        register OFD *fd2;
        OFD     *f1,*fd;
        FCB     *f;
        DND     *dn1,*dn2;
        const char *s1,*s2;
        char    buf[11];
        int     hnew,att;
        long    rc, h1;

        if (!ixsfirst(p2,0,(DTAINFO *)0L))
                return(EACCDN);

        if ((long)(dn1 = findit(p1,&s1,0)) < 0)          /* M01.01.1212.01 */
                return( (long)dn1 );
        if (!dn1)                                        /* M01.01.1214.01 */
                return( EPTHNF );

        if ((long)(dn2 = findit(p2,&s2,0)) < 0)          /* M01.01.1212.01 */
                return( (long)dn2 );
        if (!dn2)                                        /* M01.01.1214.01 */
                return( EPTHNF );

        if (contains_illegal_characters(s2))
                return( EACCDN ) ;

        if ((h1 = xopen(p1, 2)) < 0L)
                return (h1);

        f1 = getofd ((int)h1);

        fd = f1->o_dirfil;
        buf[0] = 0xe5;
        ixlseek(fd,f1->o_dirbyt);

        if (dn1 != dn2)
        {
                /* get old attribute */
                f = (FCB *) ixread(fd,32L,NULLPTR);
                att = f->f_attrib;
                /* erase (0xe5) old file */
                ixlseek(fd,f1->o_dirbyt);
                ixwrite(fd,1L,buf);

                /* copy time/date/clust, etc. */

                ixlseek(fd,f1->o_dirbyt + 22);
                ixread(fd,10L,buf);
                hnew = xcreat(p2,att);
                fd2 = getofd(hnew);
                ixlseek(fd2->o_dirfil,fd2->o_dirbyt + 22);
                ixwrite(fd2->o_dirfil,10L,buf);
                fd2->o_flag &= ~O_DIRTY;
                xclose(hnew);
                ixclose(fd2->o_dirfil,CL_DIR);
        }
        else
        {
                builds(s2,buf);
                ixwrite(fd,11L,buf);
        }

        if ((rc = xclose((int)h1)) < 0L)
                return(rc);

        return(ixclose(fd,CL_DIR));
}
Example #5
0
long xrmdir(char *p)
{
        register DND *d;
        DND     *d1,**q;
        FCB     *f;
        OFD     *fd,*f2;                /* M01.01.03 */
        long    pos;
        const char *s;
        register int i;

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

        /*  M01.01.SCC.FS.09  */
        if( ! d->d_parent )                     /*  Can't delete root  */
                return( EACCDN ) ;

        for( i = 1 ; i <= NCURDIR ; i++ )       /*  Can't delete in use  */
                if( diruse[i] && dirtbl[i] == d )
                    return( EACCDN ) ;
         
        /*  end M01.01.SCC.FS.09  */

        if (!(fd = d->d_ofd))
                if (!(fd = makofd(d))) 
                        return (ENSMEM);

        ixlseek(fd,0x40L);
        do
        {
                if (!(f = (FCB *) ixread(fd,32L,NULLPTR)))
                        break;
        } while (f->f_name[0] == (char)0x0e5 || f->f_attrib == FA_LFN);


        if( f != (FCB*)NULLPTR  &&  f->f_name[0] != 0 )
                return(EACCDN);

        for(d1 = *(q = &d->d_parent->d_left); d1 != d; d1 = *(q = &d1->d_right))
                ; /* follow sib-links */

        if( d1 != d )
                return(EINTRN);         /* internal error */

        if (d->d_files)
                return(EINTRN);         /* open files ? - internal error */

        if (d->d_left)
                return(EINTRN);         /* subdir - internal error */


        /* take him out ! */

        *q = d->d_right;

        if (d->d_ofd)
        {
                xmfreblk((char *)d->d_ofd);             
        }

        d1 = d->d_parent;
        xmfreblk((char *)d);
        ixlseek((f2 = fd->o_dirfil),(pos = fd->o_dirbyt));
        f = (FCB *) ixread(f2,32L,NULLPTR);

        return(ixdel(d1,f,pos));
}
Example #6
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);
}
Example #7
0
FCB     *scan(register DND *dnd, const char *n, WORD att, LONG *posp)
{ 
        char    name[12];
        register FCB *fcb;
        OFD     *fd;
        DND     *dnd1;
        BOOL    m;              /*  T: found a matching FCB             */

#if DBGFSDIR
        kprintf("scan(%p, '%s', 0x%x, %p)\n", dnd, n, att, posp);
#endif

        m = 0;                  /*  have_match = false                  */
        builds(n,name);         /*  format name into dir format         */
        name[11] = att;

        dnd1 = 0; /* dummy to avoid warning */

        /*
        **  if there is no open file descr for this directory, make one
        */

        if (!(fd = dnd->d_ofd))
        {
                if (!(dnd->d_ofd = (fd = makofd(dnd))))
                {
                        return ( (FCB *) 0 );
                }
        }

        /*
        **  seek to desired starting position.  If posp == -1, then start at
        **      the beginning.
        */

        ixlseek( fd , (*posp == -1) ? 0L : *posp ) ;

        /*
        **  scan thru the directory file, looking for a match
        */

        while ((fcb = (FCB *) ixread(fd,32L,NULLPTR)) && (fcb->f_name[0]))
        {
                /* 
                **  Add New DND.
                **  ( iff after scan ptr && complete flag not set && not a . 
                **  or .. && subdirectory && not deleted ) M01.01.0512.01
                */

                if( (fcb->f_attrib & FA_SUBDIR)         &&
#if     ! M0101052901
                    (!(fd->o_flag & O_COMPLETE))        &&
#endif
                    (fcb->f_name[0] != '.')             && 
                    (fcb->f_name[0] != (char)0xe5)
                )
                {       /*  see if we already have it  */
                        dnd1 = getdnd( &fcb->f_name[0] , dnd ) ;
                        if (!dnd1)
                                if (!(dnd1 = makdnd(dnd,fcb)))
                                        return( NULLPTR ) ;
                }

                if ( (m = match( name , fcb->f_name )) )
                                        break;
        }

#if DBGFSDIR
        kprintf("\n   scan(pos=%ld DND=%08lx DNDfoundFile=%08lx name=%s name1=%s, %d)",
                (long)fd->o_bytnum, (long)dnd, (long)dnd1, fcb->f_name, name, m);
#endif
        /* restore directory scanning pointer */

        if( *posp != -1L )
                *posp = fd->o_bytnum ;

        /*
        **  if there was no match, but we were looking for a deleted entry,
        **  then return a pointer to a deleted fcb.  Otherwise, if there was
        **  no match, return a null pointer
        */

        if (!m)
        {       /*  assumes that (*n != 0xe5) (if posp == -1)  */
                if( fcb && (*n == (char)0xe5) )
                        return(fcb) ;
#if     ! M0101052901
                fd->o_flag |= O_COMPLETE;
#endif
                return( (FCB *) 0 );
        }

        if (*posp == -1)
        {       /*  seek to position of found entry  */
                ixlseek(fd,fd->o_bytnum - 32);
                return(((FCB *) dnd1));
        }

        return(fcb);
}