home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / c-kermit / ck9ren.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  10KB  |  342 lines

  1. #include "ckcsym.h"
  2. #include "ckcdeb.h"
  3. #ifdef RENAME
  4. /*
  5. <file>          CK9REN.C
  6. <includes>      system: modes.h, errno.h, direct.h, sgstat.h, sg_codes.h
  7.                 user: ckcsym.h ckcdeb.h
  8. <function>      rename
  9. <syntax>        int rename ( char *old_path, char *new_path );
  10. <parameters>    char *old_path      full path name from file to rename
  11.                 char *new_path      new path name
  12. <returns>       int                 0 if successful, -1 on error
  13. <description>   rename a file
  14. <history>       1.00 05.01.94 ulli schlueter created
  15. */
  16.  
  17. #include <modes.h>
  18. #include <errno.h>
  19. #include <direct.h>
  20. #include <sgstat.h>
  21. #include <sg_codes.h>
  22.  
  23. #ifdef CK_ANSIC
  24. char *rindex(const char *, int), *strcat(char *, const char *),
  25.     *strcpy(char *, const char *), *strncpy(char *,const char *, int);
  26. char *malloc(unsigned int), *realloc(void *, unsigned int);
  27. int strlen(const char *), strcmp(const char *, const char *),
  28.     _gs_opt(int, struct sgbuf *), toupper(int),
  29.     write(int, const char *, int), read(int, char *, int),
  30.     lseek(int, long, int), _prsnam(const char *), open(const char *, int),
  31.     close(int), free(const char *), _gs_devn(int, char *),
  32.     _ss_lock(int, long);
  33. void *memset(void *, int, unsigned long);
  34. #else
  35. extern char *rindex(), *strcat(), *strcpy(), *strncpy();
  36. extern char *malloc(), *realloc();
  37. extern int strlen(), strcmp(), _gs_opt(), toupper(), write(), lseek(),
  38. _prsnam(), open(), close(), free(), _gs_devn(), _ss_lock();
  39. extern void *memset();
  40. #endif /* !CK_ANSIC */
  41.  
  42. #ifndef NULL
  43. #define NULL ((void*)0)
  44. #endif /* !NULL */
  45.  
  46. #define OFFSET_OF(typ, tag) ((long)&((typ)0)->tag)
  47.  
  48. /***************** strucmp **********************/
  49. static int
  50. #ifdef CK_ANSIC
  51. strucmp(const char *s1, const char *s2)
  52. #else
  53. strucmp(s1, s2, n)
  54. register char *s1, *s2;
  55. register int n;
  56. #endif /* !CK_ANSIC */
  57. {
  58.     int ret;
  59.  
  60.     while ((ret = toupper(*s1++) - toupper(*s2 & 0x7f)) == 0
  61.         && *s2++ > '\0') {}
  62.     if (*s1 != '\0') return -1;
  63.     return ret;
  64. }
  65.  
  66. #ifdef MOVEDIR
  67. /***************** findfd ***********************/
  68. int
  69. #ifdef CK_ANSIC
  70. findfd (char *dirname, long fdpsn, struct sgbuf *opts)
  71. #else
  72. findfd (dirname, fdpsn, opts)
  73. register char *dirname;
  74. long fdpsn;
  75. struct sgbuf *opts;
  76. #endif /* !CK_ANSIC */
  77. {
  78.     register char *p, *b, *e;
  79.     register int x, pd, size = strlen(dirname) + 256;
  80.  
  81.     if ((b = malloc(size)) == NULL) return -1;
  82.     e = b + size;
  83.     strcpy(b, dirname);
  84.     p = b + strlen(b);
  85.     *p++ = '/';
  86.     *p++ = '.';
  87.     while (x = 1, fdpsn != opts->sg_fdpsn) {
  88.         *p++ = '.';
  89.         *p = '\0';
  90.         if (p + 1 >= e) {
  91.             if ((b = realloc(b, size *= 2)) == NULL) return -1;
  92.             e = b + size;
  93.             p = b + strlen(b);
  94.         }
  95.         if ((x = open(b, S_IFDIR)) != -1) {
  96.             pd = x;
  97.             x = _gs_opt(pd, opts);
  98.             close(pd);
  99.         }
  100.         if (x == -1) break;
  101.         if (opts->sg_fdpsn == opts->sg_dipsn) {
  102.             x = 0;
  103.             break;
  104.         }
  105.     }
  106.     free(b);
  107.     return x;
  108. }
  109. #endif /* MOVEDIR */
  110.  
  111. /***************** rename ***********************/
  112. #ifdef CK_ANSIC
  113. int rename (const char *old, const char *new)
  114. #else
  115. rename(old,new)
  116. register char *old,*new;
  117. #endif /* !CK_ANSIC */
  118. {
  119. #ifdef CK_ANSIC
  120.     const char *newname;
  121.     const char *oldname;
  122. #else
  123.     register char *newname;
  124.     register char *oldname;
  125. #endif /* !CK_ANSIC */
  126.     char *pct = ".";
  127.     register char *olddir;
  128.     char *newdir;
  129.     register int oldpd;
  130.     register int odirpd;
  131.     register int ndirpd;
  132.     int newlen;
  133.     union {
  134.         struct sgbuf opts;
  135.         char devn[4*32];
  136.     } newon, oldon;
  137.     long pd_dcp;
  138. #ifdef MOVEDIR
  139.     long dirlsn;
  140. #endif /* MOVEDIR */
  141.     int amod = 0;
  142.     struct dirent ode;
  143.     char bmovedir;
  144.     char bsamedir;
  145.  
  146.     olddir = newdir = pct;
  147.     oldpd = odirpd = ndirpd = -1;
  148.  
  149.     if ((oldname = rindex(old, '/')) == old /* can't rename device */
  150.         || (newname = rindex(new, '/')) == new) /* can't rename to device */
  151.     {
  152.         errno = E_BPNAM;
  153.         return -1;
  154.     }
  155. /* Get and check old name (inhibit renaming of "." and "..") */
  156.     if (oldname != NULL) oldname += 1;
  157.     else oldname = old;
  158.     if ((newlen = _prsnam(oldname)) != strlen(oldname) || newlen > 28) {
  159.         errno = E_BPNAM;
  160.         return -1;
  161.     }
  162. /* Get and check new path name */
  163.     if (newname != NULL) newname += 1;
  164.     else newname = new;
  165.     if ((newlen = _prsnam(newname)) != strlen(newname) || newlen > 28) {
  166.         errno = E_BPNAM;
  167.         return -1; /* wrong path name */
  168.     }
  169. /* Get new directory name */
  170.     if (newname != new) {
  171.         if ((newdir = malloc(newname - new)) == NULL) return -1;
  172.         strncpy(newdir, new, newname - 1 - new);
  173.         newdir[newname - 1 - new] = '\0';
  174.     }
  175. /* Get old directory name */
  176.     if (oldname != old) {
  177.         if ((olddir = malloc(oldname - old)) == NULL) goto rete0;
  178.         strncpy(olddir, old, oldname - 1 - old);
  179.         olddir[oldname - 1 - old] = '\0';
  180.     }
  181. /* Open directories for update */
  182.     if ((odirpd = open(olddir, S_IREAD|S_IWRITE|S_IFDIR)) == -1) {
  183.         goto rete0;
  184.     }
  185.     if ((ndirpd = open(newdir, S_IREAD|S_IWRITE|S_IFDIR)) == -1) {
  186.         goto rete0;
  187.     }
  188.     if (olddir != pct) { free(olddir); olddir = pct; }
  189. /* Check if on the same device */
  190.     if (_gs_devn(odirpd, oldon.devn) == -1
  191.         || _gs_devn(ndirpd, newon.devn) == -1) {
  192.         goto rete0;
  193.     }
  194.     if (strcmp(oldon.devn, newon.devn) != 0) {
  195.         errno = E_BPNAM;
  196.         goto rete0;
  197.     }
  198. /* Check if same directory */
  199.     if (_gs_opt(odirpd, &oldon.opts) == -1
  200.         || _gs_opt(ndirpd, &newon.opts) == -1) {
  201.         goto rete0;
  202.     }
  203.     if (!!(bsamedir = oldon.opts.sg_fdpsn == newon.opts.sg_fdpsn)) {
  204.         close(odirpd);
  205.         odirpd = ndirpd;
  206.     }
  207. #ifdef MOVEDIR
  208.     dirlsn = newon.opts.sg_fdpsn
  209.         / (newon.opts.sg_sctsiz != 0 ? newon.opts.sg_sctsiz : 256);
  210. #endif /* MOVEDIR */
  211. /* Open old path */
  212.     if ((oldpd = open(old, amod)) == -1
  213.         && (errno != E_FNA
  214.         || (oldpd = open(old, amod = bsamedir ? S_IFDIR : S_IFDIR|S_IWRITE)) == -1)) {
  215.         goto rete0;
  216.     }
  217.     bmovedir = !bsamedir && (amod & S_IFDIR) != 0;
  218. #ifndef MOVEDIR
  219.     if (bmovedir) {
  220.         errno = E_FNA;
  221.         goto rete0;
  222.     }
  223. #endif /* !MOVEDIR */
  224. /* Check wether its an rbf device */
  225.     if (_gs_opt(oldpd, &oldon.opts) == -1) {
  226.         goto rete0;
  227.     }
  228.     if (oldon.opts.sg_class != DT_RBF) {
  229.         errno = E_BPNAM;
  230.         goto rete0;
  231.     }
  232. #ifdef MOVEDIR
  233. /* Check if new directory discards the old one */
  234.     if (bmovedir) {
  235.         int x;
  236.         
  237.         if ((x = findfd(newdir, oldon.opts.sg_fdpsn, &newon.opts)) != 0) {
  238.             if (x > 0) errno = E_BPNAM;
  239.             goto rete0;
  240.         }
  241.     }
  242. #endif /* MOVEDIR */
  243.     if (newdir != pct) { free(newdir), newdir = pct; }
  244. /* Lock out the record so that everybody who wants to open the old */
  245. /* path is queued, until the record is released */
  246.     pd_dcp = oldon.opts.sg_dirptr;
  247.     if (lseek(odirpd, pd_dcp, 0) != pd_dcp
  248.         || read(odirpd, (char *)&ode, sizeof ode) != sizeof ode
  249.         || lseek(odirpd, pd_dcp, 0) != pd_dcp) {
  250.         goto rete0;
  251.     }
  252.     if (!bmovedir) { close(oldpd); oldpd = -1; }
  253. /* Check if the new file already exists and wether it is the same file */
  254.     if (bsamedir) {
  255.         int newpd;
  256.         
  257.         if ((newpd = open(new, 0)) != -1 ||
  258.             errno == E_FNA && (newpd = open(new, S_IFDIR)) != -1) {
  259.             if (_gs_opt(newpd, &newon.opts) == -1) {
  260.                 close(newpd);
  261.                 goto rete0;
  262.             }
  263.             close(newpd);
  264.             if (newon.opts.sg_fdpsn != oldon.opts.sg_fdpsn) {
  265.                 errno = E_CEF;
  266.                 goto rete0;
  267.             }
  268.         }
  269.     } else {
  270.         int l, f;
  271.         struct dirent de;
  272.         
  273.         pd_dcp = 2 * sizeof de;
  274.         if (_ss_lock(ndirpd, 0xffffffff) == -1
  275.             || lseek(ndirpd, pd_dcp, 0) != pd_dcp) {
  276.             goto rete0;
  277.         }
  278.         f = 0;
  279.         while ((l = read(ndirpd, (char *)&de, sizeof de)) != 0) {
  280.             if (l != sizeof de || strucmp(newname, de.dir_name) == 0
  281.                 && (errno = E_CEF, 1)) {
  282.                 goto rete0;
  283.             }
  284.             if (!f && de.dir_name[0] != '\0')
  285.                 pd_dcp += sizeof de;
  286.             else f = 1;
  287.         }
  288.         if (f) {
  289.             if (lseek(ndirpd, pd_dcp, 0) != pd_dcp) {
  290.                 goto rete0;
  291.             }
  292.         }
  293.     }
  294. /* Rename the file, release the record and clean up */
  295.     /*memset(ode.dir_name, 0, sizeof ode.dir_name);*/
  296.     strncpy(ode.dir_name, newname, newlen);
  297.     ode.dir_name[newlen - 1] |= (char)(1<<7);
  298.     ode.dir_name[newlen] = '\0';
  299.     newlen = bsamedir ? sizeof ode.dir_name : sizeof ode;
  300.     if (write(ndirpd, (char *)&ode, newlen) != newlen) {
  301.         goto rete0;
  302.     }
  303. /* Now if in different directories delete the old file */
  304.     if (!bsamedir) {
  305. #ifdef MOVEDIR
  306.         if (bmovedir) {
  307.             /* Change ".." directory entry */
  308.             if (lseek(oldpd, OFFSET_OF(struct dirent *, dir_addr), 0)
  309.                 != OFFSET_OF(struct dirent *, dir_addr)) {
  310.                 goto rete0;
  311.             }
  312.             if (write(oldpd, (char *)&dirlsn, sizeof dirlsn) != sizeof dirlsn) {
  313.                 goto rete0;
  314.             }
  315.             close(oldpd);
  316.             oldpd = -1;
  317.         }
  318. #endif /* MOVEDIR */
  319.         /* Delete old entry */
  320.         ode.dir_name[0] = '\0';
  321.         if (write(odirpd, ode.dir_name, 1) != 1) {
  322.             goto rete0;
  323.         }
  324.     }
  325.     if (!bsamedir) close(odirpd);
  326.     if (close(ndirpd) == -1) return -1;
  327.     return 0;
  328. /* Return resources on error */
  329.     {
  330.         int err;
  331. rete0:  err = errno;
  332.         if (oldpd != -1) close(oldpd);
  333.         if (ndirpd != -1) close(ndirpd);
  334.         if (odirpd != -1 && odirpd != ndirpd) close(odirpd);
  335.         if (olddir != pct && olddir != NULL) free(olddir);
  336.         if (newdir != pct) free(newdir);
  337.         errno = err;
  338.         return -1;
  339.     }
  340. }
  341. #endif /* RENAME */
  342.