[In addition to the issues about whether turning off readlocks makes any sense (see the comment at the start of src/locks.c for details on what the readlocks are for), there are a few details with this patch. For example, new global options should have new requests, as noted in cvsclient.texi (in fact, with the patch, the server appears not to support the request which the patched client makes) -kingdon] Date: Thu, 11 Sep 1997 17:57:57 -0400 From: Greg Hudson To: bug-cvs@prep.ai.mit.edu Subject: Support for non-read-locked operation Here is a patch against CVS 1.9.16 to implement a global "-u" option to suppress read-locks. I've sent in a version of this patch before, but it had a bug and didn't support client-server operation. I realize that the maintainers of CVS may or may not want to accept this patch because of the dangers inherent in checking out a tree without read locks. I've been maintaining it as a local modification at MIT Athena for a number of months, and a lot of users have commented on how useful it is. I've never run into a case where users even ran into corruption due to lack of locking, much less got confused by it. diff -rc src.old/checkout.c src/checkout.c *** src.old/checkout.c Sun Sep 7 10:20:31 1997 --- src/checkout.c Thu Sep 11 17:14:45 1997 *************** *** 179,185 **** case 'p': pipeout = 1; run_module_prog = 0; /* don't run module prog when piping */ ! noexec = 1; /* so no locks will be created */ break; case 'c': cat = 1; --- 179,185 ---- case 'p': pipeout = 1; run_module_prog = 0; /* don't run module prog when piping */ ! nolock = 1; /* so no locks will be created */ break; case 'c': cat = 1; diff -rc src.old/client.c src/client.c *** src.old/client.c Fri Sep 5 12:00:16 1997 --- src/client.c Thu Sep 11 17:14:46 1997 *************** *** 3924,3929 **** --- 3924,3939 ---- error (1, 0, "This server does not support the global -n option."); } + if (nolock) + { + if (have_global) + { + send_to_server ("Global_option -u\012", 0); + } + else + error (1, 0, + "This server does not support the global -u option."); + } if (quiet) { if (have_global) diff -rc src.old/cvs.h src/cvs.h *** src.old/cvs.h Sun Sep 7 09:05:52 1997 --- src/cvs.h Thu Sep 11 17:14:46 1997 *************** *** 385,390 **** --- 385,391 ---- extern int trace; /* Show all commands */ extern int noexec; /* Don't modify disk anywhere */ + extern int nolock; /* Don't create locks */ extern int logoff; /* Don't write history entry */ #ifdef AUTH_SERVER_SUPPORT diff -rc src.old/history.c src/history.c *** src.old/history.c Tue Jul 8 12:22:43 1997 --- src/history.c Thu Sep 11 17:14:47 1997 *************** *** 738,744 **** #else fprintf (stderr, "-> fopen(%s,a)\n", fname); #endif ! if (noexec) goto out; fd = CVS_OPEN (fname, O_WRONLY | O_APPEND | O_CREAT | OPEN_BINARY, 0666); if (fd < 0) --- 738,744 ---- #else fprintf (stderr, "-> fopen(%s,a)\n", fname); #endif ! if (nolock) goto out; fd = CVS_OPEN (fname, O_WRONLY | O_APPEND | O_CREAT | OPEN_BINARY, 0666); if (fd < 0) diff -rc src.old/lock.c src/lock.c *** src.old/lock.c Mon Jun 16 19:04:06 1997 --- src/lock.c Thu Sep 11 17:14:47 1997 *************** *** 243,249 **** FILE *fp; char *tmp; ! if (noexec) return (0); /* we only do one directory at a time for read locks! */ --- 243,249 ---- FILE *fp; char *tmp; ! if (nolock) return (0); /* we only do one directory at a time for read locks! */ *************** *** 316,322 **** { char *wait_repos; ! if (noexec) return (0); /* We only know how to do one list at a time */ --- 316,322 ---- { char *wait_repos; ! if (nolock) return (0); /* We only know how to do one list at a time */ diff -rc src.old/main.c src/main.c *** src.old/main.c Thu Aug 14 11:06:39 1997 --- src/main.c Thu Sep 11 17:15:34 1997 *************** *** 40,45 **** --- 40,46 ---- int quiet = FALSE; int trace = FALSE; int noexec = FALSE; + int nolock = FALSE; int logoff = FALSE; mode_t cvsumask = UMASK_DFLT; *************** *** 153,158 **** --- 154,160 ---- /* Some people think that a bug-reporting address should go here. IMHO, the web sites are better because anything else is very likely to go + " -u Don't create read locks (implies -l; dangerous)\n", obsolete in the years between a release and when someone might be reading this help. Besides, we could never adequately discuss bug reporting in a concise enough way to put in a help message. */ *************** *** 482,488 **** opterr = 1; while ((c = getopt_long ! (argc, argv, "+Qqrwtnlvb:T:e:d:Hfz:s:x", long_options, &option_index)) != EOF) { switch (c) --- 484,490 ---- opterr = 1; while ((c = getopt_long ! (argc, argv, "+Qqrwtnulvb:T:e:d:Hfz:s:x", long_options, &option_index)) != EOF) { switch (c) *************** *** 520,525 **** --- 522,529 ---- break; case 'n': noexec = TRUE; + case 'u': /* Fall through */ + nolock = TRUE; case 'l': /* Fall through */ logoff = TRUE; break; *************** *** 788,794 **** * BUT, only if the history file exists. */ ! if (!client_active) { char *path; int save_errno; --- 792,798 ---- * BUT, only if the history file exists. */ ! if (!client_active && !nolock) { char *path; int save_errno; diff -rc src.old/recurse.c src/recurse.c *** src.old/recurse.c Sun Sep 7 12:15:22 1997 --- src/recurse.c Thu Sep 11 17:14:48 1997 *************** *** 330,336 **** if (frame->flags == R_SKIP_ALL) return (0); ! should_readlock = noexec ? 0 : frame->readlock; /* The fact that locks are not active here is what makes us fail to have the --- 330,336 ---- if (frame->flags == R_SKIP_ALL) return (0); ! should_readlock = nolock ? 0 : frame->readlock; /* The fact that locks are not active here is what makes us fail to have the *************** *** 372,378 **** */ if (server_active /* If there are writelocks around, we cannot pause here. */ ! && (should_readlock || noexec)) server_pause_check(); #endif --- 372,378 ---- */ if (server_active /* If there are writelocks around, we cannot pause here. */ ! && (should_readlock || nolock)) server_pause_check(); #endif diff -rc src.old/server.c src/server.c *** src.old/server.c Mon Aug 11 12:55:55 1997 --- src/server.c Thu Sep 11 17:14:48 1997 *************** *** 1629,1634 **** --- 1629,1637 ---- case 'n': noexec = 1; break; + case 'u': + nolock = 1; + break; case 'q': quiet = 1; break; diff -rc src.old/tag.c src/tag.c *** src.old/tag.c Tue Jul 1 18:55:45 1997 --- src/tag.c Thu Sep 11 17:14:49 1997 *************** *** 835,841 **** /* The tags is valid but not mentioned in val-tags. Add it. */ datum value; ! if (noexec) { if (db != NULL) dbm_close (db); --- 835,841 ---- /* The tags is valid but not mentioned in val-tags. Add it. */ datum value; ! if (nolock) { if (db != NULL) dbm_close (db); diff -rc doc.old/cvs.texinfo doc/cvs.texinfo *** doc.old/cvs.texinfo Sat Sep 6 11:53:16 1997 --- doc/cvs.texinfo Thu Sep 11 17:57:10 1997 *************** *** 6944,6949 **** --- 6944,6957 ---- @sc{cvs} will skip some of the processing that would have been required to produce the exact same output. + @item -u + Do not create read locks in the repository. This + option is dangerous, and can result in inconsistent + data in the working directory. The intent is to allow + read-only operations such as @samp{checkout} to succeed + for users who do not have write access to the + repository. This option implies the @samp{-l} option. + @item -Q Cause the command to be really quiet; the command will only generate output for serious problems.