GRASS Programmer's Manual  6.4.2(2012)
segment/format.c
Go to the documentation of this file.
00001 
00015 #include <grass/config.h>
00016 #include <stdio.h>
00017 #include <string.h>
00018 #include <errno.h>
00019 #include <unistd.h>
00020 #include <limits.h>
00021 #include <grass/segment.h>
00022 
00023 
00024 static int _segment_format(int, int, int, int, int, int, int);
00025 static int write_int(int, int);
00026 static int zero_fill(int, off_t);
00027 
00028 /* fd must be open for write */
00029 
00030 
00062 int segment_format(int fd, int nrows, int ncols, int srows, int scols,
00063                    int len)
00064 {
00065     return _segment_format(fd, nrows, ncols, srows, scols, len, 1);
00066 }
00067 
00102 int segment_format_nofill(int fd, int nrows, int ncols, int srows, int scols,
00103                           int len)
00104 {
00105     return _segment_format(fd, nrows, ncols, srows, scols, len, 0);
00106 }
00107 
00108 
00109 static int _segment_format(int fd,
00110                            int nrows, int ncols,
00111                            int srows, int scols, int len, int fill)
00112 {
00113     off_t nbytes;
00114     int spr, size;
00115 
00116     if (nrows <= 0 || ncols <= 0 || len <= 0 || srows <= 0 || scols <= 0) {
00117         G_warning("segment_format(fd,%d,%d,%d,%d,%d): illegal value(s)",
00118                   nrows, ncols, srows, scols, len);
00119         return -3;
00120     }
00121 
00122     if (lseek(fd, 0L, SEEK_SET) == (off_t) -1) {
00123         G_warning("segment_format(): Unable to seek (%s)", strerror(errno));
00124         return -1;
00125     }
00126 
00127     if (!write_int(fd, nrows) || !write_int(fd, ncols)
00128         || !write_int(fd, srows) || !write_int(fd, scols)
00129         || !write_int(fd, len))
00130         return -1;
00131 
00132     if (!fill)
00133         return 1;
00134 
00135     spr = ncols / scols;
00136     if (ncols % scols)
00137         spr++;
00138 
00139     size = srows * scols * len;
00140 
00141     /* calculate total number of segments */
00142     nbytes = spr * ((nrows + srows - 1) / srows);
00143     nbytes *= size;
00144 
00145     /* fill segment file with zeros */
00146     /* NOTE: this could be done faster using lseek() by seeking
00147      * ahead nbytes and then writing a single byte of 0,
00148      * provided lseek() on all version of UNIX will create a file
00149      * with holes that read as zeros.
00150      */
00151     if (zero_fill(fd, nbytes) < 0)
00152         return -1;
00153 
00154     return 1;
00155 }
00156 
00157 
00158 static int write_int(int fd, int n)
00159 {
00160     if (write(fd, &n, sizeof(int)) != sizeof(int)) {
00161         G_warning("segment_format(): Unable to write (%s)", strerror(errno));
00162         return 0;
00163     }
00164 
00165     return 1;
00166 }
00167 
00168 
00169 static int zero_fill(int fd, off_t nbytes)
00170 {
00171 #ifndef USE_LSEEK
00172     char buf[10240];
00173     register char *b;
00174     register int n;
00175 
00176     /* zero buf */
00177     n = nbytes > sizeof(buf) ? sizeof(buf) : nbytes;
00178     b = buf;
00179     while (n-- > 0)
00180         *b++ = 0;
00181 
00182     while (nbytes > 0) {
00183         n = nbytes > sizeof(buf) ? sizeof(buf) : nbytes;
00184         if (write(fd, buf, n) != n) {
00185             G_warning("segment zero_fill(): Unable to write (%s)", strerror(errno));
00186             return -1;
00187         }
00188         nbytes -= n;
00189     }
00190     return 1;
00191 #else
00192     /* Using lseek (faster upon initialization).
00193        NOTE: This version doesn't allocate disk storage for the file; storage will
00194        be allocated dynamically as blocks are actually written. This could 
00195        result in zero_fill() succeeding but a subsequent call to write() failing
00196        with ENOSPC ("No space left on device").
00197      */
00198 
00199     static const char buf[10];
00200 
00201     G_debug(3, "Using new segmentation code...");
00202     if (lseek(fd, nbytes - 1, SEEK_CUR) < 0) {
00203         G_warning("segment zero_fill(): Unable to seek (%s)", strerror(errno));
00204         return -1;
00205     }
00206     if (write(fd, buf, 1) != 1) {
00207         G_warning("segment zero_fill(): Unable to write (%s)", strerror(errno));
00208         return -1;
00209     }
00210 
00211     return 1;
00212 #endif
00213 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines