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