Модераторы: xvr
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Синхронизация двух каталогов Dir1 и Dir2, Копирование отсутствующих каталогов 
V
    Опции темы
Him
Дата 26.4.2010, 19:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 5.5.2009

Репутация: нет
Всего: нет



           Доброго времени суток всем!
Нужна помощь. Имелась исходная программа, листинг выкладываю. Преподаватель ее не засчитал, ссылаясь на то, что копирование файлов делать с использованием только read write и никаких iostream.h


Листинг исходной программы, незачтенной преподом (работал полностью):
Код

// Написать программу синхронизации двух каталогов, например Dir1 и Dir2.
// Пользователь задает имена Dir1 и Dir2. В результате работы программы
// файлы, имеющиеся в Dir1, но отсутствующие в Dir2, должны скопироваться 
// в Dir2 вместе с правами доступа.
// 
// Процедуры копирования должны запускаться с использованием 
//   функции fork() в отдельном процессе для каждого копируемого файла. 
// Каждый процесс выводит на экран свой pid, имя копируемого файла и 
//   число скопированных байт. 
// Число запущенных процессов не должно превышать N (вводится 
//   пользователем).
//
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <fstream>
#include <iostream>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>


using namespace std; 
void mycopyfile (const char *source_file, const char *destination_file)
{   
    ifstream in(source_file);
    ofstream out(destination_file);
    out<<in.rdbuf(); // copy file 
    in.close();
    out.close(); 
}

int main (void)
{
    DIR *dir1, *dir2;
    struct dirent *entry1, *entry2;
    struct stat *buf; // Структура Stat - информация о файле
    int flag, flag_name, k, i, m, cur, NPROC;
    string in_str, out_str;
    pid_t pids[1024], pid_end;
    int file_o;
    char str_dir1[80], str_dir2[80]; // Массив для названий каталогов
    
    printf("Dir1: \n"); // Введите Dir1
    scanf("%s", str_dir1); // Название в переменную str_dir1
    printf("Dir2: \n"); // Введите Dir2
    scanf("%s", str_dir2); // Название в переменную str_dir2
    printf("Число процессов N: \n"); // Введите число процессов
    scanf("%d", &NPROC); // Число процессов по адресу NPROC
       
    dir1 = opendir (str_dir1); // Результат открытия каталога Dir1
    dir2 = opendir (str_dir2); // Результат открытия каталога Dir2

    if ((!dir1)||(!dir2)) // Если неудачное открытие
      {
        perror ("diropen");
        return 1;
      }
      
    i = 0;
       
    while ((entry1 = readdir(dir1)) != NULL) // Пока нет ошибки в Dir1
       {
        flag = 1;
        while ((entry2 = readdir(dir2)) != NULL) // Пока нет ошибки в Dir2
          {
           for (flag_name = 1, k = 0; (k < MAXNAMLEN) &&  
                         (entry1->d_name[k] != '\0');k++)
              {  
               if(entry1->d_name[k] != entry2->d_name[k]) // Если кат. не равны...
                  flag_name = 0;
              }
           if ((flag_name == 1) && (entry1->d_type == entry2->d_type) &&
                                   (entry1->d_reclen == entry2->d_reclen)) // Если равны, то...
              flag = 0;
          }
        
          rewinddir (dir2); // Сброс потока кат., дескриптор указ. на начало
          
          if (flag)  // Если 1
                       {
              if (i == NPROC)  // Если равен числу процессов
                {
                 pid_end = wait(NULL);//wait end process (Завершение)       
                 for (m = 0; (m < NPROC) && (pids[m] != pid_end); m++); // Поиск ном. оконч. процесса
                 cur = m;
                }
                else cur = i;
                
              pids[cur] = fork();  // Порождается процесс
              if (pids[cur] < 0) 
                 {
                  perror("fork");
                  return 1;
                 } 
                 else 
                    if (!pids[cur]) 
                       {     
                        in_str = str_dir1;         // Присвоить назв. кат.
                        in_str += "/";             // Добавить косую черту
                        in_str +=  entry1->d_name; // Присв. назв. файла
                        out_str = str_dir2;        // Присвоить назв. кат.
                        out_str += "/";            // Добавить косую черту
                        out_str += entry1->d_name; // Присвоить назв. файла
                        mycopyfile (in_str.c_str(), out_str.c_str()); // Копир.
                        file_o = open (in_str.c_str(), O_RDONLY);
                        fstat (file_o, buf);
                        close (file_o);
                        printf ("%d %s %d \n", getpid(), entry1->d_name, buf->st_size);// pid, название, размер  
                        if (i < NPROC) i++;
                       }
             }
       }

    closedir (dir1);
    closedir (dir2);
    
    /*wait end all process */
    for (i = 0; i < NPROC; i++)
       waitpid (pids[i], NULL, 0);
    return 0;
};


Я его поменял, изменил процедуру mycopyfile и ввел ещё размер буфера.
Однако возникла сложность: не получается передать в процедуру параметры
in_str и out_str, в них находится строка адреса директории (каталога), которую надобно копировать.
При компиляции говорит, что in_str и out_st не описаны (понимаю это, а сообразить как их описать не могу).
Понимаю, что вопрос собственно не сложный, но разобраться в нем не смог, прошу помощи!

Вот код измененной программы:
Код

// Написать программу синхронизации двух каталогов, например Dir1 и Dir2.
// Пользователь задает имена Dir1 и Dir2. В результате работы программы
// файлы, имеющиеся в Dir1, но отсутствующие в Dir2, должны скопироваться 
// в Dir2 вместе с правами доступа.
// 
// Процедуры копирования должны запускаться с использованием 
//   функции fork() в отдельном процессе для каждого копируемого файла. 
// Каждый процесс выводит на экран свой pid, имя копируемого файла и 
//   число скопированных байт. 
// Число запущенных процессов не должно превышать N (вводится 
//   пользователем).
//
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <fstream>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>

#define BUF_SIZE  4096
char buffer [BUF_SIZE];

using namespace std; 
void mycopyfile (const char *source_file, const char *destination_file)
{   

    int infd, outfd;
    ssize_t bytes;
    
    infd = open (in_str.c_str(), O_RDONLY);
    if (infd == -1) 
       {
           fprintf (stderr, "НЕ могу открыть входящий файл ""(%s)\n", in_str.c_str);
           exit (4);
       }

    outfd = open (out_str.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0640);
    if (outfd == -1) 
    {
        fprintf (stderr, "НЕ могу открыть выходящий файл ""(%s)\n", out_str.c_str);
        exit (5);
    }

    while ((bytes = read(infd, buffer, BUF_SIZE)) > 0) 
        write (outfd, buffer, bytes);

    close (infd);
    close (outfd);
    exit (6);
}

int main (void)
{
    DIR *dir1, *dir2;
    struct dirent *entry1, *entry2;
    struct stat *buf; // Структура Stat - информация о файле
    int flag, flag_name, k, i, m, cur, NPROC;
    string in_str, out_str;
    pid_t pids[1024], pid_end;
    int file_o;
    char str_dir1[80], str_dir2[80]; // Массив для названий каталогов
    
    printf("Dir1: \n"); // Введите Dir1
    scanf("%s", str_dir1); // Название в переменную str_dir1
    printf("Dir2: \n"); // Введите Dir2
    scanf("%s", str_dir2); // Название в переменную str_dir2
    printf("Число процессов N: \n"); // Введите число процессов
    scanf("%d", &NPROC); // Число процессов по адресу NPROC
       
    dir1 = opendir (str_dir1); // Результат открытия каталога Dir1
    dir2 = opendir (str_dir2); // Результат открытия каталога Dir2

    if ((!dir1)||(!dir2)) // Если неудачное открытие
      {
        perror ("diropen");
        return 1;
      }
      
    i = 0;
       
    while ((entry1 = readdir(dir1)) != NULL) // Пока нет ошибки в Dir1
       {
        flag = 1;
        while ((entry2 = readdir(dir2)) != NULL) // Пока нет ошибки в Dir2
          {
           for (flag_name = 1, k = 0; (k < MAXNAMLEN) &&  
                         (entry1->d_name[k] != '\0');k++)
              {  
               if(entry1->d_name[k] != entry2->d_name[k]) // Если кат. не равны...
                  flag_name = 0;
              }
           if ((flag_name == 1) && (entry1->d_type == entry2->d_type) &&
                                   (entry1->d_reclen == entry2->d_reclen)) // Если равны, то...
              flag = 0;
          }
        
          rewinddir (dir2); // Сброс потока кат., дескриптор указ. на начало
          
          if (flag)  // Если 1
                       {
              if (i == NPROC)  // Если равен числу процессов
                {
                 pid_end = wait(NULL);//wait end process (Завершение)       
                 for (m = 0; (m < NPROC) && (pids[m] != pid_end); m++); // Поиск ном. оконч. процесса
                 cur = m;
                }
                else cur = i;
                
              pids[cur] = fork();  // Порождается процесс
              if (pids[cur] < 0) 
                 {
                  perror("fork");
                  return 1;
                 } 
                 else 
                    if (!pids[cur]) 
                       {     
                        in_str = str_dir1;         // Присвоить назв. кат.
                        in_str += "/";             // Добавить косую черту
                        in_str +=  entry1->d_name; // Присв. назв. файла
                        out_str = str_dir2;        // Присвоить назв. кат.
                        out_str += "/";            // Добавить косую черту
                        out_str += entry1->d_name; // Присвоить назв. файла
                        mycopyfile (in_str.c_str(), out_str.c_str()); // Копир.
                        file_o = open (in_str.c_str(), O_RDONLY);
                        fstat (file_o, buf);
                        close (file_o);
                        printf ("%d %s %d \n", getpid(), entry1->d_name, buf->st_size);// pid, название, размер  
                        if (i < NPROC) i++;
                       }
             }
       }

    closedir (dir1);
    closedir (dir2);
    
    /*wait end all process */
    for (i = 0; i < NPROC; i++)
       waitpid (pids[i], NULL, 0);
    return 0;
};




PM MAIL   Вверх
djamshud
Дата 26.4.2010, 23:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Пердупержденный
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 23.11.2009

Репутация: 1
Всего: 39



in/out_str не определены нигде. Наверное на их месте предполагается использование source/destination_file.


--------------------
'Cuz I never walk away from what I know is right
Alice Cooper - Freedom
PM   Вверх
Him
Дата 27.4.2010, 16:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 5.5.2009

Репутация: нет
Всего: нет



djamshud,  спасибо Вам за участие.

Только вот немного я не понял: как же тогда произвести изменения.
Меня смущает, что в исходной (рабочей) программе значения передавались в потоки, а здесь тогда как...

Получается надо изменить процедуру таким образом, что ли?
Код

void mycopyfile (const char *source_file, const char *destination_file)
{   

    int infd, outfd;
    ssize_t bytes;
    
    infd = open (source_file, O_RDONLY);
    if (infd == -1) 
       {
           fprintf (stderr, "НЕ могу открыть входящий файл ""(%s)\n", in_str.c_str);
           exit (4);
       }

    outfd = open (destination_file, O_WRONLY | O_CREAT | O_TRUNC, 0640);
    if (outfd == -1) 
    {
        fprintf (stderr, "НЕ могу открыть выходящий файл ""(%s)\n", out_str.c_str);
        exit (5);
    }

    while ((bytes = read(infd, buffer, BUF_SIZE)) > 0) 
        write (outfd, buffer, bytes);

    close (infd);
    close (outfd);
    exit (6);
}


а при вызове ее использвоать как и было: mycopyfile (in_str.c_str(), out_str.c_str());

Прав ли я?
Если нет помогите все же "добить" это задание.

С уважением, Him.
PM MAIL   Вверх
djamshud
Дата 27.4.2010, 17:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Пердупержденный
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 23.11.2009

Репутация: 1
Всего: 39



Да вроде так и есть. Скомпилируйте, да проверьте:).


--------------------
'Cuz I never walk away from what I know is right
Alice Cooper - Freedom
PM   Вверх
Him
Дата 27.4.2010, 17:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 5.5.2009

Репутация: нет
Всего: нет



djamshud, спасибо Вам, вечерком проверю, если что, то отпишусь завтра.
С уважением, Him.
PM MAIL   Вверх
Him
Дата 28.4.2010, 22:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 5.5.2009

Репутация: нет
Всего: нет



djamshud,  СПАСИБО ВАМ ЗА ПОМОЩЬ!
Программа запустилась, все нормально.
Тема закрыта. Привет из Минска.

Вот окончательный вариант программы:
Код

// Написать программу синхронизации двух каталогов, например Dir1 и Dir2.
// Пользователь задает имена Dir1 и Dir2. В результате работы программы
// файлы, имеющиеся в Dir1, но отсутствующие в Dir2, должны скопироваться 
// в Dir2 вместе с правами доступа.
// 
// Процедуры копирования должны запускаться с использованием 
//   функции fork() в отдельном процессе для каждого копируемого файла. 
// Каждый процесс выводит на экран свой pid, имя копируемого файла и 
//   число скопированных байт. 
// Число запущенных процессов не должно превышать N (вводится 
//   пользователем).
//
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <fstream>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>

#define BUF_SIZE  4096
char buffer [BUF_SIZE];

using namespace std; 
void mycopyfile (const char *source_file, const char *destination_file)
{   

    int infd, outfd;
    ssize_t bytes;
    
    infd = open (source_file, O_RDONLY);
    if (infd == -1) 
       {
           fprintf (stderr, "НЕ могу открыть входящий файл ""(%s)\n", source_file);
           exit (1);
       }

    outfd = open (destination_file, O_WRONLY | O_CREAT | O_TRUNC, 0640);
    if (outfd == -1) 
    {
        fprintf (stderr, "НЕ могу открыть выходящий файл ""(%s)\n", destination_file);
        exit (2);
    }

    while ((bytes = read(infd, buffer, BUF_SIZE)) > 0) 
        write (outfd, buffer, bytes);

    close (infd);
    close (outfd);
    exit (3);
}

int main (void)
{
    DIR *dir1, *dir2;
    struct dirent *entry1, *entry2;
    struct stat *buf; // Структура Stat - информация о файле
    int flag, flag_name, k, i, m, cur, NPROC;
    string in_str, out_str;
    pid_t pids[1024], pid_end;
    int file_o;
    char str_dir1[80], str_dir2[80]; // Массив для названий каталогов
    
    printf("Dir1: \n"); // Введите Dir1
    scanf("%s", str_dir1); // Название в переменную str_dir1
    printf("Dir2: \n"); // Введите Dir2
    scanf("%s", str_dir2); // Название в переменную str_dir2
    printf("Число процессов N: \n"); // Введите число процессов
    scanf("%d", &NPROC); // Число процессов по адресу NPROC
       
    dir1 = opendir (str_dir1); // Результат открытия каталога Dir1
    dir2 = opendir (str_dir2); // Результат открытия каталога Dir2

    if ((!dir1)||(!dir2)) // Если неудачное открытие
      {
        perror ("diropen");
        return 1;
      }
      
    i = 0;
       
    while ((entry1 = readdir(dir1)) != NULL) // Пока нет ошибки в Dir1
       {
        flag = 1;
        while ((entry2 = readdir(dir2)) != NULL) // Пока нет ошибки в Dir2
          {
           for (flag_name = 1, k = 0; (k < MAXNAMLEN) &&  
                         (entry1->d_name[k] != '\0');k++)
              {  
               if(entry1->d_name[k] != entry2->d_name[k]) // Если кат. не равны...
                  flag_name = 0;
              }
           if ((flag_name == 1) && (entry1->d_type == entry2->d_type) &&
                                   (entry1->d_reclen == entry2->d_reclen)) // Если равны, то...
              flag = 0;
          }
        
          rewinddir (dir2); // Сброс потока кат., дескриптор указ. на начало
          
          if (flag)  // Если 1
                       {
              if (i == NPROC)  // Если равен числу процессов
                {
                 pid_end = wait(NULL);//wait end process (Завершение)       
                 for (m = 0; (m < NPROC) && (pids[m] != pid_end); m++); // Поиск ном. оконч. процесса
                 cur = m;
                }
                else cur = i;
                
              pids[cur] = fork();  // Порождается процесс
              if (pids[cur] < 0) 
                 {
                  perror("fork");
                  return 1;
                 } 
                 else 
                    if (!pids[cur]) 
                       {     
                        in_str = str_dir1;         // Присвоить назв. кат.
                        in_str += "/";             // Добавить косую черту
                        in_str +=  entry1->d_name; // Присв. назв. файла
                        out_str = str_dir2;        // Присвоить назв. кат.
                        out_str += "/";            // Добавить косую черту
                        out_str += entry1->d_name; // Присвоить назв. файла
                        mycopyfile (in_str.c_str(), out_str.c_str()); // Копир.
                        file_o = open (in_str.c_str(), O_RDONLY);
                        fstat (file_o, buf);
                        close (file_o);
                        printf ("%d %s %d \n", getpid(), entry1->d_name, buf->st_size);// pid, название, размер  
                        if (i < NPROC) i++;
                       }
             }
       }

    closedir (dir1);
    closedir (dir2);
    
    /*wait end all process */
    for (i = 0; i < NPROC; i++)
       waitpid (pids[i], NULL, 0);
    return 0;
};

PM MAIL   Вверх
a22
Дата 17.6.2010, 21:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 1
Регистрация: 16.6.2010

Репутация: нет
Всего: нет



Может кто подскажет. Прога работает но процесс не выводит "на экран свой pid, имя копируемого файла и число скопированных байт."




Это сообщение отредактировал(а) a22 - 18.6.2010, 23:01
PM MAIL   Вверх
leonkiller
Дата 22.11.2011, 04:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 2
Регистрация: 22.11.2011

Репутация: нет
Всего: нет



Подскажите, пожалуйста, кто-нибудь. Такая же проблема, как и у a22.
Прога работает, файлы копируются но процесс не выводит "на экран свой pid, имя копируемого файла и число скопированных байт."
PM MAIL   Вверх
bsa
Дата 22.11.2011, 10:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 16
Всего: 196



подсказка. функция exit вызывает немедленное завершение процесса. Данная функция находится в mycopyfile...
PM   Вверх
leonkiller
Дата 22.11.2011, 12:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 2
Регистрация: 22.11.2011

Репутация: нет
Всего: нет



bsa, спасибо.
Убрал, теперь все отображает

Вот еще такой вопрос. Не совсем понимаю, что здесь означает параметр N - число процессов. У меня есть две папки. В первой два файла, в другой - пусто.
И вот в ходе выполнения программы при
N=2 - видны две строчки с копированием каждого файла, отличающиеся только pid,
N=5 - две строчки с первым и четыре со вторым,
N=9- тоже самое, насколько я помню.

Это сообщение отредактировал(а) leonkiller - 22.11.2011, 13:05
PM MAIL   Вверх
bsa
Дата 22.11.2011, 13:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 16
Всего: 196



leonkiller, пройдись по шагам (в уме), что делает чилд после возврата из функции копирования файлов. и ты найдешь ошибку.
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Программирование под Unix/Linux"
xvr
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • Не забывайте пользоваться кнопкой "Код".
  • Вопросы мобильной разработки тут
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к разделу форума. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, xvr.

 
 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Программирование под Unix/Linux | Следующая тема »


 




[ Время генерации скрипта: 0.0581 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.