|
22 | 22 | #include <windows.h> |
23 | 23 | #include <io.h> |
24 | 24 | #else |
25 | | -#include <sys/stat.h> |
26 | 25 | #include <sys/types.h> |
27 | 26 | #include <fcntl.h> |
28 | 27 | #include <unistd.h> |
@@ -310,166 +309,6 @@ int32_t fossil_fstream_rename(const char *old_filename, const char *new_filename |
310 | 309 | return FOSSIL_ERROR_OK; |
311 | 310 | } |
312 | 311 |
|
313 | | -// Read file with buffering |
314 | | -int fossil_fstream_read_buffered(const char *filename, void *buffer, size_t size) { |
315 | | - if (filename == NULL || buffer == NULL || size == 0) { |
316 | | - fprintf(stderr, "Error: Invalid input\n"); |
317 | | - return -1; |
318 | | - } |
319 | | - |
320 | | -#ifdef _WIN32 |
321 | | - HANDLE hFile = CreateFile(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); |
322 | | - if (hFile == INVALID_HANDLE_VALUE) { |
323 | | - fprintf(stderr, "Error opening file: %lu\n", GetLastError()); |
324 | | - return -1; |
325 | | - } |
326 | | - |
327 | | - DWORD bytesRead; |
328 | | - BOOL result = ReadFile(hFile, buffer, (DWORD)size, &bytesRead, NULL); |
329 | | - CloseHandle(hFile); |
330 | | - |
331 | | - if (!result || bytesRead != size) { |
332 | | - return -1; |
333 | | - } |
334 | | - |
335 | | -#else |
336 | | - FILE *file = fopen(filename, "rb"); |
337 | | - if (file == NULL) { |
338 | | - perror("Error opening file"); |
339 | | - return -1; |
340 | | - } |
341 | | - |
342 | | - size_t bytesRead = fread(buffer, 1, size, file); |
343 | | - fclose(file); |
344 | | - |
345 | | - if (bytesRead != size) { |
346 | | - return -1; |
347 | | - } |
348 | | -#endif |
349 | | - |
350 | | - return 0; |
351 | | -} |
352 | | - |
353 | | -// Write file with buffering |
354 | | -int fossil_fstream_write_buffered(const char *filename, const void *data, size_t size) { |
355 | | - if (filename == NULL || data == NULL || size == 0) { |
356 | | - fprintf(stderr, "Error: Invalid input\n"); |
357 | | - return -1; |
358 | | - } |
359 | | - |
360 | | -#ifdef _WIN32 |
361 | | - HANDLE hFile = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); |
362 | | - if (hFile == INVALID_HANDLE_VALUE) { |
363 | | - fprintf(stderr, "Error opening file: %lu\n", GetLastError()); |
364 | | - return -1; |
365 | | - } |
366 | | - |
367 | | - DWORD bytesWritten; |
368 | | - BOOL result = WriteFile(hFile, data, (DWORD)size, &bytesWritten, NULL); |
369 | | - CloseHandle(hFile); |
370 | | - |
371 | | - if (!result || bytesWritten != size) { |
372 | | - return -1; |
373 | | - } |
374 | | - |
375 | | -#else |
376 | | - FILE *file = fopen(filename, "wb"); |
377 | | - if (file == NULL) { |
378 | | - perror("Error opening file"); |
379 | | - return -1; |
380 | | - } |
381 | | - |
382 | | - size_t bytesWritten = fwrite(data, 1, size, file); |
383 | | - fclose(file); |
384 | | - |
385 | | - if (bytesWritten != size) { |
386 | | - return -1; |
387 | | - } |
388 | | -#endif |
389 | | - |
390 | | - return 0; |
391 | | -} |
392 | | - |
393 | | -// Lock file (POSIX: fcntl, Windows: LockFile) |
394 | | -int fossil_fstream_lock(const char *filename) { |
395 | | - if (filename == NULL) { |
396 | | - fprintf(stderr, "Error: Null pointer\n"); |
397 | | - return -1; |
398 | | - } |
399 | | - |
400 | | -#ifdef _WIN32 |
401 | | - HANDLE hFile = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); |
402 | | - if (hFile == INVALID_HANDLE_VALUE) { |
403 | | - return -1; |
404 | | - } |
405 | | - |
406 | | - if (!LockFile(hFile, 0, 0, MAXDWORD, MAXDWORD)) { |
407 | | - CloseHandle(hFile); |
408 | | - return -1; |
409 | | - } |
410 | | - |
411 | | - CloseHandle(hFile); |
412 | | -#else |
413 | | - int fd = open(filename, O_RDWR); |
414 | | - if (fd == -1) { |
415 | | - return -1; |
416 | | - } |
417 | | - |
418 | | - struct flock fl = {0}; |
419 | | - fl.l_type = F_WRLCK; |
420 | | - fl.l_whence = SEEK_SET; |
421 | | - |
422 | | - if (fcntl(fd, F_SETLK, &fl) == -1) { |
423 | | - close(fd); |
424 | | - return -1; |
425 | | - } |
426 | | - |
427 | | - close(fd); |
428 | | -#endif |
429 | | - |
430 | | - return 0; |
431 | | -} |
432 | | - |
433 | | -// Unlock file (POSIX: fcntl, Windows: UnlockFile) |
434 | | -int fossil_fstream_unlock(const char *filename) { |
435 | | - if (filename == NULL) { |
436 | | - fprintf(stderr, "Error: Null pointer\n"); |
437 | | - return -1; |
438 | | - } |
439 | | - |
440 | | -#ifdef _WIN32 |
441 | | - HANDLE hFile = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); |
442 | | - if (hFile == INVALID_HANDLE_VALUE) { |
443 | | - return -1; |
444 | | - } |
445 | | - |
446 | | - if (!UnlockFile(hFile, 0, 0, MAXDWORD, MAXDWORD)) { |
447 | | - CloseHandle(hFile); |
448 | | - return -1; |
449 | | - } |
450 | | - |
451 | | - CloseHandle(hFile); |
452 | | -#else |
453 | | - int fd = open(filename, O_RDWR); |
454 | | - if (fd == -1) { |
455 | | - return -1; |
456 | | - } |
457 | | - |
458 | | - struct flock fl = {0}; |
459 | | - fl.l_type = F_UNLCK; |
460 | | - fl.l_whence = SEEK_SET; |
461 | | - |
462 | | - if (fcntl(fd, F_SETLK, &fl) == -1) { |
463 | | - close(fd); |
464 | | - return -1; |
465 | | - } |
466 | | - |
467 | | - close(fd); |
468 | | -#endif |
469 | | - |
470 | | - return 0; |
471 | | -} |
472 | | - |
473 | 312 | // Detect file type (Regular file, Directory, Symbolic link) |
474 | 313 | int fossil_fstream_get_type(const char *filename) { |
475 | 314 | if (filename == NULL) { |
@@ -509,213 +348,3 @@ int fossil_fstream_get_type(const char *filename) { |
509 | 348 | int32_t fossil_fstream_is_open(const fossil_fstream_t *stream) { |
510 | 349 | return stream != NULL && stream->file != NULL; |
511 | 350 | } |
512 | | - |
513 | | -int32_t fossil_fstream_read_all(fossil_fstream_t *stream, void **buffer, size_t *size) { |
514 | | - if (stream == NULL || buffer == NULL || size == NULL || stream->file == NULL) { |
515 | | - fprintf(stderr, "Error: Null pointer\n"); |
516 | | - return FOSSIL_ERROR_NULL_POINTER; |
517 | | - } |
518 | | - |
519 | | - int32_t file_size = fossil_fstream_get_size(stream); |
520 | | - if (file_size < 0) { |
521 | | - fprintf(stderr, "Error: Failed to get file size\n"); |
522 | | - return FOSSIL_ERROR_IO; |
523 | | - } |
524 | | - |
525 | | - *buffer = malloc(file_size); |
526 | | - if (*buffer == NULL) { |
527 | | - fprintf(stderr, "Error: Out of memory\n"); |
528 | | - return FOSSIL_ERROR_OUT_OF_MEMORY; |
529 | | - } |
530 | | - |
531 | | - size_t bytes_read = fread(*buffer, 1, file_size, stream->file); |
532 | | - if ((size_t)bytes_read != (size_t)file_size) { |
533 | | - fprintf(stderr, "Error: File not found\n"); |
534 | | - free(*buffer); |
535 | | - return FOSSIL_ERROR_FILE_NOT_FOUND; |
536 | | - } |
537 | | - |
538 | | - *size = file_size; |
539 | | - return FOSSIL_ERROR_OK; |
540 | | -} |
541 | | - |
542 | | -int32_t fossil_fstream_write_all(fossil_fstream_t *stream, const void *buffer, size_t size) { |
543 | | - if (stream == NULL || buffer == NULL || stream->file == NULL) { |
544 | | - fprintf(stderr, "Error: Null pointer\n"); |
545 | | - return FOSSIL_ERROR_NULL_POINTER; |
546 | | - } |
547 | | - |
548 | | - size_t bytes_written = fwrite(buffer, 1, size, stream->file); |
549 | | - if (bytes_written != size) { |
550 | | - fprintf(stderr, "Error: File not found\n"); |
551 | | - return FOSSIL_ERROR_FILE_NOT_FOUND; |
552 | | - } |
553 | | - |
554 | | - return FOSSIL_ERROR_OK; |
555 | | -} |
556 | | - |
557 | | -// Check file permission (cross-platform) |
558 | | -int32_t fossil_fstream_check_permission(const char *filename, const char *mode) { |
559 | | - if (filename == NULL || mode == NULL) { |
560 | | - fprintf(stderr, "Error: Null pointer\n"); |
561 | | - return 0; |
562 | | - } |
563 | | - |
564 | | - int perm_flag = 0; |
565 | | - if (strcmp(mode, "r") == 0) perm_flag = R_OK; |
566 | | - else if (strcmp(mode, "w") == 0) perm_flag = W_OK; |
567 | | - else if (strcmp(mode, "x") == 0) perm_flag = F_OK; // Windows doesn't support execution permissions directly. |
568 | | - |
569 | | -#ifdef _WIN32 |
570 | | - return (_access(filename, perm_flag) == 0) ? 1 : 0; |
571 | | -#else |
572 | | - return (access(filename, perm_flag) == 0) ? 1 : 0; |
573 | | -#endif |
574 | | -} |
575 | | - |
576 | | -// Set file permissions (cross-platform) |
577 | | -int fossil_fstream_set_permissions(const char *filename, int permissions) { |
578 | | - if (filename == NULL) { |
579 | | - fprintf(stderr, "Error: Null pointer\n"); |
580 | | - return -1; |
581 | | - } |
582 | | - |
583 | | -#ifdef _WIN32 |
584 | | - DWORD attr = GetFileAttributesA(filename); |
585 | | - if (attr == INVALID_FILE_ATTRIBUTES) { |
586 | | - return -1; // Failed to get attributes |
587 | | - } |
588 | | - |
589 | | - // Windows only supports read-only attribute |
590 | | - if (permissions & FOSSIL_FILE_WRITE) { |
591 | | - attr &= ~FILE_ATTRIBUTE_READONLY; // Allow writing |
592 | | - } else { |
593 | | - attr |= FILE_ATTRIBUTE_READONLY; // Set read-only |
594 | | - } |
595 | | - |
596 | | - // Apply changes |
597 | | - return (SetFileAttributesA(filename, attr) != 0) ? 0 : -1; |
598 | | -#else |
599 | | - // POSIX: Use chmod to set permissions |
600 | | - mode_t mode = 0; |
601 | | - |
602 | | - // Owner permissions |
603 | | - if (permissions & FOSSIL_FILE_READ) mode |= S_IRUSR; |
604 | | - if (permissions & FOSSIL_FILE_WRITE) mode |= S_IWUSR; |
605 | | - if (permissions & FOSSIL_FILE_EXEC) mode |= S_IXUSR; |
606 | | - |
607 | | - // Group permissions (optional, can be added based on requirements) |
608 | | - if (permissions & FOSSIL_FILE_READ) mode |= S_IRGRP; |
609 | | - if (permissions & FOSSIL_FILE_WRITE) mode |= S_IWGRP; |
610 | | - if (permissions & FOSSIL_FILE_EXEC) mode |= S_IXGRP; |
611 | | - |
612 | | - // Others permissions (optional, can be added based on requirements) |
613 | | - if (permissions & FOSSIL_FILE_READ) mode |= S_IROTH; |
614 | | - if (permissions & FOSSIL_FILE_WRITE) mode |= S_IWOTH; |
615 | | - if (permissions & FOSSIL_FILE_EXEC) mode |= S_IXOTH; |
616 | | - |
617 | | - // Add sticky bit for directories (POSIX only) |
618 | | - if (permissions & 0x100) { // Assuming 0x100 flag represents sticky bit |
619 | | - mode |= S_ISVTX; |
620 | | - } |
621 | | - |
622 | | - return (chmod(filename, mode) == 0) ? 0 : -1; |
623 | | -#endif |
624 | | -} |
625 | | - |
626 | | -// Get file permissions (cross-platform) |
627 | | -int fossil_fstream_get_permissions(const char *filename) { |
628 | | - if (filename == NULL) { |
629 | | - fprintf(stderr, "Error: Null pointer\n"); |
630 | | - return -1; |
631 | | - } |
632 | | - |
633 | | -#ifdef _WIN32 |
634 | | - DWORD attr = GetFileAttributesA(filename); |
635 | | - if (attr == INVALID_FILE_ATTRIBUTES) { |
636 | | - return -1; // Failed to get attributes |
637 | | - } |
638 | | - |
639 | | - // Map Windows attributes to our portable permission flags |
640 | | - int permissions = 0; |
641 | | - if (attr & FILE_ATTRIBUTE_READONLY) { |
642 | | - permissions |= FOSSIL_FILE_READ; |
643 | | - } else { |
644 | | - permissions |= FOSSIL_FILE_WRITE; |
645 | | - } |
646 | | - return permissions; |
647 | | -#else |
648 | | - struct stat file_stat; |
649 | | - if (stat(filename, &file_stat) != 0) { |
650 | | - return -1; // Failed to get permissions |
651 | | - } |
652 | | - |
653 | | - // Map POSIX permissions to our portable permission flags |
654 | | - int permissions = 0; |
655 | | - if (file_stat.st_mode & S_IRUSR) permissions |= FOSSIL_FILE_READ; |
656 | | - if (file_stat.st_mode & S_IWUSR) permissions |= FOSSIL_FILE_WRITE; |
657 | | - if (file_stat.st_mode & S_IXUSR) permissions |= FOSSIL_FILE_EXEC; |
658 | | - |
659 | | - // Check for sticky bit in POSIX systems |
660 | | - if (file_stat.st_mode & S_ISVTX) { |
661 | | - permissions |= 0x100; // Sticky bit flag |
662 | | - } |
663 | | - |
664 | | - return permissions; |
665 | | -#endif |
666 | | -} |
667 | | - |
668 | | -int32_t fossil_fstream_restrict(const char *filename) { |
669 | | - if (filename == NULL) { |
670 | | - fprintf(stderr, "Error: Null pointer\n"); |
671 | | - return -1; |
672 | | - } |
673 | | - |
674 | | -#ifdef _WIN32 |
675 | | - // On Windows, restrict to owner-only permissions (Read/Write). |
676 | | - // Windows doesn't natively support sticky bits, so we focus on file attributes. |
677 | | - return fossil_fstream_set_permissions(filename, FOSSIL_FILE_READ | FOSSIL_FILE_WRITE); |
678 | | -#else |
679 | | - // POSIX: Restrict to owner-only permissions, allowing read and write only to the owner |
680 | | - mode_t mode = S_IRUSR | S_IWUSR; |
681 | | - |
682 | | - // Ensure sticky bit is supported on POSIX systems if needed. |
683 | | - // Sticky bit is a special permission which can be used on directories to restrict file deletions |
684 | | - // to the file's owner. It's typically used with directories like /tmp. |
685 | | - // On non-directory files, it doesn't have any effect, but it's important for portability. |
686 | | - mode |= S_ISVTX; // Apply sticky bit if desired. |
687 | | - |
688 | | - // Apply the restricted permissions |
689 | | - return (chmod(filename, mode) == 0) ? 0 : -1; |
690 | | -#endif |
691 | | -} |
692 | | - |
693 | | -int32_t fossil_fstream_check_ownership(const char *filename) { |
694 | | - if (filename == NULL) { |
695 | | - fprintf(stderr, "Error: Null pointer\n"); |
696 | | - return 0; |
697 | | - } |
698 | | - |
699 | | -#ifdef _WIN32 |
700 | | - // Windows lacks direct user ownership checking in most environments. |
701 | | - fprintf(stderr, "Error: Ownership check not implemented on Windows.\n"); |
702 | | - return 0; |
703 | | -#else |
704 | | - struct stat file_stat; |
705 | | - if (stat(filename, &file_stat) == 0) { |
706 | | - return (file_stat.st_uid == getuid()) ? 1 : 0; |
707 | | - } |
708 | | - return 0; |
709 | | -#endif |
710 | | -} |
711 | | - |
712 | | -int32_t fossil_fstream_compare_permissions(const char *file1, const char *file2) { |
713 | | - int perm1 = fossil_fstream_get_permissions(file1); |
714 | | - int perm2 = fossil_fstream_get_permissions(file2); |
715 | | - |
716 | | - if (perm1 == -1 || perm2 == -1) { |
717 | | - return -1; // Error reading permissions |
718 | | - } |
719 | | - |
720 | | - return (perm1 == perm2) ? 1 : 0; // Returns 1 if permissions are equal, 0 otherwise |
721 | | -} |
0 commit comments