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