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