]> granicus.if.org Git - pdns/commitdiff
improve line number and filename reporting in errors, dealing with $includes
authorBert Hubert <bert.hubert@netherlabs.nl>
Thu, 7 Jun 2007 21:10:21 +0000 (21:10 +0000)
committerBert Hubert <bert.hubert@netherlabs.nl>
Thu, 7 Jun 2007 21:10:21 +0000 (21:10 +0000)
support $ttl case insensitively
deal with common '$ttl 86400;' syntax
recognize '1D' as a TTL more robustly

git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@1056 d19b8d6e-7fed-0310-83ef-9ca221ded41b

pdns/zoneparser-tng.cc
pdns/zoneparser-tng.hh

index 33edaa746d71760f19a55a75f902794f994545bc..a15f33ed0b74d9c7d272dbb815d24046ba0a91f6 100644 (file)
@@ -40,14 +40,16 @@ void ZoneParserTNG::stackFile(const std::string& fname)
   FILE *fp=fopen(fname.c_str(), "r");
   if(!fp)
     throw runtime_error("Unable to open file '"+fname+"': "+stringerror());
-  d_fps.push(fp);
+
+  filestate fs(fp, fname);
+  d_filestates.push(fs);
 }
 
 ZoneParserTNG::~ZoneParserTNG()
 {
-  while(!d_fps.empty()) {
-    fclose(d_fps.top());
-    d_fps.pop();
+  while(!d_filestates.empty()) {
+    fclose(d_filestates.top().d_fp);
+    d_filestates.pop();
   }
 }
 
@@ -56,7 +58,23 @@ static string makeString(const string& line, const pair<string::size_type, strin
   return string(line.c_str() + range.first, range.second - range.first);
 }
 
-static unsigned int makeTTLFromZone(const string& str)
+static bool isTimeSpec(const string& nextpart)
+{
+  if(nextpart.empty())
+    return false;
+  for(string::const_iterator iter = nextpart.begin(); iter != nextpart.end(); ++iter) {
+    if(isdigit(*iter))
+      continue;
+    if(iter+1 != nextpart.end())
+      return false;
+    char c=tolower(*iter);
+    return (c=='m' || c=='h' || c=='d' || c=='w' || c=='y');
+  }
+  return true;
+}
+
+
+unsigned int ZoneParserTNG::makeTTLFromZone(const string& str)
 {
   if(str.empty())
     return 0;
@@ -80,8 +98,11 @@ static unsigned int makeTTLFromZone(const string& str)
     case 'Y': // ? :-)
       val*=3600*24*365;
       break;
+
     default:
-      throw ZoneParserTNG::exception("Unable to parse time specification '"+str+"'");
+      throw ZoneParserTNG::exception("Unable to parse time specification '"+str+"' on line "+
+                                    lexical_cast<string>(d_filestates.top().d_lineno)+" of file '"+
+                                    d_filestates.top().d_filename+"'");
     }
   return val;
 }
@@ -198,6 +219,7 @@ bool findAndElide(string& line, char c)
 }
 
 
+
 bool ZoneParserTNG::get(DNSResourceRecord& rr) 
 {
  retry:;
@@ -214,8 +236,8 @@ bool ZoneParserTNG::get(DNSResourceRecord& rr)
 
   if(d_line[0]=='$') { 
     string command=makeString(d_line, parts[0]);
-    if(command=="$TTL" && parts.size() > 1)
-      d_defaultttl=makeTTLFromZone(makeString(d_line,parts[1]));
+    if(iequals(command,"$TTL") && parts.size() > 1)
+      d_defaultttl=makeTTLFromZone(trim_right_copy_if(makeString(d_line, parts[1]), is_any_of(";")));
     else if(iequals(command,"$INCLUDE") && parts.size() > 1) {
       string fname=unquotify(makeString(d_line, parts[1]));
       if(!fname.empty() && fname[0]!='/' && !d_reldir.empty())
@@ -239,7 +261,8 @@ bool ZoneParserTNG::get(DNSResourceRecord& rr)
       goto retry;
     }
     else
-      throw exception("Can't parse zone line '"+d_line+"'");
+      throw exception("Can't parse zone line '"+d_line+"' on line "+lexical_cast<string>(d_filestates.top().d_lineno)+
+                     " of file '"+d_filestates.top().d_filename);
     goto retry;
   }
 
@@ -284,7 +307,7 @@ bool ZoneParserTNG::get(DNSResourceRecord& rr)
       // cout<<"Ignoring 'IN'\n";
       continue;
     }
-    if(!haveTTL && !haveQTYPE && all(nextpart, is_digit())) {
+    if(!haveTTL && !haveQTYPE && isTimeSpec(nextpart)) {
       rr.ttl=makeTTLFromZone(nextpart);
       haveTTL=true;
       // cout<<"ttl is probably: "<<rr.ttl<<endl;
@@ -300,7 +323,10 @@ bool ZoneParserTNG::get(DNSResourceRecord& rr)
       continue;
     }
     catch(...) {
-      throw runtime_error("Parsing zone content line: '"+nextpart+"' doesn't look like a qtype, stopping loop");
+      throw runtime_error("Parsing zone content on line "+
+                         lexical_cast<string>(d_filestates.top().d_lineno)+
+                         " of file '"+d_filestates.top().d_filename+"': '"+nextpart+
+                         "' doesn't look like a qtype, stopping loop");
     }
   }
   if(!haveQTYPE) 
@@ -364,14 +390,15 @@ bool ZoneParserTNG::get(DNSResourceRecord& rr)
 
 bool ZoneParserTNG::getLine()
 {
-  while(!d_fps.empty()) {
+  while(!d_filestates.empty()) {
     char buffer[1024];
-    if(fgets(buffer, 1024, d_fps.top())) {
+    if(fgets(buffer, 1024, d_filestates.top().d_fp)) {
+      d_filestates.top().d_lineno++;
       d_line=buffer;
       return true;
     }
-    fclose(d_fps.top());
-    d_fps.pop();
+    fclose(d_filestates.top().d_fp);
+    d_filestates.pop();
   }
   return false;
 }
index e83e1f8a19bbf34bc92e0d8f50ed8fd9a0334c64..2a5d1c4870cad713c7f8793dfc849bb7f1854016 100644 (file)
@@ -39,7 +39,7 @@ private:
   bool getLine();
   bool getTemplateLine();
   void stackFile(const std::string& fname);
-  stack<FILE *> d_fps;
+  unsigned makeTTLFromZone(const std::string& str);
   string d_reldir;
   string d_line;
   string d_prevqname;
@@ -48,6 +48,14 @@ private:
   uint32_t d_templatecounter, d_templatestop, d_templatestep;
   string d_templateline;
   parts_t d_templateparts;
+
+  struct filestate {
+    filestate(FILE* fp, string filename) : d_fp(fp), d_filename(filename), d_lineno(0){}
+    FILE *d_fp;
+    string d_filename;
+    int d_lineno;
+  };
+  stack<filestate> d_filestates;
 };
 
 #endif