mirror of
https://github.com/moparisthebest/curl
synced 2024-08-13 17:03:50 -04:00
curl: add --output-dir
Works with --create-dirs and with -J Add test 3008, 3009, 3011, 3012 and 3013 to verify. Closes #5637
This commit is contained in:
parent
510d98157f
commit
5620d2cc78
@ -159,7 +159,6 @@
|
|||||||
18.19 expand ~/ in config files
|
18.19 expand ~/ in config files
|
||||||
18.20 host name sections in config files
|
18.20 host name sections in config files
|
||||||
18.21 retry on the redirected-to URL
|
18.21 retry on the redirected-to URL
|
||||||
18.22 Add flag to specify download directory
|
|
||||||
18.23 Set the modification date on an uploaded file
|
18.23 Set the modification date on an uploaded file
|
||||||
18.24 Use multiple parallel transfers for a single download
|
18.24 Use multiple parallel transfers for a single download
|
||||||
|
|
||||||
@ -1122,12 +1121,6 @@ that doesn't exist on the server, just like --ftp-create-dirs.
|
|||||||
|
|
||||||
See https://github.com/curl/curl/issues/5462
|
See https://github.com/curl/curl/issues/5462
|
||||||
|
|
||||||
18.22 Add flag to specify download directory
|
|
||||||
|
|
||||||
A directory name to basically prepend to the file name -O and -o use. Saves
|
|
||||||
user from having to manually "cd" to the directory. Especially useful for
|
|
||||||
command lines with multiple -O and different download directories.
|
|
||||||
|
|
||||||
18.23 Set the modification date on an uploaded file
|
18.23 Set the modification date on an uploaded file
|
||||||
|
|
||||||
For SFTP and posssibly FTP, curl could offer an option to set the
|
For SFTP and posssibly FTP, curl could offer an option to set the
|
||||||
|
@ -127,6 +127,7 @@ DPAGES = \
|
|||||||
ntlm.d ntlm-wb.d \
|
ntlm.d ntlm-wb.d \
|
||||||
oauth2-bearer.d \
|
oauth2-bearer.d \
|
||||||
output.d \
|
output.d \
|
||||||
|
output-dir.d \
|
||||||
parallel-immediate.d \
|
parallel-immediate.d \
|
||||||
parallel-max.d \
|
parallel-max.d \
|
||||||
parallel.d \
|
parallel.d \
|
||||||
|
18
docs/cmdline-opts/output-dir.d
Normal file
18
docs/cmdline-opts/output-dir.d
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
Long: output-dir
|
||||||
|
Arg: <dir>
|
||||||
|
Help: Directory to save files in
|
||||||
|
Added: 7.72.0
|
||||||
|
See-also: remote-name remote-header-name
|
||||||
|
---
|
||||||
|
|
||||||
|
This option specifies the directory in which files should be stored, when
|
||||||
|
--remote-name or --output are used.
|
||||||
|
|
||||||
|
The given output directory is used for all URLs and output options on the
|
||||||
|
command line, up until the first --next.
|
||||||
|
|
||||||
|
If the specified target directory doesn't exist, the operation will fail
|
||||||
|
unless --create-dirs is also used.
|
||||||
|
|
||||||
|
If this option is used multiple times, the last specified directory will be
|
||||||
|
used.
|
@ -127,6 +127,7 @@
|
|||||||
--ntlm-wb 7.22.0
|
--ntlm-wb 7.22.0
|
||||||
--oauth2-bearer 7.33.0
|
--oauth2-bearer 7.33.0
|
||||||
--output (-o) 4.0
|
--output (-o) 4.0
|
||||||
|
--output-dir 7.72.0
|
||||||
--parallel (-Z) 7.66.0
|
--parallel (-Z) 7.66.0
|
||||||
--parallel-immediate 7.68.0
|
--parallel-immediate 7.68.0
|
||||||
--parallel-max 7.66.0
|
--parallel-max 7.66.0
|
||||||
|
@ -39,6 +39,15 @@
|
|||||||
|
|
||||||
#include "memdebug.h" /* keep this as LAST include */
|
#include "memdebug.h" /* keep this as LAST include */
|
||||||
|
|
||||||
|
#ifndef O_BINARY
|
||||||
|
#define O_BINARY 0
|
||||||
|
#endif
|
||||||
|
#ifdef WIN32
|
||||||
|
#define OPENMODE S_IREAD | S_IWRITE
|
||||||
|
#else
|
||||||
|
#define OPENMODE S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH
|
||||||
|
#endif
|
||||||
|
|
||||||
/* create a local file for writing, return TRUE on success */
|
/* create a local file for writing, return TRUE on success */
|
||||||
bool tool_create_output_file(struct OutStruct *outs,
|
bool tool_create_output_file(struct OutStruct *outs,
|
||||||
struct OperationConfig *config)
|
struct OperationConfig *config)
|
||||||
@ -55,21 +64,24 @@ bool tool_create_output_file(struct OutStruct *outs,
|
|||||||
|
|
||||||
if(outs->is_cd_filename) {
|
if(outs->is_cd_filename) {
|
||||||
/* don't overwrite existing files */
|
/* don't overwrite existing files */
|
||||||
#ifndef O_BINARY
|
int fd;
|
||||||
#define O_BINARY 0
|
char *name = outs->filename;
|
||||||
#endif
|
char *aname = NULL;
|
||||||
int fd = open(outs->filename, O_CREAT | O_WRONLY | O_EXCL | O_BINARY,
|
if(config->output_dir) {
|
||||||
#ifdef WIN32
|
aname = aprintf("%s/%s", config->output_dir, name);
|
||||||
S_IREAD | S_IWRITE
|
if(!aname) {
|
||||||
#else
|
errorf(global, "out of memory\n");
|
||||||
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH
|
return FALSE;
|
||||||
#endif
|
}
|
||||||
);
|
name = aname;
|
||||||
|
}
|
||||||
|
fd = open(name, O_CREAT | O_WRONLY | O_EXCL | O_BINARY, OPENMODE);
|
||||||
if(fd != -1) {
|
if(fd != -1) {
|
||||||
file = fdopen(fd, "wb");
|
file = fdopen(fd, "wb");
|
||||||
if(!file)
|
if(!file)
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
free(aname);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* open file for writing */
|
/* open file for writing */
|
||||||
|
@ -89,6 +89,7 @@ static void free_config_fields(struct OperationConfig *config)
|
|||||||
Curl_safefree(config->mail_auth);
|
Curl_safefree(config->mail_auth);
|
||||||
|
|
||||||
Curl_safefree(config->netrc_file);
|
Curl_safefree(config->netrc_file);
|
||||||
|
Curl_safefree(config->output_dir);
|
||||||
|
|
||||||
urlnode = config->url_list;
|
urlnode = config->url_list;
|
||||||
while(urlnode) {
|
while(urlnode) {
|
||||||
|
@ -80,6 +80,7 @@ struct OperationConfig {
|
|||||||
double connecttimeout;
|
double connecttimeout;
|
||||||
long maxredirs;
|
long maxredirs;
|
||||||
curl_off_t max_filesize;
|
curl_off_t max_filesize;
|
||||||
|
char *output_dir;
|
||||||
char *headerfile;
|
char *headerfile;
|
||||||
char *ftpport;
|
char *ftpport;
|
||||||
char *iface;
|
char *iface;
|
||||||
|
@ -303,6 +303,7 @@ static const struct LongShort aliases[]= {
|
|||||||
{"o", "output", ARG_FILENAME},
|
{"o", "output", ARG_FILENAME},
|
||||||
{"O", "remote-name", ARG_NONE},
|
{"O", "remote-name", ARG_NONE},
|
||||||
{"Oa", "remote-name-all", ARG_BOOL},
|
{"Oa", "remote-name-all", ARG_BOOL},
|
||||||
|
{"Ob", "output-dir", ARG_STRING},
|
||||||
{"p", "proxytunnel", ARG_BOOL},
|
{"p", "proxytunnel", ARG_BOOL},
|
||||||
{"P", "ftp-port", ARG_STRING},
|
{"P", "ftp-port", ARG_STRING},
|
||||||
{"q", "disable", ARG_BOOL},
|
{"q", "disable", ARG_BOOL},
|
||||||
@ -1911,6 +1912,10 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
|
|||||||
config->default_node_flags = toggle?GETOUT_USEREMOTE:0;
|
config->default_node_flags = toggle?GETOUT_USEREMOTE:0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
else if(subletter == 'b') { /* --output-dir */
|
||||||
|
GetStr(&config->output_dir, nextarg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case 'o': /* --output */
|
case 'o': /* --output */
|
||||||
/* output file */
|
/* output file */
|
||||||
|
@ -284,6 +284,8 @@ static const struct helptxt helptext[] = {
|
|||||||
"OAuth 2 Bearer Token"},
|
"OAuth 2 Bearer Token"},
|
||||||
{"-o, --output <file>",
|
{"-o, --output <file>",
|
||||||
"Write to file instead of stdout"},
|
"Write to file instead of stdout"},
|
||||||
|
{" --output-dir <dir>",
|
||||||
|
"Directory to save files in"},
|
||||||
{"-Z, --parallel",
|
{"-Z, --parallel",
|
||||||
"Perform transfers in parallel"},
|
"Perform transfers in parallel"},
|
||||||
{" --parallel-immediate",
|
{" --parallel-immediate",
|
||||||
|
@ -1050,6 +1050,15 @@ static CURLcode single_transfer(struct GlobalConfig *global,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(config->output_dir) {
|
||||||
|
char *d = aprintf("%s/%s", config->output_dir, per->outfile);
|
||||||
|
if(!d) {
|
||||||
|
result = CURLE_WRITE_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
free(per->outfile);
|
||||||
|
per->outfile = d;
|
||||||
|
}
|
||||||
/* Create the directory hierarchy, if not pre-existent to a multiple
|
/* Create the directory hierarchy, if not pre-existent to a multiple
|
||||||
file output call */
|
file output call */
|
||||||
|
|
||||||
|
@ -224,5 +224,5 @@ test2078 \
|
|||||||
test2080 \
|
test2080 \
|
||||||
test2100 \
|
test2100 \
|
||||||
\
|
\
|
||||||
test3000 test3001 \
|
test3000 test3001 test3002 test3003 test3004 test3005 test3006 test3007 \
|
||||||
test3002 test3003 test3004 test3005 test3006 test3007 test3010
|
test3008 test3009 test3010 test3011 test3012 test3013
|
||||||
|
59
tests/data/test3008
Normal file
59
tests/data/test3008
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<testcase>
|
||||||
|
<info>
|
||||||
|
<keywords>
|
||||||
|
-O
|
||||||
|
</keywords>
|
||||||
|
</info>
|
||||||
|
#
|
||||||
|
# Server-side
|
||||||
|
<reply>
|
||||||
|
<data nocheck="yes">
|
||||||
|
HTTP/1.1 200 OK
|
||||||
|
Date: Thu, 09 Nov 2010 14:49:00 GMT
|
||||||
|
Server: test-server/fake
|
||||||
|
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
|
||||||
|
ETag: "21025-dc7-39462498"
|
||||||
|
Accept-Ranges: bytes
|
||||||
|
Content-Length: 6
|
||||||
|
Connection: close
|
||||||
|
Content-Type: text/html
|
||||||
|
Funny-head: yesyes
|
||||||
|
|
||||||
|
-foo-
|
||||||
|
</data>
|
||||||
|
</reply>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Client-side
|
||||||
|
<client>
|
||||||
|
<server>
|
||||||
|
http
|
||||||
|
</server>
|
||||||
|
<features>
|
||||||
|
http
|
||||||
|
</features>
|
||||||
|
<name>
|
||||||
|
--output-dir
|
||||||
|
</name>
|
||||||
|
<command option="no-output,no-include">
|
||||||
|
http://%HOSTIP:%HTTPPORT/this/is/the/3008 -O --output-dir %PWD/log
|
||||||
|
</command>
|
||||||
|
</client>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Verify data after the test has been "shot"
|
||||||
|
<verify>
|
||||||
|
<strip>
|
||||||
|
^User-Agent:.*
|
||||||
|
</strip>
|
||||||
|
<protocol>
|
||||||
|
GET /this/is/the/3008 HTTP/1.1
|
||||||
|
Host: %HOSTIP:%HTTPPORT
|
||||||
|
Accept: */*
|
||||||
|
|
||||||
|
</protocol>
|
||||||
|
<file name="log/3008">
|
||||||
|
-foo-
|
||||||
|
</file>
|
||||||
|
</verify>
|
||||||
|
</testcase>
|
59
tests/data/test3009
Normal file
59
tests/data/test3009
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<testcase>
|
||||||
|
<info>
|
||||||
|
<keywords>
|
||||||
|
-O
|
||||||
|
</keywords>
|
||||||
|
</info>
|
||||||
|
#
|
||||||
|
# Server-side
|
||||||
|
<reply>
|
||||||
|
<data nocheck="yes">
|
||||||
|
HTTP/1.1 200 OK
|
||||||
|
Date: Thu, 09 Nov 2010 14:49:00 GMT
|
||||||
|
Server: test-server/fake
|
||||||
|
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
|
||||||
|
ETag: "21025-dc7-39462498"
|
||||||
|
Accept-Ranges: bytes
|
||||||
|
Content-Length: 6
|
||||||
|
Connection: close
|
||||||
|
Content-Type: text/html
|
||||||
|
Funny-head: yesyes
|
||||||
|
|
||||||
|
-foo-
|
||||||
|
</data>
|
||||||
|
</reply>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Client-side
|
||||||
|
<client>
|
||||||
|
<server>
|
||||||
|
http
|
||||||
|
</server>
|
||||||
|
<features>
|
||||||
|
http
|
||||||
|
</features>
|
||||||
|
<name>
|
||||||
|
--output-dir a non-existing directory
|
||||||
|
</name>
|
||||||
|
<command option="no-output,no-include">
|
||||||
|
http://%HOSTIP:%HTTPPORT/this/is/the/3009 -O --output-dir %PWD/not-there
|
||||||
|
</command>
|
||||||
|
</client>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Verify data after the test has been "shot"
|
||||||
|
<verify>
|
||||||
|
<strip>
|
||||||
|
^User-Agent:.*
|
||||||
|
</strip>
|
||||||
|
<protocol>
|
||||||
|
GET /this/is/the/3009 HTTP/1.1
|
||||||
|
Host: %HOSTIP:%HTTPPORT
|
||||||
|
Accept: */*
|
||||||
|
|
||||||
|
</protocol>
|
||||||
|
<errorcode>
|
||||||
|
23
|
||||||
|
</errorcode>
|
||||||
|
</verify>
|
||||||
|
</testcase>
|
59
tests/data/test3011
Normal file
59
tests/data/test3011
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<testcase>
|
||||||
|
<info>
|
||||||
|
<keywords>
|
||||||
|
-O
|
||||||
|
</keywords>
|
||||||
|
</info>
|
||||||
|
#
|
||||||
|
# Server-side
|
||||||
|
<reply>
|
||||||
|
<data nocheck="yes">
|
||||||
|
HTTP/1.1 200 OK
|
||||||
|
Date: Thu, 09 Nov 2010 14:49:00 GMT
|
||||||
|
Server: test-server/fake
|
||||||
|
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
|
||||||
|
ETag: "21025-dc7-39462498"
|
||||||
|
Accept-Ranges: bytes
|
||||||
|
Content-Length: 6
|
||||||
|
Connection: close
|
||||||
|
Content-Type: text/html
|
||||||
|
Funny-head: yesyes
|
||||||
|
|
||||||
|
-foo-
|
||||||
|
</data>
|
||||||
|
</reply>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Client-side
|
||||||
|
<client>
|
||||||
|
<server>
|
||||||
|
http
|
||||||
|
</server>
|
||||||
|
<features>
|
||||||
|
http
|
||||||
|
</features>
|
||||||
|
<name>
|
||||||
|
--output-dir with --create-dirs
|
||||||
|
</name>
|
||||||
|
<command option="no-output,no-include">
|
||||||
|
http://%HOSTIP:%HTTPPORT/this/is/the/3011 -O --output-dir %PWD/log/tmp --create-dirs
|
||||||
|
</command>
|
||||||
|
</client>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Verify data after the test has been "shot"
|
||||||
|
<verify>
|
||||||
|
<strip>
|
||||||
|
^User-Agent:.*
|
||||||
|
</strip>
|
||||||
|
<protocol>
|
||||||
|
GET /this/is/the/3011 HTTP/1.1
|
||||||
|
Host: %HOSTIP:%HTTPPORT
|
||||||
|
Accept: */*
|
||||||
|
|
||||||
|
</protocol>
|
||||||
|
<file name="log/tmp/3011">
|
||||||
|
-foo-
|
||||||
|
</file>
|
||||||
|
</verify>
|
||||||
|
</testcase>
|
62
tests/data/test3012
Normal file
62
tests/data/test3012
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
<testcase>
|
||||||
|
<info>
|
||||||
|
<keywords>
|
||||||
|
-O
|
||||||
|
-J
|
||||||
|
--output-dir
|
||||||
|
</keywords>
|
||||||
|
</info>
|
||||||
|
#
|
||||||
|
# Server-side
|
||||||
|
<reply>
|
||||||
|
<data nocheck="yes">
|
||||||
|
HTTP/1.1 200 OK
|
||||||
|
Date: Thu, 09 Nov 2010 14:49:00 GMT
|
||||||
|
Server: test-server/fake
|
||||||
|
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
|
||||||
|
ETag: "21025-dc7-39462498"
|
||||||
|
Accept-Ranges: bytes
|
||||||
|
Content-Length: 6
|
||||||
|
Connection: close
|
||||||
|
Content-Disposition: inline; filename="MMM3012MMM"
|
||||||
|
Content-Type: text/html
|
||||||
|
Funny-head: yesyes
|
||||||
|
|
||||||
|
-foo-
|
||||||
|
</data>
|
||||||
|
</reply>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Client-side
|
||||||
|
<client>
|
||||||
|
<server>
|
||||||
|
http
|
||||||
|
</server>
|
||||||
|
<features>
|
||||||
|
http
|
||||||
|
</features>
|
||||||
|
<name>
|
||||||
|
--output-dir with -J
|
||||||
|
</name>
|
||||||
|
<command option="no-output,no-include">
|
||||||
|
http://%HOSTIP:%HTTPPORT/this/is/the/3012 -OJ --output-dir %PWD/log
|
||||||
|
</command>
|
||||||
|
</client>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Verify data after the test has been "shot"
|
||||||
|
<verify>
|
||||||
|
<strip>
|
||||||
|
^User-Agent:.*
|
||||||
|
</strip>
|
||||||
|
<protocol>
|
||||||
|
GET /this/is/the/3012 HTTP/1.1
|
||||||
|
Host: %HOSTIP:%HTTPPORT
|
||||||
|
Accept: */*
|
||||||
|
|
||||||
|
</protocol>
|
||||||
|
<file name="log/MMM3012MMM">
|
||||||
|
-foo-
|
||||||
|
</file>
|
||||||
|
</verify>
|
||||||
|
</testcase>
|
69
tests/data/test3013
Normal file
69
tests/data/test3013
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
<testcase>
|
||||||
|
<info>
|
||||||
|
<keywords>
|
||||||
|
-O
|
||||||
|
-J
|
||||||
|
--output-dir
|
||||||
|
</keywords>
|
||||||
|
</info>
|
||||||
|
#
|
||||||
|
# Server-side
|
||||||
|
<reply>
|
||||||
|
<data nocheck="yes">
|
||||||
|
HTTP/1.1 200 OK
|
||||||
|
Date: Thu, 09 Nov 2010 14:49:00 GMT
|
||||||
|
Server: test-server/fake
|
||||||
|
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
|
||||||
|
ETag: "21025-dc7-39462498"
|
||||||
|
Accept-Ranges: bytes
|
||||||
|
Content-Length: 6
|
||||||
|
Connection: close
|
||||||
|
Content-Disposition: inline; filename="MMM3013MMM"
|
||||||
|
Content-Type: text/html
|
||||||
|
Funny-head: yesyes
|
||||||
|
|
||||||
|
-foo-
|
||||||
|
</data>
|
||||||
|
</reply>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Client-side
|
||||||
|
<client>
|
||||||
|
<server>
|
||||||
|
http
|
||||||
|
</server>
|
||||||
|
<features>
|
||||||
|
http
|
||||||
|
</features>
|
||||||
|
<name>
|
||||||
|
Two --output-dir with --next in between
|
||||||
|
</name>
|
||||||
|
<command option="no-output,no-include">
|
||||||
|
http://%HOSTIP:%HTTPPORT/this/is/the/3013 -O --output-dir %PWD/log http://%HOSTIP:%HTTPPORT/another/3013 -o second3013 --output-dir %PWD/log
|
||||||
|
</command>
|
||||||
|
</client>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Verify data after the test has been "shot"
|
||||||
|
<verify>
|
||||||
|
<strip>
|
||||||
|
^User-Agent:.*
|
||||||
|
</strip>
|
||||||
|
<protocol>
|
||||||
|
GET /this/is/the/3013 HTTP/1.1
|
||||||
|
Host: %HOSTIP:%HTTPPORT
|
||||||
|
Accept: */*
|
||||||
|
|
||||||
|
GET /another/3013 HTTP/1.1
|
||||||
|
Host: %HOSTIP:%HTTPPORT
|
||||||
|
Accept: */*
|
||||||
|
|
||||||
|
</protocol>
|
||||||
|
<file name="log/3013">
|
||||||
|
-foo-
|
||||||
|
</file>
|
||||||
|
<file2 name="log/second3013">
|
||||||
|
-foo-
|
||||||
|
</file2>
|
||||||
|
</verify>
|
||||||
|
</testcase>
|
@ -2713,15 +2713,21 @@ sub cleardir {
|
|||||||
my $file;
|
my $file;
|
||||||
|
|
||||||
# Get all files
|
# Get all files
|
||||||
opendir(DIR, $dir) ||
|
opendir(my $dh, $dir) ||
|
||||||
return 0; # can't open dir
|
return 0; # can't open dir
|
||||||
while($file = readdir(DIR)) {
|
while($file = readdir($dh)) {
|
||||||
if(($file !~ /^\.(|\.)$/)) {
|
if(($file !~ /^(\.|\.\.)\z/)) {
|
||||||
|
if(-d "$dir/$file") {
|
||||||
|
cleardir("$dir/$file");
|
||||||
|
rmdir("$dir/$file");
|
||||||
|
}
|
||||||
|
else {
|
||||||
unlink("$dir/$file");
|
unlink("$dir/$file");
|
||||||
|
}
|
||||||
$count++;
|
$count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
closedir DIR;
|
closedir $dh;
|
||||||
return $count;
|
return $count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user