home *** CD-ROM | disk | FTP | other *** search
- /* tmpfile.c */
-
- extern int rnd();
-
- /* Author:
- * Steve Kirkendall
- * 16820 SW Tallac Way
- * Beaverton, OR 97006
- * kirkenda@jove.cs.pdx.edu, or ...uunet!tektronix!psueea!jove!kirkenda
- */
-
-
- /* This file contains functions which create & readback a TMPFILE */
-
-
- #include <sys/types.h>
- #include <sys/stat.h>
- #include "vi.h"
-
- /* This is the name of the temp file */
- static char tmpname[80];
-
- /* This function creates the temp file and copies the original file into it.
- * Returns 0 if successful, or 1 if failure.
- */
- int tmpstart(filename)
- char *filename; /* name of the original file */
- {
- int origfd; /* fd used for reading the original file */
- struct stat statb; /* stat buffer, used to examine inode */
- register BLK *this; /* pointer to the current block buffer */
- register BLK *next; /* pointer to the next block buffer */
- int inbuf; /* number of characters in a buffer */
- int nread; /* number of bytes read */
- register int j, k;
- int i;
-
- /* switching to a different file certainly counts as a change */
- changes++;
- redraw(MARK_UNSET, FALSE);
-
- /* open the original file for reading */
- *origname = '\0';
- if (filename)
- {
- strcpy(origname, filename);
- origfd = open(origname, O_RDONLY);
- if (origfd < 0 && errno != ENOENT)
- {
- msg("Can't open \"%s\"", origname);
- exit(1);
- }
- if (origfd >= 0 && stat(origname, &statb) < 0)
- {
- msg("Can't stat \"%s\"", origname);
- exit(1);
- }
- if (origfd >= 0)
- {
- origtime = statb.st_mtime;
- if (*o_readonly || !(statb.st_mode &
- (statb.st_uid != geteuid() ? 0022 : 0200)))
- {
- setflag(file, READONLY);
- }
- }
- else
- {
- origtime = 0L;
- }
- }
- else
- {
- setflag(file, NOFILE);
- origfd = -1;
- origtime = 0L;
- stat("@", &statb);
- statb.st_type=4095; /* text file */
- }
-
- /* make a name for the tmp file */
- #ifdef ARC
- /* try to create file in ram first - for speed */
- sprintf(tmpname,"ram:vi_%x%x_",rnd(),rnd());
- if ( (tmpfd=creat(tmpname,0600)) < 0) {
- /* no ram disc, try current place */
- sprintf(tmpname,"vi_%3x%3x_",rnd(),rnd());
- tmpfd=creat(tmpname,0600);
- }
- close(tmpfd);
- #else
- sprintf(tmpname, TMPNAME, rnd(),rnd());
-
- /* create the temp file */
- close(creat(tmpname, 0600));
- #endif /* ARC */
- tmpfd = open(tmpname, O_RDWR);
- if (tmpfd < 0)
- {
- msg("Can't create temporary file %s",tmpname);
- exit(1);
- }
-
- /* allocate space for the header in the file */
- write(tmpfd, hdr.c, BLKSIZE);
-
- /* initialize lnum[] */
- for (i = 1; i < MAXBLKS; i++)
- {
- lnum[i] = INFINITY;
- }
- lnum[0] = 0;
-
- /* if there is no original file, then create a 1-line file */
- if (origfd < 0)
- {
- hdr.n[0] = 0; /* invalid inode# denotes new file */
-
- this = blkget(1); /* get the new text block */
- strcpy(this->c, "\n"); /* put a line in it */
-
- lnum[1] = 1; /* block 1 ends with line 1 */
- nlines = 1; /* there is 1 line in the file */
-
- if (*origname)
- {
- msg("\"%s\" [NEW FILE] 1 line", origname);
- }
- else
- {
- msg("\"[NO FILE]\" 1 line");
- }
- }
- else /* there is an original file -- read it in */
- {
- nlines = 0;
-
- /* preallocate 1 "next" buffer */
- i = 1;
- next = blkget(i);
- inbuf = 0;
-
- /* loop, moving blocks from orig to tmp */
- for (;;)
- {
- /* "next" buffer becomes "this" buffer */
- this = next;
-
- /* read [more] text into this block */
- nread = read(origfd, this->c + inbuf, BLKSIZE - 1 - inbuf);
- if (nread < 0)
- {
- close(origfd);
- close(tmpfd);
- tmpfd = -1;
- unlink(tmpname);
- msg("Error reading \"%s\"", origname);
- exit(1);
- }
-
- /* convert NUL characters to something else */
- for (k = inbuf; k < inbuf + nread; k++)
- {
- if (!this->c[k])
- {
- setflag(file, HADNUL);
- this->c[k] = 0x80;
- }
- }
- inbuf += nread;
-
- /* if the buffer is empty, quit */
- if (inbuf == 0)
- {
- break;
- }
-
- /* search backward for last newline */
- for (k = inbuf; --k >= 0 && this->c[k] != '\n';)
- {
- }
- if (k++ < 0)
- {
- if (inbuf >= BLKSIZE - 1)
- {
- k = 80;
- }
- else
- {
- k = inbuf;
- }
- }
-
- /* allocate next buffer */
- next = blkget(++i);
-
- /* move fragmentary last line to next buffer */
- inbuf -= k;
- for (j = 0; k < BLKSIZE; j++, k++)
- {
- next->c[j] = this->c[k];
- this->c[k] = 0;
- }
-
- /* if necessary, add a newline to this buf */
- for (k = BLKSIZE - inbuf; --k >= 0 && !this->c[k]; )
- {
- }
- if (this->c[k] != '\n')
- {
- setflag(file, ADDEDNL);
- this->c[k + 1] = '\n';
- }
-
- /* count the lines in this block */
- for (k = 0; k < BLKSIZE && this->c[k]; k++)
- {
- if (this->c[k] == '\n')
- {
- nlines++;
- }
- }
- lnum[i - 1] = nlines;
- }
-
- /* report the number of lines in the file */
- msg("\"%s\" %ld line%s", origname, nlines, nlines == 1 ? "" : "s");
- }
-
- /* initialize the cursor to start of line 1 */
- cursor = MARK_FIRST;
-
- /* close the original file */
- close(origfd);
-
- #ifndef NO_RECYCLE
- /* initialize the block allocator */
- garbage();
- #endif
- return 0;
- }
-
-
-
- /* This function copies the temp file back onto an original file.
- * Returns TRUE if successful, or FALSE if the file could NOT be saved.
- */
- tmpsave(filename)
- char *filename; /* the name to save it to */
- {
- int fd; /* fd of the file we're writing to */
- register int len; /* length of a text block */
- register BLK *this; /* a text block */
- register int i;
-
- /* if no filename is given, assume the original file name */
- if (!filename || !*filename)
- {
- filename = origname;
- }
-
- /* if still no file name, then fail */
- if (!*filename)
- {
- msg("Don't know a name for this file -- NOT WRITTEN");
- return FALSE;
- }
-
- /* open the file */
- if (*filename == '>' && filename[1] == '>')
- {
- filename += 2;
- while (*filename == ' ' || *filename == '\t')
- {
- filename++;
- }
- #ifdef O_APPEND
- fd = open(filename, O_WRONLY|O_APPEND);
- #else
- fd = open(filename, O_WRONLY);
- lseek(fd, 0L, 2);
- #endif
- }
- else
- {
- fd = creat(filename, 0666);
- }
- if (fd < 0)
- {
- msg("Can't write to \"%s\" -- NOT WRITTEN", filename);
- return FALSE;
- }
-
- /* write each text block to the file */
- for (i = 1; i < MAXBLKS && (this = blkget(i)) && this->c[0]; i++)
- {
- for (len = 0; len < BLKSIZE && this->c[len]; len++)
- {
- }
- write(fd, this->c, len);
- }
-
- /* reset the "modified" flag */
- clrflag(file, MODIFIED);
- if (strcmp(filename, SCRATCHFILE))
- {
- msg("Wrote \"%s\" %ld lines", filename, nlines);
- }
-
- /* close the file */
- close(fd);
-
- return TRUE;
- }
-
-
- /* This function deletes the temporary file. If the file has been modified
- * and "bang" is FALSE, then it returns FALSE without doing anything; else
- * it returns TRUE.
- *
- * If the "autowrite" option is set, then instead of returning FALSE when
- * the file has been modified and "bang" is false, it will call tmpend().
- */
- tmpabort(bang)
- int bang;
- {
- /* if there is no file, return successfully */
- if (tmpfd < 0)
- {
- return TRUE;
- }
-
- /* see if we must return FALSE -- can't quit */
- if (!bang && tstflag(file, MODIFIED))
- {
- /* if "autowrite" is set, then act like tmpend() */
- if (*o_autowrite)
- return tmpend(bang);
- else
- return FALSE;
- }
-
- /* delete the tmp file */
- cutswitch(tmpname);
- close(tmpfd);
- tmpfd = -1;
- unlink(tmpname);
- strcpy(prevorig, origname);
- prevline = markline(cursor);
- *origname = '\0';
- origtime = 0L;
- blkinit();
- nlines = 0;
- initflags();
- return TRUE;
- }
-
- /* This function saves the file if it has been modified, and then deletes
- * the temporary file. Returns TRUE if successful, or FALSE if the file
- * needs to be saved but can't be. When it returns FALSE, it will not have
- * deleted the tmp file, either.
- */
- tmpend(bang)
- int bang;
- {
- /* save the file if it has been modified */
- if (tstflag(file, MODIFIED) && !tmpsave((char *)0) && !bang)
- {
- return FALSE;
- }
-
- /* delete the tmp file */
- tmpabort(TRUE);
-
- return TRUE;
- }
-