#include "ckcsym.h" #include "ckcdeb.h" #ifdef RENAME /* CK9REN.C system: modes.h, errno.h, direct.h, sgstat.h, sg_codes.h user: ckcsym.h ckcdeb.h rename int rename ( char *old_path, char *new_path ); char *old_path full path name from file to rename char *new_path new path name int 0 if successful, -1 on error rename a file 1.00 05.01.94 ulli schlueter created */ #include #include #include #include #include #ifdef CK_ANSIC char *rindex(const char *, int), *strcat(char *, const char *), *strcpy(char *, const char *), *strncpy(char *,const char *, int); char *malloc(unsigned int), *realloc(void *, unsigned int); int strlen(const char *), strcmp(const char *, const char *), _gs_opt(int, struct sgbuf *), toupper(int), write(int, const char *, int), read(int, char *, int), lseek(int, long, int), _prsnam(const char *), open(const char *, int), close(int), free(const char *), _gs_devn(int, char *), _ss_lock(int, long); void *memset(void *, int, unsigned long); #else extern char *rindex(), *strcat(), *strcpy(), *strncpy(); extern char *malloc(), *realloc(); extern int strlen(), strcmp(), _gs_opt(), toupper(), write(), lseek(), _prsnam(), open(), close(), free(), _gs_devn(), _ss_lock(); extern void *memset(); #endif /* !CK_ANSIC */ #ifndef NULL #define NULL ((void*)0) #endif /* !NULL */ #define OFFSET_OF(typ, tag) ((long)&((typ)0)->tag) /***************** strucmp **********************/ static int #ifdef CK_ANSIC strucmp(const char *s1, const char *s2) #else strucmp(s1, s2, n) register char *s1, *s2; register int n; #endif /* !CK_ANSIC */ { int ret; while ((ret = toupper(*s1++) - toupper(*s2 & 0x7f)) == 0 && *s2++ > '\0') {} if (*s1 != '\0') return -1; return ret; } #ifdef MOVEDIR /***************** findfd ***********************/ int #ifdef CK_ANSIC findfd (char *dirname, long fdpsn, struct sgbuf *opts) #else findfd (dirname, fdpsn, opts) register char *dirname; long fdpsn; struct sgbuf *opts; #endif /* !CK_ANSIC */ { register char *p, *b, *e; register int x, pd, size = strlen(dirname) + 256; if ((b = malloc(size)) == NULL) return -1; e = b + size; strcpy(b, dirname); p = b + strlen(b); *p++ = '/'; *p++ = '.'; while (x = 1, fdpsn != opts->sg_fdpsn) { *p++ = '.'; *p = '\0'; if (p + 1 >= e) { if ((b = realloc(b, size *= 2)) == NULL) return -1; e = b + size; p = b + strlen(b); } if ((x = open(b, S_IFDIR)) != -1) { pd = x; x = _gs_opt(pd, opts); close(pd); } if (x == -1) break; if (opts->sg_fdpsn == opts->sg_dipsn) { x = 0; break; } } free(b); return x; } #endif /* MOVEDIR */ /***************** rename ***********************/ #ifdef CK_ANSIC int rename (const char *old, const char *new) #else rename(old,new) register char *old,*new; #endif /* !CK_ANSIC */ { #ifdef CK_ANSIC const char *newname; const char *oldname; #else register char *newname; register char *oldname; #endif /* !CK_ANSIC */ char *pct = "."; register char *olddir; char *newdir; register int oldpd; register int odirpd; register int ndirpd; int newlen; union { struct sgbuf opts; char devn[4*32]; } newon, oldon; long pd_dcp; #ifdef MOVEDIR long dirlsn; #endif /* MOVEDIR */ int amod = 0; struct dirent ode; char bmovedir; char bsamedir; olddir = newdir = pct; oldpd = odirpd = ndirpd = -1; if ((oldname = rindex(old, '/')) == old /* can't rename device */ || (newname = rindex(new, '/')) == new) /* can't rename to device */ { errno = E_BPNAM; return -1; } /* Get and check old name (inhibit renaming of "." and "..") */ if (oldname != NULL) oldname += 1; else oldname = old; if ((newlen = _prsnam(oldname)) != strlen(oldname) || newlen > 28) { errno = E_BPNAM; return -1; } /* Get and check new path name */ if (newname != NULL) newname += 1; else newname = new; if ((newlen = _prsnam(newname)) != strlen(newname) || newlen > 28) { errno = E_BPNAM; return -1; /* wrong path name */ } /* Get new directory name */ if (newname != new) { if ((newdir = malloc(newname - new)) == NULL) return -1; strncpy(newdir, new, newname - 1 - new); newdir[newname - 1 - new] = '\0'; } /* Get old directory name */ if (oldname != old) { if ((olddir = malloc(oldname - old)) == NULL) goto rete0; strncpy(olddir, old, oldname - 1 - old); olddir[oldname - 1 - old] = '\0'; } /* Open directories for update */ if ((odirpd = open(olddir, S_IREAD|S_IWRITE|S_IFDIR)) == -1) { goto rete0; } if ((ndirpd = open(newdir, S_IREAD|S_IWRITE|S_IFDIR)) == -1) { goto rete0; } if (olddir != pct) { free(olddir); olddir = pct; } /* Check if on the same device */ if (_gs_devn(odirpd, oldon.devn) == -1 || _gs_devn(ndirpd, newon.devn) == -1) { goto rete0; } if (strcmp(oldon.devn, newon.devn) != 0) { errno = E_BPNAM; goto rete0; } /* Check if same directory */ if (_gs_opt(odirpd, &oldon.opts) == -1 || _gs_opt(ndirpd, &newon.opts) == -1) { goto rete0; } if (!!(bsamedir = oldon.opts.sg_fdpsn == newon.opts.sg_fdpsn)) { close(odirpd); odirpd = ndirpd; } #ifdef MOVEDIR dirlsn = newon.opts.sg_fdpsn / (newon.opts.sg_sctsiz != 0 ? newon.opts.sg_sctsiz : 256); #endif /* MOVEDIR */ /* Open old path */ if ((oldpd = open(old, amod)) == -1 && (errno != E_FNA || (oldpd = open(old, amod = bsamedir ? S_IFDIR : S_IFDIR|S_IWRITE)) == -1)) { goto rete0; } bmovedir = !bsamedir && (amod & S_IFDIR) != 0; #ifndef MOVEDIR if (bmovedir) { errno = E_FNA; goto rete0; } #endif /* !MOVEDIR */ /* Check wether its an rbf device */ if (_gs_opt(oldpd, &oldon.opts) == -1) { goto rete0; } if (oldon.opts.sg_class != DT_RBF) { errno = E_BPNAM; goto rete0; } #ifdef MOVEDIR /* Check if new directory discards the old one */ if (bmovedir) { int x; if ((x = findfd(newdir, oldon.opts.sg_fdpsn, &newon.opts)) != 0) { if (x > 0) errno = E_BPNAM; goto rete0; } } #endif /* MOVEDIR */ if (newdir != pct) { free(newdir), newdir = pct; } /* Lock out the record so that everybody who wants to open the old */ /* path is queued, until the record is released */ pd_dcp = oldon.opts.sg_dirptr; if (lseek(odirpd, pd_dcp, 0) != pd_dcp || read(odirpd, (char *)&ode, sizeof ode) != sizeof ode || lseek(odirpd, pd_dcp, 0) != pd_dcp) { goto rete0; } if (!bmovedir) { close(oldpd); oldpd = -1; } /* Check if the new file already exists and wether it is the same file */ if (bsamedir) { int newpd; if ((newpd = open(new, 0)) != -1 || errno == E_FNA && (newpd = open(new, S_IFDIR)) != -1) { if (_gs_opt(newpd, &newon.opts) == -1) { close(newpd); goto rete0; } close(newpd); if (newon.opts.sg_fdpsn != oldon.opts.sg_fdpsn) { errno = E_CEF; goto rete0; } } } else { int l, f; struct dirent de; pd_dcp = 2 * sizeof de; if (_ss_lock(ndirpd, 0xffffffff) == -1 || lseek(ndirpd, pd_dcp, 0) != pd_dcp) { goto rete0; } f = 0; while ((l = read(ndirpd, (char *)&de, sizeof de)) != 0) { if (l != sizeof de || strucmp(newname, de.dir_name) == 0 && (errno = E_CEF, 1)) { goto rete0; } if (!f && de.dir_name[0] != '\0') pd_dcp += sizeof de; else f = 1; } if (f) { if (lseek(ndirpd, pd_dcp, 0) != pd_dcp) { goto rete0; } } } /* Rename the file, release the record and clean up */ /*memset(ode.dir_name, 0, sizeof ode.dir_name);*/ strncpy(ode.dir_name, newname, newlen); ode.dir_name[newlen - 1] |= (char)(1<<7); ode.dir_name[newlen] = '\0'; newlen = bsamedir ? sizeof ode.dir_name : sizeof ode; if (write(ndirpd, (char *)&ode, newlen) != newlen) { goto rete0; } /* Now if in different directories delete the old file */ if (!bsamedir) { #ifdef MOVEDIR if (bmovedir) { /* Change ".." directory entry */ if (lseek(oldpd, OFFSET_OF(struct dirent *, dir_addr), 0) != OFFSET_OF(struct dirent *, dir_addr)) { goto rete0; } if (write(oldpd, (char *)&dirlsn, sizeof dirlsn) != sizeof dirlsn) { goto rete0; } close(oldpd); oldpd = -1; } #endif /* MOVEDIR */ /* Delete old entry */ ode.dir_name[0] = '\0'; if (write(odirpd, ode.dir_name, 1) != 1) { goto rete0; } } if (!bsamedir) close(odirpd); if (close(ndirpd) == -1) return -1; return 0; /* Return resources on error */ { int err; rete0: err = errno; if (oldpd != -1) close(oldpd); if (ndirpd != -1) close(ndirpd); if (odirpd != -1 && odirpd != ndirpd) close(odirpd); if (olddir != pct && olddir != NULL) free(olddir); if (newdir != pct) free(newdir); errno = err; return -1; } } #endif /* RENAME */