/*************************************************************************** main.c - description ------------------- begin : Mon Sep 2 19:30:41 BST 2002 copyright : (C) 2002 by Tim-Philipp Müller email : t.i.m@orange.net ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /* ed2k_hash * * This program is a tool for the eDonkey2000 and overnet file sharing * programs and a complete rewrite of the original tool (v0.1/v0.2). * * It produces the 'ed2k-hash' and 'ed2k-link' of a file or a number of * files. * * Adding different input/output contexts ([G]UIs) shouldn't be too hard. * */ #ifdef HAVE_CONFIG_H # include #endif #include "global.h" #if (defined(__linux__) || defined(__MAC_OS_X__) || defined(__FreeBSD__) || (defined(sun) && defined(__svr4__))) # include # include # include # include #endif #ifdef __WIN32 # include #endif #include #include #include #include #include "global.h" #include "linkedlist.h" #include "options.h" #include "ui.h" /* user interface */ /* functions */ static int expand_if_directory (char *fn, SList **p_list); static int is_directory (char *fn); static int read_directory (char *fn, SList **p_list); /* main * */ int #if defined(_GUI) /* 12/01/2003 JL: this causes problem with the GUI... */ main_entry_point(int argc, char *argv[]) #else main (int argc, char *argv[]) #endif { int exit_value = EXIT_FAILURE; if (ui_init()) { /* ui_setoptions() returns the argument number that is the first file/directory * specified */ int argfiles = ui_setoptions(argc,argv); if (argfiles) { SList *files = NULL; SList *node = NULL; while (argfilesdata) free(node->data); node = (SList*)node->next; } } } if (!ui_cleanup()) exit_value = EXIT_FAILURE; return exit_value; } /* expand_if_directory * * Takes a filename and the adress of a linked list pointer. * If the filename is a directory, it will read the directory and * append all the files in it to the linked list. * If option_recursive is set, sub-directories will be searched * as well. * * returns 0 if the filename is not a directory, * returns 1 if it is a directory * returns -1 in case of error * */ static int expand_if_directory (char *fn, SList **p_list) { int ret; if ((!fn)||(!p_list)) return -1; ret = is_directory(fn); if (ret<0) /* error - neiher file nor directory */ return -1; if (ret==0) /* not a directory */ return 0; if (option_excludedirs) return 1; /* it is a directory => read in entries (unless option_excludedirs is set)*/ return read_directory (fn, p_list); } /* is_directory * * checks whether the filename specified is a directory or not * * returns 0 if the filename is not a directory, * returns 1 if it is a directory * returns -1 in case of error * */ #if (defined(__linux__) || defined(__MAC_OS_X__) || defined(__FreeBSD__) || (defined(sun) && defined(__svr4__))) static int is_directory (char *fn) { struct stat filestat; if (!fn) return -1; if (stat (fn, &filestat)<0) { ui_printerr ("stat(%s) failed - %s\n\n", fn, strerror(errno)); return -1; } /* is it a directory? */ if (S_ISDIR(filestat.st_mode)) return 1; /* is it a regular file or a symbolic link? */ if ((S_ISREG(filestat.st_mode)) || (S_ISLNK(filestat.st_mode))) return 0; return -1; } #elif defined(__WIN32) static int is_directory (char *fn) { WIN32_FIND_DATA data; HANDLE hFile = FindFirstFile(fn, &data); if (hFile != INVALID_HANDLE_VALUE) { int ret = 0; if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { ret = 1; } CloseHandle(hFile); return ret; } return -1; } #else static int is_directory (char *fn) { struct stat filestat; if (!fn) return -1; ui_print ("IMPLEMENT ME FOR THIS OPERATING SYSTEM/PLATFORM: %s\n", __FUNCTION__); return 0; } #endif /* read_directory * * reads in the files from the specified directory and appends them to the list given * */ #if (defined(__linux__) || defined(__MAC_OS_X__) || defined(__FreeBSD__) || (defined(sun) && defined(__svr4__))) static int read_directory (char *fn, SList **p_list) { struct dirent *entry; DIR *d; if ((!fn)||(!p_list)) return -1; d = opendir (fn); if (!d) { ui_printerr ("opendir() failed - %s\n", strerror(errno)); return -1; } while ((entry=readdir(d))) { if ((entry->d_name) && entry->d_name[0]!='.') /* skip hidden files and dirs */ { int pathfnlen = strlen(fn)+1+strlen(entry->d_name)+2; char *pathfn = (char*) malloc(pathfnlen); if (pathfn) { int isdir; snprintf (pathfn, pathfnlen, "%s%s%s", fn, (fn[strlen(fn)-1]=='/') ? "" : "/", entry->d_name); isdir = is_directory (pathfn); if (isdir==0) { *p_list = slist_append (*p_list, (void*) pathfn); } else { if ((isdir==1) && (option_recursive)) expand_if_directory (pathfn, p_list); free(pathfn); /* don't need to save this in the file list => free it */ } } } } closedir(d); return 1; } #elif defined(__WIN32) static int read_directory (char *fn, SList **p_list) { char *pat = (char*)malloc(strlen(fn) + 5); strcpy(pat, fn); int fullpathlen = strlen(pat); if (pat[strlen(pat) - 1] != '\\') { strcat(pat, "\\"); ++fullpathlen; } strcat(pat, "*.*"); WIN32_FIND_DATA data; HANDLE hFile = FindFirstFile(pat, &data); if (hFile != INVALID_HANDLE_VALUE) { do { if ((data.cFileName[0] != '.')) /* don't even know if it's meaningful under Windows :) */ { char *fullname = (char*)malloc(fullpathlen + strlen(data.cFileName) + 1); sprintf(fullname, "%.*s%s", fullpathlen, pat, data.cFileName); /* could use is_directory, but it's more efficient this way */ if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { *p_list = slist_append (*p_list, (void*)fullname); } else { if (option_recursive) { expand_if_directory(fullname, p_list); } free(fullname); /* don't need to save directory name in file list => free it */ } } } while (FindNextFile(hFile, &data)); CloseHandle(hFile); } free(pat); /* no error case, as far as I know */ return 1; } #else static int read_directory (char *fn, SList **p_list) { ui_print ("IMPLEMENT ME FOR THIS OPERATING SYSTEM/PLATFORM: %s\n", __FUNCTION__); return 0; } #endif