diff --git a/hdr/device.h b/hdr/device.h index 0e81fbff..0ad2fe62 100644 --- a/hdr/device.h +++ b/hdr/device.h @@ -486,6 +486,7 @@ extern request /* I/O Request packets */ /* dsk.c */ COUNT ASMCFUNC FAR blk_driver(rqptr rp); ddt * getddt(int dev); +COUNT writelabelBPB(char drive, const char *name); /* error.c */ COUNT char_error(request * rq, struct dhdr FAR * lpDevice); diff --git a/kernel/dsk.c b/kernel/dsk.c index 654f8b98..ae4c4918 100644 --- a/kernel/dsk.c +++ b/kernel/dsk.c @@ -97,6 +97,40 @@ ddt *getddt(int dev) return &(((ddt *) Dyn.Buffer)[dev]); } +STATIC WORD getbpb(ddt *pddt); +STATIC WORD RWzero(ddt *pddt, UWORD mode); + +COUNT writelabelBPB(char drive, const char *name) +{ + ddt *pddt = getddt(drive - 'A'); + struct FS_info *fs; + int offset; + int ret; + + ret = getbpb(pddt); + if (ret != 0) + return ret; + + if (DiskTransferBuffer[0x26] == 0x29 && + pddt->ddt_bpb.bpb_nfsect != 0) // BPB v4.1 + offset = 0x27; + else if (DiskTransferBuffer[0x42] == 0x29 && + pddt->ddt_bpb.bpb_nfsect == 0) // BPB v7 long + offset = 0x43; + else + return -1; + + /* store volume name */ + fs = (struct FS_info *)&DiskTransferBuffer[offset]; + memcpy(&fs->volume[0], name, 11); + + ret = RWzero(pddt, LBA_WRITE); + if (ret != 0) + return ret; + + return 0; +} + STATIC VOID tmark(ddt *pddt) { pddt->ddt_fh.ddt_lasttime = ReadPCClock(); @@ -122,7 +156,6 @@ STATIC dsk_proc mediachk, bldbpb, blockio, IoctlQueblk, Genblkdev, Getlogdev, Setlogdev, blk_Open, blk_Close, blk_Media, blk_noerr, blk_nondr, blk_error; -STATIC WORD getbpb(ddt * pddt); #ifdef PROTO STATIC WORD dskerr(COUNT); #else diff --git a/kernel/fatfs.c b/kernel/fatfs.c index eb9b97dd..8d288bdd 100644 --- a/kernel/fatfs.c +++ b/kernel/fatfs.c @@ -39,6 +39,7 @@ BYTE *RcsId = "$Id: fatfs.c 1632 2011-06-13 16:29:14Z bartoldeman $"; /* */ STATIC f_node_ptr sft_to_fnode(int fd); STATIC void fnode_to_sft(f_node_ptr fnp); +STATIC int find_fattr(const char *path, int attr, f_node_ptr fnp); STATIC int find_fname(const char *path, int attr, f_node_ptr fnp); /* /// Added - Ron Cemer */ STATIC int merge_file_changes(f_node_ptr fnp, int collect); @@ -124,10 +125,36 @@ STATIC void init_direntry(struct dirent *dentry, unsigned attrib, int dos_open(char *path, unsigned flags, unsigned attrib, int fd) { REG f_node_ptr fnp = sft_to_fnode(fd); - int status = find_fname(path, D_ALL | attrib, fnp); + int status; + + /* Special handling for volume name (they can coexist with files/directories) */ + if (((attrib & (D_DIR | D_VOLID | D_SYSTEM | D_HIDDEN | D_RDONLY)) == D_VOLID) && + (flags & O_TRUNC)) + { + int ret; + + /* Count the slashes to see if we are in the root directory */ + if (strchr(path + 3, '\\')) + return DE_ACCESS; + + /* Check to see if there are any other files with VOLID set */ + status = find_fattr(path, D_VOLID, fnp); + if (status == SUCCESS) + return DE_ACCESS; + + /* Create our new label */ + ret = alloc_find_free(fnp, path); + if (ret != SUCCESS) + return ret; + status = S_CREATED; + + writelabelBPB(path[0], path + 3); + goto doit; + } /* Check that we don't have a duplicate name, so if we */ /* find one, truncate it (O_CREAT). */ + status = find_fname(path, D_ALL | attrib, fnp); if (status == SUCCESS) { unsigned char dir_attrib = fnp->f_dir.dir_attrib; @@ -179,6 +206,8 @@ int dos_open(char *path, unsigned flags, unsigned attrib, int fd) return status; } +doit: + /* Now change to file */ fnp->f_sft_idx = fd; fnp->f_offset = 0l; @@ -232,7 +261,7 @@ COUNT dos_close(COUNT fd) } /* */ -/* split a path into it's component directory and file name */ +/* split a path into its component directory and file name */ /* */ f_node_ptr split_path(const char * path, f_node_ptr fnp) { @@ -274,6 +303,22 @@ BOOL fcbmatch(const char *fcbname1, const char *fcbname2) return memcmp(fcbname1, fcbname2, FNAME_SIZE + FEXT_SIZE) == 0; } +STATIC int find_fattr(const char *path, int attr, f_node_ptr fnp) +{ + /* check for leading backslash and open the directory given that */ + /* contains the file given by path. */ + if ((fnp = split_path(path, fnp)) == NULL) + return DE_PATHNOTFND; + + while (dir_read(fnp) == 1) + { + if ((fnp->f_dir.dir_attrib & attr) == attr) + return SUCCESS; + fnp->f_dmp->dm_entry++; + } + return DE_FILENOTFND; +} + STATIC int find_fname(const char *path, int attr, f_node_ptr fnp) { /* check for leading backslash and open the directory given that */ @@ -281,12 +326,29 @@ STATIC int find_fname(const char *path, int attr, f_node_ptr fnp) if ((fnp = split_path(path, fnp)) == NULL) return DE_PATHNOTFND; + /* + * attr = 0x00 returns NORMAL + * 0x02 returns NORMAL + HIDDEN + * 0x04 returns NORMAL + SYSTEM + * 0x06 returns NORMAL + HIDDEN + SYSTEM + * 0x08 returns VOLID only (DOS 3+) + * 0x10 returns DIRECTORIES + */ + while (dir_read(fnp) == 1) { - if (fcbmatch(fnp->f_dir.dir_name, fnp->f_dmp->dm_name_pat) - && (fnp->f_dir.dir_attrib & ~(D_RDONLY | D_ARCHIVE | attr)) == 0) + if (fcbmatch(fnp->f_dir.dir_name, fnp->f_dmp->dm_name_pat)) { - return SUCCESS; + if (attr & D_VOLID) + { + if (fnp->f_dir.dir_attrib & D_VOLID) + return SUCCESS; + } + else + { + if ((fnp->f_dir.dir_attrib & ~(D_RDONLY | D_ARCHIVE | attr)) == 0) + return SUCCESS; + } } fnp->f_dmp->dm_entry++; }