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