Index: /trunk/Ohana/src/delstar/src/RegionOps.c
===================================================================
--- /trunk/Ohana/src/delstar/src/RegionOps.c	(revision 4611)
+++ /trunk/Ohana/src/delstar/src/RegionOps.c	(revision 4611)
@@ -0,0 +1,233 @@
+# include "delstar.h"
+
+# define NBANDS 24
+
+double DecBands[] = {
+  -90.0, -82.5, -75.0, -67.5, -60.0, 
+  -52.5, -45.0, -37.5, -30.0, -22.5, 
+  -15.0, -07.5, +00.0, +07.5, +15.0, 
+  +22.5, +30.0, +37.5, +45.0, +52.5, 
+  +60.0, +67.5, +75.0, +82.5, +90.0
+};
+
+char *DecNames[] = {
+  "s8230", "s7500", "s6730", "s6000", "s5230",
+  "s4500", "s3730", "s3000", "s2230", "s1500", 
+  "s0730", "s0000", "n0000", "n0730", "n1500", 
+  "n2230", "n3000", "n3730", "n4500", "n5230", 
+  "n6000", "n6730", "n7500", "n8230", 
+};
+
+GSCRegion *LoadRegions (int *nregions) {
+  
+  int Nregions, i, NDec, Nx, Ny;
+  char temp[50], file[256];
+  double RA0, RA1, DEC0, DEC1, D0, D1;
+  FILE *f;
+  GSCRegion *regions;
+  Header header;
+  Header theader;
+  Matrix matrix;
+  FTable table;
+  
+  f = fopen (GSCFILE, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't find GSC region file %s\n", GSCFILE);
+    exit (1);
+  }
+
+  /* init & load in table data */
+  table.header = &theader;
+  if (!fits_fread_header (f, &header))           Shutdown ("can't read primary header for GSC Region table"); 
+  if (!fits_fread_matrix (f, &matrix, &header))  Shutdown ("can't read primary matrix for GSC Region table");
+  if (!fits_fread_ftable (f, &table, "REGIONS")) Shutdown ("can't read GSC Region table");
+
+  fits_scan (table.header, "NAXIS1", "%d", 1, &Nx);
+  fits_scan (table.header, "NAXIS2", "%d", 1, &Ny);
+
+  Nregions = 0;
+  ALLOCATE (regions, GSCRegion, Ny + 2);  /* allow room for N & S poles */
+
+  /* pole region is artificial - not in table */
+  sprintf (file, "%s/n8230/pole.cpt", CATDIR);
+  regions[Nregions].DEC[0] = 86.25;
+  regions[Nregions].DEC[1] = 93.75;
+  regions[Nregions].RA[0] =  0.0;
+  regions[Nregions].RA[1] =  360.0;
+  strcpy (regions[Nregions].filename, file);
+  Nregions ++;
+
+  /* fill out GSCRegion structure */
+  for (i = 0; i < Ny; i++) {
+    strncpy (temp, &table.buffer[i*48], 48);
+    temp[49] = 0;
+    hms_to_deg (&RA0, &RA1, &DEC0, &DEC1, &temp[7]);
+    if (RA1 < RA0) RA1 += 360.0;
+
+    if (DEC0 < DEC1) {
+      regions[Nregions].DEC[0] = DEC0;
+      regions[Nregions].DEC[1] = DEC1;
+    } else {
+      regions[Nregions].DEC[0] = DEC1;
+      regions[Nregions].DEC[1] = DEC0;
+    }     
+    /* skip the pole entries */
+    if (regions[Nregions].DEC[1] > 86.25) continue;
+
+    regions[Nregions].RA[0] = RA0;
+    regions[Nregions].RA[1] = RA1;
+
+    /** convert DEC0, DEC1 to NBigDec **/
+    NDec = FindDecBand (0.5*(DEC0 + DEC1), &D0, &D1);
+    if (NDec == -1) Shutdown ("programming / table error");
+
+    temp[5] = 0;
+    sprintf (file, "%s/%s/%s.cpt", CATDIR, DecNames[NDec], &temp[1]);
+
+    strcpy (regions[Nregions].filename, file);
+    Nregions ++;
+  }
+  if (Nregions > Ny + 2) {
+    fprintf (stderr, "ERROR: too many regions\n");
+    exit (2);
+  }
+
+  sort_regions (regions, Nregions);
+  *nregions = Nregions;
+  return (regions);
+}
+
+/* given dec value, find upper and lower bounds of enclosing dec band */
+int FindDecBand (double dec, double *DEC0, double *DEC1) {
+
+  int i;
+
+  for (i = 0; i < NBANDS; i++) {
+    if (DecBands[i + 0] >  dec) continue;
+    if (DecBands[i + 1] <= dec) continue;
+    *DEC0 = DecBands[i+0];
+    *DEC1 = DecBands[i+1];
+    return (i);
+  }
+  return (-1);
+}
+
+/* note that region.DEC[0] is sorted, but not necessarily DEC[1] */
+int FindRegionDecBandStart (GSCRegion *region, int Nregion, double dec) {
+
+  int N, Nlo, Nhi;
+  double D0, D1;
+
+  if (dec <= 90) return (0);
+
+  /* D0, D1 are upper lower band boundaries */
+  /* all regions in this band have DEC[0] >= D0 */
+  N = FindDecBand (dec, &D0, &D1);
+  if (N == -1) Shutdown ("programming / table error");
+
+  /* bracket value of interest */
+  Nlo = 0; Nhi = Nregion;
+  while (Nhi - Nlo > 10) {
+    N = 0.5*(Nlo + Nhi);
+    if (region[N].DEC[0] < D0) {
+      Nlo = N;
+    } else {
+      Nhi = N;
+    }
+  }
+  /* Nlo - Nhi bracket the transition across dec */
+  /* v[Nlo] < v <= v[Nhi] */ 
+
+  /* find the last entry < dec */
+  for (N = Nhi; N >= Nlo; N--) {
+    if (region[N].DEC[0] < D0) return (N);
+  }
+  return (-1);
+  /* this will fail if transition value is not in the data range */
+}
+
+/* note that region.DEC[0] is sorted, but not necessarily DEC[1] */
+int FindRegionDecBandStop (GSCRegion *region, int Nregion, double dec) {
+
+  int N, Nlo, Nhi;
+  double D0, D1;
+
+  if (dec >= 90) return (Nregion - 1);
+
+  /* D0, D1 are upper lower band boundaries */
+  /* all regions in this band have DEC[0] < D1 */
+  N = FindDecBand (dec, &D0, &D1);
+  if (N == -1) Shutdown ("programming / table error");
+
+  /* bracket value of interest */
+  Nlo = 0; Nhi = Nregion;
+  while (Nhi - Nlo > 10) {
+    N = 0.5*(Nlo + Nhi);
+    if (region[N].DEC[0] > D1) {
+      Nhi = N;
+    } else {
+      Nlo = N;
+    }
+  }
+  /* Nlo - Nhi bracket the transition across dec */
+  /* v[Nlo] <= v < v[Nhi] */ 
+
+  /* find the last entry < dec */
+  for (N = Nlo; N < Nhi; N++) {
+    if (region[N].DEC[0] > D1) return (N);
+  }
+  return (-1);
+  /* this will fail if transition value is not in the data range */
+}
+
+int FindRegionByPoint (GSCRegion *region, double ra, double dec, GSCRegion *gsc, int Ngsc) {
+
+  int i, Ns;
+
+  Ns = FindRegionDecBandStart (gsc, Ngsc, dec);
+  if (Ns < 0) return (FALSE);
+
+  for (i = Ns; i < Ngsc; i++) {
+    if (gsc[i].RA[0]  >= ra) continue;
+    if (gsc[i].RA[1]  <  ra) continue;
+    if (gsc[i].DEC[0] >= dec) continue;
+    if (gsc[i].DEC[1] <  dec) continue;
+    region[0] = gsc[i];
+    return (TRUE);
+  }
+  return (FALSE);
+}
+
+/* bracket search:
+
+   Nlo            T      N                   Nhi
+   X X X X X X X V X X X X X X X X X X X X X X
+                         Nhi
+
+   Nlo                   N      T            Nhi
+   X X X X X X X X X X X X X X X V X X X X X X
+                         Nlo 
+
+*/
+
+/*
+      if (buffer[i*48 + 19] == ' ') continue;
+      strncpy (temp, &buffer[i*48 + 19], 20);       temp[20] = 0;
+      hms_to_deg (&RA,  &DEC, temp, ' ', 3);
+
+
+  dBigRA = 360.0 / (int)(0.5 + 48*cos(3.1415927*0.5*(BigDecBounds[NBigDec] + BigDecBounds[NBigDec + 1])/180.0));
+
+  NBigRA = ra / dBigRA;
+
+  NBig = NBigRA;
+  for (i = 0; (i < 12) && (i < NBigDec); i++) {
+    NBig += NBigRASections[i];
+  }
+  for (i = 13; (i < 24) && (i < NBigDec); i++) {
+    NBig += NBigRASections[i];
+  }
+
+
+  fprintf (stderr, "%d %d %d %d %f %f -> %f %f %f\n", NBigDec, NBigRA, NBigRASections[NBigDec], NBig, ra, dec, BigDecBounds[NBigDec], BigDecBounds[NBigDec + 1], dBigRA);
+*/
Index: /trunk/Ohana/src/delstar/src/check_permissions.c
===================================================================
--- /trunk/Ohana/src/delstar/src/check_permissions.c	(revision 4611)
+++ /trunk/Ohana/src/delstar/src/check_permissions.c	(revision 4611)
@@ -0,0 +1,67 @@
+# include "addstar.h"
+
+void check_permissions (char *basefile) {
+  
+  char *c, dir[256], filename[256];
+  struct stat filestat;
+  uid_t uid;
+  gid_t gid;
+  int status, cmode;
+
+  uid = getuid();
+  gid = getgid();
+
+  /* check permission to write to directory */
+  sprintf (filename, "%s", basefile);
+  c = strrchr (filename, '/');
+  if (c == (char *) NULL) {
+    strcpy (dir, ".");
+  } else {
+    *c = 0;
+    strcpy (dir, filename);
+  }
+  status = stat (dir, &filestat);
+  if (status == -1) {
+    fprintf (stderr, "directory %s does not exist, creating...\n", dir);
+    cmode = S_IRWXU | S_IRWXG | S_IRWXO;
+    status = mkdir (dir, cmode);
+    if (status == -1) {
+      fprintf (stderr, "ERROR: can't create %s\n", dir);
+      exit (1);
+    }
+  } 
+  status = stat (dir, &filestat);
+  if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRWXU)) ||
+      ((gid == filestat.st_gid) && (filestat.st_mode & S_IRWXG)) || 
+      (filestat.st_mode & S_IRWXO)) {
+  } else {
+    fprintf (stderr, "ERROR: can't write to %s\n", dir);
+    exit (1);
+  }
+  
+  /* check permission to write to file */
+  sprintf (filename, "%s", basefile);
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, are permissions OK? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR) && (filestat.st_mode & S_IWUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP) && (filestat.st_mode & S_IWGRP)) || 
+	((filestat.st_mode & S_IROTH) && (filestat.st_mode & S_IWOTH))) {
+    } else {
+      fprintf (stderr, "ERROR: can't write to %s\n", filename);
+      exit (1);
+    }
+  }
+  
+  /* check permission to write to backup file */
+  sprintf (filename, "%s~", basefile);
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, are permissions OK? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR) && (filestat.st_mode & S_IWUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP) && (filestat.st_mode & S_IWGRP)) || 
+	((filestat.st_mode & S_IROTH) && (filestat.st_mode & S_IWOTH))) {
+    } else {
+      fprintf (stderr, "ERROR: can't write to %s\n", filename);
+      exit (1);
+    }
+  }
+}
Index: /trunk/Ohana/src/delstar/src/delete_imagefile.c
===================================================================
--- /trunk/Ohana/src/delstar/src/delete_imagefile.c	(revision 4611)
+++ /trunk/Ohana/src/delstar/src/delete_imagefile.c	(revision 4611)
@@ -0,0 +1,58 @@
+# include "delstar.h"
+
+void delete_imagefile (char *filename) {
+
+  int i, j;
+  int Nregions, Nimlist;
+  int *imlist;
+  double trange;
+  time_t start, stop;
+  Image *image;
+  GSCRegion *region;
+  Catalog catalog;
+
+  /* load information about file - time/photcode */
+  image = gimages (filename);
+  
+  if (VERBOSE) fprintf (stderr, "deleting %s\n", image[0].name);
+  region = gregion_image (image, &Nregions);
+
+  for (i = 0; i < Nregions; i++) {
+    if (VERBOSE) fprintf (stderr, "deleting from %s\n", region[i].filename);
+    catalog.filename = region[i].filename;  /* don't free region before catalog! */
+    switch (lock_catalog (&catalog, LCK_XCLD)) {
+      case 0:
+	fprintf (stderr, "ERROR: can't lock file %s\n", catalog.filename);
+	exit (1);
+      case 1:
+	gcatalog (&catalog);
+	break;
+      case 2:
+	if (VERBOSE) fprintf (stderr, "no data in %s, skipping\n", catalog.filename);
+	unlock_catalog (&catalog);
+	continue;
+      default:
+	fprintf (stderr, "weird lock_catalog exit state\n");
+	exit (1);
+    }
+    /* pad exposure time by 1 sec to require a valid time */
+    /* trate is in 0.1 msec / row  - stop is the latest exposure end time */
+    trange = 1e-4*image[0].NY*image[0].trate + image[0].exptime + 1;  
+    start = image[0].tzero;
+    stop  = image[0].tzero + trange;
+    find_matches (&catalog, image[j].source, start, stop);
+    wcatalog (&catalog);
+    unlock_catalog (&catalog);
+  }
+
+  /* find and delete matching images */
+  imlist = find_images_data (image, &Nimlist);
+  if (!Nimlist) Shutdown ("image %s not found in db", filename);
+
+  dimages (imlist, Nimlist); 
+
+  save_image_db ();
+  unlock_image_db ();
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+}
Index: /trunk/Ohana/src/delstar/src/gregion_image.c
===================================================================
--- /trunk/Ohana/src/delstar/src/gregion_image.c	(revision 4611)
+++ /trunk/Ohana/src/delstar/src/gregion_image.c	(revision 4611)
@@ -0,0 +1,33 @@
+# include "delstar.h"
+
+/* given image with coords, find regions which overlap image */
+GSCRegion *gregion_image (Image *image, int *Nregions) {
+  
+  GSCRegion *regions, impatch;
+  double x, y, X, Y, ra, dec;
+  
+  /* this has trouble for images which overlap 0,360 */
+  impatch.RA[0]  = 360;
+  impatch.RA[1]  =   0;
+  impatch.DEC[0] = +90;
+  impatch.DEC[1] = -90;
+
+  if (!strcmp (&image[0].coords.ctype[4], "-WRP")) {
+    Shutdown ("method for deleting mosaic data not defined");
+    // RegisterMosaic (MOSAIC);
+  }    
+
+  for (x = 0; x <= 1; x++) {
+    for (y = 0; y <= 1; y++) {
+      X = image[0].NX*(1.1*x - 0.05);
+      Y = image[0].NY*(1.1*y - 0.05);
+      XY_to_RD (&ra, &dec, X, Y, &image[0].coords);
+      impatch.RA[0]  = MIN (ra,  impatch.RA[0]);
+      impatch.RA[1]  = MAX (ra,  impatch.RA[1]);
+      impatch.DEC[0] = MIN (dec, impatch.DEC[0]);
+      impatch.DEC[1] = MAX (dec, impatch.DEC[1]);
+    }
+  }
+  regions = gregion_patch (&impatch, Nregions);
+  return (regions);
+}
Index: /trunk/Ohana/src/delstar/src/gregion_patch.c
===================================================================
--- /trunk/Ohana/src/delstar/src/gregion_patch.c	(revision 4611)
+++ /trunk/Ohana/src/delstar/src/gregion_patch.c	(revision 4611)
@@ -0,0 +1,43 @@
+# include "delstar.h"
+
+GSCRegion *gregion_patch (GSCRegion *patch, int *nregions) {
+  
+  int i, Ns, Ne, Ngsc, Nregions;
+  GSCRegion *gsc, *regions;
+  
+  gsc = LoadRegions (&Ngsc);
+
+  /* find lower and upper boundaries */
+  Ns = FindRegionDecBandStart (gsc, Ngsc, patch[0].DEC[0]);
+  Ne = FindRegionDecBandStop (gsc, Ngsc, patch[0].DEC[1]);
+  if (Ns < 0) Shutdown ("invalid patch lower bound %f", patch[0].DEC[0]);
+  if (Ne < 0) Shutdown ("invalid patch upper bound %f", patch[0].DEC[1]);
+  
+  Nregions = 0;
+  ALLOCATE (regions, GSCRegion, Ne - Ns);
+
+  /* find all regions in range within ra range */
+  for (i = Ns; i < Ne; i++) {
+    if (gsc[i].RA[0]  >= patch[0].RA[1]) continue;
+    if (gsc[i].RA[1]  <  patch[0].RA[0]) continue;
+    if (gsc[i].DEC[0] >= patch[0].DEC[1]) continue;
+    if (gsc[i].DEC[1] <  patch[0].DEC[0]) continue;
+    /* add to the list */
+    regions[Nregions] = gsc[i];
+    Nregions ++;
+  }
+
+  if (VERBOSE) fprintf (stderr, "Nregions in patch: %d, Ne: %d, Ns: %d\n", Nregions, Ne, Ns);
+  if (Nregions > (Ne - Ns)) {
+    fprintf (stderr, "ERROR: too many regions found\n");
+    exit (1);
+  }
+
+  *nregions = Nregions;
+  return (regions);
+}
+
+/* given a ra,dec bounded region, find all region files which overlap it
+   - split region into two if overlapping 0,360 boundary 
+*/
+
