static int msdos_create_entry(struct inode *dir,char *name,int is_dir, struct inode **result) { struct buffer_head *bh; struct msdos_dir_entry *de; int res,ino; if ((res = msdos_scan(dir,NULL,&bh,&de,&ino)) < 0) { if (dir->i_ino == MSDOS_ROOT_INO) return -ENOSPC; if ((res = msdos_add_cluster(dir)) < 0) return res; if ((res = msdos_scan(dir,NULL,&bh,&de,&ino)) < 0) return res; } memcpy(de->name,name,MSDOS_NAME); de->attr = is_dir ? ATTR_DIR : ATTR_ARCH; de->start = 0; date_unix2dos(CURRENT_TIME,&de->time,&de->date); de->size = 0; bh->b_dirt = 1; if (*result = iget(dir->i_dev,ino)) msdos_read_inode(*result); brelse(bh); if (!*result) return -EIO; (*result)->i_mtime = (*result)->i_atime = (*result)->i_ctime = CURRENT_TIME; (*result)->i_dirt = 1; return 0; }
int fileinfo_to_ino(char *databuf, struct inode *ino, int level, unsigned short datalen, struct sffsi32 *psffsi) { int rc; pCommonFileInfo pCommon; unsigned short time; unsigned short date; rc = NO_ERROR; /* * Only FIL_STANDARD is significant. FIL_QUERYEASIZE is not because one can't SET EAS in an ext2 * file system. */ if (level == FIL_STANDARD) { if (datalen >= sizeof(pCommonFileInfo)) { pCommon = (pCommonFileInfo) databuf; /* * Creation date */ date_unix2dos(ino->i_ctime, __StackToFlat(&time), __StackToFlat(&date)); if (pCommon->timeCreate) time = pCommon->timeCreate; if (pCommon->dateCreate) date = pCommon->dateCreate; ino->i_ctime = date_dos2unix(time, date); if (psffsi) { psffsi->sfi_cdate = date; psffsi->sfi_ctime = time; if ((pCommon->timeCreate) || (pCommon->dateCreate)) { /* * Clears the stamp creation date bit if we've just modified the creation date. */ psffsi->sfi_tstamp &= ~ST_SCREAT; // disable kernel time stamp psffsi->sfi_tstamp |= ST_PCREAT; // propagate new value to other sft } } /* * Last write date */ date_unix2dos(ino->i_mtime, __StackToFlat(&time), __StackToFlat(&date)); if (pCommon->timeWrite) time = pCommon->timeWrite; if (pCommon->dateWrite) date = pCommon->dateWrite; ino->i_mtime = date_dos2unix(time, date); if (psffsi) { psffsi->sfi_mdate = date; psffsi->sfi_mtime = time; if ((pCommon->timeWrite) || (pCommon->dateWrite)) { /* * Clears the stamp last write date bit if we've just modified the last write date. */ psffsi->sfi_tstamp &= ~ST_SWRITE; // disable kernel time stamp psffsi->sfi_tstamp |= ST_PWRITE; // propagate new value to other sft } } /* * Last access date */ date_unix2dos(ino->i_atime, __StackToFlat(&time), __StackToFlat(&date)); if (pCommon->timeAccess) time = pCommon->timeAccess; if (pCommon->dateAccess) date = pCommon->dateAccess; ino->i_atime = date_dos2unix(time, date); if (psffsi) { psffsi->sfi_adate = date; psffsi->sfi_atime = time; if ((pCommon->timeAccess) || (pCommon->dateAccess)) { /* * Clears the stamp last access date bit if we've just modified the last access date. */ psffsi->sfi_tstamp &= ~ST_SREAD; // disable kernel time stamp psffsi->sfi_tstamp |= ST_PREAD; // propagate new value to other sft } } /* * File size - neither the IFS document nor the Control Program Reference * are clear about if we must change the file size when DosSetPathInfo * or DosSetFIleInfo is called. HPFS does NOT change it .... so we don't * change it also. */ /* * File attributes */ DOS_To_Linux_Attrs(ino, pCommon->attr); /* * Marks the inode as dirty */ ino->i_dirt = 1; } else { rc = ERROR_BUFFER_OVERFLOW; } } return rc; }
int ino_to_fileinfo( struct inode *pino, char *databuf, UINT32 maxlen, PUINT32 plen, unsigned short level, unsigned short flags, unsigned short attrs, struct dirent *pDir, INT32 position, int TypeOp) { pCommonFileInfo pCommon; pFileName pFile; PINT32 pPosition; *plen = 0; /***************************************************************************/ /*** First field : long position if FF_GETPOS - nothing if FF_NOPOS ***/ /***************************************************************************/ if (TypeOp == TYPEOP_FILEFIND) { if (flags == FF_GETPOS) { if (sizeof(INT32) + *plen > maxlen) { fs_log("ino_to_fileinfo() - Buffer overflow for first field"); return ERROR_BUFFER_OVERFLOW; } pPosition = (PINT32) (databuf + *plen); *pPosition = position; *plen += sizeof(INT32); } } /***************************************************************************/ /***************************************************************************/ /*** Second field : common file information to all level/flags ***/ /***************************************************************************/ if (sizeof(CommonFileInfo) + *plen > maxlen) { kernel_printf("ino_to_fileinfo() - Buffer overflow for second field - len = %lu - maxlen = %lu", (UINT32) sizeof(CommonFileInfo) + (UINT32) (*plen), (UINT32) maxlen); return ERROR_BUFFER_OVERFLOW; } pCommon = (pCommonFileInfo) (databuf + *plen); date_unix2dos(pino->i_ctime, &(pCommon->timeCreate), &(pCommon->dateCreate)); date_unix2dos(pino->i_atime, &(pCommon->timeAccess), &(pCommon->dateAccess)); date_unix2dos(pino->i_mtime, &(pCommon->timeWrite), &(pCommon->dateWrite)); pCommon->cbEOF = pino->i_size; pCommon->cbAlloc = pino->i_blocks; pCommon->attr = FILE_NORMAL; if ((S_ISLNK(pino->i_mode)) || (S_ISBLK(pino->i_mode)) || (S_ISCHR(pino->i_mode)) || (S_ISFIFO(pino->i_mode)) || (S_ISSOCK(pino->i_mode))) { pCommon->attr |= FILE_SYSTEM; /*** UNIXish special files are seen as SYSTEM files ***/ } /* endif */ if (S_ISDIR(pino->i_mode)) { pCommon->attr |= FILE_DIRECTORY; } /* endif */ if ((!(pino->i_mode & S_IWUSR)) && (!(pino->i_mode & S_IWGRP)) && (!(pino->i_mode & S_IWOTH))) { pCommon->attr |= FILE_READONLY; } *plen += sizeof(CommonFileInfo); /***************************************************************************/ /***************************************************************************/ /*** Third field : nothing for level FIL_STANDARD ***/ /***************************************************************************/ /***************************************************************************/ /***************************************************************************/ /*** Third field : Size on disk of EA set for FIL_QUERYEASIZE ***/ /***************************************************************************/ if (level == FIL_QUERYEASIZE) { if (sizeof(INT32) + *plen > maxlen) { fs_log("ino_to_fileinfo() - Buffer overflow for Third field - FIL_QUERYEASIZE"); return ERROR_BUFFER_OVERFLOW; } *((PINT32) (databuf + *plen)) = 0; /*** No EAS in ext2 ***/ *plen += sizeof(INT32); } /***************************************************************************/ /***************************************************************************/ /*** Third field : FEAList for level QUERYEASFROMLIST ***/ /***************************************************************************/ if (level == FIL_QUERYEASFROMLIST) { if (sizeof(INT32) + *plen > maxlen) { fs_log("ino_to_fileinfo() - Buffer overflow for Third field - FIL_QUERYEASFROMLIST"); return ERROR_BUFFER_OVERFLOW; } *((PINT32) (databuf + *plen)) = 4; /*** No EAS in ext2 ***//* this is the length field of FEAList */ *plen += sizeof(INT32); } /***************************************************************************/ /***************************************************************************/ /*** Fourth field : name ***/ /***************************************************************************/ if (TypeOp == TYPEOP_FILEFIND) { if (*plen + sizeof(FileName) + pDir->d_reclen > maxlen) { fs_log("ino_to_fileinfo() - Buffer overflow for fourth field"); return ERROR_BUFFER_OVERFLOW; } pFile = (pFileName) (databuf + *plen); pFile->cbName = (unsigned char)pDir->d_reclen; /* name length WITHOUT '\0' */ strcpy(pFile->szName, pDir->d_name); /* name WITH '\0' */ *plen += sizeof(FileName) + pDir->d_reclen; /* sizeof(FileName) + strlen(Dir.d_name) */ } /***************************************************************************/ return NO_ERROR; }
/* * struct fs32_opencreate_parms { * PTR16 pfgenflag; * PTR16 pEABuf; * unsigned short attr; * PTR16 pAction; * unsigned short openflag; * unsigned long openmode; * PTR16 psffsd; * PTR16 psffsi; * unsigned short iCurDirEnd; * PTR16 pName; * PTR16 pcdfsd; * PTR16 pcdfsi; * }; */ int FS32ENTRY fs32_opencreate(struct fs32_opencreate_parms *parms) { char *pName; struct cdfsi32 *pcdfsi; union cdfsd32 *pcdfsd; struct sffsi32 *psffsi; union sffsd32 *psffsd; unsigned short *pAction; int rc; struct super_block *sb; struct file *p_file, *dir; UINT32 openmode, DOSmode; UINT32 accessmode; UINT16 newflag, existflag; char component[CCHMAXPATH]; char parent[CCHMAXPATH]; struct inode *inode; struct inode *inode_parent; struct inode *base; char *tmp; ino_t ino_no; psffsi = VDHQueryLin(parms->psffsi); psffsd = VDHQueryLin(parms->psffsd); if (parms->pcdfsi.seg) pcdfsi = VDHQueryLin(parms->pcdfsi); else pcdfsi = 0; if (parms->pcdfsd.seg) pcdfsd = VDHQueryLin(parms->pcdfsd); else pcdfsd = 0; pName = VDHQueryLin(parms->pName); pAction = VDHQueryLin(parms->pAction); if (trace_FS_OPENCREATE) { kernel_printf("FS_OPENCREATE(%s)", pName); } #ifdef FS_TRACE if (parms->ulOpenMode & OPEN_FLAGS_DASD) { fs_log("OPEN_FLAGS_DASD"); } if (parms->ulOpenMode & OPEN_FLAGS_WRITE_THROUGH) { fs_log("OPEN_FLAGS_WRITE_THROUGH"); } if (parms->ulOpenMode & OPEN_FLAGS_FAIL_ON_ERROR) { fs_log("OPEN_FLAGS_FAIL_ON_ERROR"); } if (parms->ulOpenMode & OPEN_FLAGS_NO_CACHE) { fs_log("OPEN_FLAGS_NO_CACHE"); } if (parms->ulOpenMode & OPEN_FLAGS_NOINHERIT) { fs_log("OPEN_FLAGS_NO_INHERIT"); } #endif accessmode = parms->ulOpenMode & OPEN_ACCESS_MASK; if (accessmode == OPEN_ACCESS_READONLY) { #ifdef FS_TRACE fs_log("OPEN_ACCESS_READONLY"); #endif openmode = OPENMODE_READONLY; } if (accessmode == OPEN_ACCESS_WRITEONLY) { #ifdef FS_TRACE fs_log("OPEN_ACCESS_WRITEONLY"); #endif openmode = OPENMODE_WRITEONLY; } if (accessmode == OPEN_ACCESS_READWRITE) { #ifdef FS_TRACE fs_log("OPEN_ACCESS_READWRITE"); #endif openmode = OPENMODE_READWRITE; } #ifdef FS_TRACE if (accessmode == OPEN_ACCESS_EXECUTE) { fs_log("OPEN_ACCESS_EXECUTE"); } #endif newflag = parms->openflag & OPEN_ACTION_NEW_MASK; #ifdef FS_TRACE if (newflag == OPEN_ACTION_FAIL_IF_NEW) { fs_log("OPEN_ACTION_FAIL_IF_NEW"); } if (newflag == OPEN_ACTION_CREATE_IF_NEW) { fs_log("OPEN_ACTION_CREATE_IF_NEW"); } #endif existflag = parms->openflag & OPEN_ACTION_EXIST_MASK; #ifdef FS_TRACE if (existflag == OPEN_ACTION_OPEN_IF_EXISTS) { fs_log("OPEN_ACTION_OPEN_IF_EXISTS"); } if (existflag == OPEN_ACTION_FAIL_IF_EXISTS) { fs_log("OPEN_ACTION_FAIL_IF_EXISTS"); } if (existflag == OPEN_ACTION_REPLACE_IF_EXISTS) { fs_log("OPEN_ACTION_REPLACE_IF_EXISTS"); } #endif if ((!Read_Write) && ((accessmode == OPEN_ACCESS_READWRITE) || (accessmode == OPEN_ACCESS_WRITEONLY))) { fs_log("FS_OPENCREATE() - Write access not enabled"); return ERROR_WRITE_PROTECT; } // // Direct access open of the whole device // if (parms->ulOpenMode & OPEN_FLAGS_DASD) { sb = getvolume(psffsi->sfi_hVPB); kernel_printf("OPEN_FLAGS_DASD"); if ((p_file = _open_by_inode(sb, INODE_DASD, openmode)) == 0) { kernel_printf("FS_OPENCREATE() - couldn't DASD open %s", pName); return ERROR_OPEN_FAILED; } psffsd->f = p_file; psffsi->sfi_tstamp = ST_SCREAT | ST_PCREAT; psffsi->sfi_size = p_file->f_inode->i_size; psffsi->sfi_position = p_file->f_pos; date_unix2dos(p_file->f_inode->i_ctime, &(psffsi->sfi_ctime), &(psffsi->sfi_cdate)); date_unix2dos(p_file->f_inode->i_atime, &(psffsi->sfi_atime), &(psffsi->sfi_adate)); date_unix2dos(p_file->f_inode->i_mtime, &(psffsi->sfi_mtime), &(psffsi->sfi_mdate)); return NO_ERROR; } // // Now that we treated the OPEN_FLAGS_DASD special case, lets treat the general case : // Try to open the file readonly // Success : the file exists // if !S_ISDIR && !S_ISREG => error // if OPEN_ACTION_FAIL_IF_EXISTS set => error // if OPEN_ACTION_OPEN_IF_EXISTS set // <test file attrs> // change the open mode and return OK // if OPEN_ACTION_REPLACE_IF_EXISTS set // OPEN_ACCESS_READONLY or OPEN_ACCESS_EXECUTE set => error // OPEN_ACCESS_READWRITE or OPEN_ACCESS_WRITEONLY set // truncate // change openmode and return // Failure : the file does not exist // OPEN_ACCESS_READONLY or OPEN_ACCESS_EXECUTE set => error // OPEN_ACCESS_READWRITE or OPEN_ACCESS_WRITEONLY set // if OPEN_ACTION_CREATE_IF_NEW set // try to create the file // open the file and return // if OPEN_ACTION_FAIL_IF_NEW set => error rc = ERROR_INVALID_PARAMETER; if (parms->iCurDirEnd != CURDIREND_INVALID) { tmp = pName + parms->iCurDirEnd; if ((pcdfsd->u.p_file) && (pcdfsd->u.p_file->f_magic == FILE_MAGIC)) { base = pcdfsd->u.p_file->f_inode; if (base) { sb = base->i_sb; rc = NO_ERROR; } } } else { sb = getvolume(psffsi->sfi_hVPB); if ((sb) && (sb->s_magic_internal == SUPER_MAGIC)) { tmp = skip_drive(pName); base = sb->s_mounted; if (base) { rc = NO_ERROR; } } } if (rc != NO_ERROR) { return rc; } p_file = open_by_name(base, tmp, openmode); if (p_file) { // The file exists // // If it's not a regular file or a directory we cannot open // if (!S_ISREG(p_file->f_inode->i_mode)) { // kernel_printf("Can't FS_OPENCREATE - %s is not a regular file", pName); if ((rc = vfs_close(p_file)) != NO_ERROR) { fs_err(FUNC_FS_OPENCREATE, FUNC_CLOSE, rc, FILE_TEST_C, __LINE__); return rc; } return ERROR_ACCESS_DENIED; } // // if OPEN_ACTION_FAIL_IF_EXISTS set => error // if (existflag == OPEN_ACTION_FAIL_IF_EXISTS) { #ifdef FS_TRACE fs_log("Can't FS_OPENCREATE() - File exists & OPEN_ACTION_FAIL_IF_EXISTS"); #endif if ((rc = vfs_close(p_file)) != NO_ERROR) { fs_err(FUNC_FS_OPENCREATE, FUNC_CLOSE, rc, FILE_TEST_C, __LINE__); return rc; } return ERROR_FILE_EXISTS; } // // if OPEN_ACTION_OPEN_IF_EXISTS : OK // if (existflag == OPEN_ACTION_OPEN_IF_EXISTS) { *pAction = FILE_EXISTED; } // // if OPEN_ACTION_REPLACE_IF_EXISTS : truncate // if (existflag == OPEN_ACTION_REPLACE_IF_EXISTS) { p_file->f_inode->i_size = psffsi->sfi_size; p_file->f_inode->i_op->truncate(p_file->f_inode); p_file->f_inode->i_dirt = 1; p_file->f_flags = O_TRUNC; *pAction = FILE_TRUNCATED; #if 0 psffsi->sfi_tstamp = ST_PWRITE | ST_SWRITE; #else /* * Time stamping is done by inode routines - Only propagate value. */ psffsi->sfi_tstamp = ST_PWRITE; #endif } } else { // The file doesn't exist ExtractPath(pName, __StackToFlat(parent)); ExtractName(pName, __StackToFlat(component)); // // We try to open the parent dir // if ((dir = open_by_name(sb->s_mounted, Skip_drive(__StackToFlat(parent)), OPENMODE_READONLY)) == 0) { // kernel_printf("FS_OPENCREATE() - The parent directory %s doesn't seem to exist", parent); return ERROR_PATH_NOT_FOUND; } // // The parent dir exists // // // If the file is open for execution : error (it doesn't even exist) // if (accessmode == OPEN_ACCESS_EXECUTE) { #ifdef FS_TRACE fs_log("Can't FS_OPENCREATE() - File doesn't exist & OPEN_ACCESS_EXECUTE"); #endif if ((rc = vfs_close(dir)) != NO_ERROR) { fs_err(FUNC_FS_OPENCREATE, FUNC_CLOSE, rc, FILE_TEST_C, __LINE__); return rc; } return ERROR_FILE_NOT_FOUND; } // // If the file is open for writing or readwrite ... // if ((accessmode == OPEN_ACCESS_READONLY) || (accessmode == OPEN_ACCESS_READWRITE) || (accessmode == OPEN_ACCESS_WRITEONLY)) { if (newflag == OPEN_ACTION_FAIL_IF_NEW) { #ifdef FS_TRACE fs_log("Can't FS_OPENCREATE() - File doesn't exist & OPEN_ACTION_FAIL_IF_NEW"); #endif if ((rc = vfs_close(dir)) != NO_ERROR) { fs_err(FUNC_FS_OPENCREATE, FUNC_CLOSE, rc, FILE_TEST_C, __LINE__); return rc; } return ERROR_OPEN_FAILED; } if (newflag == OPEN_ACTION_CREATE_IF_NEW) { // ino_no = dir->f_inode->i_ino; inode_parent = dir->f_inode; inode_parent->i_count++; if ((rc = vfs_close(dir)) != NO_ERROR) { fs_err(FUNC_FS_OPENCREATE, FUNC_CLOSE, rc, THISFILE, __LINE__); return rc; } // inode_parent = iget(sb, ino_no); inode_parent->i_count++; down(&inode_parent->i_sem); rc = inode_parent->i_op->create(inode_parent, __StackToFlat(component), strlen(component), S_IRWXU | S_IFREG, __StackToFlat(&inode)); up(&inode_parent->i_sem); if (rc) { kernel_printf("Couldn't create %s", pName); iput(inode_parent); return rc; } ino_no = inode->i_ino; iput(inode_parent); iput(inode); if ((p_file = _open_by_inode(sb, ino_no, openmode)) == 0) { kernel_printf("open_by_inode(%lu) failed in FS_OPENCREATE", ino_no); return ERROR_OPEN_FAILED; } p_file->f_inode->i_size = psffsi->sfi_size; p_file->f_inode->i_dirt = 1; p_file->f_flags = O_CREAT; *pAction = FILE_CREATED; #if 0 psffsi->sfi_tstamp = ST_SCREAT | ST_PCREAT | ST_PWRITE | ST_SWRITE; #else /* * Time stamping is done by inode routines - Only propagate value. */ psffsi->sfi_tstamp = ST_PCREAT | ST_PWRITE; #endif } } } psffsd->f = p_file; /* * Time stamping is done by inode routines - Only propagate value. */ #if 0 psffsi->sfi_tstamp |= ST_PREAD | ST_SREAD; #else /* * Time stamping is done by inode routines - Only propagate value. */ psffsi->sfi_tstamp |= ST_PREAD; #endif psffsi->sfi_size = p_file->f_inode->i_size; psffsi->sfi_position = p_file->f_pos; // kernel_printf("date = %u/%u/%u", (pCommon->dateCreate) & 31, (pCommon->dateCreate >> 5) & 15 , (pCommon->dateCreate) >> 9); date_unix2dos(p_file->f_inode->i_ctime, &(psffsi->sfi_ctime), &(psffsi->sfi_cdate)); date_unix2dos(p_file->f_inode->i_atime, &(psffsi->sfi_atime), &(psffsi->sfi_adate)); date_unix2dos(p_file->f_inode->i_mtime, &(psffsi->sfi_mtime), &(psffsi->sfi_mdate)); psffsi->sfi_DOSattr = (unsigned char)Linux_To_DOS_Attrs(p_file->f_inode, __StackToFlat(component)); if (write_through_support) { if ((parms->ulOpenMode & OPEN_FLAGS_WRITE_THROUGH) || (parms->ulOpenMode & OPEN_FLAGS_NO_CACHE)) { p_file->f_flags |= O_SYNC; p_file->f_inode->i_flags |= MS_SYNCHRONOUS; } } return NO_ERROR; }