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