/* 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; }
/*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)); }