Provided by GNU Savannah

Savannah CVS Surfing - project cvs - Diff of /ccvs/src/tag.c

[cvs] / ccvs / src / tag.c
cvs -d:pserver:anonymous@cvs.sv.gnu.org:/sources/cvs co ccvs/src/tag.c
(to check out web pages for a project, replace /sources with /web in the path above)

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.100.4.7, Tue Apr 6 19:18:50 2004 UTC revision 1.100.4.16, Fri May 26 16:25:25 2006 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (c) 1992, Brian Berliner and Jeff Polk   * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
3   * Copyright (c) 1989-1992, Brian Berliner   *
4     * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
5     *                                  and others.
6     *
7     * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
8     * Portions Copyright (C) 1989-1992, Brian Berliner
9   *   *
10   * You may distribute under the terms of the GNU General Public License as   * You may distribute under the terms of the GNU General Public License as
11   * specified in the README file that comes with the CVS source distribution.   * specified in the README file that comes with the CVS source distribution.
# Line 150  Line 155 
155                  break;                  break;
156              case 'Q':              case 'Q':
157              case 'q':              case 'q':
 #ifdef SERVER_SUPPORT  
158                  /* The CVS 1.5 client sends these options (in addition to                  /* The CVS 1.5 client sends these options (in addition to
159                     Global_option requests), so we must ignore them.  */                     Global_option requests), so we must ignore them.  */
160                  if (!server_active)                  if (!server_active)
 #endif  
161                      error (1, 0,                      error (1, 0,
162                             "-q or -Q must be specified before \"%s\"",                             "-q or -Q must be specified before \"%s\"",
163                             cvs_cmd_name);                             cvs_cmd_name);
# Line 352  Line 355 
355          {          {
356              error (0, errno, "cannot chdir to %s", repository);              error (0, errno, "cannot chdir to %s", repository);
357              free (repository);              free (repository);
358                free (where);
359              return (1);              return (1);
360          }          }
361          /* End section which is identical to patch_proc.  */          /* End section which is identical to patch_proc.  */
362    
363          if (delete_flag || attic_too || (force_tag_match && numtag))          if (delete_flag || force_tag_move || attic_too || numtag)
364              which = W_REPOS | W_ATTIC;              which = W_REPOS | W_ATTIC;
365          else          else
366              which = W_REPOS;              which = W_REPOS;
# Line 1132  Line 1136 
1136    
1137    
1138    
1139    /* This routine determines whether a tag appears in CVSROOT/val-tags.
1140     *
1141     * The val-tags file will be open read-only when IDB is NULL.  Since writes to
1142     * val-tags always append to it, the lack of locking is okay.  The worst case
1143     * race condition might misinterpret a partially written "foobar" matched, for
1144     * instance,  a request for "f", "foo", of "foob".  Such a mismatch would be
1145     * caught harmlessly later.
1146     *
1147     * Before CVS adds a tag to val-tags, it will lock val-tags for write and
1148     * verify that the tag is still not present to avoid adding it twice.
1149     *
1150     * NOTES
1151     *   This function expects its parent to handle any necessary locking of the
1152     *   val-tags file.
1153     *
1154     * INPUTS
1155     *   idb        When this value is NULL, the val-tags file is opened in
1156     *              in read-only mode.  When present, the val-tags file is opened
1157     *              in read-write mode and the DBM handle is stored in *IDB.
1158     *   name       The tag to search for.
1159     *
1160     * OUTPUTS
1161     *   *idb       The val-tags file opened for read/write, or NULL if it couldn't
1162     *              be opened.
1163     *
1164     * ERRORS
1165     *   Exits with an error message if the val-tags file cannot be opened for
1166     *   read (failure to open val-tags read/write is harmless - see below).
1167     *
1168     * RETURNS
1169     *   true       1. If NAME exists in val-tags.
1170     *              2. If IDB is non-NULL and val-tags cannot be opened for write.
1171     *                 This allows callers to ignore the harmless inability to
1172     *                 update the val-tags cache.
1173     *   false      If the file could be opened and the tag is not present.
1174     */
1175    static int is_in_val_tags PROTO((DBM **idb, const char *name));
1176    static int
1177    is_in_val_tags (idb, name)
1178        DBM **idb;
1179        const char *name;
1180    {
1181        DBM *db = NULL;
1182        char *valtags_filename;
1183        datum mytag;
1184        int status;
1185    
1186        /* Casting out const should be safe here - input datums are not
1187         * written to by the myndbm functions.
1188         */
1189        mytag.dptr = (char *)name;
1190        mytag.dsize = strlen (name);
1191    
1192        valtags_filename = xmalloc (strlen (current_parsed_root->directory)
1193                                    + sizeof CVSROOTADM
1194                                    + sizeof CVSROOTADM_VALTAGS + 3);
1195        sprintf (valtags_filename, "%s/%s/%s", current_parsed_root->directory,
1196                                               CVSROOTADM, CVSROOTADM_VALTAGS);
1197    
1198        if (idb)
1199        {
1200            db = dbm_open (valtags_filename, O_RDWR, 0666);
1201            if (!db)
1202            {
1203                mode_t omask;
1204    
1205                if (!existence_error (errno))
1206                {
1207                    error (0, errno, "warning: cannot open %s read/write",
1208                           valtags_filename);
1209                    *idb = NULL;
1210                    return 1;
1211                }
1212    
1213                omask = umask (cvsumask);
1214                db = dbm_open (valtags_filename, O_RDWR | O_CREAT | O_TRUNC, 0666);
1215                umask (omask);
1216                if (!db)
1217                {
1218                    error (0, errno, "warning: cannot create %s",
1219                           valtags_filename);
1220                    *idb = NULL;
1221                    return 1;
1222                }
1223    
1224                *idb = db;
1225                return 0;
1226            }
1227    
1228            *idb = db;
1229        }
1230        else
1231        {
1232            db = dbm_open (valtags_filename, O_RDONLY, 0444);
1233            if (!db && !existence_error (errno))
1234                error (1, errno, "cannot read %s", valtags_filename);
1235        }
1236    
1237        /* If the file merely fails to exist, we just keep going and create
1238           it later if need be.  */
1239    
1240        status = 0;
1241        if (db)
1242        {
1243            datum val;
1244    
1245            val = dbm_fetch (db, mytag);
1246            if (val.dptr != NULL)
1247                /* Found.  The tag is valid.  */
1248                status = 1;
1249    
1250            /* FIXME: should check errors somehow (add dbm_error to myndbm.c?).  */
1251    
1252            if (!idb) dbm_close (db);
1253        }
1254    
1255        free (valtags_filename);
1256        return status;
1257    }
1258    
1259    
1260    
1261    /* Add a tag to the CVSROOT/val-tags cache.  Establishes a write lock and
1262     * reverifies that the tag does not exist before adding it.
1263     */
1264    static void add_to_val_tags PROTO((const char *name));
1265    static void
1266    add_to_val_tags (name)
1267        const char *name;
1268    {
1269        DBM *db;
1270        datum mytag;
1271        datum value;
1272    
1273        if (noexec) return;
1274    
1275        val_tags_lock (current_parsed_root->directory);
1276    
1277        /* Check for presence again since we have a lock now.  */
1278        if (is_in_val_tags (&db, name))
1279        {
1280            clear_val_tags_lock ();
1281            if (db)
1282                dbm_close (db);
1283            return;
1284        }
1285    
1286        /* Casting out const should be safe here - input datums are not
1287         * written to by the myndbm functions.
1288         */
1289        mytag.dptr = (char *)name;
1290        mytag.dsize = strlen (name);
1291        value.dptr = "y";
1292        value.dsize = 1;
1293    
1294        if (dbm_store (db, mytag, value, DBM_REPLACE) < 0)
1295            error (0, errno, "failed to store %s into val-tags", name);
1296        dbm_close (db);
1297    
1298        clear_val_tags_lock ();
1299    }
1300    
1301    
1302    
1303  static Dtype val_direntproc PROTO ((void *, const char *, const char *,  static Dtype val_direntproc PROTO ((void *, const char *, const char *,
1304                                      const char *, List *));                                      const char *, List *));
1305    
# Line 1173  Line 1341 
1341      int aflag;      int aflag;
1342      char *repository;      char *repository;
1343  {  {
     DBM *db;  
     char *valtags_filename;  
     int nowrite = 0;  
     datum mytag;  
1344      struct val_args the_val_args;      struct val_args the_val_args;
1345      struct saved_cwd cwd;      struct saved_cwd cwd;
1346      int which;      int which;
# Line 1199  Line 1363 
1363          || strcmp (name, TAG_HEAD) == 0)          || strcmp (name, TAG_HEAD) == 0)
1364          return;          return;
1365    
1366      /* FIXME: This routine doesn't seem to do any locking whatsoever      /* Verify that the tag is valid syntactically.  Some later code once made
1367         (and it is called from places which don't have locks in place).       * assumptions about this.
1368         If two processes try to write val-tags at the same time, it would       */
1369         seem like we are in trouble.  */      RCS_check_tag (name);
   
     mytag.dptr = name;  
     mytag.dsize = strlen (name);  
   
     valtags_filename = xmalloc (strlen (current_parsed_root->directory)  
                                 + sizeof CVSROOTADM  
                                 + sizeof CVSROOTADM_VALTAGS + 3);  
     sprintf (valtags_filename, "%s/%s/%s", current_parsed_root->directory,  
                                            CVSROOTADM, CVSROOTADM_VALTAGS);  
     db = dbm_open (valtags_filename, O_RDWR, 0666);  
     if (db == NULL)  
     {  
         if (!existence_error (errno))  
         {  
             error (0, errno, "warning: cannot open %s read/write",  
                    valtags_filename);  
             db = dbm_open (valtags_filename, O_RDONLY, 0666);  
             if (db != NULL)  
                 nowrite = 1;  
             else if (!existence_error (errno))  
                 error (1, errno, "cannot read %s", valtags_filename);  
         }  
         /* If the file merely fails to exist, we just keep going and create  
            it later if need be.  */  
     }  
     if (db != NULL)  
     {  
         datum val;  
1370    
1371          val = dbm_fetch (db, mytag);      if (is_in_val_tags (NULL, name)) return;
         if (val.dptr != NULL)  
         {  
             /* Found.  The tag is valid.  */  
             dbm_close (db);  
             free (valtags_filename);  
             return;  
         }  
         /* FIXME: should check errors somehow (add dbm_error to myndbm.c?).  */  
     }  
1372    
1373      /* We didn't find the tag in val-tags, so look through all the RCS files      /* We didn't find the tag in val-tags, so look through all the RCS files
1374         to see whether it exists there.  Yes, this is expensive, but there         to see whether it exists there.  Yes, this is expensive, but there
# Line 1286  Line 1413 
1413      if (!the_val_args.found)      if (!the_val_args.found)
1414          error (1, 0, "no such tag %s", name);          error (1, 0, "no such tag %s", name);
1415      else      else
     {  
1416          /* The tags is valid but not mentioned in val-tags.  Add it.  */          /* The tags is valid but not mentioned in val-tags.  Add it.  */
1417          datum value;          add_to_val_tags (name);
   
         if (noexec || nowrite)  
         {  
             if (db != NULL)  
                 dbm_close (db);  
             free (valtags_filename);  
             return;  
1418          }          }
1419    
         if (db == NULL)  
         {  
             mode_t omask;  
             omask = umask (cvsumask);  
             db = dbm_open (valtags_filename, O_RDWR | O_CREAT | O_TRUNC, 0666);  
             (void)umask (omask);  
1420    
             if (db == NULL)  
             {  
                 error (0, errno, "warning: cannot create %s", valtags_filename);  
                 free (valtags_filename);  
                 return;  
             }  
         }  
         value.dptr = "y";  
         value.dsize = 1;  
         if (dbm_store (db, mytag, value, DBM_REPLACE) < 0)  
             error (0, errno, "cannot store %s into %s", name,  
                    valtags_filename);  
         dbm_close (db);  
     }  
     free (valtags_filename);  
 }  
1421    
1422  /*  /*
1423   * Check whether a join tag is valid.  This is just like   * Check whether a join tag is valid.  This is just like

Legend:
Removed from v.1.100.4.7  
changed lines
  Added in v.1.100.4.16

Send suggestions and report system problems to the Savannah Hackers.
ViewVC Help
Powered by ViewVC 1.0.7