/* * file.c * * File Access Module */ #include #include "fd.h" #include "func.h" #include "kctype.h" #include "kanji.h" #ifndef ENOSPC #define ENOSPC EACCES #endif #if MSDOS #include extern int getcurdrv __P_((VOID_A)); # ifndef _NOUSELFN extern char *preparefile __P_((char *, char *, int)); # endif #else #include #include #include #include #endif #ifndef _NODOSDRIVE extern int flushdrv __P_((int, VOID_T (*)__P_((VOID_A)))); extern int shutdrv __P_((int)); extern int lastdrv; # if MSDOS extern int checkdrive __P_((int)); # endif #endif extern int mark; extern off_t marksize; extern off_t totalsize; extern off_t blocksize; extern char fullpath[]; extern char *tmpfilename; #define DOSDIRENT 32 #define LFNENTSIZ 13 #ifndef O_BINARY #define O_BINARY 0 #endif #define realdirsiz(name) ((dos) ? ((k_strlen(name) / LFNENTSIZ + 1) \ * DOSDIRENT + DOSDIRENT) \ : (((strlen(name) + boundary) \ & ~(boundary - 1)) + dirsize)) #define getnamlen(ent) ((dos) ? ((((ent) - DOSDIRENT) \ / DOSDIRENT) * LFNENTSIZ - 1) \ : ((((ent) - dirsize) \ & ~(boundary - 1)) - 1)) static int NEAR cpfile __P_((char *, char *, struct stat *, struct stat *)); static VOID changemes __P_((VOID_A)); #ifndef _NOWRITEFS static int NEAR k_strlen __P_((char *)); static int NEAR nofile __P_((char *)); static char *NEAR maketmpfile __P_((int, int, char *, char *)); #if !MSDOS static char *NEAR getentnum __P_((char *, int, int)); #endif static VOID NEAR restorefile __P_((char *, char *, int)); #endif /* !_NOWRITEFS */ char *deftmpdir = NULL; #ifndef _NODOSDRIVE static int dosdrv = -1; #endif #if MSDOS int logical_access(mode) u_short mode; #else int logical_access(mode, uid, gid) u_short mode; uid_t uid; gid_t gid; #endif { #if !MSDOS struct group *gp; uid_t euid; char *name; int i; #endif int dir; dir = ((mode & S_IFMT) == S_IFDIR); #if MSDOS mode >>= 6; #else euid = geteuid(); if (uid == euid) mode >>= 6; else if (gid == getegid()) mode >>= 3; else if ((name = getpwuid2(euid))) { setgrent(); while ((gp = getgrent())) { if (gid != gp -> gr_gid) continue; for (i = 0; gp -> gr_mem[i]; i++) { if (!strcmp(name, gp -> gr_mem[i])) { mode >>= 3; break; } } break; } endgrent(); } #endif if (dir && !(mode & F_ISEXE)) mode &= ~(F_ISRED | F_ISWRI); return(mode & 007); } int getstatus(list) namelist *list; { struct stat st, lst; #if MSDOS if (stat2(list -> name, &st) < 0) return(-1); memcpy((char *)&lst, (char *)&st, sizeof(struct stat)); #else # ifndef _NODOSDRIVE if (dospath(list -> name, NULL)) { if (stat2(list -> name, &st) < 0) return(-1); memcpy((char *)&lst, (char *)&st, sizeof(struct stat)); } else # endif if (Xlstat(list -> name, &lst) < 0 || stat2(list -> name, &st) < 0) return(-1); #endif list -> flags = 0; if ((st.st_mode & S_IFMT) == S_IFDIR) list -> flags |= F_ISDIR; if ((lst.st_mode & S_IFMT) == S_IFLNK) list -> flags |= F_ISLNK; if (isdisplnk(dispmode)) memcpy((char *)&lst, (char *)&st, sizeof(struct stat)); #if !MSDOS if ((lst.st_mode & S_IFMT) == S_IFCHR || (lst.st_mode & S_IFMT) == S_IFBLK) list -> flags |= F_ISDEV; #endif list -> st_mode = lst.st_mode; list -> st_nlink = lst.st_nlink; #if MSDOS list -> st_size = lst.st_size; #else list -> st_uid = lst.st_uid; list -> st_gid = lst.st_gid; list -> st_size = isdev(list) ? lst.st_rdev : lst.st_size; #endif #ifdef HAVEFLAGS list -> st_flags = lst.st_flags; #endif list -> st_mtim = lst.st_mtime; list -> flags |= #if MSDOS logical_access((u_short)(st.st_mode)); #else logical_access((u_short)(st.st_mode), st.st_uid, st.st_gid); #endif if (isfile(list) && list -> st_size) { totalsize += getblock(list -> st_size); if (ismark(list)) marksize += getblock(list -> st_size); } list -> tmpflags |= F_STAT; return(0); } int isdotdir(name) char *name; { if (name[0] == '.' && (!name[1] || (name[1] == '.' && !name[2]))) return(1); return(0); } int cmplist(vp1, vp2) CONST VOID_P vp1; CONST VOID_P vp2; { namelist *list1, *list2; char *cp1, *cp2; long tmp; list1 = (namelist *)vp1; list2 = (namelist *)vp2; if (!sorton) return(list1 -> ent - list2 -> ent); #ifndef _NOPRECEDE if (!havestat(list1) && getstatus(list1) < 0) return(1); if (!havestat(list2) && getstatus(list2) < 0) return(-1); #endif if (!isdir(list1) && isdir(list2)) return(1); if (isdir(list1) && !isdir(list2)) return(-1); if (list1 -> name[0] == '.' && list1 -> name[1] == '\0') return(-1); if (list2 -> name[0] == '.' && list2 -> name[1] == '\0') return(1); if (list1 -> name[0] == '.' && list1 -> name[1] == '.' && list1 -> name[2] == '\0') return(-1); if (list2 -> name[0] == '.' && list2 -> name[1] == '.' && list2 -> name[2] == '\0') return(1); switch (sorton & 7) { case 5: tmp = strlen(list1 -> name) - strlen(list2 -> name); if (tmp != 0) break; case 1: tmp = strpathcmp2(list1 -> name, list2 -> name); break; case 2: if (isdir(list1)) { tmp = strpathcmp2(list1 -> name, list2 -> name); break; } cp1 = list1 -> name + strlen(list1 -> name); cp2 = list2 -> name + strlen(list2 -> name); for (;;) { while (cp1 > list1 -> name) if (*(--cp1) == '.') break; while (cp2 > list2 -> name) if (*(--cp2) == '.') break; if (*cp2 != '.') { tmp = (*cp1 == '.'); break; } else if (*cp1 != '.') { tmp = -1; break; } if ((tmp = strpathcmp2(cp1 + 1, cp2 + 1))) break; } break; case 3: if (isdir(list1)) tmp = strpathcmp2(list1 -> name, list2 -> name); else tmp = (long)(list1 -> st_size) - (long)(list2 -> st_size); break; case 4: tmp = list1 -> st_mtim - list2 -> st_mtim; break; default: tmp = 0; break; } if (sorton > 7) tmp = -tmp; if (!tmp) tmp = list1 -> ent - list2 -> ent; if (tmp > 0) return(1); if (tmp < 0) return(-1); return(0); } #ifndef _NOTREE int cmptree(vp1, vp2) CONST VOID_P vp1; CONST VOID_P vp2; { char *cp1, *cp2; int tmp; if (!(((treelist *)vp1) -> name)) return(1); if (!(((treelist *)vp2) -> name)) return(-1); switch (sorton & 7) { case 1: tmp = strpathcmp2(((treelist *)vp1) -> name, ((treelist *)vp2) -> name); break; case 2: if ((cp1 = strrchr(((treelist *)vp1) -> name, '.'))) cp1++; else cp1 = ""; if ((cp2 = strrchr(((treelist *)vp2) -> name, '.'))) cp2++; else cp2 = ""; tmp = strpathcmp2(cp1, cp2); break; case 3: case 4: default: tmp = 0; break; } if (sorton > 7) tmp = -tmp; return(tmp); } #endif /*ARGSUSED*/ struct dirent *searchdir(dirp, regexp, arcregstr) DIR *dirp; reg_t *regexp; char *arcregstr; { struct dirent *dp; #ifndef _NOARCHIVE struct stat st; namelist tmp; int i; #endif if (regexp) while ((dp = Xreaddir(dirp))) { if (regexp_exec(regexp, dp -> d_name, 1)) break; } #ifndef _NOARCHIVE else if (arcregstr) while ((dp = Xreaddir(dirp))) { if (stat2(dp -> d_name, &st) < 0 || (st.st_mode & S_IFMT) == S_IFDIR) continue; tmp.name = dp -> d_name; tmp.flags = 0; tmp.tmpflags = F_STAT; i = searcharc(arcregstr, &tmp, 1, -1); if (i < 0) return(NULL); if (i) break; } #endif else dp = Xreaddir(dirp); return(dp); } int underhome(buf) char *buf; { static char *homedir = NULL; char *cp, cwd[MAXPATHLEN]; int len; #if MSDOS if (!buf) return(1); #endif if (!Xgetwd(cwd)) { lostcwd(cwd); return(-1); } if (!homedir) { if (!(cp = gethomedir())) return(-1); if ( #ifndef _NODOSDRIVE dospath2(cp) || #endif _chdir2(cp) < 0) return(-1); homedir = getwd2(); if (_chdir2(cwd) < 0) error(cwd); } len = strlen(homedir); #if MSDOS if (len <= 3 || strnpathcmp(cwd, homedir, len)) { #else if (len <= 1 || strnpathcmp(cwd, homedir, len)) { #endif cp = NULL; if (buf) *buf = '\0'; } else { cp = cwd + len; if (buf) strcpy(buf, cp); } #ifdef DEBUG free(homedir); homedir = NULL; #endif return(cp ? 1 : 0); } int preparedir(dir) char *dir; { struct stat st; char tmp[MAXPATHLEN]; #if MSDOS char *cp; #endif if (stat2(dir, &st) < 0) { if (errno != ENOENT) return(-1); if (Xmkdir(dir, 0777) < 0) { #if MSDOS if (errno != EEXIST) return(-1); cp = (_dospath(dir)) ? dir + 2 : dir; if (cp[0] != _SC_ || cp[1]) { if ((cp = strrdelim(dir, 1))) cp++; else cp = dir; if (cp[0] != '.' || cp[1]) return(-1); } st.st_mode = S_IFDIR; #else return(-1); #endif } else if (stat2(dir, &st) < 0) return(-1); } if ((st.st_mode & S_IFMT) != S_IFDIR) { errno = ENOTDIR; return(-1); } entryhist(1, realpath2(dir, tmp, 0), 1); return(0); } int touchfile(path, stp) char *path; struct stat *stp; { struct stat st, dummy; int ret, duperrno; if (Xlstat(path, &st) < 0) return(-1); if ((st.st_mode & S_IFMT) == S_IFLNK) return(1); ret = 0; #if MSDOS if (!(st.st_mode & S_IWRITE)) Xchmod(path, (st.st_mode | S_IWRITE)); #endif if (stp -> st_atime != (time_t)-1 && stp -> st_mtime != (time_t)-1) { #ifdef USEUTIME struct utimbuf times; times.actime = stp -> st_atime; times.modtime = stp -> st_mtime; if (Xutime(path, ×) < 0) { duperrno = errno; ret = -1; } #else struct timeval tvp[2]; tvp[0].tv_sec = stp -> st_atime; tvp[0].tv_usec = 0; tvp[1].tv_sec = stp -> st_mtime; tvp[1].tv_usec = 0; if (Xutimes(path, tvp) < 0) { duperrno = errno; ret = -1; } #endif } #ifdef HAVEFLAGS if (stp -> st_flags != 0xffffffff) { # ifndef _NODOSDRIVE if (dospath(path, NULL)) { errno = EACCES; ret = -1; } else # endif if (chflags(path, stp -> st_flags) < 0) { duperrno = errno; ret = -1; } } #endif dummy.st_mode = 0xffff; if (stp -> st_mode != dummy.st_mode) { stp -> st_mode &= ~S_IFMT; stp -> st_mode |= (st.st_mode & S_IFMT); if (Xchmod(path, stp -> st_mode) < 0) { duperrno = errno; ret = -1; } } #if MSDOS else if (!(st.st_mode & S_IWRITE)) Xchmod(path, st.st_mode); #else if (stp -> st_gid != (gid_t)-1) { if (chown(path, stp -> st_uid, stp -> st_gid) < 0) chown(path, -1, stp -> st_gid); } #endif if (ret < 0) errno = duperrno; return(ret); } VOID lostcwd(path) char *path; { char *cp, buf[MAXPATHLEN]; int duperrno; duperrno = errno; if (!path) path = buf; if (path != fullpath && !rawchdir(fullpath) && _Xgetwd(path)) cp = NOCWD_K; else { if ((cp = gethomedir()) && !rawchdir(cp) && _Xgetwd(path)) cp = GOHOM_K; else if (!rawchdir(_SS_) && _Xgetwd(path)) cp = GOROT_K; else error(_SS_); strncpy2(fullpath, path, MAXPATHLEN - 1); } warning(0, cp); errno = duperrno; } int safewrite(fd, buf, size) int fd; char *buf; int size; { int n; n = Xwrite(fd, buf, size); #if MSDOS if (n < size) n = 0; #else if (n < 0) { if (errno == EINTR) n = size; else if (errno == ENOSPC) n = 0; } #endif return(n); } /*ARGSUSED*/ static int NEAR cpfile(src, dest, stp1, stp2) char *src, *dest; struct stat *stp1, *stp2; { #if MSDOS struct stat st; #endif char buf[BUFSIZ]; int i, n, fd1, fd2, tmperrno; #if MSDOS if (!stp2 && Xlstat(dest, &st) >= 0) stp2 = &st; if (stp2 && !(stp2 -> st_mode & S_IWRITE)) Xchmod(src, stp2 -> st_mode | S_IWRITE); #endif if ((stp1 -> st_mode & S_IFMT) == S_IFLNK) { if ((i = Xreadlink(src, buf, BUFSIZ - 1)) < 0) return(-1); buf[i] = '\0'; return(Xsymlink(buf, dest)); } if ((fd1 = Xopen(src, O_RDONLY | O_BINARY, stp1 -> st_mode)) < 0) return(-1); if ((fd2 = Xopen(dest, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, #if MSDOS stp1 -> st_mode | S_IWRITE)) < 0) { #else stp1 -> st_mode)) < 0) { #endif Xclose(fd1); return(-1); } for (;;) { while ((i = Xread(fd1, buf, BUFSIZ)) < 0 && errno == EINTR); tmperrno = errno; if (i < BUFSIZ) break; if ((n = safewrite(fd2, buf, BUFSIZ)) <= 0) { tmperrno = (n < 0) ? errno : ENOSPC; i = -1; break; } } if (i > 0 && (n = safewrite(fd2, buf, i)) <= 0) { tmperrno = (n < 0) ? errno : ENOSPC; i = -1; } Xclose(fd2); Xclose(fd1); if (i < 0) { Xunlink(dest); errno = tmperrno; return(-1); } #if MSDOS if (touchfile(dest, stp1) < 0) return(-1); #endif return(0); } static VOID changemes(VOID_A) { warning(0, CHGFD_K); } int safecpfile(src, dest, stp1, stp2) char *src, *dest; struct stat *stp1, *stp2; { #ifndef _NODOSDRIVE int drive; #endif for (;;) { if (cpfile(src, dest, stp1, stp2) >= 0) return(0); if (errno && errno != ENOSPC) return(-1); for (;;) { if (!yesno(NOSPC_K)) { errno = ENOSPC; return(-1); } #ifndef _NODOSDRIVE if ((drive = dospath3(dest))) { if (flushdrv(drive, changemes) < 0) continue; } else #endif changemes(); break; } } } int safemvfile(src, dest, stp1, stp2) char *src, *dest; struct stat *stp1, *stp2; { if (Xrename(src, dest) >= 0) return(0); if (errno != EXDEV || (stp1 -> st_mode & S_IFMT) == S_IFDIR) return(-1); if (safecpfile(src, dest, stp1, stp2) < 0 || Xunlink(src) < 0 || touchfile(dest, stp1) < 0) return(-1); return(0); } int mktmpdir(dir) char *dir; { char *cp, path[MAXPATHLEN]; int no; if (!deftmpdir || !*deftmpdir || !tmpfilename || !*tmpfilename || !dir || !*dir) { errno = ENOENT; return(-1); } realpath2(deftmpdir, path, 1); free(deftmpdir); #if MSDOS && !defined (_NODOSDRIVE) if (checkdrive(toupper2(path[0]) - 'A')) if (!_Xgetwd(path)) { lostcwd(path); deftmpdir = NULL; return(-1); } #endif deftmpdir = strdup2(path); #if MSDOS no = getcurdrv(); *path = (no >= 'A' && no <= 'Z') ? toupper2(*path) : tolower2(*path); #endif strcpy(strcatdelim(path), tmpfilename); if (_Xmkdir(path, 0777) < 0 && errno != EEXIST) return(-1); strcpy((cp = strcatdelim(path)), dir); if (_Xmkdir(path, 0777) < 0 && errno != EEXIST) { *(--cp) = '\0'; no = errno; if (_Xrmdir(path) < 0 && errno != ENOTEMPTY && errno != EEXIST && errno != EACCES) error(path); errno = no; return(-1); } strcpy(dir, path); return(0); } int rmtmpdir(dir) char *dir; { char path[MAXPATHLEN]; if (dir && *dir && _Xrmdir(dir) < 0) return(-1); if (!deftmpdir || !*deftmpdir || !tmpfilename || !*tmpfilename) { errno = ENOENT; return(-1); } strcatdelim2(path, deftmpdir, tmpfilename); if (_Xrmdir(path) < 0 && errno != ENOTEMPTY && errno != EEXIST && errno != EACCES) return(-1); return(0); } VOID removetmp(dir, subdir, file) char *dir, *subdir, *file; { char *cp, *tmp, *dupdir; if (!dir || !*dir) subdir = file = NULL; else if (_chdir2(dir) < 0) { warning(-1, dir); *dir = '\0'; subdir = file = NULL; } if (subdir) { while (*subdir == _SC_) subdir++; if (*subdir && _chdir2(subdir) < 0) { warning(-1, subdir); subdir = file = NULL; } } if (file) { if (*file) { if (Xunlink(file) < 0) { warning(-1, file); subdir = NULL; } } else if (applydir(".", Xunlink, NULL, NULL, 0, NULL) < 0) { warning(-1, dir); subdir = NULL; } } if (subdir && *subdir) { if (_chdir2(dir) < 0) error(dir); dupdir = strdup2(subdir); cp = dupdir + strlen(dupdir); for (;;) { *cp = '\0'; if ((tmp = strrdelim(dupdir, 1))) tmp++; else tmp = dupdir; if ((*tmp && strcmp(tmp, ".") && _Xrmdir(dupdir) < 0) || tmp == dupdir) break; cp = tmp - 1; } free(dupdir); } #if MSDOS && !defined (_NODOSDRIVE) if (_chdir2(deftmpdir) < 0) error(deftmpdir); #endif #ifndef _NODOSDRIVE if (dosdrv >= 0) { if (lastdrv >= 0) shutdrv(lastdrv); lastdrv = dosdrv; dosdrv = -1; } #endif if (_chdir2(fullpath) < 0) lostcwd(fullpath); if (dir) { if (rmtmpdir(dir) < 0) warning(-1, dir); free(dir); } } int forcecleandir(dir, file) char *dir, *file; { #if !MSDOS long pid; #endif extern char **environ; char buf[MAXPATHLEN]; if (!dir || !*dir || !file || !*file) return(0); strcatdelim2(buf, dir, file); if (rawchdir(buf) != 0) return(0); rawchdir(_SS_); #if MSDOS spawnlpe(P_WAIT, "DELTREE.EXE", "DELTREE", "/Y", buf, NULL, environ); #else if ((pid = fork()) < 0) return(-1); else if (!pid) { execle("/bin/rm", "rm", "-rf", buf, NULL, environ); _exit(1); } #endif return(0); } #ifndef _NODOSDRIVE int tmpdosdupl(dir, dirp, single) char *dir, **dirp; int single; { struct stat st; char *cp, path[MAXPATHLEN]; int i, drive; if (!(drive = dospath2(dir))) return(0); cp = path; *(cp++) = 'D'; *(cp++) = drive; *cp = '\0'; if (mktmpdir(path) < 0) { warning(-1, path); return(-1); } cp = strcatdelim(path); waitmes(); if (single || mark <= 0) { strcpy(cp, filelist[filepos].name); st.st_mode = filelist[filepos].st_mode; st.st_atime = st.st_mtime = filelist[filepos].st_mtim; if (cpfile(filelist[filepos].name, path, &st, NULL) < 0) { *(--cp) = '\0'; removetmp(path, NULL, NULL); return(-1); } } else for (i = 0; i < maxfile; i++) { if (!ismark(&(filelist[i]))) continue; strcpy(cp, filelist[i].name); st.st_mode = filelist[i].st_mode; st.st_atime = st.st_mtime = filelist[i].st_mtim; if (cpfile(filelist[i].name, path, &st, NULL) < 0) { *(--cp) = '\0'; removetmp(path, NULL, ""); return(-1); } } *(--cp) = '\0'; dosdrv = lastdrv; lastdrv = -1; if (_chdir2(path) < 0) error(path); *dirp = strdup2(path); return(drive); } int tmpdosrestore(drive, file) int drive; char *file; { struct stat st; char path[MAXPATHLEN]; path[0] = drive; path[1] = ':'; strcpy(path + 2, file); waitmes(); if (Xlstat(file, &st) < 0 || cpfile(file, path, &st, NULL) < 0) return(-1); return(0); } #endif /* !_NODOSDRIVE */ #ifndef _NOWRITEFS static int NEAR k_strlen(s) char *s; { int i; for (i = 0; s[i]; i++) if (iskanji1(s, i)) i++; return(i); } static int NEAR nofile(file) char *file; { #if MSDOS && !defined (_NOUSELFN) char *cp, buf[MAXPATHLEN]; if (!(cp = preparefile(file, buf, 0)) && errno == ENOENT) return(1); if (cp != file) return(0); #endif if (Xaccess(file, F_OK) < 0 && errno == ENOENT) return(1); return(0); } static char *NEAR maketmpfile(len, dos, tmpdir, old) int len, dos; char *tmpdir, *old; { char *fname, path[MAXPATHLEN]; int i, l, fd; if (len < 0) return(NULL); fname = malloc2(len + 1); for (i = 0; i < len; i++) fname[i] = '_'; fname[i] = '\0'; if (tmpdir) l = strcatdelim2(path, tmpdir, NULL) - path; for (;;) { if (tmpdir) { strcpy(path + l, fname); if (nofile(path)) { if (old) { #if !MSDOS if (!nofile(fname)); else #endif { if (rename2(old, fname) >= 0) return(fname); #if MSDOS if (errno != EACCES) #endif break; } } else { if ((fd = Xopen(fname, O_CREAT | O_EXCL, 0600))) { Xclose(fd); return(fname); } if (errno != EEXIST) break; } } } else { if (_Xmkdir(fname, 0777) >= 0) return(fname); if (errno != EEXIST) break; } for (i = len - 1; i >= 0; i--) { if (fname[i] == '9') { fname[i] = '_'; continue; } else if (fname[i] == '_') fname[i] = 'a'; else if (dos) { if (fname[i] == 'z') fname[i] = '0'; else fname[i]++; } else { if (fname[i] == 'z') fname[i] = 'A'; else if (fname[i] == 'Z') fname[i] = '0'; else fname[i]++; } break; } if (i < 0) break; } free(fname); return(NULL); } #if !MSDOS static char *NEAR getentnum(dir, bsiz, fs) char *dir; int bsiz, fs; { FILE *fp; struct stat st; char *tmp; int i, n; if (fs != 2) return(NULL); /* without IRIX File System */ if (_Xlstat(dir, &st) < 0) error(dir); n = (long)(st.st_size) / bsiz; tmp = malloc2(n + 1); fp = fopen(dir, "r"); for (i = 0; i < n; i++) { if (fseek(fp, i * bsiz + 3, 0) < 0) error(dir); tmp[i] = fgetc(fp) + 1; } tmp[i] = 0; fclose(fp); return(tmp); } #endif static VOID NEAR restorefile(dir, path, fnamp) char *dir, *path; int fnamp; { DIR *dirp; struct dirent *dp; if (!(dirp = _Xopendir(dir))) error(dir); while ((dp = Xreaddir(dirp))) { if (isdotdir(dp -> d_name)) continue; else { strcpy(path + fnamp, dp -> d_name); if (rename2(path, dp -> d_name) < 0) error(path); } } Xclosedir(dirp); if (_Xrmdir(dir) < 0) error(dir); free(dir); } VOID arrangedir(fs) int fs; { DIR *dirp; struct dirent *dp; int dos, headbyte, boundary, dirsize; int i, top, len, fnamp, ent; char *cp, *tmpdir, path[MAXPATHLEN]; #if !MSDOS long persec; char *entnum, **tmpfile; int tmpno, block, totalent, ptr, totalptr; #endif switch (fs) { #if !MSDOS case 2: /* IRIX File System */ dos = 0; headbyte = 4; boundary = 2; dirsize = sizeof(u_long); break; case 3: /* SystemV R3 File System */ dos = 0; headbyte = 0; boundary = 8; dirsize = sizeof(u_short); break; #endif case 4: /* MS-DOS File System */ dos = 1; headbyte = -1; boundary = 1; dirsize = DOSDIRENT; break; case 5: /* Windows95 File System */ dos = 2; headbyte = -1; boundary = LFNENTSIZ; dirsize = DOSDIRENT; break; default: dos = 0; headbyte = 0; boundary = 4; dirsize = sizeof(u_long) + sizeof(u_short) * 2; break; } for (i = 0; i < maxfile; i++) if (!isdotdir(filelist[i].name)) break; if (i >= maxfile) return; top = i; if (dos == 1) len = 8; else len = getnamlen(realdirsiz(filelist[top].name)); if (!(tmpdir = maketmpfile(len, dos, NULL, NULL))) { warning(0, NOWRT_K); return; } #if !MSDOS persec = getblocksize(tmpdir); #endif fnamp = strcatdelim2(path, tmpdir, NULL) - path; waitmes(); if (!(dirp = _Xopendir("."))) { lostcwd(path); return; } i = ent = 0; while ((dp = Xreaddir(dirp))) { if (isdotdir(dp -> d_name)) continue; else if (!strpathcmp(dp -> d_name, tmpdir)) { #if MSDOS if (!(dp -> d_alias[0])) len = 8; #else if (dos == 2 && dp -> d_reclen == DOSDIRENT) len = 8; #endif ent = i; } else { strcpy(path + fnamp, dp -> d_name); if (rename2(dp -> d_name, path) < 0) { Xclosedir(dirp); warning(-1, dp -> d_name); restorefile(tmpdir, path, fnamp); return; } } i++; } Xclosedir(dirp); if (ent > 0) { if (!(cp = maketmpfile(len, dos, tmpdir, tmpdir))) error(tmpdir); free(tmpdir); tmpdir = cp; strcatdelim2(path, tmpdir, NULL); } #if !MSDOS entnum = getentnum(".", persec, fs); totalent = headbyte + realdirsiz(".") + realdirsiz("..") + realdirsiz(tmpdir); block = tmpno = 0; ptr = 3; totalptr = 0; if (entnum) totalptr = entnum[block]; tmpfile = NULL; #endif for (i = 0; i < maxfile; i++) { if (isdotdir(filelist[i].name) || i == top) continue; #if !MSDOS ent = persec - totalent; switch (fs) { case 2: /* IRIX File System */ if (totalptr > ptr + 1) ent -= totalptr; else ent -= ptr + 1; break; case 3: /* SystemV R3 File System */ case 4: /* MS-DOS File System */ case 5: /* Windows95 File System */ ent = realdirsiz(filelist[i].name); break; default: break; } if (ent < realdirsiz(filelist[i].name)) { tmpfile = b_realloc(tmpfile, tmpno, char *); tmpfile[tmpno] = maketmpfile(getnamlen(ent), dos, tmpdir, NULL); tmpno++; ptr = 0; totalent = headbyte; if (entnum) totalptr = entnum[++block]; } #endif strcpy(path + fnamp, filelist[i].name); if (rename2(path, filelist[i].name) < 0) error(path); #if !MSDOS totalent += realdirsiz(filelist[i].name); ptr++; #endif } #if !MSDOS if (entnum) free(entnum); #endif if (!(cp = maketmpfile(len, dos, tmpdir, tmpdir))) error(tmpdir); free(tmpdir); tmpdir = cp; strcatdelim2(path, tmpdir, filelist[top].name); if (rename2(path, filelist[top].name) < 0) error(path); restorefile(tmpdir, path, fnamp); #if !MSDOS for (i = 0; i < tmpno; i++) if (tmpfile[i]) { if (unlink(tmpfile[i]) < 0) error(tmpfile[i]); free(tmpfile[i]); } free(tmpfile); #endif } #endif /* !_NOWRITEFS */