From: Martin Stromberg Message-Id: <199803161212.NAA22497@propus.lu.erisoft.se> Subject: Re: Where to get the latest sources for djtar To: eliz AT is DOT elta DOT co DOT il (Eli Zaretskii) Date: Mon, 16 Mar 1998 13:12:37 +0100 (MET) Cc: djgpp-workers AT delorie DOT com In-Reply-To: from "Eli Zaretskii" at Mar 16, 98 01:30:15 pm MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Precedence: bulk > The problem is that `djtar' automatically applied change rules for > directory names without testing whether they have ever worked before. > This made it loop endlessly, eventually overwriting the stack. Please > try the patch below and tell me if it helps. I'll try that. > I think testing for a full disk is too expensive, and also doesn't > cover all the cases (e.g., a write-protected floppy that isn't full). Hardly too expensive, it's only done when an error occurs. Isn't some better diagnostics worth the time? Here's my mkdir.c patch, for what it is worth. Some things to note: ENOSPC and ENAMETOOLONG: I don't know if these are the right E-codes to use. 24 slashes: this is what I empirically determined on my two partitions. I couldn't find any #define for this. Does anybody know if this is defined somewhere? I mean a #define in a header file as well as some DOS-ish FAT definition. Setting errno: I don't know if it is a bug or a feature, but in case of errno == EACCES, the original mkdir.c clobbers errno, without restoring it by the call to access(). *** mkdir.org Sat Aug 31 21:09:32 1996 --- mkdir.c Mon Mar 16 01:02:24 1998 *************** *** 2,12 **** --- 2,18 ---- #include #include #include + #include #include #include #include #include + #include #include + + #if 0 + #include + #endif int mkdir(const char *dirname, mode_t mode) *************** *** 27,40 **** if (r.x.flags & 1) { errno = __doserr_to_errno(r.x.ax); if (errno == EACCES) { /* see if the directory existed, in which case we should return EEXIST - DJ */ if (access(dirname, D_OK) == 0) errno = EEXIST; } ! return -1; } /* DOS ignores directory permissions, and mkdir is stub'd, --- 33,99 ---- if (r.x.flags & 1) { errno = __doserr_to_errno(r.x.ax); + #if 0 + fprintf(stderr, "mkdir: errno = %d.\n", errno); + #endif if (errno == EACCES) { + struct statfs sfs; + char tn[PATH_MAX]; + /* see if the directory existed, in which case we should return EEXIST - DJ */ if (access(dirname, D_OK) == 0) + { errno = EEXIST; + return(-1); + } + #if 0 + fprintf(stderr, "mkdir: dirname = '%s'.\n", dirname); + #endif + /* See if the disk is full, in which case + we should return ENOSPC - AMS */ + if(!statfs(dirname, &sfs)) + { + #if 0 + fprintf(stderr, "mkdir statfs.(bfree, bavail, ffree) = (%ld, %ld, %ld).\n", + sfs.f_bfree, sfs.f_bavail, sfs.f_ffree); + #endif + if(!sfs.f_bfree) + { + errno = ENOSPC; + return(-1); + } + } + /* See if its to deep directory nesting, in which case + we should return ENAMETOOLONG - AMS */ + if(_truename(dirname, tn)) + { + const char *p; + int slashes; + #if 0 + fprintf(stderr, "mkdir: tn = '%s'.\n", tn); + #endif + p = tn; + slashes = 0; + while(*p != '\0') + { + if(*p == '\\') + { + slashes++; + } + p++; + } + if(24 < slashes) + { + errno = ENAMETOOLONG; + return(-1); + } + } + /* Restore errno. */ + errno = EACCES; } ! return(-1); } /* DOS ignores directory permissions, and mkdir is stub'd,