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