home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
kermit.columbia.edu
/
kermit.columbia.edu.tar
/
kermit.columbia.edu
/
archives
/
ck9192.tar.Z
/
ck9192.tar
/
ck9ren.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-12-14
|
10KB
|
342 lines
#include "ckcsym.h"
#include "ckcdeb.h"
#ifdef RENAME
/*
<file> CK9REN.C
<includes> system: modes.h, errno.h, direct.h, sgstat.h, sg_codes.h
user: ckcsym.h ckcdeb.h
<function> rename
<syntax> int rename ( char *old_path, char *new_path );
<parameters> char *old_path full path name from file to rename
char *new_path new path name
<returns> int 0 if successful, -1 on error
<description> rename a file
<history> 1.00 05.01.94 ulli schlueter created
*/
#include <modes.h>
#include <errno.h>
#include <direct.h>
#include <sgstat.h>
#include <sg_codes.h>
#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 */