home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / gnustuff / tos / gnulib / libsrc98.zoo / unlink.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-24  |  3.5 KB  |  156 lines

  1. /* unlink.c: by ERS. This routine is in the public domain */
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <unistd.h>
  6. #include <errno.h>
  7. #include <osbind.h>
  8. #include <unixlib.h>
  9. #include <support.h>
  10. #include <fcntl.h>
  11. #include <string.h>
  12. #include "symdir.h"
  13. #include "lib.h"
  14.  
  15. #define error(x) ((errno = (x)), -1)
  16. __EXTERN char *strdup __PROTO((const char *s));
  17.  
  18. /* remove provided for ansi compatibility */
  19. #ifndef __GNUC__
  20. int remove(filename)
  21.     const char *filename;
  22. {
  23.     return unlink(filename);
  24. }
  25. #endif
  26.  
  27. static struct delete {
  28.     char *fname;
  29.     struct delete *next;
  30. } *D = (struct delete *)NULL;
  31.  
  32. static void
  33. do_deletes()
  34. {
  35.     struct delete *d;
  36.  
  37.     d = D;
  38.     while (d) {
  39.         if(d->fname) {
  40.         (void)Fdelete(d->fname);
  41.         free(d->fname);
  42.         }
  43.         d = d->next;
  44.     }
  45. }
  46.  
  47. #ifdef __GNUC__
  48. asm(".stabs \"_remove\",5,0,0,_unlink"); /* dept of clean tricks */
  49. #endif
  50. int
  51. unlink(filename)
  52.     const char * filename;
  53. {
  54.     char name[FILENAME_MAX];
  55.     char *s;
  56.     int r, fd;
  57.     struct delete *d;
  58.     int nameinfo;
  59.     SYMDIR *dir = 0;
  60.     SYMENTRY *ent = 0, *old;
  61. /*
  62.  * _unx2dos returns _NM_LINK if "filename" was a symbolic link,
  63.  * in which case __link_path[] is the path to the directory containing
  64.  * the link, and __link_name[] is the name of the link.
  65.  */
  66.     nameinfo = _unx2dos(filename, name);
  67.  
  68.     if (nameinfo == _NM_LINK) {        /* a symbolic link */
  69.         if (!(dir = _read_symdir(__link_path)))
  70.             return -1;
  71.         old = 0; ent = dir->s_dir;
  72.         while (ent) {
  73.             if (!strcmp(ent->linkname, __link_name))
  74.                 break;
  75.             old = ent; ent = ent->next;
  76.         }
  77.     }
  78.     else if (_lOK && nameinfo == _NM_CHANGE) {
  79. /* if symlinks are active, insist that the correct file name be given */
  80.         errno = ENOENT;
  81.         return -1;
  82.     }
  83. /*
  84.  * unlink the real file, if no symbolic link was found (ent == 0)
  85.  * or if the link was an automatic link. Unix allows open files
  86.  * to be unlinked; TOS does not, and to get around this we check
  87.  * the names of all the open files; if the one we want is found,
  88.  * we arrange to unlink it on exit.
  89.  */
  90.  
  91.     if (!ent || (ent->flags & SD_AUTO)) {
  92.         for (fd = 0; fd < __NHANDLES; fd++) {
  93.             if ((s = __open_stat[fd].filename) && !strcmp(s, name)) {
  94.     /* D == 0 means the atexit routine was not installed yet */
  95.             if (!D && atexit(do_deletes)) {
  96.                 _free_symdir(dir);
  97.                 return error(ENOMEM);
  98.             }
  99.             d = (struct delete *)malloc(sizeof(struct delete));
  100.             if (!d) {
  101.                 _free_symdir(dir);
  102.                 return error(ENOMEM);
  103.             }
  104.     /* hook the new "delete" structure into the chain */
  105.             d->fname = strdup(name);
  106.             d->next = D; D = d;
  107.             if(!(d->fname)) {
  108.                 /* note we link it in and then check, as
  109.                    we cannot undo the atexit(), (nor do we
  110.                    want to because there maybe others on the
  111.                    chain already). in do_deletes we'll
  112.                    just skip the null name entries */
  113.                 _free_symdir(dir);
  114.                 return error(ENOMEM);
  115.             }
  116.             
  117.     /* if there was an automatic link, delete it now */
  118.             if (ent)
  119.                 goto unlink_sym;
  120.             return 0;
  121.             }
  122.         }
  123.         r = (int)Fdelete(name);
  124.     }
  125. /*
  126.  * watch out for delete errors; if we have an auto link to a write
  127.  * protected file, preserve the link; but if the auto link points
  128.  * to a non-existent file, delete it
  129.  */
  130.     if ( ent && r == -EACCESS) {
  131.         _free_symdir(dir);
  132.         return error(-r);
  133.     }
  134. /*
  135.  * having gotten this far, all that's left is to unlink the symbolic
  136.  * link itself. "old" was set to the previous directory entry; we
  137.  * remove "ent" from the chain, then rewrite the directory.
  138.  */
  139.  
  140. unlink_sym:
  141.  
  142.     if (ent) {
  143.         if (old)
  144.             old->next = ent->next;
  145.         else
  146.             dir->s_dir = ent->next;
  147.         r = _write_symdir(__link_path,dir);
  148.         _free_symdir(dir);
  149.     }
  150.  
  151.     if (r < 0) {
  152.             return error(-r);
  153.     }
  154.     return 0;
  155. }
  156.