1 /*- 2 * Copyright (c) 1992, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * Copyright (c) 1992, 1993, 1994, 1995, 1996 5 * Keith Bostic. All rights reserved. 6 * 7 * See the LICENSE file for redistribution information. 8 */ 9 10 #include "config.h" 11 12 #include <sys/types.h> 13 #include <sys/queue.h> 14 #include <sys/stat.h> 15 #include <sys/time.h> 16 17 /* 18 * We include <sys/file.h>, because the flock(2) and open(2) #defines 19 * were found there on historical systems. We also include <fcntl.h> 20 * because the open(2) #defines are found there on newer systems. 21 */ 22 #include <sys/file.h> 23 24 #include <bitstring.h> 25 #include <dirent.h> 26 #include <errno.h> 27 #include <fcntl.h> 28 #include <limits.h> 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <unistd.h> 33 34 #include "common.h" 35 36 static int file_backup(SCR *, char *, char *); 37 static void file_cinit(SCR *); 38 static void file_encinit(SCR *); 39 static void file_comment(SCR *); 40 static int file_spath(SCR *, FREF *, struct stat *, int *); 41 42 /* 43 * file_add -- 44 * Insert a file name into the FREF list, if it doesn't already 45 * appear in it. 46 * 47 * !!! 48 * The "if it doesn't already appear" changes vi's semantics slightly. If 49 * you do a "vi foo bar", and then execute "next bar baz", the edit of bar 50 * will reflect the line/column of the previous edit session. Historic nvi 51 * did not do this. The change is a logical extension of the change where 52 * vi now remembers the last location in any file that it has ever edited, 53 * not just the previously edited file. 54 * 55 * PUBLIC: FREF *file_add(SCR *, char *); 56 */ 57 FREF * 58 file_add(SCR *sp, char *name) 59 { 60 GS *gp; 61 FREF *frp, *tfrp; 62 63 /* 64 * Return it if it already exists. Note that we test against the 65 * user's name, whatever that happens to be, including if it's a 66 * temporary file. 67 * 68 * If the user added a file but was unable to initialize it, there 69 * can be file list entries where the name field is NULL. Discard 70 * them the next time we see them. 71 */ 72 gp = sp->gp; 73 if (name != NULL) 74 TAILQ_FOREACH_SAFE(frp, gp->frefq, q, tfrp) { 75 if (frp->name == NULL) { 76 TAILQ_REMOVE(gp->frefq, frp, q); 77 free(frp->name); 78 free(frp); 79 continue; 80 } 81 if (!strcmp(frp->name, name)) 82 return (frp); 83 } 84 85 /* Allocate and initialize the FREF structure. */ 86 CALLOC(sp, frp, 1, sizeof(FREF)); 87 if (frp == NULL) 88 return (NULL); 89 90 /* 91 * If no file name specified, or if the file name is a request 92 * for something temporary, file_init() will allocate the file 93 * name. Temporary files are always ignored. 94 */ 95 if (name != NULL && strcmp(name, TEMPORARY_FILE_STRING) && 96 (frp->name = strdup(name)) == NULL) { 97 free(frp); 98 msgq(sp, M_SYSERR, NULL); 99 return (NULL); 100 } 101 102 /* Append into the chain of file names. */ 103 TAILQ_INSERT_TAIL(gp->frefq, frp, q); 104 105 return (frp); 106 } 107 108 /* 109 * file_init -- 110 * Start editing a file, based on the FREF structure. If successsful, 111 * let go of any previous file. Don't release the previous file until 112 * absolutely sure we have the new one. 113 * 114 * PUBLIC: int file_init(SCR *, FREF *, char *, int); 115 */ 116 int 117 file_init(SCR *sp, FREF *frp, char *rcv_name, int flags) 118 { 119 EXF *ep; 120 RECNOINFO oinfo = { 0 }; 121 struct stat sb; 122 size_t psize; 123 int fd, exists, open_err, readonly; 124 char *oname, *tname; 125 126 open_err = readonly = 0; 127 128 /* 129 * If the file is a recovery file, let the recovery code handle it. 130 * Clear the FR_RECOVER flag first -- the recovery code does set up, 131 * and then calls us! If the recovery call fails, it's probably 132 * because the named file doesn't exist. So, move boldly forward, 133 * presuming that there's an error message the user will get to see. 134 */ 135 if (F_ISSET(frp, FR_RECOVER)) { 136 F_CLR(frp, FR_RECOVER); 137 return (rcv_read(sp, frp)); 138 } 139 140 /* 141 * Required FRP initialization; the only flag we keep is the 142 * cursor information. 143 */ 144 F_CLR(frp, ~FR_CURSORSET); 145 146 /* 147 * Required EXF initialization: 148 * Flush the line caches. 149 * Default recover mail file fd to -1. 150 * Set initial EXF flag bits. 151 */ 152 CALLOC_RET(sp, ep, 1, sizeof(EXF)); 153 ep->c_lno = ep->c_nlines = OOBLNO; 154 ep->rcv_fd = -1; 155 F_SET(ep, F_FIRSTMODIFY); 156 157 /* 158 * Scan the user's path to find the file that we're going to 159 * try and open. 160 */ 161 if (file_spath(sp, frp, &sb, &exists)) 162 return (1); 163 164 /* 165 * If no name or backing file, for whatever reason, create a backing 166 * temporary file, saving the temp file name so we can later unlink 167 * it. If the user never named this file, copy the temporary file name 168 * to the real name (we display that until the user renames it). 169 */ 170 oname = frp->name; 171 if (LF_ISSET(FS_OPENERR) || oname == NULL || !exists) { 172 struct stat sb; 173 174 if (opts_empty(sp, O_TMPDIR, 0)) 175 goto err; 176 if ((tname = 177 join(O_STR(sp, O_TMPDIR), "vi.XXXXXXXXXX")) == NULL) { 178 msgq(sp, M_SYSERR, NULL); 179 goto err; 180 } 181 if ((fd = mkstemp(tname)) == -1 || fstat(fd, &sb)) { 182 free(tname); 183 msgq(sp, M_SYSERR, 184 "237|Unable to create temporary file"); 185 goto err; 186 } 187 (void)close(fd); 188 189 frp->tname = tname; 190 if (frp->name == NULL) { 191 F_SET(frp, FR_TMPFILE); 192 if ((frp->name = strdup(tname)) == NULL) { 193 msgq(sp, M_SYSERR, NULL); 194 goto err; 195 } 196 } 197 oname = frp->tname; 198 psize = 1024; 199 if (!LF_ISSET(FS_OPENERR)) 200 F_SET(frp, FR_NEWFILE); 201 202 #if defined HAVE_STRUCT_STAT_ST_MTIMESPEC 203 ep->mtim = sb.st_mtimespec; 204 #elif defined HAVE_STRUCT_STAT_ST_MTIM 205 ep->mtim = sb.st_mtim; 206 #else 207 ep->mtim.tv_sec = sb.st_mtime; 208 ep->mtim.tv_nsec = 0; 209 #endif 210 } else { 211 /* 212 * XXX 213 * A seat of the pants calculation: try to keep the file in 214 * 15 pages or less. Don't use a page size larger than 16K 215 * (vi should have good locality) or smaller than 1K. 216 */ 217 psize = ((sb.st_size / 15) + 1023) / 1024; 218 if (psize > 16) 219 psize = 16; 220 if (psize == 0) 221 psize = 1; 222 psize = p2roundup(psize) << 10; 223 224 F_SET(ep, F_DEVSET); 225 ep->mdev = sb.st_dev; 226 ep->minode = sb.st_ino; 227 228 #if defined HAVE_STRUCT_STAT_ST_MTIMESPEC 229 ep->mtim = sb.st_mtimespec; 230 #elif defined HAVE_STRUCT_STAT_ST_MTIM 231 ep->mtim = sb.st_mtim; 232 #else 233 ep->mtim.tv_sec = sb.st_mtime; 234 ep->mtim.tv_nsec = 0; 235 #endif 236 237 if (!S_ISREG(sb.st_mode)) 238 msgq_str(sp, M_ERR, oname, 239 "238|Warning: %s is not a regular file"); 240 } 241 242 /* Set up recovery. */ 243 oinfo.bval = '\n'; /* Always set. */ 244 oinfo.psize = psize; 245 oinfo.flags = F_ISSET(sp->gp, G_SNAPSHOT) ? R_SNAPSHOT : 0; 246 if (rcv_name == NULL) { 247 if (!rcv_tmp(sp, ep, frp->name)) 248 oinfo.bfname = ep->rcv_path; 249 } else { 250 if ((ep->rcv_path = strdup(rcv_name)) == NULL) { 251 msgq(sp, M_SYSERR, NULL); 252 goto err; 253 } 254 oinfo.bfname = ep->rcv_path; 255 F_SET(ep, F_MODIFIED); 256 } 257 258 /* Open a db structure. */ 259 if ((ep->db = dbopen(rcv_name == NULL ? oname : NULL, 260 O_NONBLOCK | O_RDONLY, 261 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, 262 DB_RECNO, &oinfo)) == NULL) { 263 msgq_str(sp, 264 M_SYSERR, rcv_name == NULL ? oname : rcv_name, "%s"); 265 if (F_ISSET(frp, FR_NEWFILE)) 266 goto err; 267 /* 268 * !!! 269 * Historically, vi permitted users to edit files that couldn't 270 * be read. This isn't useful for single files from a command 271 * line, but it's quite useful for "vi *.c", since you can skip 272 * past files that you can't read. 273 */ 274 open_err = 1; 275 goto oerr; 276 } 277 278 /* 279 * Do the remaining things that can cause failure of the new file, 280 * mark and logging initialization. 281 */ 282 if (mark_init(sp, ep) || log_init(sp, ep)) 283 goto err; 284 285 /* 286 * Set the alternate file name to be the file we're discarding. 287 * 288 * !!! 289 * Temporary files can't become alternate files, so there's no file 290 * name. This matches historical practice, although it could only 291 * happen in historical vi as the result of the initial command, i.e. 292 * if vi was executed without a file name. 293 */ 294 if (LF_ISSET(FS_SETALT)) 295 set_alt_name(sp, sp->frp == NULL || 296 F_ISSET(sp->frp, FR_TMPFILE) ? NULL : sp->frp->name); 297 298 /* 299 * Close the previous file; if that fails, close the new one and run 300 * for the border. 301 * 302 * !!! 303 * There's a nasty special case. If the user edits a temporary file, 304 * and then does an ":e! %", we need to re-initialize the backing 305 * file, but we can't change the name. (It's worse -- we're dealing 306 * with *names* here, we can't even detect that it happened.) Set a 307 * flag so that the file_end routine ignores the backing information 308 * of the old file if it happens to be the same as the new one. 309 * 310 * !!! 311 * Side-effect: after the call to file_end(), sp->frp may be NULL. 312 */ 313 if (sp->ep != NULL) { 314 F_SET(frp, FR_DONTDELETE); 315 if (file_end(sp, NULL, LF_ISSET(FS_FORCE))) { 316 (void)file_end(sp, ep, 1); 317 goto err; 318 } 319 F_CLR(frp, FR_DONTDELETE); 320 } 321 322 /* 323 * Lock the file; if it's a recovery file, it should already be 324 * locked. Note, we acquire the lock after the previous file 325 * has been ended, so that we don't get an "already locked" error 326 * for ":edit!". 327 * 328 * XXX 329 * While the user can't interrupt us between the open and here, 330 * there's a race between the dbopen() and the lock. Not much 331 * we can do about it. 332 * 333 * XXX 334 * We don't make a big deal of not being able to lock the file. As 335 * locking rarely works over NFS, and often fails if the file was 336 * mmap(2)'d, it's far too common to do anything like print an error 337 * message, let alone make the file readonly. At some future time, 338 * when locking is a little more reliable, this should change to be 339 * an error. 340 */ 341 if (rcv_name == NULL) 342 switch (file_lock(sp, oname, ep->db->fd(ep->db), 0)) { 343 case LOCK_FAILED: 344 F_SET(frp, FR_UNLOCKED); 345 break; 346 case LOCK_UNAVAIL: 347 readonly = 1; 348 if (F_ISSET(sp, SC_READONLY)) 349 break; 350 msgq_str(sp, M_INFO, oname, 351 "239|%s already locked, session is read-only"); 352 break; 353 case LOCK_SUCCESS: 354 break; 355 } 356 357 /* 358 * Historically, the readonly edit option was set per edit buffer in 359 * vi, unless the -R command-line option was specified or the program 360 * was executed as "view". (Well, to be truthful, if the letter 'w' 361 * occurred anywhere in the program name, but let's not get into that.) 362 * So, the persistent readonly state has to be stored in the screen 363 * structure, and the edit option value toggles with the contents of 364 * the edit buffer. If the persistent readonly flag is set, set the 365 * readonly edit option. 366 * 367 * Otherwise, try and figure out if a file is readonly. This is a 368 * dangerous thing to do. The kernel is the only arbiter of whether 369 * or not a file is writeable, and the best that a user program can 370 * do is guess. Obvious loopholes are files that are on a file system 371 * mounted readonly (access catches this one on a few systems), or 372 * alternate protection mechanisms, ACL's for example, that we can't 373 * portably check. Lots of fun, and only here because users whined. 374 * 375 * !!! 376 * Historic vi displayed the readonly message if none of the file 377 * write bits were set, or if an an access(2) call on the path 378 * failed. This seems reasonable. If the file is mode 444, root 379 * users may want to know that the owner of the file did not expect 380 * it to be written. 381 * 382 * Historic vi set the readonly bit if no write bits were set for 383 * a file, even if the access call would have succeeded. This makes 384 * the superuser force the write even when vi expects that it will 385 * succeed. I'm less supportive of this semantic, but it's historic 386 * practice and the conservative approach to vi'ing files as root. 387 * 388 * It would be nice if there was some way to update this when the user 389 * does a "^Z; chmod ...". The problem is that we'd first have to 390 * distinguish between readonly bits set because of file permissions 391 * and those set for other reasons. That's not too hard, but deciding 392 * when to reevaluate the permissions is trickier. An alternative 393 * might be to turn off the readonly bit if the user forces a write 394 * and it succeeds. 395 * 396 * XXX 397 * Access(2) doesn't consider the effective uid/gid values. This 398 * probably isn't a problem for vi when it's running standalone. 399 */ 400 if (readonly || F_ISSET(sp, SC_READONLY) || 401 (!F_ISSET(frp, FR_NEWFILE) && 402 (!(sb.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) || 403 access(frp->name, W_OK)))) 404 O_SET(sp, O_READONLY); 405 else 406 O_CLR(sp, O_READONLY); 407 408 /* Switch... */ 409 ++ep->refcnt; 410 sp->ep = ep; 411 sp->frp = frp; 412 413 /* Detect and set the file encoding */ 414 file_encinit(sp); 415 416 /* Set the initial cursor position, queue initial command. */ 417 file_cinit(sp); 418 419 /* Redraw the screen from scratch, schedule a welcome message. */ 420 F_SET(sp, SC_SCR_REFORMAT | SC_STATUS); 421 422 return (0); 423 424 err: free(frp->name); 425 frp->name = NULL; 426 if (frp->tname != NULL) { 427 (void)unlink(frp->tname); 428 free(frp->tname); 429 frp->tname = NULL; 430 } 431 432 oerr: if (F_ISSET(ep, F_RCV_ON)) 433 (void)unlink(ep->rcv_path); 434 free(ep->rcv_path); 435 ep->rcv_path = NULL; 436 437 if (ep->db != NULL) 438 (void)ep->db->close(ep->db); 439 free(ep); 440 441 return (open_err ? 442 file_init(sp, frp, rcv_name, flags | FS_OPENERR) : 1); 443 } 444 445 /* 446 * file_spath -- 447 * Scan the user's path to find the file that we're going to 448 * try and open. 449 */ 450 static int 451 file_spath(SCR *sp, FREF *frp, struct stat *sbp, int *existsp) 452 { 453 int savech; 454 size_t len; 455 int found; 456 char *name, *p, *t, *path; 457 458 /* 459 * If the name is NULL or an explicit reference (i.e., the first 460 * component is . or ..) ignore the O_PATH option. 461 */ 462 name = frp->name; 463 if (name == NULL) { 464 *existsp = 0; 465 return (0); 466 } 467 if (name[0] == '/' || (name[0] == '.' && 468 (name[1] == '/' || (name[1] == '.' && name[2] == '/')))) { 469 *existsp = !stat(name, sbp); 470 return (0); 471 } 472 473 /* Try . */ 474 if (!stat(name, sbp)) { 475 *existsp = 1; 476 return (0); 477 } 478 479 /* Try the O_PATH option values. */ 480 for (found = 0, p = t = O_STR(sp, O_PATH);; ++p) 481 if (*p == ':' || *p == '\0') { 482 /* 483 * Ignore the empty strings and ".", since we've already 484 * tried the current directory. 485 */ 486 if (t < p && (p - t != 1 || *t != '.')) { 487 savech = *p; 488 *p = '\0'; 489 if ((path = join(t, name)) == NULL) { 490 msgq(sp, M_SYSERR, NULL); 491 break; 492 } 493 len = strlen(path); 494 *p = savech; 495 if (!stat(path, sbp)) { 496 found = 1; 497 break; 498 } 499 free(path); 500 } 501 t = p + 1; 502 if (*p == '\0') 503 break; 504 } 505 506 /* If we found it, build a new pathname and discard the old one. */ 507 if (found) { 508 free(frp->name); 509 frp->name = path; 510 } 511 *existsp = found; 512 return (0); 513 } 514 515 /* 516 * file_cinit -- 517 * Set up the initial cursor position. 518 */ 519 static void 520 file_cinit(SCR *sp) 521 { 522 GS *gp; 523 MARK m; 524 size_t len; 525 int nb; 526 CHAR_T *wp; 527 size_t wlen; 528 529 /* Set some basic defaults. */ 530 sp->lno = 1; 531 sp->cno = 0; 532 533 /* 534 * Historically, initial commands (the -c option) weren't executed 535 * until a file was loaded, e.g. "vi +10 nofile", followed by an 536 * :edit or :tag command, would execute the +10 on the file loaded 537 * by the subsequent command, (assuming that it existed). This 538 * applied as well to files loaded using the tag commands, and we 539 * follow that historic practice. Also, all initial commands were 540 * ex commands and were always executed on the last line of the file. 541 * 542 * Otherwise, if no initial command for this file: 543 * If in ex mode, move to the last line, first nonblank character. 544 * If the file has previously been edited, move to the last known 545 * position, and check it for validity. 546 * Otherwise, move to the first line, first nonblank. 547 * 548 * This gets called by the file init code, because we may be in a 549 * file of ex commands and we want to execute them from the right 550 * location in the file. 551 */ 552 nb = 0; 553 gp = sp->gp; 554 if (gp->c_option != NULL && !F_ISSET(sp->frp, FR_NEWFILE)) { 555 if (db_last(sp, &sp->lno)) 556 return; 557 if (sp->lno == 0) { 558 sp->lno = 1; 559 sp->cno = 0; 560 } 561 CHAR2INT(sp, gp->c_option, strlen(gp->c_option) + 1, 562 wp, wlen); 563 if (ex_run_str(sp, "-c option", wp, wlen - 1, 1, 0)) 564 return; 565 gp->c_option = NULL; 566 } else if (F_ISSET(sp, SC_EX)) { 567 if (db_last(sp, &sp->lno)) 568 return; 569 if (sp->lno == 0) { 570 sp->lno = 1; 571 sp->cno = 0; 572 return; 573 } 574 nb = 1; 575 } else { 576 if (F_ISSET(sp->frp, FR_CURSORSET)) { 577 sp->lno = sp->frp->lno; 578 sp->cno = sp->frp->cno; 579 580 /* If returning to a file in vi, center the line. */ 581 F_SET(sp, SC_SCR_CENTER); 582 } else { 583 if (O_ISSET(sp, O_COMMENT)) 584 file_comment(sp); 585 else 586 sp->lno = 1; 587 nb = 1; 588 } 589 if (db_get(sp, sp->lno, 0, NULL, &len)) { 590 sp->lno = 1; 591 sp->cno = 0; 592 return; 593 } 594 if (!nb && sp->cno > len) 595 nb = 1; 596 } 597 if (nb) { 598 sp->cno = 0; 599 (void)nonblank(sp, sp->lno, &sp->cno); 600 } 601 602 /* 603 * !!! 604 * The initial column is also the most attractive column. 605 */ 606 sp->rcm = sp->cno; 607 608 /* 609 * !!! 610 * Historically, vi initialized the absolute mark, but ex did not. 611 * Which meant, that if the first command in ex mode was "visual", 612 * or if an ex command was executed first (e.g. vi +10 file) vi was 613 * entered without the mark being initialized. For consistency, if 614 * the file isn't empty, we initialize it for everyone, believing 615 * that it can't hurt, and is generally useful. Not initializing it 616 * if the file is empty is historic practice, although it has always 617 * been possible to set (and use) marks in empty vi files. 618 */ 619 m.lno = sp->lno; 620 m.cno = sp->cno; 621 (void)mark_set(sp, ABSMARK1, &m, 0); 622 } 623 624 /* 625 * file_end -- 626 * Stop editing a file. 627 * 628 * PUBLIC: int file_end(SCR *, EXF *, int); 629 */ 630 int 631 file_end(SCR *sp, EXF *ep, int force) 632 { 633 FREF *frp; 634 635 /* 636 * !!! 637 * ep MAY NOT BE THE SAME AS sp->ep, DON'T USE THE LATTER. 638 * (If argument ep is NULL, use sp->ep.) 639 * 640 * If multiply referenced, just decrement the count and return. 641 */ 642 if (ep == NULL) 643 ep = sp->ep; 644 if (--ep->refcnt != 0) 645 return (0); 646 647 /* 648 * 649 * Clean up the FREF structure. 650 * 651 * Save the cursor location. 652 * 653 * XXX 654 * It would be cleaner to do this somewhere else, but by the time 655 * ex or vi knows that we're changing files it's already happened. 656 */ 657 frp = sp->frp; 658 frp->lno = sp->lno; 659 frp->cno = sp->cno; 660 F_SET(frp, FR_CURSORSET); 661 662 /* 663 * We may no longer need the temporary backing file, so clean it 664 * up. We don't need the FREF structure either, if the file was 665 * never named, so lose it. 666 * 667 * !!! 668 * Re: FR_DONTDELETE, see the comment above in file_init(). 669 */ 670 if (!F_ISSET(frp, FR_DONTDELETE) && frp->tname != NULL) { 671 if (unlink(frp->tname)) 672 msgq_str(sp, M_SYSERR, frp->tname, "240|%s: remove"); 673 free(frp->tname); 674 frp->tname = NULL; 675 if (F_ISSET(frp, FR_TMPFILE)) { 676 TAILQ_REMOVE(sp->gp->frefq, frp, q); 677 free(frp->name); 678 free(frp); 679 } 680 sp->frp = NULL; 681 } 682 683 /* 684 * Clean up the EXF structure. 685 * 686 * Close the db structure. 687 */ 688 if (ep->db->close != NULL && ep->db->close(ep->db) && !force) { 689 msgq_str(sp, M_SYSERR, frp->name, "241|%s: close"); 690 ++ep->refcnt; 691 return (1); 692 } 693 694 /* COMMITTED TO THE CLOSE. THERE'S NO GOING BACK... */ 695 696 /* Stop logging. */ 697 (void)log_end(sp, ep); 698 699 /* Free up any marks. */ 700 (void)mark_end(sp, ep); 701 702 /* 703 * Delete recovery files, close the open descriptor, free recovery 704 * memory. See recover.c for a description of the protocol. 705 * 706 * XXX 707 * Unlink backup file first, we can detect that the recovery file 708 * doesn't reference anything when the user tries to recover it. 709 * There's a race, here, obviously, but it's fairly small. 710 */ 711 if (!F_ISSET(ep, F_RCV_NORM)) { 712 if (ep->rcv_path != NULL && unlink(ep->rcv_path)) 713 msgq_str(sp, M_SYSERR, ep->rcv_path, "242|%s: remove"); 714 if (ep->rcv_mpath != NULL && unlink(ep->rcv_mpath)) 715 msgq_str(sp, M_SYSERR, ep->rcv_mpath, "243|%s: remove"); 716 } 717 if (ep->rcv_fd != -1) 718 (void)close(ep->rcv_fd); 719 free(ep->rcv_path); 720 free(ep->rcv_mpath); 721 if (ep->c_blen > 0) 722 free(ep->c_lp); 723 724 free(ep); 725 return (0); 726 } 727 728 /* 729 * file_write -- 730 * Write the file to disk. Historic vi had fairly convoluted 731 * semantics for whether or not writes would happen. That's 732 * why all the flags. 733 * 734 * PUBLIC: int file_write(SCR *, MARK *, MARK *, char *, int); 735 */ 736 int 737 file_write(SCR *sp, MARK *fm, MARK *tm, char *name, int flags) 738 { 739 enum { NEWFILE, OLDFILE } mtype; 740 struct stat sb; 741 EXF *ep; 742 FILE *fp; 743 FREF *frp; 744 MARK from, to; 745 size_t len; 746 u_long nlno, nch; 747 int fd, nf, noname, oflags, rval; 748 char *p, *s, *t, buf[1024]; 749 const char *msgstr; 750 751 ep = sp->ep; 752 frp = sp->frp; 753 754 /* 755 * Writing '%', or naming the current file explicitly, has the 756 * same semantics as writing without a name. 757 */ 758 if (name == NULL || !strcmp(name, frp->name)) { 759 noname = 1; 760 name = frp->name; 761 } else 762 noname = 0; 763 764 /* Can't write files marked read-only, unless forced. */ 765 if (!LF_ISSET(FS_FORCE) && noname && O_ISSET(sp, O_READONLY)) { 766 msgq(sp, M_ERR, LF_ISSET(FS_POSSIBLE) ? 767 "244|Read-only file, not written; use ! to override" : 768 "245|Read-only file, not written"); 769 return (1); 770 } 771 772 /* If not forced, not appending, and "writeany" not set ... */ 773 if (!LF_ISSET(FS_FORCE | FS_APPEND) && !O_ISSET(sp, O_WRITEANY)) { 774 /* Don't overwrite anything but the original file. */ 775 if ((!noname || F_ISSET(frp, FR_NAMECHANGE)) && 776 !stat(name, &sb)) { 777 msgq_str(sp, M_ERR, name, 778 LF_ISSET(FS_POSSIBLE) ? 779 "246|%s exists, not written; use ! to override" : 780 "247|%s exists, not written"); 781 return (1); 782 } 783 784 /* 785 * Don't write part of any existing file. Only test for the 786 * original file, the previous test catches anything else. 787 */ 788 if (!LF_ISSET(FS_ALL) && noname && !stat(name, &sb)) { 789 msgq(sp, M_ERR, LF_ISSET(FS_POSSIBLE) ? 790 "248|Partial file, not written; use ! to override" : 791 "249|Partial file, not written"); 792 return (1); 793 } 794 } 795 796 /* 797 * Figure out if the file already exists -- if it doesn't, we display 798 * the "new file" message. The stat might not be necessary, but we 799 * just repeat it because it's easier than hacking the previous tests. 800 * The information is only used for the user message and modification 801 * time test, so we can ignore the obvious race condition. 802 * 803 * One final test. If we're not forcing or appending the current file, 804 * and we have a saved modification time, object if the file changed 805 * since we last edited or wrote it, and make them force it. 806 */ 807 if (stat(name, &sb)) 808 mtype = NEWFILE; 809 else { 810 if (noname && !LF_ISSET(FS_FORCE | FS_APPEND) && 811 ((F_ISSET(ep, F_DEVSET) && 812 (sb.st_dev != ep->mdev || sb.st_ino != ep->minode)) || 813 #if defined HAVE_STRUCT_STAT_ST_MTIMESPEC 814 timespeccmp(&sb.st_mtimespec, &ep->mtim, !=))) { 815 #elif defined HAVE_STRUCT_STAT_ST_MTIM 816 timespeccmp(&sb.st_mtim, &ep->mtim, !=))) { 817 #else 818 sb.st_mtime != ep->mtim.tv_sec)) { 819 #endif 820 msgq_str(sp, M_ERR, name, LF_ISSET(FS_POSSIBLE) ? 821 "250|%s: file modified more recently than this copy; use ! to override" : 822 "251|%s: file modified more recently than this copy"); 823 return (1); 824 } 825 826 mtype = OLDFILE; 827 } 828 829 /* Set flags to create, write, and either append or truncate. */ 830 oflags = O_CREAT | O_WRONLY | 831 (LF_ISSET(FS_APPEND) ? O_APPEND : O_TRUNC); 832 833 /* Backup the file if requested. */ 834 if (!opts_empty(sp, O_BACKUP, 1) && 835 file_backup(sp, name, O_STR(sp, O_BACKUP)) && !LF_ISSET(FS_FORCE)) 836 return (1); 837 838 /* Open the file. */ 839 if ((fd = open(name, oflags, 840 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) < 0) { 841 if (errno == EACCES && LF_ISSET(FS_FORCE)) { 842 /* 843 * If the user owns the file but does not 844 * have write permission on it, grant it 845 * automatically for the duration of the 846 * opening of the file, if possible. 847 */ 848 struct stat sb; 849 mode_t fmode; 850 851 if (stat(name, &sb) != 0) 852 goto fail_open; 853 fmode = sb.st_mode; 854 if (!(sb.st_mode & S_IWUSR) && sb.st_uid == getuid()) 855 fmode |= S_IWUSR; 856 else 857 goto fail_open; 858 if (chmod(name, fmode) != 0) 859 goto fail_open; 860 fd = open(name, oflags, S_IRUSR | S_IWUSR | 861 S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); 862 if (fd == -1) 863 goto fail_open; 864 (void)fchmod(fd, sb.st_mode); 865 goto success_open; 866 fail_open: 867 errno = EACCES; 868 } 869 msgq_str(sp, M_SYSERR, name, "%s"); 870 return (1); 871 } 872 success_open: 873 874 /* Try and get a lock. */ 875 if (!noname && file_lock(sp, NULL, fd, 0) == LOCK_UNAVAIL) 876 msgq_str(sp, M_ERR, name, 877 "252|%s: write lock was unavailable"); 878 879 /* 880 * Use stdio for buffering. 881 * 882 * XXX 883 * SVR4.2 requires the fdopen mode exactly match the original open 884 * mode, i.e. you have to open with "a" if appending. 885 */ 886 if ((fp = fdopen(fd, LF_ISSET(FS_APPEND) ? "a" : "w")) == NULL) { 887 msgq_str(sp, M_SYSERR, name, "%s"); 888 (void)close(fd); 889 return (1); 890 } 891 892 /* Build fake addresses, if necessary. */ 893 if (fm == NULL) { 894 from.lno = 1; 895 from.cno = 0; 896 fm = &from; 897 if (db_last(sp, &to.lno)) 898 return (1); 899 to.cno = 0; 900 tm = &to; 901 } 902 903 rval = ex_writefp(sp, name, fp, fm, tm, &nlno, &nch, 0); 904 905 /* 906 * Save the new last modification time -- even if the write fails 907 * we re-init the time. That way the user can clean up the disk 908 * and rewrite without having to force it. 909 */ 910 if (noname) { 911 if (stat(name, &sb)) 912 timepoint_system(&ep->mtim); 913 else { 914 F_SET(ep, F_DEVSET); 915 ep->mdev = sb.st_dev; 916 ep->minode = sb.st_ino; 917 918 #if defined HAVE_STRUCT_STAT_ST_MTIMESPEC 919 ep->mtim = sb.st_mtimespec; 920 #elif defined HAVE_STRUCT_STAT_ST_MTIM 921 ep->mtim = sb.st_mtim; 922 #else 923 ep->mtim.tv_sec = sb.st_mtime; 924 ep->mtim.tv_nsec = 0; 925 #endif 926 } 927 } 928 929 /* 930 * If the write failed, complain loudly. ex_writefp() has already 931 * complained about the actual error, reinforce it if data was lost. 932 */ 933 if (rval) { 934 if (!LF_ISSET(FS_APPEND)) 935 msgq_str(sp, M_ERR, name, 936 "254|%s: WARNING: FILE TRUNCATED"); 937 return (1); 938 } 939 940 /* 941 * Once we've actually written the file, it doesn't matter that the 942 * file name was changed -- if it was, we've already whacked it. 943 */ 944 F_CLR(frp, FR_NAMECHANGE); 945 946 /* 947 * If wrote the entire file, and it wasn't by appending it to a file, 948 * clear the modified bit. If the file was written to the original 949 * file name and the file is a temporary, set the "no exit" bit. This 950 * permits the user to write the file and use it in the context of the 951 * filesystem, but still keeps them from discarding their changes by 952 * exiting. 953 */ 954 if (LF_ISSET(FS_ALL) && !LF_ISSET(FS_APPEND)) { 955 F_CLR(ep, F_MODIFIED); 956 if (F_ISSET(frp, FR_TMPFILE)) { 957 if (noname) 958 F_SET(frp, FR_TMPEXIT); 959 else 960 F_CLR(frp, FR_TMPEXIT); 961 } 962 } 963 964 p = msg_print(sp, name, &nf); 965 switch (mtype) { 966 case NEWFILE: 967 msgstr = msg_cat(sp, 968 "256|%s: new file: %lu lines, %lu characters", NULL); 969 len = snprintf(buf, sizeof(buf), msgstr, p, nlno, nch); 970 break; 971 case OLDFILE: 972 msgstr = msg_cat(sp, LF_ISSET(FS_APPEND) ? 973 "315|%s: appended: %lu lines, %lu characters" : 974 "257|%s: %lu lines, %lu characters", NULL); 975 len = snprintf(buf, sizeof(buf), msgstr, p, nlno, nch); 976 break; 977 default: 978 abort(); 979 } 980 981 /* 982 * There's a nasty problem with long path names. Cscope and tags files 983 * can result in long paths and vi will request a continuation key from 984 * the user. Unfortunately, the user has typed ahead, and chaos will 985 * result. If we assume that the characters in the filenames only take 986 * a single screen column each, we can trim the filename. 987 */ 988 s = buf; 989 if (len >= sp->cols) { 990 for (s = buf, t = buf + strlen(p); s < t && 991 (*s != '/' || len >= sp->cols - 3); ++s, --len); 992 if (s == t) 993 s = buf; 994 else { 995 *--s = '.'; /* Leading ellipses. */ 996 *--s = '.'; 997 *--s = '.'; 998 } 999 } 1000 msgq(sp, M_INFO, "%s", s); 1001 if (nf) 1002 FREE_SPACE(sp, p, 0); 1003 return (0); 1004 } 1005 1006 /* 1007 * file_backup -- 1008 * Backup the about-to-be-written file. 1009 * 1010 * XXX 1011 * We do the backup by copying the entire file. It would be nice to do 1012 * a rename instead, but: (1) both files may not fit and we want to fail 1013 * before doing the rename; (2) the backup file may not be on the same 1014 * disk partition as the file being written; (3) there may be optional 1015 * file information (MACs, DACs, whatever) that we won't get right if we 1016 * recreate the file. So, let's not risk it. 1017 */ 1018 static int 1019 file_backup(SCR *sp, char *name, char *bname) 1020 { 1021 struct dirent *dp; 1022 struct stat sb; 1023 DIR *dirp; 1024 EXCMD cmd; 1025 off_t off; 1026 size_t blen; 1027 int flags, maxnum, nr, num, nw, rfd, wfd, version; 1028 char *bp, *estr, *p, *pct, *slash, *t, *wfname, buf[8192]; 1029 CHAR_T *wp; 1030 size_t wlen; 1031 size_t nlen; 1032 char *d = NULL; 1033 1034 rfd = wfd = -1; 1035 bp = estr = wfname = NULL; 1036 1037 /* 1038 * Open the current file for reading. Do this first, so that 1039 * we don't exec a shell before the most likely failure point. 1040 * If it doesn't exist, it's okay, there's just nothing to back 1041 * up. 1042 */ 1043 errno = 0; 1044 if ((rfd = open(name, O_RDONLY, 0)) < 0) { 1045 if (errno == ENOENT) 1046 return (0); 1047 estr = name; 1048 goto err; 1049 } 1050 1051 /* 1052 * If the name starts with an 'N' character, add a version number 1053 * to the name. Strip the leading N from the string passed to the 1054 * expansion routines, for no particular reason. It would be nice 1055 * to permit users to put the version number anywhere in the backup 1056 * name, but there isn't a special character that we can use in the 1057 * name, and giving a new character a special meaning leads to ugly 1058 * hacks both here and in the supporting ex routines. 1059 * 1060 * Shell and file name expand the option's value. 1061 */ 1062 ex_cinit(sp, &cmd, 0, 0, 0, 0, 0); 1063 if (bname[0] == 'N') { 1064 version = 1; 1065 ++bname; 1066 } else 1067 version = 0; 1068 CHAR2INT(sp, bname, strlen(bname), wp, wlen); 1069 if ((wp = v_wstrdup(sp, wp, wlen)) == NULL) 1070 return (1); 1071 if (argv_exp2(sp, &cmd, wp, wlen)) { 1072 free(wp); 1073 return (1); 1074 } 1075 free(wp); 1076 1077 /* 1078 * 0 args: impossible. 1079 * 1 args: use it. 1080 * >1 args: object, too many args. 1081 */ 1082 if (cmd.argc != 1) { 1083 msgq_str(sp, M_ERR, bname, 1084 "258|%s expanded into too many file names"); 1085 (void)close(rfd); 1086 return (1); 1087 } 1088 1089 /* 1090 * If appending a version number, read through the directory, looking 1091 * for file names that match the name followed by a number. Make all 1092 * of the other % characters in name literal, so the user doesn't get 1093 * surprised and sscanf doesn't drop core indirecting through pointers 1094 * that don't exist. If any such files are found, increment its number 1095 * by one. 1096 */ 1097 if (version) { 1098 GET_SPACE_GOTOC(sp, bp, blen, cmd.argv[0]->len * 2 + 50); 1099 INT2CHAR(sp, cmd.argv[0]->bp, cmd.argv[0]->len + 1, 1100 p, nlen); 1101 d = strdup(p); 1102 p = d; 1103 for (t = bp, slash = NULL; 1104 p[0] != '\0'; *t++ = *p++) 1105 if (p[0] == '%') { 1106 if (p[1] != '%') 1107 *t++ = '%'; 1108 } else if (p[0] == '/') 1109 slash = t; 1110 pct = t; 1111 *t++ = '%'; 1112 *t++ = 'd'; 1113 *t = '\0'; 1114 1115 if (slash == NULL) { 1116 dirp = opendir("."); 1117 p = bp; 1118 } else { 1119 *slash = '\0'; 1120 dirp = opendir(bp); 1121 *slash = '/'; 1122 p = slash + 1; 1123 } 1124 if (dirp == NULL) { 1125 INT2CHAR(sp, cmd.argv[0]->bp, cmd.argv[0]->len + 1, 1126 estr, nlen); 1127 goto err; 1128 } 1129 1130 for (maxnum = 0; (dp = readdir(dirp)) != NULL;) 1131 if (sscanf(dp->d_name, p, &num) == 1 && num > maxnum) 1132 maxnum = num; 1133 (void)closedir(dirp); 1134 1135 /* Format the backup file name. */ 1136 (void)snprintf(pct, blen - (pct - bp), "%d", maxnum + 1); 1137 wfname = bp; 1138 } else { 1139 bp = NULL; 1140 INT2CHAR(sp, cmd.argv[0]->bp, cmd.argv[0]->len + 1, 1141 wfname, nlen); 1142 } 1143 1144 /* Open the backup file, avoiding lurkers. */ 1145 if (stat(wfname, &sb) == 0) { 1146 if (!S_ISREG(sb.st_mode)) { 1147 msgq_str(sp, M_ERR, bname, 1148 "259|%s: not a regular file"); 1149 goto err; 1150 } 1151 if (sb.st_uid != getuid()) { 1152 msgq_str(sp, M_ERR, bname, "260|%s: not owned by you"); 1153 goto err; 1154 } 1155 if (sb.st_mode & (S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) { 1156 msgq_str(sp, M_ERR, bname, 1157 "261|%s: accessible by a user other than the owner"); 1158 goto err; 1159 } 1160 flags = O_TRUNC; 1161 } else 1162 flags = O_CREAT | O_EXCL; 1163 if ((wfd = open(wfname, flags | O_WRONLY, S_IRUSR | S_IWUSR)) < 0) { 1164 estr = bname; 1165 goto err; 1166 } 1167 1168 /* Copy the file's current contents to its backup value. */ 1169 while ((nr = read(rfd, buf, sizeof(buf))) > 0) 1170 for (off = 0; nr != 0; nr -= nw, off += nw) 1171 if ((nw = write(wfd, buf + off, nr)) < 0) { 1172 estr = wfname; 1173 goto err; 1174 } 1175 if (nr < 0) { 1176 estr = name; 1177 goto err; 1178 } 1179 1180 if (close(rfd)) { 1181 estr = name; 1182 goto err; 1183 } 1184 if (close(wfd)) { 1185 estr = wfname; 1186 goto err; 1187 } 1188 free(d); 1189 if (bp != NULL) 1190 FREE_SPACE(sp, bp, blen); 1191 return (0); 1192 1193 alloc_err: 1194 err: if (rfd != -1) 1195 (void)close(rfd); 1196 if (wfd != -1) { 1197 (void)unlink(wfname); 1198 (void)close(wfd); 1199 } 1200 if (estr) 1201 msgq_str(sp, M_SYSERR, estr, "%s"); 1202 free(d); 1203 if (bp != NULL) 1204 FREE_SPACE(sp, bp, blen); 1205 return (1); 1206 } 1207 1208 /* 1209 * file_encinit -- 1210 * Read the first line and set the O_FILEENCODING. 1211 */ 1212 static void 1213 file_encinit(SCR *sp) 1214 { 1215 #if defined(USE_WIDECHAR) && defined(USE_ICONV) 1216 size_t len; 1217 char *p; 1218 size_t blen = 0; 1219 char buf[4096]; /* not need to be '\0'-terminated */ 1220 recno_t ln = 1; 1221 EXF *ep; 1222 1223 ep = sp->ep; 1224 1225 while (!db_rget(sp, ln++, &p, &len)) { 1226 if (blen + len > sizeof(buf)) 1227 len = sizeof(buf) - blen; 1228 memcpy(buf + blen, p, len); 1229 blen += len; 1230 if (blen == sizeof(buf)) 1231 break; 1232 else 1233 buf[blen++] = '\n'; 1234 } 1235 1236 /* 1237 * Detect UTF-8 and fallback to the locale/preset encoding. 1238 * 1239 * XXX 1240 * A manually set O_FILEENCODING indicates the "fallback 1241 * encoding", but UTF-8, which can be safely detected, is not 1242 * inherited from the old screen. 1243 */ 1244 if (looks_utf8(buf, blen) > 1) 1245 o_set(sp, O_FILEENCODING, OS_STRDUP, "utf-8", 0); 1246 else if (!O_ISSET(sp, O_FILEENCODING) || 1247 !strcasecmp(O_STR(sp, O_FILEENCODING), "utf-8")) 1248 o_set(sp, O_FILEENCODING, OS_STRDUP, codeset(), 0); 1249 1250 conv_enc(sp, O_FILEENCODING, 0); 1251 #endif 1252 } 1253 1254 /* 1255 * file_comment -- 1256 * Skip the first comment. 1257 */ 1258 static void 1259 file_comment(SCR *sp) 1260 { 1261 recno_t lno; 1262 size_t len; 1263 CHAR_T *p; 1264 1265 for (lno = 1; !db_get(sp, lno, 0, &p, &len) && len == 0; ++lno); 1266 if (p == NULL) 1267 return; 1268 if (p[0] == '#') { 1269 F_SET(sp, SC_SCR_TOP); 1270 while (!db_get(sp, ++lno, 0, &p, &len)) 1271 if (len < 1 || p[0] != '#') { 1272 sp->lno = lno; 1273 return; 1274 } 1275 } else if (len > 1 && p[0] == '/' && p[1] == '*') { 1276 F_SET(sp, SC_SCR_TOP); 1277 do { 1278 for (; len > 1; --len, ++p) 1279 if (p[0] == '*' && p[1] == '/') { 1280 sp->lno = lno; 1281 return; 1282 } 1283 } while (!db_get(sp, ++lno, 0, &p, &len)); 1284 } else if (len > 1 && p[0] == '/' && p[1] == '/') { 1285 F_SET(sp, SC_SCR_TOP); 1286 p += 2; 1287 len -= 2; 1288 do { 1289 for (; len > 1; --len, ++p) 1290 if (p[0] == '/' && p[1] == '/') { 1291 sp->lno = lno; 1292 return; 1293 } 1294 } while (!db_get(sp, ++lno, 0, &p, &len)); 1295 } 1296 } 1297 1298 /* 1299 * file_m1 -- 1300 * First modification check routine. The :next, :prev, :rewind, :tag, 1301 * :tagpush, :tagpop, ^^ modifications check. 1302 * 1303 * PUBLIC: int file_m1(SCR *, int, int); 1304 */ 1305 int 1306 file_m1(SCR *sp, int force, int flags) 1307 { 1308 EXF *ep; 1309 1310 ep = sp->ep; 1311 1312 /* If no file loaded, return no modifications. */ 1313 if (ep == NULL) 1314 return (0); 1315 1316 /* 1317 * If the file has been modified, we'll want to write it back or 1318 * fail. If autowrite is set, we'll write it back automatically, 1319 * unless force is also set. Otherwise, we fail unless forced or 1320 * there's another open screen on this file. 1321 */ 1322 if (F_ISSET(ep, F_MODIFIED)) { 1323 if (O_ISSET(sp, O_AUTOWRITE)) { 1324 if (!force && file_aw(sp, flags)) 1325 return (1); 1326 } else if (ep->refcnt <= 1 && !force) { 1327 msgq(sp, M_ERR, LF_ISSET(FS_POSSIBLE) ? 1328 "262|File modified since last complete write; write or use ! to override" : 1329 "263|File modified since last complete write; write or use :edit! to override"); 1330 return (1); 1331 } 1332 } 1333 1334 return (file_m3(sp, force)); 1335 } 1336 1337 /* 1338 * file_m2 -- 1339 * Second modification check routine. The :edit, :quit, :recover 1340 * modifications check. 1341 * 1342 * PUBLIC: int file_m2(SCR *, int); 1343 */ 1344 int 1345 file_m2(SCR *sp, int force) 1346 { 1347 EXF *ep; 1348 1349 ep = sp->ep; 1350 1351 /* If no file loaded, return no modifications. */ 1352 if (ep == NULL) 1353 return (0); 1354 1355 /* 1356 * If the file has been modified, we'll want to fail, unless forced 1357 * or there's another open screen on this file. 1358 */ 1359 if (F_ISSET(ep, F_MODIFIED) && ep->refcnt <= 1 && !force) { 1360 msgq(sp, M_ERR, 1361 "264|File modified since last complete write; write or use ! to override"); 1362 return (1); 1363 } 1364 1365 return (file_m3(sp, force)); 1366 } 1367 1368 /* 1369 * file_m3 -- 1370 * Third modification check routine. 1371 * 1372 * PUBLIC: int file_m3(SCR *, int); 1373 */ 1374 int 1375 file_m3(SCR *sp, int force) 1376 { 1377 EXF *ep; 1378 1379 ep = sp->ep; 1380 1381 /* If no file loaded, return no modifications. */ 1382 if (ep == NULL) 1383 return (0); 1384 1385 /* 1386 * Don't exit while in a temporary files if the file was ever modified. 1387 * The problem is that if the user does a ":wq", we write and quit, 1388 * unlinking the temporary file. Not what the user had in mind at all. 1389 * We permit writing to temporary files, so that user maps using file 1390 * system names work with temporary files. 1391 */ 1392 if (F_ISSET(sp->frp, FR_TMPEXIT) && ep->refcnt <= 1 && !force) { 1393 msgq(sp, M_ERR, 1394 "265|File is a temporary; exit will discard modifications"); 1395 return (1); 1396 } 1397 return (0); 1398 } 1399 1400 /* 1401 * file_aw -- 1402 * Autowrite routine. If modified, autowrite is set and the readonly bit 1403 * is not set, write the file. A routine so there's a place to put the 1404 * comment. 1405 * 1406 * PUBLIC: int file_aw(SCR *, int); 1407 */ 1408 int 1409 file_aw(SCR *sp, int flags) 1410 { 1411 if (!F_ISSET(sp->ep, F_MODIFIED)) 1412 return (0); 1413 if (!O_ISSET(sp, O_AUTOWRITE)) 1414 return (0); 1415 1416 /* 1417 * !!! 1418 * Historic 4BSD vi attempted to write the file if autowrite was set, 1419 * regardless of the writeability of the file (as defined by the file 1420 * readonly flag). System V changed this as some point, not attempting 1421 * autowrite if the file was readonly. This feels like a bug fix to 1422 * me (e.g. the principle of least surprise is violated if readonly is 1423 * set and vi writes the file), so I'm compatible with System V. 1424 */ 1425 if (O_ISSET(sp, O_READONLY)) { 1426 msgq(sp, M_INFO, 1427 "266|File readonly, modifications not auto-written"); 1428 return (1); 1429 } 1430 return (file_write(sp, NULL, NULL, NULL, flags)); 1431 } 1432 1433 /* 1434 * set_alt_name -- 1435 * Set the alternate pathname. 1436 * 1437 * Set the alternate pathname. It's a routine because I wanted some place 1438 * to hang this comment. The alternate pathname (normally referenced using 1439 * the special character '#' during file expansion and in the vi ^^ command) 1440 * is set by almost all ex commands that take file names as arguments. The 1441 * rules go something like this: 1442 * 1443 * 1: If any ex command takes a file name as an argument (except for the 1444 * :next command), the alternate pathname is set to that file name. 1445 * This excludes the command ":e" and ":w !command" as no file name 1446 * was specified. Note, historically, the :source command did not set 1447 * the alternate pathname. It does in nvi, for consistency. 1448 * 1449 * 2: However, if any ex command sets the current pathname, e.g. the 1450 * ":e file" or ":rew" commands succeed, then the alternate pathname 1451 * is set to the previous file's current pathname, if it had one. 1452 * This includes the ":file" command and excludes the ":e" command. 1453 * So, by rule #1 and rule #2, if ":edit foo" fails, the alternate 1454 * pathname will be "foo", if it succeeds, the alternate pathname will 1455 * be the previous current pathname. The ":e" command will not set 1456 * the alternate or current pathnames regardless. 1457 * 1458 * 3: However, if it's a read or write command with a file argument and 1459 * the current pathname has not yet been set, the file name becomes 1460 * the current pathname, and the alternate pathname is unchanged. 1461 * 1462 * If the user edits a temporary file, there may be times when there is no 1463 * alternative file name. A name argument of NULL turns it off. 1464 * 1465 * PUBLIC: void set_alt_name(SCR *, char *); 1466 */ 1467 void 1468 set_alt_name(SCR *sp, char *name) 1469 { 1470 free(sp->alt_name); 1471 if (name == NULL) 1472 sp->alt_name = NULL; 1473 else if ((sp->alt_name = strdup(name)) == NULL) 1474 msgq(sp, M_SYSERR, NULL); 1475 } 1476 1477 /* 1478 * file_lock -- 1479 * Get an exclusive lock on a file. 1480 * 1481 * PUBLIC: lockr_t file_lock(SCR *, char *, int, int); 1482 */ 1483 lockr_t 1484 file_lock(SCR *sp, char *name, int fd, int iswrite) 1485 { 1486 if (!O_ISSET(sp, O_LOCKFILES)) 1487 return (LOCK_SUCCESS); 1488 1489 /* 1490 * !!! 1491 * We need to distinguish a lock not being available for the file 1492 * from the file system not supporting locking. Flock is documented 1493 * as returning EWOULDBLOCK; add EAGAIN for good measure, and assume 1494 * they are the former. There's no portable way to do this. 1495 */ 1496 errno = 0; 1497 if (!flock(fd, LOCK_EX | LOCK_NB)) { 1498 fcntl(fd, F_SETFD, 1); 1499 return (LOCK_SUCCESS); 1500 } 1501 return (errno == EAGAIN 1502 #ifdef EWOULDBLOCK 1503 || errno == EWOULDBLOCK 1504 #endif 1505 ? LOCK_UNAVAIL : LOCK_FAILED); 1506 } 1507