/* * join_path_components - join two path components, inserting a slash * * We omit the slash if either given component is empty. * * ret_path is the output area (must be of size MAXPGPATH) * * ret_path can be the same as head, but not the same as tail. */ void join_path_components(char *ret_path, const char *head, const char *tail) { if (ret_path != head) strlcpy(ret_path, head, MAXPGPATH); /* * Remove any leading "." in the tail component. * * Note: we used to try to remove ".." as well, but that's tricky to get * right; now we just leave it to be done by canonicalize_path() later. */ while (tail[0] == '.' && IS_DIR_SEP(tail[1])) tail += 2; if (*tail) { /* only separate with slash if head wasn't empty */ snprintf(ret_path + strlen(ret_path), MAXPGPATH - strlen(ret_path), "%s%s", (*(skip_drive(head)) != '\0') ? "/" : "", tail); } }
int target_lookup(MainParam_t *mp, const char *arg) { if((mp->lookupflags & NO_UNIX) || skip_drive(arg) > arg) return dos_target_lookup(mp, arg); else return unix_target_lookup(mp, arg); }
/* * Extracts the actual name of the program as called - * stripped of .exe suffix if any */ const char * get_progname(const char *argv0) { const char *nodir_name; nodir_name = last_dir_separator(argv0); if (nodir_name) nodir_name++; else nodir_name = skip_drive(argv0); #if defined(__CYGWIN__) || defined(WIN32) /* strip .exe suffix, regardless of case */ if (strlen(nodir_name) > sizeof(EXE) - 1 && pg_strcasecmp(nodir_name + strlen(nodir_name)-(sizeof(EXE)-1), EXE) == 0) { char *progname; progname = strdup(nodir_name); if (progname == NULL) { fprintf(stderr, "%s: out of memory\n", nodir_name); exit(1); /* This could exit the postmaster */ } progname[strlen(progname) - (sizeof(EXE) - 1)] = '\0'; nodir_name = progname; } #endif return nodir_name; }
/* * Extracts the actual name of the program as called - * stripped of .exe suffix if any */ const char * get_progname(const char *argv0) { const char *nodir_name; char *progname; nodir_name = last_dir_separator(argv0); if (nodir_name) nodir_name++; else nodir_name = skip_drive(argv0); /* * Make a copy in case argv[0] is modified by ps_status. Leaks memory, but * called only once. */ progname = strdup(nodir_name); if (progname == NULL) { fprintf(stderr, "%s: out of memory\n", nodir_name); exit(1); /* This could exit the postmaster */ } #if defined(__CYGWIN__) || defined(WIN32) /* strip ".exe" suffix, regardless of case */ if (strlen(progname) > sizeof(EXE) - 1 && pg_strcasecmp(progname + strlen(progname) - (sizeof(EXE) - 1), EXE) == 0) progname[strlen(progname) - (sizeof(EXE) - 1)] = '\0'; #endif return progname; }
/* Returns a malloced string */ char *SLpath_pathname_sans_extname (SLFUTURE_CONST char *drivefile) { char *b; char *file; drivefile = SLmake_string (drivefile); if (drivefile == NULL) return NULL; file = (char *)skip_drive (drivefile); b = file + strlen (file); while (b != file) { b--; if (IS_PATH_SEP(*b)) break; if (*b == '.') { *b = 0; break; } } return drivefile; }
/* * first_dir_separator * * Find the location of the first directory separator, return * NULL if not found. */ char * first_dir_separator(const char *filename) { const char *p; for (p = skip_drive(filename); *p; p++) if (IS_DIR_SEP(*p)) return (char *) p; return NULL; }
/* * trim_trailing_separator * * trim off trailing slashes, but not a leading slash */ static void trim_trailing_separator(char *path) { char *p; path = skip_drive(path); p = path + strlen(path); if (p > path) for (p--; p > path && IS_DIR_SEP(*p); p--) *p = '\0'; }
/* * last_dir_separator * * Find the location of the last directory separator, return * NULL if not found. */ char * last_dir_separator(const char *filename) { const char *p, *ret = NULL; for (p = skip_drive(filename); *p; p++) if (IS_DIR_SEP(*p)) ret = p; return (char *) ret; }
static int common_dos_loop(MainParam_t *mp, const char *pathname, lookupState_t *lookupState, int open_mode) { Stream_t *RootDir; char *cwd; char *drive; char *rest; int ret; mp->loop = _dos_loop; drive='\0'; cwd = ""; if((rest = skip_drive(pathname)) > pathname) { drive = get_drive(pathname, NULL); if (strncmp(pathname, mp->mcwd, rest - pathname) == 0) cwd = skip_drive(mp->mcwd); pathname = rest; } else { drive = get_drive(mp->mcwd, NULL); cwd = skip_drive(mp->mcwd); } if(*pathname=='/') /* absolute path name */ cwd = ""; RootDir = mp->File = open_root_dir(drive, open_mode); if(!mp->File) return ERROR_ONE; ret = recurs_dos_loop(mp, cwd, pathname, lookupState); if(ret & NO_CWD) { /* no CWD */ *mp->mcwd = '\0'; unlink_mcwd(); ret = recurs_dos_loop(mp, "", pathname, lookupState); } FREE(&RootDir); return ret; }
int SLpath_is_absolute_path (SLFUTURE_CONST char *name) { if (name == NULL) return -1; #ifdef UNIX_PATHNAMES_OK return (*name == '/'); #else if (IS_PATH_SEP (*name)) return 1; /* If it contains a drive specifier, regard it as absolute */ if (name != skip_drive (name)) return 1; return 0; #endif }
/* If file is /a/b/c/basename, this function returns a pointer to basename */ SLFUTURE_CONST char *SLpath_basename (SLFUTURE_CONST char *drivefile) { SLFUTURE_CONST char *b, *file; if (drivefile == NULL) return NULL; file = skip_drive (drivefile); b = file + strlen (file); while (b != file) { b--; if (IS_PATH_SEP(*b)) return b + 1; } return b; }
int main_loop(MainParam_t *mp, char **argv, int argc) { int i; int ret, Bret; Bret = 0; if(argc != 1 && mp->targetName) { fprintf(stderr, "Several file names given, but last argument (%s) not a directory\n", mp->targetName); } for (i = 0; i < argc; i++) { if ( got_signal ) break; mp->originalArg = argv[i]; mp->basenameHasWildcard = strpbrk(_basename(mp->originalArg), "*[?") != 0; if (mp->unixcallback && skip_drive(argv[i]) == argv[i]) ret = unix_loop(0, mp, argv[i], 1); else ret = dos_loop(mp, argv[i]); if (! (ret & (GOT_ONE | ERROR_ONE)) ) { /* one argument was unmatched */ fprintf(stderr, "%s: File \"%s\" not found\n", progname, argv[i]); ret |= ERROR_ONE; } Bret |= ret; if(mp->fast_quit && (Bret & (MISSED_ONE | ERROR_ONE))) break; } FREE(&mp->targetDir); if(Bret & ERROR_ONE) return 1; if ((Bret & GOT_ONE) && ( Bret & MISSED_ONE)) return 2; if (Bret & MISSED_ONE) return 1; return 0; }
/* * Detect whether a path contains any parent-directory references ("..") * * The input *must* have been put through canonicalize_path previously. * * This is a bit tricky because we mustn't be fooled by "..a.." (legal) * nor "C:.." (legal on Unix but not Windows). */ bool path_contains_parent_reference(const char *path) { int path_len; path = skip_drive(path); /* C: shouldn't affect our conclusion */ path_len = strlen(path); /* * ".." could be the whole path; otherwise, if it's present it must be at * the beginning, in the middle, or at the end. */ if (strcmp(path, "..") == 0 || strncmp(path, "../", 3) == 0 || strstr(path, "/../") != NULL || (path_len >= 3 && strcmp(path + path_len - 3, "/..") == 0)) return true; return false; }
/* * trim_directory * * Trim trailing directory from path, that is, remove any trailing slashes, * the last pathname component, and the slash just ahead of it --- but never * remove a leading slash. */ static void trim_directory(char *path) { char *p; path = skip_drive(path); if (path[0] == '\0') return; /* back up over trailing slash(es) */ for (p = path + strlen(path) - 1; IS_DIR_SEP(*p) && p > path; p--) ; /* back up over directory name */ for (; !IS_DIR_SEP(*p) && p > path; p--) ; /* if multiple slashes before directory name, remove 'em all */ for (; p > path && IS_DIR_SEP(*(p - 1)); p--) ; /* don't erase a leading slash */ if (p == path && IS_DIR_SEP(*p)) p++; *p = '\0'; }
/* * Clean up path by: * o make Win32 path use Unix slashes * o remove trailing quote on Win32 * o remove trailing slash * o remove duplicate adjacent separators * o remove trailing '.' * o process trailing '..' ourselves */ void canonicalize_path(char *path) { char *p, *to_p; char *spath; bool was_sep = false; int pending_strips; #ifdef WIN32 /* * The Windows command processor will accept suitably quoted paths with * forward slashes, but barfs badly with mixed forward and back slashes. */ for (p = path; *p; p++) { if (*p == '\\') *p = '/'; } /* * In Win32, if you do: prog.exe "a b" "\c\d\" the system will pass \c\d" * as argv[2], so trim off trailing quote. */ if (p > path && *(p - 1) == '"') *(p - 1) = '/'; #endif /* * Removing the trailing slash on a path means we never get ugly double * trailing slashes. Also, Win32 can't stat() a directory with a trailing * slash. Don't remove a leading slash, though. */ trim_trailing_separator(path); /* * Remove duplicate adjacent separators */ p = path; #ifdef WIN32 /* Don't remove leading double-slash on Win32 */ if (*p) p++; #endif to_p = p; for (; *p; p++, to_p++) { /* Handle many adjacent slashes, like "/a///b" */ while (*p == '/' && was_sep) p++; if (to_p != p) *to_p = *p; was_sep = (*p == '/'); } *to_p = '\0'; /* * Remove any trailing uses of "." and process ".." ourselves * * Note that "/../.." should reduce to just "/", while "../.." has to be * kept as-is. In the latter case we put back mistakenly trimmed ".." * components below. Also note that we want a Windows drive spec to be * visible to trim_directory(), but it's not part of the logic that's * looking at the name components; hence distinction between path and * spath. */ spath = skip_drive(path); pending_strips = 0; for (;;) { int len = strlen(spath); if (len >= 2 && strcmp(spath + len - 2, "/.") == 0) trim_directory(path); else if (strcmp(spath, ".") == 0) { /* Want to leave "." alone, but "./.." has to become ".." */ if (pending_strips > 0) *spath = '\0'; break; } else if ((len >= 3 && strcmp(spath + len - 3, "/..") == 0) || strcmp(spath, "..") == 0) { trim_directory(path); pending_strips++; } else if (pending_strips > 0 && *spath != '\0') { /* trim a regular directory name canceled by ".." */ trim_directory(path); pending_strips--; /* foo/.. should become ".", not empty */ if (*spath == '\0') strcpy(spath, "."); } else break; } if (pending_strips > 0) { /* * We could only get here if path is now totally empty (other than a * possible drive specifier on Windows). We have to put back one or * more ".."'s that we took off. */ while (--pending_strips > 0) strcat(path, "../"); strcat(path, ".."); } }
void mcat(int argc, char **argv, int type) { struct device *dev; struct device out_dev; char *drive, name[EXPAND_BUF]; char errmsg[200]; Stream_t *Stream; char buf[BUF_SIZE]; mt_off_t address = 0; char mode = O_RDONLY; int optindex = 1; size_t len; noPrivileges = 1; if (argc < 2) { usage(); } if (argv[1][0] == '-') { if (argv[1][1] != 'w') { usage(); } mode = O_WRONLY; optindex++; } if (argc - optindex < 1) usage(); if (skip_drive(argv[optindex]) == argv[optindex]) usage(); drive = get_drive(argv[optindex], NULL); /* check out a drive whose letter and parameters match */ sprintf(errmsg, "Drive '%s:' not supported", drive); Stream = NULL; for (dev=devices; dev->name; dev++) { FREE(&Stream); if (strcmp(dev->drive, drive) != 0) continue; out_dev = *dev; expand(dev->name,name); #ifdef USING_NEW_VOLD strcpy(name, getVoldName(dev, name)); #endif Stream = 0; #ifdef USE_XDF Stream = XdfOpen(&out_dev, name, mode, errmsg, 0); if(Stream) out_dev.use_2m = 0x7f; #endif #ifdef USE_FLOPPYD if(!Stream) Stream = FloppydOpen(&out_dev, dev, name, mode, errmsg, 0, 1); #endif if (!Stream) Stream = SimpleFileOpen(&out_dev, dev, name, mode, errmsg, 0, 1, 0); if( !Stream) continue; break; } /* print error msg if needed */ if ( dev->drive == 0 ) { FREE(&Stream); fprintf(stderr,"%s\n",errmsg); exit(1); } if (mode == O_WRONLY) { while ((len = fread(buf, 1, BUF_SIZE, stdin)) == BUF_SIZE) { WRITES(Stream, buf, address, BUF_SIZE); address += BUF_SIZE; } if (len) WRITES(Stream, buf, address, len); } else { while ((len = READS(Stream, buf, address, BUF_SIZE)) == BUF_SIZE) { fwrite(buf, 1, BUF_SIZE, stdout); address += BUF_SIZE; } if (len) fwrite(buf, 1, len, stdout); } FREE(&Stream); exit(0); }
/* * has_drive_prefix * * Return true if the given pathname has a drive prefix. */ bool has_drive_prefix(const char *path) { return skip_drive(path) != path; }
/* * struct fs32_chdir_parms { * unsigned short iCurDirEnd; * PTR16 pDir; * PTR16 pcdfsd; * PTR16 pcdfsi; * unsigned short flag; * }; */ int FS32ENTRY fs32_chdir(struct fs32_chdir_parms *parms) { char *pDir; struct cdfsi32 *pcdfsi; union cdfsd32 *pcdfsd; int rc; struct file *p_file; struct super_block *sb; int valid; char *tmp; struct inode *base; switch (parms->flag) { case CD_EXPLICIT: pcdfsi = VDHQueryLin(parms->pcdfsi); pcdfsd = VDHQueryLin(parms->pcdfsd); pDir = VDHQueryLin(parms->pDir); if (trace_FS_CHDIR) { kernel_printf("FS_CHDIR( CD_EXPLICIT, %s )", pDir); } rc = ERROR_INVALID_PARAMETER; if (parms->iCurDirEnd != CURDIREND_INVALID) { tmp = pDir + parms->iCurDirEnd; if ((pcdfsd->u.p_file) && (pcdfsd->u.p_file->f_magic == FILE_MAGIC)) { base = pcdfsd->u.p_file->f_inode; if (base) { rc = NO_ERROR; } } } else { sb = getvolume(pcdfsi->cdi_hVPB); if ((sb) && (sb->s_magic_internal == SUPER_MAGIC)) { tmp = skip_drive(pDir); base = sb->s_mounted; if (base) { rc = NO_ERROR; } } } if (rc == NO_ERROR) { if ((p_file = open_by_name(base, tmp, OPENMODE_READONLY)) == 0) { rc = ERROR_PATH_NOT_FOUND; } else { if (!S_ISDIR(p_file->f_inode->i_mode)) { kernel_printf("FS_CHDIR( %s ) Not a directory", pDir); vfs_close(p_file); rc = ERROR_ACCESS_DENIED; } else { pcdfsd->u.is_valid = 1; pcdfsd->u.p_file = p_file; rc = NO_ERROR; } } } break; case CD_VERIFY: pcdfsi = VDHQueryLin(parms->pcdfsi); pcdfsd = VDHQueryLin(parms->pcdfsd); if (trace_FS_CHDIR) { kernel_printf("FS_CHDIR : flag = CD_VERIFY hVPB=0x%04X", pcdfsi->cdi_hVPB); } // // Gets the superblock from pcdfsi // sb = getvolume(pcdfsi->cdi_hVPB); valid = 1; if ((p_file = open_by_name(sb->s_mounted, skip_drive(pcdfsi->cdi_curdir), OPENMODE_READONLY)) == 0) { valid = 0; } else { if (!S_ISDIR(p_file->f_inode->i_mode)) { vfs_close(p_file); valid = 0; } if (pcdfsi->cdi_flags & CDI_ISVALID) { vfs_close(pcdfsd->u.p_file); } if (valid) { pcdfsd->u.is_valid = 1; pcdfsd->u.p_file = p_file; return NO_ERROR; } else { vfs_close(p_file); return ERROR_PATH_NOT_FOUND; } } break; case CD_FREE: pcdfsd = VDHQueryLin(parms->pcdfsd); if (trace_FS_CHDIR) { kernel_printf("FS_CHDIR( CD_FREE )"); } if (pcdfsd->u.is_valid == 1) { pcdfsd->u.is_valid = 0; if ((rc = vfs_close(pcdfsd->u.p_file)) != NO_ERROR) { fs_err(FUNC_FS_CHDIR, FUNC_CLOSE, rc, THISFILE, __LINE__); } // return rc; } else { rc = NO_ERROR; } break; default: fs_log("FS_CHDIR : invalid flag"); rc = ERROR_INVALID_PARAMETER; } return rc; }
int _mwrite_one(Stream_t *Dir, char *argname, char *shortname, write_data_callback *cb, void *arg, ClashHandling_t *ch) { char longname[VBUFSIZE]; const char *dstname; char dosname[13]; int expanded; struct scan_state scan; clash_action ret; expanded = 0; if(isSpecial(argname)) { fprintf(stderr, "Cannot create entry named . or ..\n"); return -1; } if(ch->name_converter == dos_name) { if(shortname) stripspaces(shortname); if(argname) stripspaces(argname); } if(shortname){ ch->name_converter(shortname,0, &ch->use_longname, dosname); if(ch->use_longname & 1){ /* short name mangled, treat it as a long name */ argname = shortname; shortname = 0; } } /* Skip drive letter */ dstname = skip_drive(argname); /* Copy original argument dstname to working value longname */ strncpy(longname, dstname, VBUFSIZE-1); if(shortname) { ch->name_converter(shortname,0, &ch->use_longname, dosname); if(strcmp(shortname, longname)) ch->use_longname |= 1; } else ch->name_converter(longname,0, &ch->use_longname, dosname); ch->action[0] = ch->namematch_default[0]; ch->action[1] = ch->namematch_default[1]; while (1) { switch((ret=get_slots(Dir, dosname, longname, &scan, ch))){ case NAMEMATCH_ERROR: return -1; /* Non-file-specific error, * quit */ case NAMEMATCH_SKIP: return -1; /* Skip file (user request or * error) */ case NAMEMATCH_PRENAME: ch->name_converter(longname,0, &ch->use_longname, dosname); continue; case NAMEMATCH_RENAME: continue; /* Renamed file, loop again */ case NAMEMATCH_GREW: /* No collision, and not enough slots. * Try to grow the directory */ if (expanded) { /* Already tried this * once, no good */ fprintf(stderr, "%s: No directory slots\n", progname); return -1; } expanded = 1; if (dir_grow(Dir, scan.max_entry)) return -1; continue; case NAMEMATCH_OVERWRITE: case NAMEMATCH_SUCCESS: return write_slots(Dir, dosname, longname, &scan, cb, arg, ch->use_longname); default: fprintf(stderr, "Internal error: clash_action=%d\n", ret); return -1; } } }
/* * 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; }
/* If path looks like: A/B/C/D/whatever, it returns A/B/C/D as a malloced * string. */ char *SLpath_dirname (SLFUTURE_CONST char *drivefile) { SLCONST char *b; const char *file; char *dir, *drivedir; size_t len; if (drivefile == NULL) return NULL; file = skip_drive (drivefile); b = file + strlen (file); while (b != file) { b--; if (0 == IS_PATH_SEP(*b)) continue; #ifdef VMS b++; /* make sure final ] is included */ #else /* collapse multiple slashes */ while ((b != file) && IS_PATH_SEP(*(b-1))) b--; if (b == file) b++; #endif break; } /* now b should point to the character after the slash: * file="zzz/xxxx" * b------^ */ if (b == file) { /* pathological cases -- what is the parent? For simplicity * simply return the current directory. */ len = file - drivefile; if (NULL == (dir = SLmalloc (len + 1 + strlen(THIS_DIR_STRING)))) return NULL; strncpy (dir, drivefile, len); strcpy (dir + len, THIS_DIR_STRING); return dir; } if (NULL == (drivedir = SLmake_nstring (drivefile, b - drivefile))) return NULL; dir = drivedir + (file - drivefile); len = b - file; /* len is from start of file on drive */ #ifndef VMS /* handle special cases * /foo/. --> /foo * /. --> / * /foo/.. --> / * C:/. */ while ((len > 1) && (dir[len-1] == '.')) { if (IS_PATH_SEP(dir[len-2])) { len--; /* lose "." */ while ((len > 1) && IS_PATH_SEP(dir[len-1])) len--; /* lose "/" */ dir[len] = 0; continue; } if ((len > 2) && (dir[len-2] == '.') && IS_PATH_SEP(dir[len-3])) { len -= 2; /* lose ".." */ if (len > 1) { len--; /* lose "/" */ dir[len] = 0; b = SLpath_basename (dir); /* will not fail: zzz/xxx --> zzz/x */ len = b - dir; while ((len > 1) && IS_PATH_SEP(dir[len-1])) len--; } dir[len] = 0; continue; } break; } #endif /* not VMS */ return drivedir; }
void minfo(int argc, char **argv, int type) { struct bootsector boot0; #define boot (&boot0) char name[EXPAND_BUF]; int media; int tot_sectors; struct device dev; char *drive; int verbose=0; int c; Stream_t *Stream; struct label_blk_t *labelBlock; while ((c = getopt(argc, argv, "v")) != EOF) { switch (c) { case 'v': verbose = 1; break; default: usage(); } } if(argc == optind) usage(); for(;optind < argc; optind++) { if(skip_drive(argv[optind]) == argv[optind]) usage(); drive = get_drive(argv[optind], NULL); if(! (Stream = find_device(drive, O_RDONLY, &dev, boot, name, &media, 0))) exit(1); tot_sectors = DWORD(bigsect); SET_INT(tot_sectors, WORD(psect)); printf("device information:\n"); printf("===================\n"); printf("filename=\"%s\"\n", name); printf("sectors per track: %d\n", dev.sectors); printf("heads: %d\n", dev.heads); printf("cylinders: %d\n\n", dev.tracks); printf("mformat command line: mformat -t %d -h %d -s %d ", dev.tracks, dev.heads, dev.sectors); if(DWORD(nhs)) printf("-H %d ", DWORD(nhs)); printf("%s:\n", drive); printf("\n"); printf("bootsector information\n"); printf("======================\n"); printf("banner:\"%8s\"\n", boot->banner); printf("sector size: %d bytes\n", WORD(secsiz)); printf("cluster size: %d sectors\n", boot->clsiz); printf("reserved (boot) sectors: %d\n", WORD(nrsvsect)); printf("fats: %d\n", boot->nfat); printf("max available root directory slots: %d\n", WORD(dirents)); printf("small size: %d sectors\n", WORD(psect)); printf("media descriptor byte: 0x%x\n", boot->descr); printf("sectors per fat: %d\n", WORD(fatlen)); printf("sectors per track: %d\n", WORD(nsect)); printf("heads: %d\n", WORD(nheads)); printf("hidden sectors: %d\n", DWORD(nhs)); printf("big size: %d sectors\n", DWORD(bigsect)); if(WORD(fatlen)) { labelBlock = &boot->ext.old.labelBlock; } else { labelBlock = &boot->ext.fat32.labelBlock; } printf("physical drive id: 0x%x\n", labelBlock->physdrive); printf("reserved=0x%x\n", labelBlock->reserved); printf("dos4=0x%x\n", labelBlock->dos4); printf("serial number: %08X\n", _DWORD(labelBlock->serial)); printf("disk label=\"%11.11s\"\n", labelBlock->label); printf("disk type=\"%8.8s\"\n", labelBlock->fat_type); if(!WORD(fatlen)){ printf("Big fatlen=%u\n", DWORD(ext.fat32.bigFat)); printf("Extended flags=0x%04x\n", WORD(ext.fat32.extFlags)); printf("FS version=0x%04x\n", WORD(ext.fat32.fsVersion)); printf("rootCluster=%u\n", DWORD(ext.fat32.rootCluster)); if(WORD(ext.fat32.infoSector) != MAX32) printf("infoSector location=%d\n", WORD(ext.fat32.infoSector)); if(WORD(ext.fat32.backupBoot) != MAX32) printf("backup boot sector=%d\n", WORD(ext.fat32.backupBoot)); displayInfosector(Stream,boot); } if(verbose) { int size; unsigned char *buf; printf("\n"); size = WORD(secsiz); buf = (unsigned char *) malloc(size); if(!buf) { fprintf(stderr, "Out of memory error\n"); exit(1); } size = READS(Stream, buf, (mt_off_t) 0, size); if(size < 0) { perror("read boot sector"); exit(1); } print_sector("Boot sector hexdump", buf, size); } } exit(0); }